home *** CD-ROM | disk | FTP | other *** search
/ Audio Version 4.94 / audioversion4.94knowledgemediaresourcelibraryoctober1994.iso / msdos / players / modgus / mod.asm < prev    next >
Assembly Source File  |  1992-12-25  |  50KB  |  2,337 lines

  1. ideal
  2. P286
  3. model    Huge
  4. jumps
  5.  
  6. stack    1024
  7.  
  8. include "pps.inc"
  9.  
  10. segment MyCode
  11.  
  12.         assume    cs:Mycode,ds:MyData
  13.  
  14.  
  15. Start:
  16.         mov    ax,es
  17.         mov    bx,zzzzzseg
  18.         sub    bx,ax
  19.         add    bx,2
  20.         mov    ah, 4ah
  21.         int    21h
  22.  
  23.         mov    ax,MyData
  24.         mov    ds,ax
  25.  
  26.         call    U_DetectGUS
  27.         jnb    @@FoundGUS
  28.         mov    ah,9
  29.         mov    dx,offset NoGUS
  30.         int    21h
  31.         jmp    @@Exit
  32.  
  33. @@FoundGUS:
  34.         call    U_Reset
  35.         mov    al,0
  36.         call    U_ChangeInOut
  37.         mov    dx,offset FName
  38.         call    s_LoadModule
  39.         call    sd_SetMaxVolume
  40.         call    s_PlayMusic
  41.         jmp    @@WaitLoop
  42. @@Myloop:
  43.         call    MyT
  44.         call    MyT
  45.         call    MyT
  46.         call    MyT
  47.         call    MyT
  48.         call    MyT
  49.         mov    ah,1
  50.         int    16h
  51.                 jnz     @@Below
  52.         jmp    @@Myloop
  53. @@WaitLoop:
  54.         mov    ah,1
  55.         int    16h
  56.         jnz    @@Below
  57.         assume    ds:Sound
  58.         mov    ax,Sound
  59.         mov    ds,ax
  60.         mov    al,[Byte mt_Counter]
  61.         mov    di,0
  62.         mov    bx,0b800h
  63.         mov    es,bx
  64.         add    al,'0'
  65.         stosb
  66.         jmp    @@WaitLoop
  67. @@Below:
  68.         mov    ah,0
  69.                 int     16h
  70.         call    s_StopMusic
  71.         call    s_CloseAllMusic
  72.         call    U_Reset
  73. @@Exit:
  74.         mov    ax,4C00h
  75.         int    21h
  76.  
  77.  
  78. ends    MyCode
  79. segment MyData
  80.  
  81. NoGUS        db    'A GUS was not found on this system...',13,10,'$'
  82. FName        db    'PUSH.MOD',0
  83.  
  84. ends    MyData
  85.  
  86. segment         Sound
  87. assume        cs:Sound,ds:Sound
  88.  
  89. Header:
  90. songname    db    20 dup (0)
  91. samples     db    31*size SampleRec dup (0)
  92. songlen     db    0
  93. restart     db    0
  94. sequences    db    128 dup (0)
  95. mk        dd    0
  96. HeaderSize     =    $-Header
  97. PatternLoc    dw    64 dup (0)
  98. InsLoc        dd    32 dup (0)
  99. NumPatterns    dw    0
  100.  
  101. IntStore    dd    0
  102.  
  103. Base    dw    220h
  104.  
  105. proc    UDelay
  106.         push    dx ax
  107.         mov     dx,300h
  108.         in      al,dx
  109.         in      al,dx
  110.         in      al,dx
  111.         in      al,dx
  112.         in      al,dx
  113.         in      al,dx
  114.         in      al,dx
  115.         pop     ax dx
  116.         ret
  117. endp    UDelay
  118.  
  119. ; BX:CX Set to whatever.
  120. proc    U_Peek
  121.         push    dx
  122.         mov     dx,[cs:Base]
  123.         add     dx,103h                 ; 103h
  124.         mov     al,43h
  125.         out     dx,al
  126.         inc     dx                      ; 104h
  127.         mov     ax,cx
  128.         out     dx,ax
  129.         dec     dx                      ; 103h
  130.         mov     al,44h
  131.         out     dx,al
  132.         add     dx,2
  133.         mov     al,bl
  134.         out     dx,al
  135.         add     dx,2
  136.         in      al,dx
  137.         pop     dx
  138.         ret
  139. endp    U_Peek
  140.  
  141. ; BX:CX Set to whatever.
  142. ; AX Value to poke
  143. proc    U_Poke
  144.         push    dx ax
  145.         mov     dx,[cs:Base]
  146.         add     dx,103h
  147.         mov     al,43h
  148.         out     dx,al
  149.         inc     dx
  150.         mov     ax,cx
  151.         out     dx,ax
  152.         dec     dx
  153.         mov     al,44h
  154.         out     dx,al
  155.         add     dx,2
  156.         mov     al,bl
  157.         out     dx,al
  158.         add     dx,2
  159.         pop     ax
  160.         out     dx,al
  161.         pop     dx
  162.         ret
  163. endp    U_Poke
  164.  
  165.  
  166. ; DX - Base.
  167. proc    U_Probe
  168.         mov     dx,[cs:Base]
  169.         add     dx,0103h                ; 103h
  170.         mov     al,4Ch
  171.         out     dx,al
  172.         add     dx,2                    ; 105h
  173.         mov     al,0
  174.         out     dx,al
  175.         call    UDelay
  176.         call    UDelay
  177.         sub     dx,2                    ; 103h
  178.         mov     al,4Ch
  179.         out     dx,al
  180.         add     dx,2                    ; 105h
  181.         mov     al,1
  182.         out     dx,al
  183.         mov     ax,0AAh
  184.         mov     bx,0
  185.         mov     cx,0
  186.         call    U_Poke
  187.         mov     ax,055h
  188.         mov     bx,1
  189.         call    U_Poke
  190.         mov     bx,0
  191.         call    U_Peek
  192.         push    ax
  193.         mov     ax,0
  194.         call    U_Poke
  195.         sub     dx,2                    ; 103h
  196.         mov     al,4Ch
  197.         out     dx,al
  198.         add     dx,2                    ; 105h
  199.         mov     al,0
  200.         out     dx,al
  201.         pop     ax
  202.         cmp     al,0AAh
  203.         jnz     @@Nope
  204.         clc
  205.         ret
  206. @@Nope: stc
  207.         ret
  208. endp    U_Probe
  209.  
  210. proc    U_Reset
  211.         mov     dx,[cs:Base]
  212.         add     dx,103h                 ; 103h
  213.         mov     al,4Ch
  214.         out     dx,al
  215.         add     dx,2                    ; 105h
  216.         mov     al,1
  217.         out     dx,al
  218.         call    UDelay
  219.         sub     dx,2
  220.         mov     al,4Ch
  221.         out     dx,al
  222.         add     dx,2                    ; 105h
  223.         mov     al,7
  224.         out     dx,al
  225.         sub     dx,2
  226.         mov     al,0Eh
  227.         out     dx,al
  228.         add     dx,2
  229.         mov     al,0dfh
  230.         out     dx,al
  231.  
  232.     mov    cx,0
  233. @@VoiceClearLoop:
  234.     mov    dx,[cs:VoiceAddr]
  235.     mov    al,cl
  236.     out    dx,al
  237.     inc    dx
  238.     mov    al,0
  239.     out    dx,al
  240.     add    dx,2
  241.     mov    al,3            ; Turn voice off
  242.     out    dx,al
  243.     sub    dx,2
  244.     mov    al,0Dh
  245.     out    dx,al
  246.     add    dx,2
  247.     mov    al,3
  248.     out    dx,al
  249.     inc    cx
  250.     cmp    cx,32
  251.     jnz    @@VoiceClearLoop
  252.     ret
  253. endp    U_Reset
  254.  
  255.  
  256. proc    U_SizeDRAM
  257.         mov     bx,0
  258.         mov     cx,0
  259. @@DRAMLoop:
  260.         push    cx
  261.         mov     cx,0
  262.         mov     ax,0AAh
  263.         call    U_Poke
  264.         call    U_Peek
  265.         pop     cx
  266.         cmp     al,0AAh
  267.         jnz     @@Exit
  268.         add     bx,4
  269.         inc     cx
  270.         cmp     cx,5
  271.         jb      @@DRAMLoop
  272. @@Exit: shr     bx,2
  273.         mov     ax,bx
  274.         ret
  275. endp    U_SizeDRAM
  276.  
  277.  
  278. ; BX - Voice
  279. ; AX - Frequency
  280. proc    U_SetFreq               ; Close enough for me...
  281.         xor     dx,dx
  282.         mov     cx,19
  283.         div     cx
  284.         push    ax
  285.         mov     dx,[cs:Base]
  286.         add     dx,102h         ; 102h
  287.         mov     ax,bx
  288.         out     dx,al
  289.         inc     dx              ; 103h
  290.  
  291.         mov     al,1
  292.         out     dx,al
  293.         inc     dx              ; 104h
  294.         pop     ax
  295.         out     dx,ax
  296.         ret
  297. endp    U_SetFreq
  298.  
  299.  
  300. ; AX - Voice
  301. ; BX - Balance (0-f) 7 is middle
  302. proc    U_SetBalance
  303.         mov     dx,[cs:Base]
  304.         add     dx,102h
  305.         out     dx,al
  306.         inc     dx
  307.         mov     al,0ch
  308.         out     dx,al
  309.         add     dx,2
  310.         mov     ax,bx
  311.         out     dx,al
  312.         ret
  313. endp    U_SetBalance
  314.  
  315. ; AX - Voice
  316. ; BX - Volume
  317. proc    U_SetVolume
  318.         mov     dx,[cs:Base]
  319.         add     dx,102h
  320.         out     dx,al
  321.         inc     dx
  322.         mov     al,9
  323.         out     dx,al
  324.         inc     dx
  325.         mov     ax,bx
  326.         out     dx,ax
  327.         ret
  328. endp    U_SetVolume
  329.  
  330. ; AX - Voice
  331. ; BX - Mode
  332. ;          bit 0: 0=voice on (along with bit 1)
  333. ;          bit 1: 0=voice on (along with bit 0)
  334. ;          bit 2: 0=8 bit data, 1=16 bit data
  335. ;          bit 3: 0=No loop, 1=Loop
  336. ;          bit 4: 0=Go forward, 1=Go backward
  337. proc    U_SetLoopMode
  338.         mov     dx,[cs:Base]
  339.         add     dx,102h
  340.         out     dx,al
  341.         inc     dx
  342.         mov     al,80h
  343.         add     dx,2
  344.         in      al,dx
  345.         mov     bh,al
  346.         sub     dx,2
  347.         xor     al,al
  348.         out     dx,al
  349.         add     dx,2
  350.         and     bh,0e7h
  351.         or      bh,bl
  352.         mov     al,bh
  353.         out     dx,al
  354.         ret
  355. endp    U_SetLoopMode
  356.  
  357. ; AX - Voice
  358. proc    U_StopVoice
  359.         mov     dx,[cs:Base]
  360.         add     dx,102h
  361.         out     dx,al
  362.         inc     dx
  363.         mov     al,80h
  364.         add     dx,2
  365.         in      al,dx
  366.         mov     bh,al
  367.         sub     dx,2
  368.         xor     al,al
  369.         out     dx,al
  370.         add     dx,2
  371.         mov     al,bh
  372.         and     bh,0dfh
  373.         or      al,3
  374.         out     dx,al
  375.         call    UDelay
  376.         sub     dx,2
  377.         xor     al,al
  378.         out     dx,al
  379.         add     dx,2
  380.         mov     al,bh
  381.         and     bh,0dfh
  382.         or      al,3
  383.         out     dx,al
  384.         ret
  385. endp    U_StopVoice
  386.  
  387.  
  388.  
  389. SampleBegin     dd      0       ; (Start location in DRAM, apparently 32-byte aligned)
  390. SampleStart     dd      0       ; (Start location of loop)
  391. SampleEnd       dd      0       ; (End of sample)
  392.  
  393. ; AX - Voice
  394. ; BX - Mode
  395. proc    U_StartVoice
  396.         push    bx
  397.         mov     dx,[cs:Base]
  398.         add     dx,102h         ; 102h
  399.         out     dx,al
  400.  
  401.         ; Send sample begin
  402.         inc     dx              ; 103h
  403.         mov     al,0ah
  404.         out     dx,al
  405.         inc     dx              ; 104h
  406.         mov     ax,[Word cs:SampleBegin]
  407.         mov     cx,[Word cs:SampleBegin+2]
  408.         call    RShift
  409.         out     dx,ax
  410.         dec     dx              ; 103h
  411.         mov     al,0bh
  412.         out     dx,al
  413.         inc     dx              ; 104h
  414.         mov     ax,[Word cs:SampleBegin]
  415.         shl     ax,9
  416.         out     dx,ax
  417.         dec     dx              ; 103h
  418.  
  419.         ; Send sample start
  420.         mov     al,2
  421.         out     dx,al
  422.         inc     dx              ; 104h
  423.         mov     ax,[Word cs:SampleStart]
  424.         mov     cx,[Word cs:SampleStart+2]
  425.         call    RShift
  426.         out     dx,ax
  427.         dec     dx              ; 103h
  428.         mov     al,3
  429.         out     dx,al
  430.         inc     dx              ; 104h
  431.         mov     ax,[Word cs:SampleStart]
  432.         shl     ax,9
  433.         out     dx,ax
  434.         dec     dx              ; 103h
  435.  
  436.         ; Send sample start
  437.         mov     al,4
  438.         out     dx,al
  439.         inc     dx              ; 104h
  440.         mov     ax,[Word cs:SampleEnd]
  441.         mov     cx,[Word cs:SampleEnd+2]
  442.         call    RShift
  443.         out     dx,ax
  444.         dec     dx              ; 103h
  445.         mov     al,5
  446.         out     dx,al
  447.         inc     dx              ; 104h
  448.         mov     ax,[Word cs:SampleEnd]
  449.         shl     ax,9
  450.         out     dx,ax
  451.         dec     dx              ; 103h
  452.  
  453.         mov     al,0
  454.         out     dx,al
  455.         pop     ax
  456.         add     dx,2            ; 105h
  457.         out     dx,al
  458.         ret
  459. endp    U_StartVoice
  460.  
  461.  
  462. ; CX:AX  - Number
  463. proc    RShift
  464.         mov     bx,cx
  465.         shr     ax,7
  466.         shr     cx,7
  467.         shl     bx,9
  468.         or      ax,bx
  469.         ret
  470. endp    RShift
  471.  
  472. ; AX - Voice
  473. ; Returns:  DX:AX - Position
  474. proc    U_ReadPos
  475.         mov     dx,[cs:Base]
  476.         add     dx,102h         ; 102h
  477.         out     dx,al
  478.         inc     dx              ; 103h
  479.         mov     al,8ah
  480.         out     dx,al
  481.         inc     dx              ; 104h
  482.         in      ax,dx           ; TEMP0
  483.         mov     cx,ax
  484.         dec     dx              ; 103h
  485.         mov     al,8bh
  486.         out     dx,al
  487.         inc     dx              ; 104h
  488.         in      ax,dx           ; TEMP1
  489.         shl     cx,7
  490.         shr     ax,9
  491.         and     ax,7Fh
  492.         mov     dx,ax
  493.         and     dx,0Fh
  494.         mov     ax,cx
  495.         ret
  496. endp    U_ReadPos
  497.  
  498. ; AX-Mixer control
  499. ;  bit 0: 0=linein on, 1=linein off
  500. ;  bit 1: 0=output on, 1=output off
  501. ;  bit 2: 0=micin off, 1=micin on
  502. proc    U_ChangeInOut
  503.         mov     dx,[cs:Base]
  504.         out     dx,al
  505.         ret
  506. endp    U_ChangeInOut
  507.  
  508. ; The only reason I do it this way is because I haven't figured out the dump
  509. ; RAM to DRAM via DMA yet.
  510. ;
  511. ; Dump sample to Ram
  512. ;   ES:BX - Max 64k sample to dump to RAM.
  513. ;   SI:DI - DRAM location to dump to.
  514. ;   CX    - Max bytes to dump.
  515. ;
  516. ; Approximate time to dump 1 megabyte of samples to DRAM (assuming they were
  517. ; all loaded in memory) is 5 seconds.
  518. proc    U_DumpSampleToDRAM
  519.         push    cx
  520.         mov     dx,[cs:Base]
  521.         add     dx,103h
  522.         mov     al,44h          ; Dump upper byte, only do it on carry from now
  523.         out     dx,al           ; on.
  524.         add     dx,2
  525.         push    ax
  526.         mov     ax,si
  527.         out     dx,al
  528.         pop     ax
  529.         sub     dx,2
  530. @@MainLoop:
  531.         mov     al,43h
  532.         out     dx,al
  533.         inc     dx
  534.         push    ax
  535.         mov     ax,di
  536.         out     dx,ax
  537.         pop     ax
  538.         dec     dx
  539.         add     di,1
  540.         jnc     @@DumpByte
  541.         inc     si
  542.         mov     al,44h
  543.         out     dx,al
  544.         add     dx,2
  545.         push    ax
  546.         mov     ax,si
  547.         out     dx,al
  548.         pop     ax
  549.         sub     dx,2
  550. @@DumpByte:
  551.         add     dx,4
  552.         mov     al,[es:bx]
  553.         xor     al,ah
  554.         inc     bx
  555.         out     dx,al
  556.         sub     dx,4
  557.         loop    @@MainLoop
  558.     pop    cx
  559.         ret
  560. endp    U_DumpSampleToDRAM
  561.  
  562. proc    U_DumpDRAMToMemory
  563.         mov     dx,[cs:Base]
  564.         add     dx,103h
  565.         mov     al,44h          ; Dump upper byte, only do it on carry from now
  566.         out     dx,al           ; on.
  567.         add     dx,2
  568.         mov     ax,si
  569.         out     dx,al
  570.         sub     dx,2
  571. @@MainLoop:
  572.         mov     al,43h
  573.         out     dx,al
  574.         inc     dx
  575.         mov     ax,di
  576.         out     dx,ax
  577.         dec     dx
  578.         add     di,1
  579.         jnc     @@DumpByte
  580.         inc     si
  581.         mov     al,44h
  582.         out     dx,al
  583.         add     dx,2
  584.         mov     ax,si
  585.         out     dx,al
  586.         sub     dx,2
  587. @@DumpByte:
  588.         add     dx,4
  589.         in      al,dx
  590.         mov     [es:bx],al
  591.         inc     bx
  592.         sub     dx,4
  593.         loop    @@MainLoop
  594.         ret
  595. endp    U_DumpDRAMToMemory
  596.  
  597. VoiceAddr    dw    0
  598. ComAddr     dw    0
  599. DataLo        dw    0
  600. DataHi        dw    0
  601.  
  602. ; Carry set - No GUS
  603. ; No carry  - GUS at Base
  604. proc    U_DetectGUS
  605.         mov     [Word cs:Base],210h
  606. @@TestIt:
  607.         call    U_Probe
  608.         jnb     @@FoundIt
  609.         add     [Word cs:Base],10h
  610.         cmp     [Word cs:Base],270h
  611.         jb      @@TestIt
  612.         stc
  613. @@FoundIt:
  614.     mov    dx,[cs:Base]
  615.     add    dx,102h
  616.     mov    [cs:VoiceAddr],dx
  617.     inc    dx
  618.     mov    [cs:ComAddr],dx
  619.     inc    dx
  620.     mov    [cs:DataLo],dx
  621.     inc    dx
  622.     mov    [cs:DataHi],dx
  623.     ret
  624. endp    U_DetectGUS
  625.  
  626. ;▓────────────────────────────────────────────────────────────────────────────▓
  627. ; s_PlayMusic - Make proper calls and interrupt sets for module playing.
  628. ;▓────────────────────────────────────────────────────────────────────────────▓
  629.  
  630. proc        sd_SetMaxVolume
  631.         push    ds
  632.         mov    ax,cs
  633.         mov    ds,ax
  634.         mov    al,200
  635.         mov    [Byte Channel1+(offset (MS).MasterVolume)],al
  636.         mov    [Byte Channel2+(offset (MS).MasterVolume)],al
  637.         mov    [Byte Channel3+(offset (MS).MasterVolume)],al
  638.         mov    [Byte Channel4+(offset (MS).MasterVolume)],al
  639.         pop    ds
  640.         ret
  641. endp        sd_SetMaxVolume
  642.  
  643. proc            s_PlayMusic     far
  644.         pusha
  645.         push    ds
  646.                 mov     [word cs:mt_Speed],6
  647.                 mov     [word cs:mt_Counter],1
  648.         mov    [word cs:mt_SongPos],0
  649.         mov    [Word cs:mt_PatternPos],0
  650.         call    sd_SetMaxVolume
  651. ; Set it up.
  652.         mov    ax,0
  653.         mov    ds,ax
  654.         mov    bx,8*4
  655.         mov    ax,[ds:bx]
  656.         mov    [Word cs:IntStore],ax
  657.         mov    ax,[ds:bx+2]
  658.         mov    [Word cs:IntStore+2],ax
  659.         cli
  660.         mov    [Word ds:bx],offset PlayInt
  661.         mov    [ds:bx+2],cs
  662.         mov    ax,cs
  663.         mov    ds,ax
  664.         mov    al,36h
  665.         out    43h,al
  666.         mov    ax,1193180/50
  667.         out    40h,al
  668.         mov    al,ah
  669.         out    40h,al
  670.         sti
  671. @@End:
  672.         pop    ds
  673.         popa
  674.         ret
  675. endp        s_PlayMusic
  676.   
  677.   
  678. ;▓────────────────────────────────────────────────────────────────────────────▓
  679. ; s_StopMusic - Shuts down the interrupts for generating music.
  680. ;▓────────────────────────────────────────────────────────────────────────────▓
  681.   
  682. proc        s_StopMusic    far
  683.         pusha
  684.         push    ds
  685.         cli
  686.         mov    ax,0
  687.         mov    ds,ax
  688.         mov    bx,8*4
  689.         mov    ax,[Word cs:IntStore]
  690.         mov    [ds:bx],ax
  691.         mov    ax,[Word cs:IntStore+2]
  692.         mov    [ds:bx+2],ax
  693.         mov    al,36h
  694.         out    43h,al
  695.         xor    al,al
  696.         out    40h,al
  697.         out    40h,al
  698.         sti
  699.         pop    ds
  700.         popa
  701.         ret
  702. endp        s_StopMusic
  703.   
  704. ; CX - Sample Size
  705. ; SI:DI - Place in DRAM
  706. ; BX - Handle
  707. LDSeg   dw      ?
  708. proc    LoadDumpSample
  709.         push    cx bx
  710.         mov     ah,48h
  711.         mov     bx,cx
  712.         shr     bx,4
  713.         inc     bx
  714.         int     21h
  715.         mov     [cs:LDSeg],ax
  716.         pop     bx
  717.         push    ds
  718.         mov     ah,3Fh
  719.         mov     dx,0
  720.         mov     ds,[cs:LDSeg]
  721.         int     21h
  722.         pop     ds
  723.  
  724.         pop     cx
  725.         mov     es,[cs:LDSeg]
  726.         mov     bx,0
  727.         mov     ah,0
  728.         call    U_DumpSampleToDRAM
  729.     mov    ax,di
  730.         and     al,11110000b
  731.         add     ax,32
  732.         adc     si,0
  733.         mov     di,ax
  734.         mov     ah,49h
  735.         mov     es,[cs:LDSeg]
  736.         int     21h
  737.         ret
  738. endp    LoadDumpSample
  739.  
  740. ;▓────────────────────────────────────────────────────────────────────────────▓
  741. ; s_LoadModule - Load in the module pointed to by DS:DX.
  742. ;▓────────────────────────────────────────────────────────────────────────────▓
  743. Handle        dw    0
  744. proc        s_LoadModule
  745.         pusha
  746.         push    ds es
  747.         mov    ax,3D00h
  748.         int    21h
  749.         mov    [cs:Handle],ax
  750.         mov    ax,cs
  751.                 mov     ds,ax
  752.                 mov     es,ax
  753.                 call    s_ReadMod
  754.         mov    ax,3E00h
  755.         mov    bx,[cs:Handle]
  756.         int    21h
  757.         pop    es ds
  758.         popa
  759.         ret
  760. endp        s_LoadModule
  761.  
  762. ;▓────────────────────────────────────────────────────────────────────────────▓
  763. ; s_ReadMod - Read the header, all patterns, and all samples from module.
  764. ;▓────────────────────────────────────────────────────────────────────────────▓
  765. LocInList    dw    ?
  766. proc        s_ReadMod
  767.         push    ds
  768.         mov    ax,3F00h        ; Read the header
  769.         mov    bx,[cs:Handle]
  770.         mov    dx,offset Header
  771.         mov    cx,HeaderSize
  772.         int    21h
  773.  
  774.         call    s_LoadPatterns
  775.  
  776.         mov    cx,31
  777.         mov    bx,offset samples+(offset (SampleRec).Length)
  778. @@FlipLoop:
  779.         mov    ax,[cs:bx]    ; Flip length
  780.         xchg    ah,al
  781.         shl    ax,1
  782.         mov    [cs:bx],ax
  783.         mov    ax,[cs:bx+4]    ; Flip repeat
  784.         xchg    ah,al
  785.         shl    ax,1
  786.         mov    [cs:bx+4],ax
  787.         mov    ax,[cs:bx+6]    ; Flip repeat length
  788.         xchg    ah,al
  789.         shl    ax,1
  790.         mov    [cs:bx+6],ax
  791.         add    bx,size SampleRec
  792.         loop    @@FlipLoop
  793.  
  794.         mov    cx,31
  795.         mov    bx,offset samples+(offset (SampleRec).Length)
  796.         mov    [Word cs:LocInList],0
  797.         mov    si,0        ; Location in DRAM to begin
  798.         mov    di,0
  799. @@DoSamples:    push    cx
  800.         mov    ax,[cs:bx]
  801.         or    ax,ax
  802.         jz    @@ZeroByteSample
  803.         mov    cx,ax        ; Save for read from disk.
  804.         push    bx
  805.         mov    bx,[cs:LocInList]
  806.         mov    [Word cs:bx+InsLoc],di
  807.         mov    [Word cs:bx+InsLoc+2],si
  808.         add    [Word cs:LocInList],4
  809.         mov    bx,[cs:Handle]
  810.         call    LoadDumpSample
  811.         pop    bx
  812.         jmp    @@Bottom
  813. @@ZeroByteSample:
  814.         push    bx
  815.         mov    bx,[cs:LocInList]
  816.         mov    [Word cs:bx+InsLoc],0
  817.         mov    [Word cs:bx+InsLoc+2],0f000h
  818.         add    [Word cs:LocInList],4
  819.         pop    bx
  820. @@Bottom:    add    bx,size SampleRec
  821.         pop    cx
  822.         loop    @@DoSamples
  823.         pop    ds
  824.         ret
  825. endp        s_ReadMod
  826.  
  827. proc        s_GetHighestBlock
  828.                 mov     si,offset sequences
  829.                 mov     cx,128
  830.                 xor     ax,ax
  831. @@SetBlock:    mov    ah,al
  832.                 jmp     @@BotLoop
  833. @@SearchLoop:    lodsb
  834.                 cmp     al,ah
  835.         jg    @@SetBlock
  836. @@BotLoop:    loop    @@SearchLoop
  837.                 mov     al,ah
  838.         inc    al
  839.                 xor     ah,ah                   ; Clear ah.
  840.                 ret
  841. endp            s_GetHighestBlock
  842.  
  843. proc            s_LoadPatterns
  844.         mov    cx,64
  845.         mov    di,offset PatternLoc
  846.         xor    ax,ax
  847.         rep    stosw
  848.  
  849.         call    s_GetHighestBlock
  850.         mov    [cs:NumPatterns],ax
  851.         mov    di,offset PatternLoc
  852.         mov    cx,ax
  853. @@BlockAllocLoop:
  854.         mov    bx,1024/4+1
  855.         mov    ah,48h
  856.         int    21h
  857.         stosw
  858.         loop    @@BlockAllocLoop
  859.  
  860.         mov    si,offset PatternLoc
  861.         xor    dx,dx            ; Load all segments at 0 offset.
  862.         xor    cx,cx
  863. @@BlockReadLoop:
  864.         push    cx
  865.         push    ds
  866.         mov    cx,1024
  867.         mov    bx,[cs:Handle]
  868.         lodsw
  869.         mov    ds,ax
  870.         mov    ax,3F00h        ; Load in the block.
  871.         int    21h
  872.         pop    ds cx
  873.         inc    cx
  874.         cmp    cx,[cs:NumPatterns]
  875.         jnz    @@BlockReadLoop
  876.         clc
  877.         ret
  878. endp        s_LoadPatterns
  879.  
  880. proc        s_CloseAllMusic
  881.         push    ds
  882.         mov    ax,cs
  883.         mov    ds,ax
  884. @@FreePatterns: mov     si,offset PatternLoc
  885.         mov    cx,64
  886. @@FreePatLoop:    lodsw
  887.         or    ax,ax
  888.         jz    @@BotFreePatLoop
  889.         mov    es,ax
  890.         mov    ax,4900h
  891.         int    21h
  892.         jnb    @@BotFreePatLoop
  893.         stc
  894.         pop    ds
  895.         ret
  896. @@BotFreePatLoop:
  897.         loop    @@FreePatLoop
  898.         pop    ds
  899.         ret
  900. endp        s_CloseAllMusic
  901.  
  902. proc    MyT
  903.         call    sd_UpdateChannels
  904.         ret
  905. endp    MyT
  906.  
  907. proc            PlayInt
  908.         pusha
  909.         push    ds es
  910.         call    sd_UpdateChannels
  911.         sti
  912.                 mov     al,20h
  913.                 out     20h,al
  914.                 pop     es ds
  915.         popa
  916.         iret
  917. endp            PlayInt
  918.  
  919. ;┌──────────────────────────────────────────────────────────────────────────┐
  920. ;│││──────────────────────── Protracker Stuff ────────────────────────────│││
  921. ;└──────────────────────────────────────────────────────────────────────────┘
  922. ;┌─┐ Protracker specific
  923. ;└─┘ variables.
  924. mt_speed        db    6
  925. mt_counter        db    0
  926. mt_PatternPos        dw    0
  927. mt_SongPos        db    0
  928. mt_PattDelayTime2    db    0
  929. mt_PattDelayTime    db    0
  930. mt_PBreakFlag        db    0
  931. mt_PBreakPos        db    0
  932. mt_PosJumpFlag        db    0
  933. mt_LowMask        db    0FFh
  934.  
  935. mt_FunkTable        db    0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
  936.  
  937. mt_VibratoTable:    db      0, 24, 49, 74, 97,120,141,161
  938.             db    180,197,212,224,235,244,250,253
  939.             db    255,253,250,244,235,224,212,197
  940.             db    180,161,141,120, 97, 74, 49, 24
  941.  
  942. Channel1  MS      <0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
  943. Channel2  MS      <0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
  944. Channel3  MS      <0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
  945. Channel4  MS      <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
  946. PlayStatus    db    0
  947. MStatus     db    0
  948. MainFreq    dd    0
  949. Mode        db    0
  950. SOffsetSet    db    0
  951.  
  952. mt_VolTable    dw    00000h,0A000h,0A800h,0B000h,0B800h,0C000h,0C400h,0C800h,0CC00h
  953.         dw    0D000h,0D200h,0D400h,0D600h,0D800h,0DA00h,0DC00h,0DE00h
  954.         dw    0E000h,0E100h,0E200h,0E300h,0E400h,0E500h,0E600h,0E700h
  955.         dw    0E800h,0E900h,0EA00h,0EB00h,0EC00h,0ED00h,0EE00h,0EF00h
  956.         dw    0F080h,0F100h,0F180h,0F200h,0F280h,0F300h,0F380h,0F400h
  957.         dw    0F480h,0F500h,0F580h,0F600h,0F680h,0F700h,0F780h,0F800h
  958.         dw    0F880h,0F900h,0F980h,0FA00h,0FA80h,0FB00h,0FB80h,0FC00h
  959.         dw    0FC80h,0FD00h,0FD80h,0FE00h,0FE80h,0FF00h,0FF80h,0FFFFh
  960.  
  961. mt_PeriodTable:
  962. ; Tuning 0, Normal
  963.     dw    856,808,762,720,678,640,604,570,538,508,480,453
  964.     dw    428,404,381,360,339,320,302,285,269,254,240,226
  965.     dw    214,202,190,180,170,160,151,143,135,127,120,113,0
  966. ; Tuning 1
  967.     dw    850,802,757,715,674,637,601,567,535,505,477,450
  968.     dw    425,401,379,357,337,318,300,284,268,253,239,225
  969.     dw    213,201,189,179,169,159,150,142,134,126,119,113,0
  970. ; Tuning 2
  971.     dw    844,796,752,709,670,632,597,563,532,502,474,447
  972.     dw    422,398,376,355,335,316,298,282,266,251,237,224
  973.     dw    211,199,188,177,167,158,149,141,133,125,118,112,0
  974. ; Tuning 3
  975.     dw    838,791,746,704,665,628,592,559,528,498,470,444
  976.     dw    419,395,373,352,332,314,296,280,264,249,235,222
  977.     dw    209,198,187,176,166,157,148,140,132,125,118,111,0
  978. ; Tuning 4
  979.     dw    832,785,741,699,660,623,588,555,524,495,467,441
  980.     dw    416,392,370,350,330,312,294,278,262,247,233,220
  981.     dw    208,196,185,175,165,156,147,139,131,124,117,110,0
  982. ; Tuning 5
  983.     dw    826,779,736,694,655,619,584,551,520,491,463,437
  984.     dw    413,390,368,347,328,309,292,276,260,245,232,219
  985.     dw    206,195,184,174,164,155,146,138,130,123,116,109,0
  986. ; Tuning 6
  987.     dw    820,774,730,689,651,614,580,547,516,487,460,434
  988.     dw    410,387,365,345,325,307,290,274,258,244,230,217
  989.     dw    205,193,183,172,163,154,145,137,129,122,115,109,0
  990. ; Tuning 7
  991.     dw    814,768,725,684,646,610,575,543,513,484,457,431
  992.     dw    407,384,363,342,323,305,288,272,256,242,228,216
  993.     dw    204,192,181,171,161,152,144,136,128,121,114,108,0
  994. ; Tuning -8
  995.     dw    907,856,808,762,720,678,640,604,570,538,508,480
  996.     dw    453,428,404,381,360,339,320,302,285,269,254,240
  997.     dw    226,214,202,190,180,170,160,151,143,135,127,120,0
  998. ; Tuning -7
  999.     dw    900,850,802,757,715,675,636,601,567,535,505,477
  1000.     dw    450,425,401,379,357,337,318,300,284,268,253,238
  1001.     dw    225,212,200,189,179,169,159,150,142,134,126,119,0
  1002. ; Tuning -6
  1003.     dw    894,844,796,752,709,670,632,597,563,532,502,474
  1004.     dw    447,422,398,376,355,335,316,298,282,266,251,237
  1005.     dw    223,211,199,188,177,167,158,149,141,133,125,118,0
  1006. ; Tuning -5
  1007.     dw    887,838,791,746,704,665,628,592,559,528,498,470
  1008.     dw    444,419,395,373,352,332,314,296,280,264,249,235
  1009.     dw    222,209,198,187,176,166,157,148,140,132,125,118,0
  1010. ; Tuning -4
  1011.     dw    881,832,785,741,699,660,623,588,555,524,494,467
  1012.     dw    441,416,392,370,350,330,312,294,278,262,247,233
  1013.     dw    220,208,196,185,175,165,156,147,139,131,123,117,0
  1014. ; Tuning -3
  1015.     dw    875,826,779,736,694,655,619,584,551,520,491,463
  1016.     dw    437,413,390,368,347,328,309,292,276,260,245,232
  1017.     dw    219,206,195,184,174,164,155,146,138,130,123,116,0
  1018. ; Tuning -2
  1019.     dw    868,820,774,730,689,651,614,580,547,516,487,460
  1020.     dw    434,410,387,365,345,325,307,290,274,258,244,230
  1021.     dw    217,205,193,183,172,163,154,145,137,129,122,115,0
  1022. ; Tuning -1
  1023.     dw    862,814,768,725,684,646,610,575,543,513,484,457
  1024.     dw    431,407,384,363,342,323,305,288,272,256,242,228
  1025.     dw    216,203,192,181,171,161,152,144,136,128,121,114,0
  1026.  
  1027.  
  1028. Voice    db    0
  1029.  
  1030. Hex    db    '0123456789ABCDEF'
  1031.  
  1032. ; AX - Hex value
  1033. proc    MakeHex
  1034.     push    ax bx cx dx
  1035.     mov    cl,al
  1036.     shr    al,4
  1037.     mov    bl,al
  1038.     xor    bh,bh
  1039.     mov    al,[cs:bx+Hex]
  1040.     mov    dl,al
  1041.     mov    ah,02h
  1042.     int    21h
  1043.     mov    al,cl
  1044.     and    al,0Fh
  1045.     mov    bl,al
  1046.     xor    bh,bh
  1047.     mov    al,[cs:bx+Hex]
  1048.     mov    dl,al
  1049.     mov    ah,02h
  1050.         int     21h
  1051.     mov    dl,' '
  1052.     mov    ah,2
  1053.     int    21h
  1054.     pop    dx cx bx ax
  1055.     ret
  1056. endp    MakeHex
  1057.  
  1058. ;╒═══════════════════════════════════════════════════════════════════════════╕
  1059. ;│ NAME       : sd_UpdateChannels                                            │
  1060. ;│              *** Original code: Amiga Protracker by Lars "Zap" Hamre.     │
  1061. ;│              *** Converted by Joshua C. Jensen.                           │
  1062. ;╘═══════════════════════════════════════════════════════════════════════════╛
  1063. proc    sd_UpdateChannels near
  1064.     mov    ax,cs
  1065.     mov    ds,ax
  1066.     mov    es,ax
  1067.  
  1068. mt_ContinueUpdate:
  1069.     inc    [Byte cs:mt_counter]
  1070.     mov    al,[cs:mt_counter]
  1071.     cmp    al,[cs:mt_speed]
  1072.     jb    mt_NoNewNote
  1073.     mov    [Byte cs:mt_counter],0
  1074.     cmp    [Byte cs:mt_PattDelayTime2],0
  1075.     jz    mt_GetNewNote
  1076.     call    mt_NoNewAllChannels
  1077.     jmp    mt_dskip
  1078.  
  1079. mt_NoNewNote:
  1080.     call    mt_NoNewAllChannels
  1081.     jmp    mt_NoNewPosYet
  1082.  
  1083. mt_NoNewAllChannels:
  1084.     mov    [Byte cs:Voice],1
  1085.     mov    dx,[cs:VoiceAddr]
  1086.     mov    al,1
  1087.     out    dx,al
  1088.         mov     si,offset Channel1
  1089.     call    mt_CheckEfx
  1090.     mov    [Byte cs:Voice],2
  1091.     mov    dx,[cs:VoiceAddr]
  1092.     mov    al,2
  1093.         out     dx,al
  1094.         mov     si,offset Channel2
  1095.         call    mt_CheckEfx
  1096.     mov    [Byte cs:Voice],3
  1097.     mov    dx,[cs:VoiceAddr]
  1098.     mov    al,3
  1099.         out     dx,al
  1100.         mov     si,offset Channel3
  1101.     call    mt_CheckEfx
  1102.     mov    [Byte cs:Voice],4
  1103.     mov    dx,[cs:VoiceAddr]
  1104.     mov    al,4
  1105.         out     dx,al
  1106.         mov     si,offset Channel4
  1107.     jmp    mt_CheckEfx
  1108.  
  1109. mt_GetNewNote:
  1110.     xor    ax,ax
  1111.     mov    al,[cs:mt_SongPos]
  1112.     mov    di,ax
  1113.     mov    al,[cs:di+sequences]
  1114.     shl    al,1
  1115.     mov    di,offset PatternLoc
  1116.     add    di,ax
  1117.     mov    es,[cs:di]
  1118.     mov    di,[cs:mt_PatternPos]
  1119.  
  1120.  
  1121.     mov    [Byte cs:Voice],1
  1122.     mov    dx,[cs:VoiceAddr]
  1123.     mov    al,1
  1124.         out     dx,al
  1125.         mov     si,offset Channel1
  1126.     call    mt_PlayVoice
  1127.     mov    [Byte cs:Voice],2
  1128.     mov    dx,[cs:VoiceAddr]
  1129.     mov    al,2
  1130.         out     dx,al
  1131.         mov     si,offset Channel2
  1132.     call    mt_PlayVoice
  1133.     mov    [Byte cs:Voice],3
  1134.     mov    dx,[cs:VoiceAddr]
  1135.     mov    al,3
  1136.         out     dx,al
  1137.         mov     si,offset Channel3
  1138.     call    mt_PlayVoice
  1139.     mov    [Byte cs:Voice],4
  1140.     mov    dx,[cs:VoiceAddr]
  1141.     mov    al,4
  1142.         out     dx,al
  1143.         mov     si,offset Channel4
  1144.         call    mt_PlayVoice
  1145.  
  1146.     jmp    mt_dskip
  1147.  
  1148. mt_PlayVoice:
  1149.     mov    [Byte cs:Mode],0
  1150.         cmp     [Word cs:si],0
  1151.     jnz    mt_plvskip
  1152.     cmp    [Word cs:si+2],0
  1153.     jnz    mt_plvskip
  1154.     call    mt_PerNop
  1155. mt_plvskip:
  1156.     mov    ax,[es:di]
  1157.     mov    [cs:si+MS.Note],ax
  1158.     mov    ax,[es:di+02h]
  1159.     mov    [Word cs:si+MS.cmd],ax
  1160.     add    di,4
  1161.  
  1162.     mov    al,[cs:si+MS.cmd]
  1163.     and    al,0F0h
  1164.     shr    al,4
  1165.     mov    ah,[Byte cs:si+MS.Note]
  1166.     and    ah,0F0h
  1167.     or    al,ah            ; Is there an ins?
  1168.     jz    mt_SetRegisters
  1169.     dec    al
  1170.         mov     bl,al
  1171. ;     mov     [cs:bp+CD.sins],al
  1172.     cmp    [Byte cs:Voice],1
  1173.     jnz    @@2
  1174.     call    MakeHex
  1175. @@2:
  1176.     mov    [cs:si+MS.SampleNum],al
  1177.     mov    bh,size SampleRec
  1178.     mul    bh
  1179.     mov    dx,ax
  1180.  
  1181.     cmp    [Byte cs:Voice],1
  1182.     jnz    @@3
  1183.     mov    dx,dx
  1184. @@3:
  1185.     xor    bh,bh
  1186.     shl    bx,2
  1187.     add    bx,offset InsLoc
  1188.     mov    ax,[cs:bx]
  1189.     mov    [Word cs:si+MS.start],ax
  1190.     mov    ax,[cs:bx+2]
  1191.     mov    [Word cs:si+(offset (MS).start)+2],ax
  1192.         mov     bx,dx
  1193.     add    bx,(offset (SampleRec).Length)
  1194.     add    bx,offset samples
  1195.     mov    cx,[Word cs:bx]
  1196.     sub    cx,2
  1197.     mov    ax,[Word cs:si+MS.start]
  1198.     mov    dx,[Word cs:si+(offset (MS).start)+2]
  1199.     add    ax,cx
  1200.         adc     dx,0
  1201.         mov     [Word cs:si+MS.Length],ax
  1202.     mov    [Word cs:si+(offset (MS).Length)+2],dx
  1203.     mov    [Word cs:si+MS.RealLength],cx
  1204.     mov    ax,[Word cs:bx+2]
  1205.     mov    [Word cs:si+MS.FineTune],ax
  1206.     mov    al,ah
  1207.     call    volequ
  1208.  
  1209.     mov    cx,[Word cs:bx+6]; Get the Repeat length.
  1210.     cmp    cx,2
  1211.     jbe    mt_NoLoop
  1212.     mov    cx,[Word cs:bx+4]
  1213.     or    [Byte cs:Mode],00001000b
  1214.     mov    ax,[Word cs:si+MS.start]
  1215.     mov    dx,[Word cs:si+(offset (MS).start)+2]
  1216.     add    ax,cx
  1217.     adc    dx,0
  1218.     mov    [Word cs:si+MS.loopstart],ax
  1219.     mov    [Word cs:si+(offset (MS).loopstart)+2],dx
  1220.     mov    [Word cs:si+MS.wavestart],ax
  1221.     mov    [Word cs:si+(offset (MS).wavestart)+2],dx
  1222.     mov    ax,[Word cs:bx]
  1223.     mov    [Word cs:si+MS.RepLen],ax
  1224.     jmp    mt_SetRegisters
  1225. mt_NoLoop:
  1226.     mov    ax,[Word cs:si+MS.start]
  1227.     mov    dx,[Word cs:si+(offset (MS).start)+2]
  1228.     add    ax,cx
  1229.     adc    dx,0
  1230.     mov    [Word cs:si+MS.loopstart],ax
  1231.     mov    [Word cs:si+(offset (MS).loopstart)+2],dx
  1232.     mov    [Word cs:si+MS.wavestart],ax
  1233.     mov    [Word cs:si+(offset (MS).wavestart)+2],dx
  1234.     mov    ax,[Word cs:bx]
  1235.         mov     [Word cs:si+MS.RepLen],ax
  1236. mt_SetRegisters:
  1237.     mov    ax,[cs:si+MS.Note]
  1238.     xchg    ah,al
  1239.     and    ax,0FFFh
  1240.     jz    mt_CheckMoreEfx
  1241.     mov    ax,[Word cs:si+MS.cmd]
  1242.     xchg    ah,al
  1243.     and    ax,0FF0h
  1244.     cmp    ax,0E50h
  1245.     jz    mt_DoSetFineTune
  1246.     cmp    ah,3            ; Is it a tone portamento?
  1247.     jz    mt_ChkTonePorta
  1248.     cmp    ah,5            ; Is it a tone and volume slide?
  1249.     jz    mt_ChkTonePorta
  1250. ;     cmp     ah,9             ; Is it a sample offset command?
  1251. ;     jnz     mt_SetPeriod
  1252.     jmp    mt_SetPeriod
  1253.     call    mt_CheckMoreEfx
  1254.     jmp    mt_SetPeriod
  1255.  
  1256. mt_DoSetFineTune:
  1257.     call    mt_SetFineTune
  1258.     jmp    mt_SetPeriod
  1259.  
  1260. mt_ChkTonePorta:
  1261.     call    mt_SetTonePorta
  1262.     jmp    mt_CheckMoreEfx
  1263.  
  1264. mt_SetPeriod:
  1265.     mov    ax,[cs:si+MS.Note]
  1266.     xchg    ah,al
  1267.     and    ax,0FFFh
  1268.     mov    bx,offset mt_PeriodTable
  1269.     mov    cx,36
  1270. mt_ftuloop:
  1271.     cmp    ax,[cs:bx]
  1272.     jnb    mt_ftufound
  1273.     add    bx,2
  1274.     loop    mt_ftuloop
  1275. mt_ftufound:
  1276.     mov    al,[cs:si+MS.FineTune]
  1277.     mov    cl,37*2
  1278.     mul    cl
  1279.     add    bx,ax
  1280.     mov    ax,[cs:bx]
  1281.     mov    [cs:si+MS.Period],ax
  1282.  
  1283.     mov    ax,[Word cs:si+MS.cmd]
  1284.     xchg    ah,al
  1285.     and    ax,0FF0h
  1286.     cmp    ax,0ED0h
  1287.     jz    mt_CheckMoreEfx
  1288.  
  1289.     mov    al,[cs:si+MS.WaveControl]  ; Get the WaveControl.
  1290.     and    al,00000100b        ; Amiga: BTST #2,WaveControl.
  1291.     jz    mt_vibnoc        ; If it is zero, then skip.
  1292.     mov    [Byte cs:si+MS.VibratoPos],0
  1293. mt_vibnoc:
  1294.     mov    al,[cs:si+MS.WaveControl]  ; Get it again.
  1295.     and    al,01000000b        ; Amiga: BTST #6,WaveControl
  1296.     jz    mt_trenoc        ; If it is zero, then skip.
  1297.     mov    [Byte cs:si+MS.TremoloPos],0 ; Zero the Tremolo offset.
  1298. mt_trenoc:
  1299.     cmp    [Word cs:si+(offset (MS).start)+2],0f000h
  1300.         jz      @@NoVoice
  1301.     cmp    [Byte cs:SOffsetSet],1
  1302.     jz    @@SkipBegin
  1303.         ; Send sample begin
  1304.     mov    dx,[cs:ComAddr]
  1305.         mov     al,0ah
  1306.         out     dx,al
  1307.         inc     dx              ; 104h
  1308.         mov     ax,[Word cs:si+MS.start]
  1309.         mov     cx,[Word cs:si+(offset (MS).start)+2]
  1310.         call    RShift
  1311.         out     dx,ax
  1312.         dec     dx              ; 103h
  1313.         mov     al,0bh
  1314.         out     dx,al
  1315.         inc     dx              ; 104h
  1316.         mov     ax,[Word cs:si+MS.start]
  1317.         shl     ax,9
  1318.         out     dx,ax
  1319.  
  1320. @@SkipBegin:
  1321.     mov    [Byte cs:SOffsetSet],0
  1322.     mov    dx,[cs:ComAddr]
  1323.         mov     al,2
  1324.     out    dx,al
  1325.     inc    dx        ; 104h
  1326.     mov    ax,[Word cs:si+MS.loopstart]
  1327.     mov    cx,[Word cs:si+(offset (MS).loopstart)+2]
  1328.     call    RShift
  1329.     out    dx,ax
  1330.     dec    dx        ; 103h
  1331.     mov    al,3
  1332.     out    dx,al
  1333.     inc    dx        ; 104h
  1334.     mov    ax,[Word cs:si+MS.loopstart]
  1335.     shl    ax,9
  1336.     out    dx,ax
  1337.  
  1338.     mov    dx,[cs:ComAddr]
  1339.         mov     al,4
  1340.     out    dx,al
  1341.     inc    dx        ; 104h
  1342.     mov    ax,[Word cs:si+MS.length]
  1343.     mov    cx,[Word cs:si+(offset (MS).length)+2]
  1344.     call    RShift
  1345.     out    dx,ax
  1346.     dec    dx        ; 103h
  1347.     mov    al,5
  1348.     out    dx,al
  1349.     inc    dx        ; 104h
  1350.     mov    ax,[Word cs:si+MS.length]
  1351.     shl    ax,9
  1352.     out    dx,ax
  1353.     dec    dx        ; 103h
  1354.  
  1355.     mov    cx,[cs:si+MS.Period]
  1356.     call    mt_PerNop
  1357.     mov    dx,[cs:ComAddr]
  1358.     mov    al,0ch
  1359.     out    dx,al
  1360.     add    dx,2
  1361.     mov    al,0
  1362.     cmp    [cs:Voice],2
  1363.     jnz    @@C2
  1364.     mov    al,15
  1365. @@C2:
  1366.     cmp    [cs:Voice],3
  1367.     jnz    @@C3
  1368.     mov    al,15
  1369. @@C3:
  1370.     out    dx,al
  1371.     sub    dx,2
  1372.     mov    al,0
  1373.         out     dx,al
  1374.         add     dx,2
  1375.     mov    al,[Byte cs:Mode]
  1376.         out     dx,al
  1377.     jmp    @@Bottom
  1378.  
  1379. @@NoVoice:
  1380.     mov    [Byte cs:SOffsetSet],0
  1381.         mov     al,0
  1382.         out     dx,al
  1383.         add     dx,2
  1384.     mov    al,[Byte cs:Mode]
  1385.     or    al,00000011b
  1386.         out     dx,al
  1387. @@Bottom:
  1388. ;        call    SpectrumAnalyzer
  1389.     mov    [cs:si+MS.Trigger],1
  1390.     jmp    mt_CheckMoreEfx
  1391. endp    sd_UpdateChannels
  1392.  
  1393. proc    mt_dskip near
  1394.         add     [Word cs:mt_PatternPos],16
  1395.     mov    al,[cs:mt_PattDelayTime]
  1396.     or    al,al
  1397.     jz    mt_dskc
  1398.     mov    [cs:mt_PattDelayTime2],al
  1399.     mov    [Byte cs:mt_PattDelayTime],0
  1400. mt_dskc:
  1401.     cmp    [Byte cs:mt_PattDelayTime2],0
  1402.     jz    mt_dska
  1403.     dec    [Byte cs:mt_PattDelayTime2]
  1404.     jz    mt_dska
  1405.     sub    [Word cs:mt_PatternPos],16
  1406. mt_dska:
  1407.     cmp    [Byte cs:mt_PBreakFlag],0
  1408.     jz    mt_nnpysk
  1409.     mov    [Byte cs:mt_PBreakFlag],0
  1410.     xor    ax,ax
  1411.     mov    al,[cs:mt_PBreakPos]
  1412.     mov    [cs:mt_PBreakPos],ah
  1413.     shl    ax,4
  1414.     mov    [cs:mt_PatternPos],ax
  1415. mt_nnpysk:
  1416.     cmp    [Word cs:mt_PatternPos],1024
  1417.     jb    mt_NoNewPosYet
  1418.  
  1419. mt_NextPosition:
  1420.     xor    ax,ax
  1421.     mov    al,[cs:mt_PBreakPos]
  1422.     shl    ax,4
  1423.     mov    [cs:mt_PatternPos],ax
  1424.     mov    [Byte cs:mt_PBreakPos],0
  1425.     mov    [Byte cs:mt_PosJumpFlag],0
  1426.     inc    [Byte cs:mt_SongPos]
  1427.     and    [Byte cs:mt_SongPos],7Fh
  1428.     mov    al,[cs:mt_SongPos]
  1429.     cmp    al,[cs:songlen]
  1430.     jnz    mt_NoNewPosYet
  1431.     mov    [Byte cs:mt_SongPos],0
  1432.     cmp    [Byte cs:PlayStatus],1
  1433.     jnz    @@Quit
  1434.     mov    [Byte cs:mt_SongPos],0
  1435.     ret
  1436. ;---------------------------------------------------
  1437. @@Quit: mov    [Byte cs:MStatus],1
  1438.     mov    [Byte cs:mt_SongPos],0
  1439.     ret
  1440.  
  1441. mt_NoNewPosYet:
  1442.     cmp    [Byte cs:mt_PosJumpFlag],0
  1443.     jnz    mt_NextPosition
  1444.     ret
  1445. endp    mt_dskip
  1446.  
  1447. proc    mt_CheckEfx near
  1448.     call    mt_UpdateFunk
  1449.     mov    ax,[Word cs:si+MS.cmd]            ; Get the special command
  1450.     xchg    al,ah
  1451.     and    ax,0FFFh
  1452.     jz    mt_Return            ;mt_Return
  1453.     mov    bl,[cs:si+MS.cmd]           ; Contains the command to do
  1454.     and    bl,0Fh
  1455.     cmp    bl,0
  1456.     jz    mt_Arpeggio
  1457.     cmp    bl,1
  1458.     jz    mt_PortaUp
  1459.     cmp    bl,2
  1460.     jz    mt_PortaDown
  1461.     cmp    bl,3
  1462.     jz    mt_TonePortamento
  1463.     cmp    bl,4
  1464.     jz    mt_Vibrato
  1465.     cmp    bl,5
  1466.     jz    mt_TonePlusVolSlide
  1467.     cmp    bl,6
  1468.     jz    mt_VibratoPlusVolSlide
  1469.     cmp    bl,0Eh
  1470.     jz    mt_E_Commands
  1471. SetBack:call    mt_PerNop
  1472.     cmp    bl,7
  1473.     jz    mt_Tremolo
  1474.     cmp    bl,0Ah
  1475.     jz    mt_VolumeSlide
  1476. mt_Return:
  1477.     ret
  1478. endp    mt_CheckEfx
  1479.  
  1480. proc    mt_PerNop near
  1481.     mov    ax,[cs:si+MS.Period]
  1482.     and    ax,0FFFh
  1483.     or    ax,ax
  1484.     jz    @@Outit
  1485.     mov    cx,ax
  1486.     xor    dx,dx
  1487.     mov    ax,8448
  1488.     div    cx
  1489.     mov    cx,428
  1490.     mul    cx
  1491.     mov    cx,19
  1492.     div    cx
  1493. @@OutIt:
  1494.     push    ax
  1495.     mov    dx,[cs:ComAddr]
  1496.     mov    al,1
  1497.     out    dx,al
  1498.     inc    dx
  1499.     pop    ax
  1500.         out     dx,ax
  1501.         ret
  1502. endp    mt_PerNop
  1503.  
  1504. ; Effect 0 -- Arpeggio
  1505. proc    mt_Arpeggio near
  1506.     xor    ax,ax
  1507.     mov    al,[cs:mt_counter]
  1508.     mov    bl,3
  1509.     div    bl
  1510.     xchg    al,ah
  1511.     cmp    al,1
  1512.     jz    mt_Arpeggio1
  1513.     cmp    al,2
  1514.     jz    mt_Arpeggio2
  1515. mt_Arpeggio0:
  1516.     mov    cx,[cs:si+MS.period]
  1517.     jmp    ArpeggioSet
  1518.  
  1519. mt_Arpeggio1:
  1520.     xor    ax,ax
  1521.     mov    al,[Byte cs:si+MS.cmdlo]
  1522.     shr    al,4
  1523.     jmp    ArpeggioFind
  1524.  
  1525. mt_Arpeggio2:
  1526.     xor    ax,ax
  1527.     mov    al,[cs:si+MS.cmdlo]
  1528.     and    al,15
  1529. ArpeggioFind:
  1530.     shl    ax,1
  1531.     mov    bx,ax
  1532.     mov    al,[cs:si+MS.FineTune]
  1533.     mov    cl,37*2
  1534.     mul    cl
  1535.     mov    dx,[cs:si+MS.Period]
  1536.     push    di
  1537.     mov    di,offset mt_PeriodTable
  1538.     add    di,ax
  1539.     mov    cx,36
  1540. mt_arploop:
  1541.     mov    ax,[cs:bx+di]
  1542.     cmp    dx,[cs:di]
  1543.     jnb    mt_arpafterloop
  1544.     add    di,2
  1545.     loop    mt_arploop
  1546.     pop    di
  1547.     ret
  1548. mt_arpafterloop:
  1549.     pop    di
  1550.     mov    cx,ax
  1551.  
  1552. ArpeggioSet:
  1553.     call    mt_PerNop
  1554.     ret
  1555. endp    mt_Arpeggio
  1556.  
  1557. ; Effect 1 -- Portamento Up
  1558. proc    mt_PortaUp near
  1559.     xor    ax,ax
  1560.     mov    al,[cs:si+MS.cmdlo]           ; Number to slide up
  1561.     and    al,[cs:mt_LowMask]
  1562.     mov    [Byte cs:mt_LowMask],0FFh
  1563.     sub    [cs:si+MS.Period],ax
  1564.     mov    cx,[cs:si+MS.Period]
  1565.     and    cx,0FFFh
  1566.     cmp    cx,71h
  1567.     jnb    mt_PortaUSkip
  1568.     and    [cs:si+MS.Period],0F000h
  1569.     or    [cs:si+MS.Period],71h
  1570. mt_PortaUSkip:
  1571.     mov    cx,[cs:si+MS.Period]
  1572.     and    cx,0FFFh
  1573.     call    mt_PerNop
  1574.     ret
  1575. endp    mt_PortaUp
  1576.  
  1577.  
  1578. ; Effect 2 -- Portamento Down
  1579. proc    mt_PortaDown near
  1580.     xor    ax,ax
  1581.     mov    al,[cs:si+MS.cmdlo]           ; Number to slide down
  1582.     and    al,[cs:mt_LowMask]
  1583.     mov    [Byte cs:mt_LowMask],0FFh
  1584.     add    [cs:si+MS.Period],ax
  1585.     mov    cx,[cs:si+MS.Period]
  1586.     and    cx,0FFFh
  1587.     cmp    cx,358h
  1588.     jb    mt_PortaDSkip
  1589.     and    [cs:si+MS.Period],0F000h
  1590.     or    [cs:si+MS.Period],856
  1591. mt_PortaDSkip:
  1592.     mov    cx,[cs:si+MS.Period]
  1593.     and    cx,0FFFh
  1594.     call    mt_PerNop
  1595.     ret
  1596. endp    mt_PortaDown
  1597.  
  1598. proc    mt_SetTonePorta near
  1599.     push    di
  1600.     mov    dx,[cs:si+MS.Note]
  1601.     xchg    dh,dl
  1602.     and    dx,0FFFh
  1603.     xor    ax,ax
  1604.     mov    al,[cs:si+MS.FineTune]
  1605.     mov    cl,37*2
  1606.     mul    cl
  1607.     mov    di,offset mt_PeriodTable
  1608.     add    di,ax
  1609.     mov    bx,0
  1610. mt_StpLoop:
  1611.     cmp    dx,[cs:bx+di]
  1612.     jnb    mt_StpFound
  1613.     add    bx,2
  1614.     cmp    bx,37*2
  1615.     jb    mt_StpLoop
  1616.     mov    bx,35*2
  1617. mt_StpFound:
  1618.     mov    dl,[cs:si+MS.FineTune]
  1619.     and    dl,8
  1620.     jz    mt_StpGoss
  1621.     or    bx,bx
  1622.     jz    mt_StpGoss
  1623.     sub    bx,2
  1624. mt_StpGoss:
  1625.     mov    dx,[cs:bx+di]
  1626.     pop    di
  1627.     mov    [cs:si+MS.WantedPeriod],dx
  1628.     mov    ax,[cs:si+MS.Period]
  1629.     mov    [Byte cs:si+MS.TonePortDirec],0
  1630.     cmp    dx,ax
  1631.     jz    mt_ClearTonePorta
  1632.     jnb    mt_Return
  1633.     mov    [Byte cs:si+MS.TonePortDirec],1
  1634.     ret
  1635.  
  1636. mt_ClearTonePorta:
  1637.     mov    [Word cs:si+MS.WantedPeriod],0
  1638.     ret
  1639. endp    mt_SetTonePorta
  1640.  
  1641.  
  1642. ; Effect 3 -- Tone Portamento
  1643. proc    mt_TonePortamento near
  1644.     mov    al,[cs:si+MS.cmdlo]
  1645.     or    al,al
  1646.     jz    mt_TonePortNoChange
  1647.     mov    [cs:si+MS.TonePortSpeed],al
  1648.     mov    [Byte cs:si+MS.cmdlo],0
  1649. mt_TonePortNoChange:
  1650.     cmp    [Word cs:si+MS.WantedPeriod],0
  1651.     jz    mt_Return
  1652.     xor    ax,ax
  1653.     mov    al,[cs:si+MS.TonePortSpeed]
  1654.     cmp    [Byte cs:si+MS.TonePortDirec],0
  1655.     jnz    mt_TonePortaUp
  1656. mt_TonePortaDown:
  1657.     add    [cs:si+MS.Period],ax
  1658.     mov    ax,[cs:si+MS.WantedPeriod]
  1659.     cmp    ax,[cs:si+MS.Period]
  1660.     jg    mt_TonePortaSetPer
  1661.     mov    [cs:si+MS.Period],ax
  1662.     mov    [Word cs:si+MS.WantedPeriod],0
  1663.     jmp    mt_TonePortaSetPer
  1664.  
  1665. mt_TonePortaUp:
  1666.     sub    [cs:si+MS.Period],ax
  1667.     mov    ax,[cs:si+MS.WantedPeriod]
  1668.     cmp    ax,[cs:si+MS.Period]
  1669.     jl    mt_TonePortaSetPer
  1670.     mov    [cs:si+MS.Period],ax
  1671.     mov    [Word cs:si+MS.WantedPeriod],0
  1672.  
  1673. mt_TonePortaSetPer:
  1674.     mov    cx,[cs:si+MS.Period]
  1675.     mov    al,[cs:si+MS.GlissFunk]
  1676.     and    al,0Fh
  1677.     jz    mt_GlissSkip
  1678.     mov    al,[cs:si+MS.FineTune]
  1679.     mov    bl,37*2
  1680.     mul    bl
  1681.     push    di
  1682.     mov    di,offset mt_PeriodTable
  1683.     add    di,ax
  1684.     mov    bx,0
  1685. mt_GlissLoop:
  1686.     cmp    cx,[cs:bx+di]
  1687.     jnb    mt_GlissFound
  1688.     add    bx,2
  1689.     cmp    bx,37*2
  1690.     jb    mt_GlissLoop
  1691.     mov    bx,35*2
  1692. mt_GlissFound:
  1693.     mov    cx,[cs:bx+di]
  1694.     pop    di
  1695. mt_GlissSkip:
  1696.     call    mt_PerNop
  1697.     ret
  1698. endp    mt_TonePortamento
  1699.  
  1700.  
  1701. ; Effect 4 -- Vibrato
  1702. proc    mt_Vibrato near
  1703.     mov    al,[cs:si+MS.cmdlo]
  1704.     or    al,al
  1705.     jz    mt_Vibrato2
  1706.     mov    cl,[cs:si+MS.VibratoCmd]
  1707.     and    al,0fh
  1708.     jz    mt_vibskip
  1709.     and    cl,0F0h
  1710.     or    cl,al
  1711. mt_vibskip:
  1712.     mov    al,[cs:si+MS.cmdlo]
  1713.     and    al,0F0h
  1714.     jz    mt_vibskip2
  1715.     and    cl,0Fh
  1716.     or    cl,al
  1717. mt_vibskip2:
  1718.     mov    [cs:si+MS.VibratoCmd],cl
  1719. mt_Vibrato2:
  1720.     mov    al,[cs:si+MS.VibratoPos]
  1721.     mov    bx,offset mt_VibratoTable
  1722.     shr    ax,2
  1723.     and    ax,001Fh
  1724.     xor    cx,cx
  1725.     mov    cl,[cs:si+MS.WaveControl]
  1726.     and    cl,03h
  1727.     jz    mt_vib_sine
  1728.     shl    al,3
  1729.     cmp    cl,1
  1730.     jz    mt_vib_rampdown
  1731.     mov    cl,255
  1732.     jmp    mt_vib_set
  1733. mt_vib_rampdown:
  1734.     cmp    [Byte cs:si+MS.VibratoPos],0
  1735.     jnb    mt_vib_rampdown2
  1736.     mov    cl,255
  1737.     sub    cl,al
  1738.     jmp    mt_vib_set
  1739. mt_vib_rampdown2:
  1740.     mov    cl,al
  1741.     jmp    mt_vib_set
  1742. mt_vib_sine:
  1743.     add    bl,al
  1744.     mov    cl,[cs:bx]
  1745. mt_vib_set:
  1746.     mov    al,[cs:si+MS.VibratoCmd]
  1747.     and    al,0Fh
  1748.     mul    cl
  1749.     shr    ax,7
  1750.     mov    cx,ax
  1751.     mov    ax,[cs:si+MS.Period]
  1752.     cmp    [Byte cs:si+MS.VibratoPos],0
  1753.     jb    mt_VibratoNeg        ; BMI
  1754.     add    ax,cx
  1755.     jmp    mt_Vibrato3
  1756. mt_VibratoNeg:
  1757.     sub    ax,cx
  1758. mt_Vibrato3:
  1759.     mov    cx,ax
  1760.     call    mt_PerNop
  1761.     mov    al,[cs:si+MS.VibratoCmd]
  1762.     shr    ax,2
  1763.     and    ax,3Ch
  1764.     add    [cs:si+MS.VibratoPos],al
  1765.     ret
  1766. endp    mt_Vibrato
  1767.  
  1768.  
  1769. ; Effect 5 -- Tone and Volume Slide
  1770. proc    mt_TonePlusVolSlide near
  1771.     call    mt_TonePortNoChange
  1772.     jmp    mt_VolumeSlide
  1773. endp    mt_TonePlusVolSlide
  1774.  
  1775. ; Effect 6 -- Vibrato and Volume Slide
  1776. proc    mt_VibratoPlusVolSlide near
  1777.     call    mt_Vibrato2
  1778.     jmp    mt_VolumeSlide
  1779. endp    mt_VibratoPlusVolSlide
  1780.  
  1781.  
  1782. ; Effect 7 -- Tremolo
  1783. proc    mt_Tremolo near
  1784.     mov    al,[Byte cs:si+MS.cmdlo]
  1785.     or    al,al
  1786.     jz    mt_Tremolo2
  1787.     mov    cl,[cs:si+MS.TremoloCmd]
  1788.     and    al,0Fh
  1789.     jz    mt_treskip
  1790.     and    cl,0F0h
  1791.     or    cl,al
  1792. mt_treskip:
  1793.     mov    al,[Byte cs:si+MS.cmdlo]
  1794.     and    al,0F0h
  1795.     jz    mt_treskip2
  1796.     and    cl,0Fh
  1797.     or    cl,al
  1798. mt_treskip2:
  1799.     mov    [cs:si+MS.TremoloCmd],cl
  1800. mt_Tremolo2:
  1801.     mov    al,[cs:si+MS.TremoloPos]
  1802.     shr    al,2
  1803.     and    ax,001Fh
  1804.     xor    cx,cx
  1805.     mov    cl,[cs:si+MS.WaveControl]
  1806.     shr    cl,4
  1807.     and    cl,03h
  1808.     jz    mt_tre_sine
  1809.     shl    al,3
  1810.     cmp    cl,1
  1811.     jz    mt_tre_rampdown
  1812.     mov    cl,255
  1813.     jmp    mt_tre_set
  1814. mt_tre_rampdown:
  1815.     cmp    [Byte cs:si+MS.VibratoPos],0
  1816.     jnb    mt_tre_rampdown2
  1817.     mov    cl,255
  1818.     sub    cl,al
  1819.     jmp    mt_tre_set
  1820. mt_tre_rampdown2:
  1821.     mov    cl,al
  1822.     jmp    mt_tre_set
  1823. mt_tre_sine:
  1824.     xor    bx,bx
  1825.     mov    bl,al
  1826.     mov    cl,[cs:bx+offset mt_VibratoTable]
  1827. mt_tre_set:
  1828.     mov    al,[cs:si+MS.TremoloCmd]
  1829.     and    al,0Fh
  1830.     mul    cl
  1831.     mov    cx,ax
  1832.     shr    cx,6
  1833.     mov    al,[cs:si+MS.Volume]
  1834.     cmp    [Byte cs:si+MS.TremoloPos],0
  1835.     jb    mt_TremoloNeg        ; BMI  jns
  1836.     add    al,cl
  1837.     jmp    mt_Tremolo3
  1838. mt_TremoloNeg:
  1839.     sub    al,cl
  1840. mt_Tremolo3:
  1841.     jnb    mt_TremoloSkip
  1842.     xor    ax,ax
  1843. mt_TremoloSkip:
  1844.     cmp    al,40h
  1845.     jb    mt_TremoloOK        ; BLS
  1846.     mov    al,40h
  1847. mt_TremoloOK:
  1848.     call    volequ
  1849.     mov    al,[cs:si+MS.TremoloCmd]
  1850.     shr    al,2
  1851.     and    al,3Ch
  1852.     add    [cs:si+MS.TremoloPos],al
  1853.     ret
  1854. endp    mt_Tremolo
  1855.  
  1856. TempHi    dw    0
  1857. TempLo    dw    0
  1858.  
  1859. ; Effect 9 -- Sample Offset
  1860. proc    mt_SampleOffset near
  1861.     xor    ax,ax
  1862.     mov    al,[Byte cs:si+MS.cmdlo]
  1863.     or    al,al
  1864.     jz    mt_sononew
  1865.     mov    [cs:si+MS.SampleOffset],al
  1866. mt_sononew:
  1867.     mov    al,[cs:si+MS.SampleOffset]       ; Variance in Protracker code.
  1868.     shl    ax,8
  1869. ;     cmp     ax,[cs:si+MS.Reallength]
  1870. ;     jge     mt_sofskip
  1871.     mov    cx,ax
  1872.     mov    ax,[Word cs:si+MS.start]
  1873.     mov    dx,[Word cs:si+(offset (MS).start)+2]
  1874.     add    ax,cx
  1875.         adc     dx,0
  1876.     mov    [cs:TempLo],ax
  1877.         mov     [cs:TempHi],dx
  1878.     ; Send sample begin
  1879.     mov    dx,[cs:ComAddr]
  1880.         mov     al,0ah
  1881.         out     dx,al
  1882.         inc     dx              ; 104h
  1883.     mov    ax,[cs:TempLo]
  1884.     mov    cx,[cs:TempHi]
  1885.         call    RShift
  1886.         out     dx,ax
  1887.         dec     dx              ; 103h
  1888.         mov     al,0bh
  1889.         out     dx,al
  1890.         inc     dx              ; 104h
  1891.     mov    ax,[cs:TempLo]
  1892.     shl    ax,9
  1893.         out     dx,ax
  1894.     mov    [Byte cs:SOffsetSet],1
  1895.  
  1896. @@Bottom:
  1897.     ret
  1898. mt_sofskip:
  1899. ;     mov     dx,[cs:ComAddr]
  1900. ;     mov     al,80h
  1901. ;     out     dx,al
  1902. ;     add     dx,2
  1903. ;     in     al,dx
  1904. ;     mov     ah,al
  1905. ;     or     ah,00000011b
  1906. ;     sub     dx,2
  1907. ;     mov     al,0
  1908. ;     out     dx,al
  1909. ;     add     dx,2
  1910. ;     mov     al,ah
  1911. ;     out     dx,al
  1912.     ret
  1913. endp    mt_SampleOffset
  1914.  
  1915.  
  1916. ; Effect A -- Volume Slide
  1917. proc    mt_VolumeSlide near
  1918.     mov    al,[cs:si+MS.cmdlo]
  1919.     shr    al,4
  1920.     or    al,al
  1921.     jz    mt_VolSlideDown
  1922. mt_VolSlideUp:
  1923.     add    [Byte cs:si+MS.Volume],al
  1924.     cmp    [Byte cs:si+MS.Volume],40h
  1925.     jb    mt_vsuskip
  1926.     mov    [Byte cs:si+MS.Volume],40h
  1927. mt_vsuskip:
  1928.     mov    al,[Byte cs:si+MS.Volume]
  1929.     call    volequ
  1930.     ret
  1931.  
  1932. mt_VolSlideDown:
  1933.     mov    al,[cs:si+MS.cmdlo]
  1934.     and    al,0Fh
  1935. mt_VolSlideDown2:
  1936.     sub    [Byte cs:si+MS.Volume],al
  1937.     jnb    mt_vsdskip
  1938.     mov    [Byte cs:si+MS.Volume],0
  1939. mt_vsdskip:
  1940.     mov    al,[Byte cs:si+MS.Volume]
  1941.     call    volequ
  1942.     ret
  1943. endp    mt_VolumeSlide
  1944.  
  1945.  
  1946. ; Effect B -- Position Jump
  1947. proc    mt_PositionJump near
  1948.     mov    al,[Byte cs:si+MS.cmdlo]     ; Get where to jump
  1949.     dec    al                  ; Update the
  1950.     mov    [cs:mt_SongPos],al         ; information.
  1951. mt_pj2: mov    [Byte cs:mt_PBreakPos],0
  1952.     mov    [Byte cs:mt_PosJumpFlag],1
  1953.     ret
  1954. endp    mt_PositionJump
  1955.  
  1956. ; Effect C -- Volume Change
  1957. proc    mt_VolumeChange near
  1958.     mov    al,[Byte cs:si+MS.cmdlo]   ; Get value for volume
  1959.     cmp    al,40h            ; Is it greater than 40h?
  1960.     jb    mt_VolumeOK        ; Nope
  1961.     mov    al,40h
  1962. mt_VolumeOK:
  1963.     mov    [cs:si+MS.Volume],al       ; Get it again
  1964.     call    volequ
  1965.     ret
  1966. endp    mt_VolumeChange
  1967.  
  1968. ; Effect D -- Pattern Break
  1969. proc    mt_PatternBreak near
  1970.     mov    al,[Byte cs:si+MS.cmdlo]         ; Break to where?
  1971.     mov    cl,al
  1972.     shr    al,4
  1973.     mov    bl,10
  1974.     mul    bl
  1975.     and    cl,0Fh
  1976.     add    al,cl
  1977.     cmp    al,63
  1978.     jg    mt_pj2
  1979.     mov    [cs:mt_PBreakPos],al
  1980.     mov    [Byte cs:mt_PosJumpFlag],1
  1981.     ret
  1982. endp    mt_PatternBreak
  1983.  
  1984.  
  1985. ; Effect F -- Set Speed
  1986. ;   Doesn't handle Protracker extended speeds.
  1987. proc    mt_SetSpeed near
  1988.     mov    al,[Byte cs:si+MS.cmdlo]         ; Get value for speed
  1989.     or    al,al
  1990.     jz    @@SSpe1
  1991.     cmp    al,32
  1992.     jnb    @@SSpe1
  1993.     mov    [Byte cs:mt_counter],0
  1994.     mov    [Byte cs:mt_speed],al
  1995. @@SSPe1:ret
  1996. endp    mt_SetSpeed
  1997.  
  1998.  
  1999. proc    mt_CheckMoreEfx near
  2000.     call    mt_UpdateFunk
  2001.     mov    bl,[cs:si+MS.cmd]
  2002.     and    bl,0Fh
  2003. ;     cmp     bl,09h
  2004. ;     jz     mt_SampleOffset
  2005.     cmp    bl,0Bh
  2006.     jz    mt_PositionJump
  2007.     cmp    bl,0Dh
  2008.     jz    mt_PatternBreak
  2009.     cmp    bl,0Eh
  2010.     jz    mt_E_Commands
  2011.     cmp    bl,0Fh
  2012.     jz    mt_SetSpeed
  2013.     cmp    bl,0Ch
  2014.     jz    mt_VolumeChange
  2015.     jmp    mt_PerNop
  2016. endp    mt_CheckMoreEfx
  2017.  
  2018. proc    mt_E_Commands near
  2019.     mov    bl,[Byte cs:si+MS.cmdlo]
  2020.     and    bl,0F0h
  2021.     shr    bl,4
  2022.     cmp    bl,0
  2023.     jz    mt_FilterOnOff
  2024.     cmp    bl,1
  2025.     jz    mt_FinePortaUp
  2026.     cmp    bl,2
  2027.     jz    mt_FinePortaDown
  2028.     cmp    bl,3
  2029.     jz    mt_SetGlissControl
  2030.     cmp    bl,4
  2031.     jz    mt_SetVibratoControl
  2032.     cmp    bl,5
  2033.     jz    mt_SetFineTune
  2034.     cmp    bl,6
  2035.     jz    mt_JumpLoop
  2036.     cmp    bl,7
  2037.     jz    mt_SetTremoloControl
  2038.     cmp    bl,8
  2039.     jz    mt_KarplusStrong
  2040.     cmp    bl,0Eh
  2041.     jz    mt_PatternDelay
  2042.     cmp    bl,9
  2043.     jz    mt_RetrigNote
  2044.     cmp    bl,0Ah
  2045.     jz    mt_VolumeFineUp
  2046.     cmp    bl,0Bh
  2047.     jz    mt_VolumeFineDown
  2048.     cmp    bl,0Ch
  2049.     jz    mt_NoteCut
  2050.     cmp    bl,0Dh
  2051.     jz    mt_NoteDelay
  2052.     cmp    bl,0Fh
  2053.     jz    mt_FunkIt
  2054.     ret
  2055. endp    mt_E_Commands
  2056.  
  2057. ;──────────────────────────────────────────────────────────────────────────
  2058. ; Effect E
  2059. ;──────────────────────────────────────────────────────────────────────────
  2060. ; Effect 0 -- FilterOnOff
  2061. proc    mt_FilterOnOff near
  2062.     mov    al,[Byte cs:si+MS.cmdlo]
  2063.     and    al,1
  2064.     sal    al,1
  2065.     ; Amiga
  2066.     ; Stuff
  2067.     ret
  2068. endp    mt_FilterOnOff
  2069.  
  2070. ; Effect 1 -- Fine Porta Up
  2071. proc    mt_FinePortaUp near
  2072.     cmp    [Byte cs:mt_counter],0
  2073.     jnz    mt_Return
  2074.     mov    [Byte cs:mt_LowMask],0Fh
  2075.     jmp    mt_PortaUp
  2076. endp    mt_FinePortaUp
  2077.  
  2078. ; Effect 2 -- Fine Porta Down
  2079. proc    mt_FinePortaDown near
  2080.     cmp    [Byte cs:mt_counter],0
  2081.     jnz    mt_Return
  2082.     mov    [Byte cs:mt_LowMask],0Fh
  2083.     jmp    mt_PortaDown
  2084. endp    mt_FinePortaDown
  2085.  
  2086. ; Effect 3 -- Set Gliss Control
  2087. proc    mt_SetGlissControl near
  2088.     mov    al,[Byte cs:si+MS.cmdlo]
  2089.     and    al,0Fh
  2090.     and    [Byte cs:si+MS.GlissFunk],0F0h
  2091.     or    [cs:si+MS.GlissFunk],al
  2092.     ret
  2093. endp    mt_SetGlissControl
  2094.  
  2095. ; Effect 4 -- Set Vibrato Control
  2096. proc    mt_SetVibratoControl near
  2097.     mov    al,[cs:si+MS.cmdlo]
  2098.     and    al,0Fh
  2099.     and    [Byte cs:si+MS.WaveControl],0F0h
  2100.     or    [cs:si+MS.WaveControl],al
  2101.     ret
  2102. endp    mt_SetVibratoControl
  2103.  
  2104. ; Effect 5 -- Set Fine Tune
  2105. proc    mt_SetFineTune near
  2106.     mov    al,[cs:si+MS.cmdlo]
  2107.     and    al,0Fh
  2108.     mov    [cs:si+MS.FineTune],al
  2109.     ret
  2110. endp    mt_SetFineTune
  2111.  
  2112. ; Effect 6 -- Jump Loop
  2113. proc    mt_JumpLoop near
  2114.     cmp    [Byte cs:mt_counter],0
  2115.     jnz    mt_Return
  2116.     mov    al,[cs:si+MS.cmdlo]
  2117.     and    al,0Fh
  2118.     jz    mt_SetLoop
  2119.     cmp    [Byte cs:si+MS.loopcount],0
  2120.     jz    mt_jumpcnt
  2121.     dec    [Byte cs:si+MS.loopcount]
  2122.     jz    mt_Return
  2123. mt_jmploop:
  2124.     mov    al,[cs:si+MS.pattpos]
  2125.     mov    [cs:mt_PBreakPos],al
  2126.     mov    [Byte cs:mt_PBreakFlag],1
  2127.     ret
  2128.  
  2129. mt_jumpcnt:
  2130.     mov    [cs:si+MS.loopcount],al
  2131.     jmp    mt_jmploop
  2132.  
  2133. mt_SetLoop:
  2134.     mov    ax,[cs:mt_PatternPos]
  2135.     shr    ax,4
  2136.     and    ax,63
  2137.     mov    [cs:si+MS.pattpos],al
  2138.     ret
  2139. endp    mt_JumpLoop
  2140.  
  2141. ; Effect 7 -- Set Tremolo Control
  2142. proc    mt_SetTremoloControl near
  2143.     mov    al,[Byte cs:si+MS.cmdlo]
  2144.     and    al,0Fh
  2145.     shl    al,4
  2146.     and    [Byte cs:si+MS.WaveControl],0Fh
  2147.     or    [cs:si+MS.WaveControl],al
  2148.     ret
  2149. endp    mt_SetTremoloControl
  2150.  
  2151. proc    mt_KarplusStrong near
  2152. ;     mov     ax,[cs:si+MS.loopstart]
  2153.     mov    bx,ax
  2154. ;     mov     ax,[cs:si+MS.RepLen]
  2155.     add    ax,ax
  2156.     sub    ax,2
  2157. karplop:
  2158.     ; More here.
  2159.     ret
  2160. endp    mt_KarplusStrong
  2161.  
  2162. ; Effect 9 -- Retrig Note
  2163. proc    mt_RetrigNote near
  2164.     mov    bl,[Byte cs:si+MS.cmdlo]
  2165.     and    bl,0Fh
  2166.     jz    mt_rtnend
  2167.     xor    ax,ax
  2168.     mov    al,[cs:mt_counter]
  2169.     or    al,al
  2170.     jnz    mt_rtnskp
  2171.     mov    ax,[cs:si+MS.Note]
  2172.     xchg    ah,al
  2173.     and    ax,0FFFh
  2174.     jnz    mt_rtnend
  2175. ;     mov     [Byte cs:mt_counter],0
  2176.     xor    ax,ax
  2177.     mov    al,[cs:mt_counter]
  2178. mt_rtnskp:
  2179.     div    bl
  2180.     xchg    ah,al
  2181.     or    ax,ax
  2182.     jnz    mt_rtnend
  2183. mt_DoRetrig:
  2184.     xor    ax,ax
  2185. ;     mov     [cs:bp+CD.sofs],ax
  2186. ;     mov     ax,[cs:si+MS.Length]
  2187.     shl    ax,1
  2188. ;     mov     [cs:bp+CD.slen],ax
  2189. ;     mov     ax,[cs:si+MS.LoopStart]
  2190. ;     mov     [cs:bp+CD.sloops],ax
  2191. ;     mov     cx,[cs:si+MS.RepLen]
  2192.     add    ax,cx            ; Add on the offset.
  2193.     add    ax,cx            ; Add it again.
  2194.     sub    ax,3
  2195. ;     mov     [cs:bp+CD.sloope],ax
  2196. mt_rtnend:
  2197.     ret
  2198. endp    mt_RetrigNote
  2199.  
  2200. ; Effect A -- Volume Fine Up
  2201. proc    mt_VolumeFineUp near
  2202.     cmp    [Byte cs:mt_counter],0
  2203.     jnz    mt_Return
  2204.     mov    al,[cs:si+MS.cmdlo]
  2205.     and    al,0Fh
  2206.     jmp    mt_VolSlideUp
  2207. endp    mt_VolumeFineUp
  2208.  
  2209. ; Effect B -- Volume Fine Down
  2210. proc    mt_VolumeFineDown near
  2211.     cmp    [Byte cs:mt_counter],0
  2212.     jnz    mt_Return
  2213.     mov    al,[cs:si+MS.cmdlo]
  2214.     and    al,0Fh
  2215.     jmp    mt_VolSlideDown2
  2216. endp    mt_VolumeFineDown
  2217.  
  2218. ; Effect C -- Note Cut
  2219. proc    mt_NoteCut near
  2220.     mov    al,[Byte cs:si+MS.cmdlo]
  2221.     and    al,0Fh
  2222.     cmp    al,[cs:mt_counter]
  2223.     jnz    mt_Return
  2224.     mov    [Byte cs:si+MS.Volume],0
  2225.     mov    al,[Byte cs:si+MS.Volume]
  2226.         call    volequ
  2227.     ret
  2228. endp    mt_NoteCut
  2229.  
  2230. ; Effect D -- Note Delay
  2231. proc    mt_NoteDelay near
  2232.     mov    al,[Byte cs:si+MS.cmdlo]
  2233.     and    al,0Fh
  2234.     cmp    al,[cs:mt_counter]
  2235.     jnz    mt_Return
  2236.     mov    ax,[cs:si]
  2237.     and    ax,0FFFh
  2238.     jz    mt_Return
  2239.     jmp    mt_DoRetrig
  2240. endp    mt_NoteDelay
  2241.  
  2242. ; Effect E -- Pattern Delay
  2243. proc    mt_PatternDelay near
  2244.     cmp    [Byte cs:mt_counter],0
  2245.     jnz    mt_Return
  2246.     mov    al,[Byte cs:si+MS.cmdlo]
  2247.     and    al,0Fh
  2248.     cmp    [Byte cs:mt_PattDelayTime2],0
  2249.     jnz    mt_Return
  2250.     inc    al
  2251.     mov    [cs:mt_PattDelayTime],al
  2252.     ret
  2253. endp    mt_PatternDelay
  2254.  
  2255. ; Effect F -- Funk It
  2256. proc    mt_FunkIt near
  2257.     cmp    [Byte cs:mt_counter],0
  2258.     jnz    mt_Return
  2259.     mov    al,[Byte cs:si+MS.cmdlo]
  2260.     and    al,0Fh
  2261.     shl    al,4
  2262.     and    [Byte cs:si+MS.GlissFunk],0Fh
  2263.     or    [cs:si+MS.GlissFunk],al
  2264.     or    al,al
  2265.     jz    mt_Return
  2266.     jmp    mt_UpdateFunk
  2267. endp    mt_FunkIt
  2268.  
  2269. proc    mt_UpdateFunk near
  2270.     xor    bx,bx
  2271.     mov    bl,[cs:si+MS.GlissFunk]
  2272.     shr    bl,4
  2273.     or    bl,bl
  2274.     jz    mt_funkend
  2275.     mov    al,[cs:bx+offset mt_FunkTable]
  2276.     add    [cs:si+MS.FunkOffset],al
  2277.     mov    al,[cs:si+MS.FunkOffset]
  2278.     and    al,10000000b
  2279.     jz    mt_funkend
  2280.     mov    [Byte cs:si+MS.FunkOffset],0
  2281.     ; This is my best try at converting this code.
  2282. ;     mov     ax,[cs:si+MS.LoopStart]
  2283. ;     mov     bx,[cs:si+MS.RepLen]
  2284. ;     add     ax,bx
  2285. ;     add     ax,bx
  2286. ;     mov     cx,[cs:si+MS.WaveStart]
  2287. ;     inc     cx
  2288. ;     cmp     cx,ax
  2289. ;     jb     mt_funkok
  2290. ;     mov     cx,[cs:si+MS.LoopStart]
  2291. ;mt_funkok:
  2292. ;     mov     [cs:si+MS.WaveStart],cx
  2293. ;     mov     ax,-1
  2294. ;     mov     bx,cx
  2295. ;     sub     [cs:bx],ax
  2296. ;     mov     ax,[cs:bx]
  2297. mt_funkend:
  2298.     ret
  2299. endp    mt_UpdateFunk
  2300.  
  2301.  
  2302.  
  2303. proc    volequ near
  2304.     push    bx
  2305.     mul    [Byte cs:si+MS.MasterVolume]
  2306.     mov    bl,ah
  2307.     xor    bh,bh
  2308.     shl    bx,1
  2309.     mov    dx,[cs:ComAddr]
  2310.         mov     al,9
  2311.     out    dx,al
  2312.     inc    dx
  2313. ;     cmp     [Byte cs:Voice],2
  2314. ;     jz     @@Leave
  2315. ;     cmp     [Byte cs:Voice],3
  2316. ;     jz     @@Leave
  2317.         mov     ax,[cs:bx+mt_VolTable]
  2318.     out    dx,ax
  2319.     pop    bx
  2320.     ret
  2321. @@Leave:
  2322.     mov    ax,0
  2323.     out    dx,ax
  2324.     pop    bx
  2325.     ret
  2326. endp    volequ
  2327.  
  2328. ends    Sound
  2329.  
  2330.  
  2331. segment zzzzzseg
  2332.     db    16 dup (?)
  2333. ends    zzzzzseg
  2334.  
  2335.         end     Start
  2336.  
  2337.