home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / MODINFO.ZIP / DMAPLAY2.ASM < prev    next >
Assembly Source File  |  1993-04-16  |  11KB  |  490 lines

  1.       DOSSEG
  2.       .MODEL SMALL
  3.       .STACK 200h
  4.       .CODE
  5.       .386
  6.       ASSUME CS:@CODE, DS:@CODE
  7.       Ideal
  8.  
  9. ────────────────────────────────────────────────────────
  10.  
  11. OldInt  dd  0       ;for the old DMA interrupt
  12.  
  13. BaseAddress dw  220h
  14. IrqNumber   db  7
  15. DMANumber   db  1
  16.  
  17. SampleSeg   dw  0
  18. SampleSeg2  dw  0
  19. SampleOff   dw  0
  20.  
  21. FileName    db  "jamhot.sam",0
  22. SamLength   dw  ?
  23.  
  24. STRUC DMAInfo
  25.     Page    dw  ?,?
  26.     Length  dw  ?,?
  27.     Offset  dw  ?,?
  28.     Next    dw  0,0     ;changes 2nd one to a "2" if 2 buffers are needed
  29.     Current dw  0       ;0 or 1
  30. ENDS DMAInfo
  31.  
  32. DMA DMAInfo <>
  33.  
  34. ────────────────────────────────────────────────────────
  35.  
  36. ;==================
  37. ;==- Interrupts -==
  38. ;==================
  39.  
  40. PROC DMAINT FAR
  41.     pusha
  42.     cli
  43.  
  44.     mov     dx,[cs:BaseAddress]
  45.     add     dx,0eh   
  46.     in      al,dx               ;acknowledge interrupt
  47.  
  48.     xor     [cs:DMA.Current],1
  49.     mov     bx,[cs:DMA.Current]
  50.     add     bx,bx
  51.     mov     bx,[cs:bx + DMA.NEXT]
  52.     
  53.     mov     ax,[cs:bx + DMA.Page]
  54.     mov     ah,al
  55.     mov     cx,[cs:bx + DMA.Length]
  56.     mov     dx,[cs:bx + DMA.Offset]
  57.     call    TransferDma
  58.  
  59.     mov     al,20h
  60.     out     20h,al              ;end of hardware interrupt
  61.  
  62.     popa
  63.     sti
  64.     iret
  65. ENDP DMAINT
  66.  
  67. ;======================
  68. ;==- Start Transfer -==
  69. ;======================
  70.  
  71. PROC StartTransferDma NEAR
  72.     pusha
  73.  
  74.     mov     al,[cs:IrqNumber]
  75.     add     al,8
  76.     cbw
  77.     shl     al,2
  78.     mov     bx,ax
  79.  
  80.     push    es
  81.     sub     ax,ax
  82.     mov     es,ax
  83.     mov     ax,[es:bx]
  84.     mov     [WORD LOW  cs:OldInt],ax           ; Grab the current interrupt
  85.     mov     ax,[es:bx+2]
  86.     mov     [WORD HIGH cs:OldInt],ax              ; so we can restore it later
  87.     pop     es
  88.  
  89.     mov     ax,[cs:DMA.Page]
  90.     mov     ah,al
  91.     mov     cx,[cs:DMA.Length]
  92.     mov     dx,[cs:DMA.Offset]
  93.     
  94.     mov      al,5
  95.     out     0ah,al          ;Mask off channel 1
  96.     xor      al,al
  97.     out     0ch,al          ;Clear byte pointer F/F to lowerbyte
  98.     mov      al,49h  
  99.     out     0bh,al          ;Set transfer mode to DAC (ADC = 45h)
  100.     mov      al,dl          ;LSB of BASE_ADDRESS
  101.     out       2,al
  102.     mov      al,dh          ;MSB of BASE_ADDRESS
  103.     out       2,al
  104.     mov      al,ah
  105.     out     83h,al          ;Page Number
  106.     mov      al,cl
  107.     out       3,al          ;LSB of DATA_Length
  108.     mov      al,ch
  109.     out       3,al          ;MSB of DATA_Length
  110.     mov      al,1
  111.     out     0ah,al          ;Enable Channel 1
  112.  
  113.     mov     ax,offset DMAInt
  114.     call    DoRealInt
  115.  
  116.     mov     al,14h          ;function 14h DMAmode 8-bit DAC
  117.     call    Sendcommand
  118.     mov     al,cl           ;send LSB of DATALENGTH
  119.     call    SendCommand
  120.     mov     al,ch           ;send MSB of DATALENGTH
  121.     call    SendCommand
  122.     
  123.     popa
  124.     ret
  125. ENDP StartTransferDma
  126.  
  127.     ;ah= page number
  128.     ;dx= BASE_ADDRESS
  129.     ;cx= DATA_LENGTH (-1)
  130. PROC TransferDma NEAR
  131.     pusha
  132.     mov     al,5
  133.     out     0ah,al          ;Mask off channel 1
  134.     xor     al,al
  135.     out     0ch,al          ;Clear byte pointer F/F to lowerbyte
  136.     mov     al,49h  
  137.     out     0bh,al          ;Set transfer mode to DAC (ADC = 45h)
  138.     mov     al,dl           ;LSB of BASE_ADDRESS
  139.     out     2,al
  140.     mov     al,dh           ;MSB of BASE_ADDRESS
  141.     out     2,al
  142.     mov     al,ah
  143.     out     83h,al          ;Page Number
  144.     mov     al,cl
  145.     out     3,al            ;LSB of DATA_Length
  146.     mov     al,ch
  147.     out     3,al            ;MSB of DATA_Length
  148.     mov     al,1
  149.     out     0ah,al          ;Enable Channel 1
  150.  
  151.     mov     al,14h          ;function 14h DMAmode 8-bit DAC
  152.     call    Sendcommand
  153.     mov     al,cl           ;send LSB of DATALENGTH
  154.     call    SendCommand
  155.     mov     al,ch           ;send MSB of DATALENGTH
  156.     call    SendCommand
  157.  
  158.     popa
  159.     ret
  160. ENDP TransferDMA
  161.  
  162.     ;ah= TC (Time Constant = 256 - 1,000,000/HZ)
  163. PROC SetTimeConstant NEAR
  164.     mov     al,40h
  165.     call    SendCommand
  166.     mov     al,ah
  167.     call    SendCommand
  168.     ret
  169. ENDP SetTimeConstant
  170.  
  171. PROC TurnOffSpeaker NEAR
  172.     mov     al,0d3h         ;turn off speaker
  173.     call    Sendcommand
  174.     ret
  175. ENDP TurnOffSpeaker
  176.  
  177. PROC HaltDMA NEAR
  178.     mov     al,0d0h         ;Halt DMA
  179.     call    SendCommand
  180.     ret
  181. ENDP HaltDma
  182.  
  183.     ;al = command
  184. PROC SendCommand NEAR
  185.     push    dx
  186.     push    ax
  187.     mov     dx,[cs:BaseAddress]
  188.     add     dx,0ch
  189. @@Sendcommandloop:
  190.     in      al,dx
  191.     or      al,al
  192.     js      @@Sendcommandloop
  193.     pop     ax
  194.     out     dx,al
  195.     pop     dx
  196.     ret
  197. ENDP SendCommand
  198.  
  199. PROC TurnOnSpeaker NEAR
  200.     mov     al,0d1h
  201.     call    SendCommand
  202.     ret
  203. ENDP TurnOnSpeaker
  204.  
  205.     ;input- none 
  206.     ;output al=0 successful
  207.     ;       al=1 unsuccessful
  208.     ;DESTROYED: ax,dx,cx
  209.  
  210. PROC DspReset NEAR
  211.     mov     dx,[cs:baseaddress]
  212.     add     dx,6
  213.     mov     al,1
  214.     out     dx,al
  215.     in      al,dx
  216.     in      al,dx
  217.     in      al,dx
  218.     in      al,dx
  219.     mov     al,0
  220.     out     dx,al
  221.     add     dx,4
  222.     mov     cx,100
  223. @@NotYet:
  224.     in      al,dx
  225.     cmp     al,0AAh
  226.     je      @@Success
  227.     loop    @@NotYet
  228.     mov     ax,1
  229.     ret
  230. @@Success:
  231.     mov     ax,0
  232.     ret
  233. ENDP DspReset
  234.  
  235. ;========================
  236. ;==- Start Interrupts -==
  237. ;========================
  238.  
  239.     ;cs:ax=location of interrupt
  240. PROC DoRealint NEAR
  241.     push    bx
  242.     push    cx
  243.     push    dx
  244.     cli                             ; Disable interrupts
  245.  
  246.     mov     dx,ax
  247.     mov     al,[cs:IrqNumber]
  248.     add     al,8
  249.     cbw                             ; Convrt byte to word
  250.     shl     ax,2                    ; Shift w/zeros fill
  251.     mov     bx,ax
  252.  
  253.     push    es
  254.     sub     ax,ax
  255.     mov     es,ax
  256.     mov     [es:bx],dx
  257.     mov     [es:bx+2],cs
  258.     pop     es
  259.  
  260.     mov     cl,[cs:IrqNumber]
  261.     mov     ah,1
  262.     shl     ah,cl                   ; Shift w/zeros fill
  263.     not     ah
  264.     in      al,21h                  ; port 21h, 8259-1 int IMR
  265.     and     al,ah
  266.     out     21h,al                  ; port 21h, 8259-1 int comands
  267.  
  268.     pop     dx
  269.     pop     cx
  270.     pop     bx
  271.     sti
  272.     ret
  273. ENDP DoRealint
  274.   
  275. PROC UnDoREALint NEAR
  276.     pusha
  277.     cli
  278.  
  279.     mov     al,[cs:IrqNumber]
  280.     add     al,8
  281.     cbw
  282.     shl     ax,2
  283.     mov     bx,ax
  284.  
  285.     push    es
  286.     sub     ax,ax
  287.     mov     es,ax
  288.     mov     ax,[WORD LOW  cs:OldInt]              
  289.     mov     [es:bx],ax
  290.     mov     ax,[WORD HIGH cs:OldInt]              
  291.     mov     [es:bx+2],ax
  292.     pop     es
  293.  
  294.     mov     cl,[cs:IrqNumber]
  295.     mov     ah,1
  296.     shl     ah,cl
  297.     in      al,21h                  ; port 21h, 8259-1 int IMR
  298.     or      al,ah
  299.     out     21h,al                  ; port 21h, 8259-1 int comands
  300.  
  301.     sti
  302.     popa
  303.     ret
  304. ENDP UnDoREALint
  305.  
  306.     ;Figgures the DMA buffer info
  307. PROC CalcForDMA NEAR
  308.     pushad
  309.     push    ds
  310.  
  311.     mov     ax,cs
  312.     mov     ds,ax
  313.     
  314.     mov     [2 + DMA.Next],0          ;assume we do only 1 buffer
  315.     
  316.     movzx   eax,[SampleSeg]
  317.     movzx   edx,[SampleOff]
  318.     call    MakePage
  319.     
  320.     cmp     cx,[SamLength]          ;is max less than needed?
  321.     jb      Skiplengthset           ;yes, must do 2 buffers
  322.  
  323.     mov     cx,[SamLength]
  324.     mov     [2 + DMA.NEXT],2
  325.     jmp     NoMore
  326.  
  327. Skiplengthset:
  328.     mov     bx,[SamLength]
  329.     sub     bx,cx
  330.     sub     bx,2
  331.     mov     [2 + DMA.Length],bx
  332.     mov     [2 + DMA.Offset],0
  333.     mov     [2 + DMA.Page],ax
  334.     inc     [2 + DMA.Page]
  335.  
  336. NoMore:
  337.     mov     [DMA.Page],ax
  338.     mov     [DMA.Offset],dx
  339.     sub     cx,2
  340.     mov     [DMA.Length],cx
  341.  
  342.     pop     ds
  343.     popad
  344.     ret
  345. ENDP CalcForDMA
  346.  
  347.     ;input: eax=segment
  348.     ;       edx=offset
  349.     ;output: ax=page
  350.     ;        dx=offset
  351.     ;        cx=MAX_LENGTH
  352. PROC MakePage NEAR 
  353.     shl     eax,4
  354.     add     edx,eax         ;edx = 32bit absolute address
  355.     
  356.     ror     edx,16
  357.     mov     al,dl           ;ax= page
  358.     xor     ah,ah
  359.     ror     edx,16
  360.  
  361.     mov     cx,dx
  362.     neg     cx
  363.     ret
  364. ENDP MakePage
  365.  
  366.     ;al = selection#, ah= value
  367. PROC SetMixer NEAR
  368.     push    ax dx
  369.     mov     dx,224h
  370.     out     dx,al
  371.     inc     dx
  372.  
  373.     jmp     $+2
  374.     jmp     $+2
  375.  
  376.     mov     al,ah
  377.     out     dx,al
  378.     pop     dx ax
  379.     ret
  380. ENDP SetMixer
  381.  
  382.   ; returns -1 if load not successful
  383. PROC  LoadSample NEAR
  384.     pusha
  385.     push    ds
  386.  
  387.     mov     ax,cs
  388.     mov     ds,ax
  389.     mov     dx,offset FileName
  390.     mov     ax,3D00h        ;open the file
  391.     int     21h
  392.     jc      @@Error
  393.  
  394.     mov     bx,ax
  395.     xor     dx,dx             ;load at offset 0
  396.     mov     cx,0ffffh         ;read in a whole segments worth
  397.     mov     ds,[cs:SampleSeg]
  398.     mov     ax,3F00h          ; Load in the sample
  399.     int     21h
  400.  
  401.     mov     [cs:SamLength],ax
  402.  
  403.     mov     ax,3E00h          ;close the file
  404.     int     21h
  405.  
  406.     ;now fix the sam so it's playable on a SB & make one channel play forward
  407.     ; and one in reverse - doesn't do it perfectly
  408.  
  409.     push    es
  410.     mov     es,[cs:SampleSeg2]
  411.  
  412.     mov     si,0
  413.     mov     bp,0
  414.     mov     cx,[cs:SamLength]
  415.     add     [cs:SamLength],cx
  416.     mov     di,[cs:SamLength]
  417.     dec     di
  418.     cld
  419. FixItLoop:
  420.     mov     al,[ds:si]
  421.     inc     si
  422.     add     al,128
  423.     mov     [es:bp],al
  424.     mov     [es:di],al
  425.     sub     di,2
  426.     add     bp,2
  427.  
  428.     loop    FixItLoop
  429.  
  430.     mov     [cs:SampleSeg],es
  431.     pop     es
  432.  
  433.     pop     ds
  434.     popa
  435.     xor     ax,ax
  436.     ret
  437.  
  438. @@Error:
  439.     pop     ds
  440.     popa
  441.     mov     ax,-1
  442.     ret
  443. ENDP  LoadSample
  444.  
  445. ────────────────────────────────────────────────────────────────────────────
  446.  
  447. START:
  448.     mov   ax,cs
  449.     mov   ds,ax
  450.     mov   es,ax
  451.  
  452.     mov   bx,ss
  453.     add   bx,20h            ;put sample right after stack
  454.     mov   [SampleSeg],bx
  455.     add   bx,1000h
  456.     mov   [SampleSeg2],bx
  457.  
  458.     call  LoadSample
  459.     call  CalcForDMA
  460.     call  DspReset
  461.  
  462.     mov   ah, 256- 1000000/16000  ; 256- 1000000/ HZ
  463.     call  SetTimeConstant
  464.  
  465.     mov   ax,0130eh
  466.     call  SetMixer      ;turn stereo ON
  467.     mov   ax,0FF22h
  468.     call  SetMixer      ;set master volume to R= 0Fh, L= 0Fh
  469.     mov   ax,0FF04h
  470.     call  SetMixer      ;set VOC volume to R= 0Fh, L= 0Fh
  471.  
  472.     call  TurnOnSpeaker
  473.     call  StartTransferDMA
  474.     
  475.     mov   ah,0
  476.     int   16h               ;get keypress
  477.     
  478.     mov   ax,0110eh
  479.     call  SetMixer      ;turn stereo OFF
  480.  
  481.     call  HaltDMA
  482.     call  TurnOffSpeaker
  483.     call  DSPReset
  484.     call  UnDoRealInt
  485.  
  486.     mov   ax,4c00h
  487.     int   21h
  488.  
  489. END START
  490.