home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / g / gusmod11.zip / GUSMOD.ASM < prev    next >
Assembly Source File  |  1993-01-15  |  45KB  |  2,080 lines

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