home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sound / newbeep / newbeep.asm next >
Assembly Source File  |  1992-03-20  |  11KB  |  265 lines

  1. ;--------------------------------------------------------------------------
  2. ; NEWBEEP.ASM  --  redirect DOS's standard BEL to the SoundBlaster FM chips
  3. ; ver 1.2  (Wednesday March 6, 1992)
  4. ;--------------------------------------------------------------------------
  5. ; Copyright (C) 1992, Heath I. Hunnicutt
  6. ; This document may be freely distributed if no fee is assigned and the
  7. ; document including this notice is unaltered.
  8. ;--------------------------------------------------------------------------
  9. ; By: heathh@tybalt.cco.caltech.edu -or- @cco.caltech.edu  (preferred acct)
  10. ;     aka hihunn@through.ugcs.caltech.edu  (NOT preferred)
  11. ;--------------------------------------------------------------------------
  12. ; Requires: SoundBlaster sound card or compatible,
  13. ;           Turbo Assembler from Borland
  14. ;--------------------------------------------------------------------------
  15. ; Assumes: I/O address of card is based at 0388h.
  16. ;--------------------------------------------------------------------------
  17. ; Acknowledgements: Ralf Brown -- Interrupt List 29a
  18. ;                   Jeffrey S. Lee -- Programming DOCs for SB FM
  19. ;--------------------------------------------------------------------------
  20. ; Legal: SoundBlaster is a trademark of Creative Labs, Inc.
  21. ;        Turbo Assembler is a trademark of Borland International.
  22. ;--------------------------------------------------------------------------
  23. ;History: 1.0 - Initial posting
  24. ;         1.1 - Video call now preserves flags register.
  25. ;         1.2 - Broke code into procedures, hopefully useful to programmers,
  26. ;               used different default I/O address.  (388h, not 220h)
  27. ;               Also, checks for presence of card first!  ;)
  28. ;               Plus, more melodious beep!
  29. ;               Entirely revamped delay handling!  Now beeps decay!
  30. ;--------------------------------------------------------------------------
  31.  
  32.                 IDEAL           ;Depends on TASM's truly ideal mode
  33.                 MODEL small
  34.  
  35. SB_Port EQU 0388h               ;Base I/O address of card
  36. FM_Reg  EQU 0388h               ;More descriptive constants
  37. FM_Data EQU 0389h
  38.  
  39. Delay   EQU 36                  ;Length of beep (18 = 1sec)
  40.  
  41. Modulation_FM  EQU 0            ;Constants regarding how to
  42. Modulation_Add EQU 1            ;modulate components
  43.  
  44.                 CODESEG         ;No DATASEG or STACK for TSRs.
  45. Begin:
  46.  
  47. ;Concept: Hook the BIOS video interrupt and watch for BEL characters
  48. ;         being output.
  49. ;         Hook the clock tick to time note durations.
  50.  
  51. OldVideo DD 0   ;Store address of previous Video BIOS routine
  52. OldClock DD 0   ;Store address of previous Clock tick handler
  53. TimeLeft DW 0   ;Count of how many ticks note has left to live
  54.  
  55. Codes   DB 01h,20h      ;Waveform select
  56.         DB 20h,81h      ;No Amplitude modultation / No vibrato
  57.                         ;Sustain until released / No KYB Scaling?
  58.                         ;Operator one octave below voice
  59.         DB 23h,81h
  60.         DB 40h,10h      ;No quieter with high frequency / 12dB attenuated
  61.         DB 43h,00h
  62.         DB 60h,0F3h     ;Fastest attack / Slowest Decay
  63.         DB 63h,0F3h
  64.         DB 80h,077h      ;Sustain level:21 / Release level:21 (?)
  65.         DB 83h,07Bh
  66. ;Feedback Algorithm and Modulation Technique
  67. ;Reg= (Feedback (0-7) SHL 1) OR Mod_Technique
  68.         DB 0C0h,(0h OR Modulation_FM)          ;Channel 1
  69.  
  70.         DB 0A0h,98h     ;Freq MSB.  Will be 4D#
  71.         DB 0B0h,31h     ;Note: D# / Octave: 4 / Voice ON
  72.         DB 0FFh,0FFh    ;END OF CODES
  73.  
  74. ;Above values will be sent to IO address in sequence.
  75. ;Example: Register 20h will be loaded with 81h, 0B0h with 31h
  76. ;Based on Jeffrey S. Lee's programming documentation.
  77.  
  78.  
  79. PROC NewVideo
  80. ;----------------------------------------------------------
  81. ;This procedure will become the new video BIOS call handler
  82. ;----------------------------------------------------------
  83.         pushf                           ;Preserve flags through cmp
  84.         cmp ax,0E07h                    ;Is function displaying BEL character?
  85.           je Handle_This                ; y: Jump to our BEL code
  86.         popf                            ; n: Restore original flags...
  87.         jmp [DWORD PTR cs:OldVideo]     ;    ...Pass function on to BIOS
  88. Handle_This:
  89.         call _FM_Beep C, OFFSET Codes, SEG Codes
  90.                                         ;Doin' da Beep...
  91.         popf                            ;Restore flags, as if it mattered.
  92.         iret                            ;See ya.
  93. ENDP NewVideo
  94.  
  95. PROC NewClock
  96. ;----------------------------------------------------------
  97. ;This procedure will become the new timer BIOS call handler
  98. ;----------------------------------------------------------
  99.         pushf                           ;Preserve flags
  100.         cmp  [WORD PTR cs:TimeLeft],0   ;Are we counting?
  101.           je @@See_Ya                   ; n: Skip this
  102.         dec  [WORD PTR cs:TimeLeft]     ; y: Count down
  103.          jnz @@See_Ya                   ;Done?
  104.         call _Reset_FM                  ; y: Silence voice
  105. @@See_Ya:
  106.         popf                            ;Restore flags
  107.         jmp  [DWORD PTR cs:OldClock]    ;Pass through to next handler
  108. ENDP NewClock
  109.  
  110. PROC SB_Delay
  111. ;--------------------------------------
  112. ;Delays for cx reads of the status port
  113. ;--------------------------------------
  114.         push ax dx
  115.         mov  dx,FM_Reg
  116.     @@D:
  117.         in   al,dx
  118.         loop @@D
  119.         pop  dx ax
  120.         ret
  121. ENDP SB_Delay
  122.  
  123. PROC _FM_Beep
  124. ARG Params:DWORD
  125. ;------------------------------
  126. ;Produces a tone through the SB
  127. ;Preserves all registers
  128. ;------------------------------
  129.         push bp
  130.         mov  bp,sp
  131.     push cx si ds                        ;Preserve these registers
  132.         call _Reset_FM                  ;Set the card up
  133.         lds  si,[Params]
  134.         cmp  [BYTE PTR si],0FFh         ;At end of list?
  135.           je Done                       ; y: Don't program card
  136. Looper:
  137.         call _Write_FM_Register C, [si], [si+1]
  138.         inc  si                         ;Index to next register/
  139.         inc  si                         ; value pair.
  140.         cmp  [BYTE PTR si],0FFh         ;At end of list?
  141.          jne Looper                     ; n: Repeat
  142.         mov  [TimeLeft],Delay           ; y: Store the number of ticks for
  143.                                         ;       tone
  144. Done:
  145.     pop ds si cx                        ;Restore those precious registers
  146.         pop  bp
  147.         ret
  148. ENDP _FM_Beep
  149.  
  150. PROC _Reset_FM
  151. ;--------------------------------------------------------------------
  152. ;Writes zeros to all FM registers, resetting chips (turns off sound.)
  153. ;--------------------------------------------------------------------
  154.         push cx                         ;Preserve cx
  155.         mov  cx,0ffh                    ;cx holds current register number
  156. Next_Reg:
  157.         call _Write_FM_Register C, cx, 0
  158.         loop Next_Reg                   ;Continue until cx = 0
  159.         pop  cx                         ;Restore cx
  160.         ret                             ;then return
  161. ENDP _Reset_FM
  162.  
  163. ;void Write_FM_Register(int Reg, int Value)
  164. PROC _Write_FM_Register
  165. ARG Reg:Word,Value:Word
  166. ;------------------------------------------------------------
  167. ;Writes a given value to a given register, with proper delays
  168. ;------------------------------------------------------------
  169.         push bp                         ;preserve bp
  170.         mov  bp,sp                      ;Standard Stack frame (for C)
  171.     push ax cx dx                       ;preserve 'em
  172.         mov  dx,FM_Reg
  173.         mov  ax,[Reg]                   ;Register <- reg
  174.         out  dx,al
  175.         mov  cx,6                       ;Let SB 'swallow' that byte
  176.         call SB_Delay
  177.         mov  dx,FM_Data
  178.         mov  ax,[Value]                 ;Data <- Value
  179.         out  dx,al
  180.         mov  cx,35                      ;Pause
  181.         call SB_Delay
  182.     pop  dx cx ax                       ;Restore all regs...
  183.         pop  bp
  184.         ret
  185. ENDP _Write_FM_Register
  186.  
  187. Last:
  188. ;=================================================================
  189. ;Only the code prior to this label (Last) is kept memory resident.
  190. ;=================================================================
  191.  
  192. PROC _ADLib_Installed
  193. ;----------------------------------------------------------------
  194. ;Returns: AX==0 and Carry set if no card detected
  195. ;         AX==-1 and Carry clear if card succesfully detected
  196. ;----------------------------------------------------------------
  197.         call _Reset_FM
  198.         call _Write_FM_Register C, 4, 60h       ;Reset timers
  199.         call _Write_FM_Register C, 4, 80h       ;Enable interrupts
  200.         mov  dx,FM_Reg
  201.         in   al,dx                              ;Read status
  202.         and  al,0E0h                            ;Mask bits
  203.          jnz @@Sorry                            ;Not zero -> fail
  204.         call _Write_FM_Register C, 2, 0FFh      ;Set timer
  205.         call _Write_FM_Register C, 4, 21h       ;Start timer
  206.         mov  cx,14000                           ;SB_Delay 80 usec
  207.         call SB_Delay                           ;Wait for timer to expire
  208.         mov  dx,FM_Reg
  209.         in   al,dx                              ;Read status
  210.         call _Write_FM_Register C, 4, 60h       ;Turn off timers
  211.         call _Write_FM_Register C, 4, 00h       ;Disable interrupts
  212.         and  ax,00E0h                           ;Mask bits
  213.         cmp  al,0C0h                            ;Desired value?
  214.          jne @@Sorry                            ; n: Fail
  215.         mov  ax,-1                              ; y: Return(-1)
  216.         clc                                     ;  Clear carry
  217.         ret
  218. @@Sorry:
  219.         xor  ax,ax                              ;Return(0)
  220.         stc                                     ;Set carry
  221.         ret
  222. ENDP _ADLib_Installed
  223.  
  224. No_Card DB "Good job, dude, but you don't have a sound card.",10,13,"$"
  225. Ok      DB "NEWBEEP installed in memory.",10,13,"$"
  226.  
  227. Start:
  228.         mov  ax,cs                      ;Set up segments
  229.         mov  es,ax
  230.         mov  ds,ax
  231.         call _AdLib_Installed           ;Is there a card out there?
  232.          jnc Go_Ahead                   ; y: Continue
  233.         mov  dx,OFFSET No_Card          ; n: Print a message of great
  234.         mov  ah,9                       ;     disappointment
  235.         int  21h
  236.         mov  ax,4C00h                   ;exit(0)
  237.         int  21h
  238. Go_Ahead:
  239.         mov  ax,3510h                   ;Get interrupt vector for Video
  240.         int  21h
  241.         mov  [WORD PTR OldVideo],bx     ;Store it in OldVideo
  242.         mov  ax,es
  243.         mov  [WORD PTR OldVideo+2],ax
  244.         mov  dx,OFFSET NewVideo         ;ds:dx -> NewVideo
  245.         mov  ax,2510h                   ;Set new interrupt vector
  246.         int  21h
  247.  
  248.         mov  ax,3508h                   ;Get interrupt vector for Clock
  249.         int  21h
  250.         mov  [WORD PTR OldClock],bx     ;Store it in OldClock
  251.         mov  ax,es
  252.         mov  [WORD PTR OldClock+2],ax
  253.         mov  dx,OFFSET NewClock         ;ds:dx -> NewClock
  254.         mov  ax,2508h                   ;Set new interrupt vector
  255.         int  21h
  256.  
  257.         mov  dx,OFFSET Ok               ;Print message of great joy
  258.         mov  ah,9
  259.         int  21h
  260.         mov  dx,((Last-Begin)+100h+15)/16      ;Calculate memory size..
  261.         mov  ax,3100h                   ;Termiante Stay Resident
  262.         int  21h
  263. ENDS
  264. END Start                               ;Execution begins at Start: label
  265.