home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1991 / 08 / ballgame.c next >
Text File  |  1991-01-04  |  5KB  |  211 lines

  1. [[Code Box]]
  2. [[BALLGAME.C, COMPLETE LISTING, INCLUDE MAGNET LOGO]]
  3.  
  4.  
  5.  
  6. #include <conio.h>
  7. #include <dos.h>
  8.  
  9. /* The following are the frequencies for each note.  An S following the note
  10.    means that the note is a sharp (#). */
  11. #define S     0.0 /* Silence */
  12. #define C1  261.63
  13. #define CS1 277.18
  14. #define D1  293.66
  15. #define DS1 311.13
  16. #define E1  329.63
  17. #define F1  349.23
  18. #define FS1 369.99
  19. #define G1  392.0
  20. #define GS1 415.3
  21. #define A1  440.0
  22. #define AS1 466.16
  23. #define B1  493.88
  24. #define C2  523.25
  25. #define CS2 554.37
  26. #define D2  587.33
  27. #define DS2 622.25
  28. #define E2  659.26
  29. #define F2  698.46
  30. #define FS2 739.99
  31. #define G2  783.99
  32. #define GS2 830.61
  33. #define A2  880.0
  34. #define AS2 932.33
  35. #define B2  987.77
  36.  
  37. /* The following are the durations of the notes.  To make the song go faster,
  38.    make the definition of E smaller.  To make the song go slower, make the
  39.    definition of E larger.  A P in the second position of the name means that
  40.    this note is half again as large as the one preceding it. */
  41. #define E  0.125    // Eighth note
  42. #define EP (E*1.5)  // dotted 8th 
  43. #define Q  (E*2.0)  // quarter note
  44. #define QP (E*3.0)  // dotted quarter
  45. #define H  (Q*2.0)  // half note
  46. #define HP (Q*3.0)  // dotted half
  47. #define W  (H*2.0)  // whole note
  48. #define WP (H*3.0)  // dotted whole
  49.  
  50. /* The following define the duration of each note (or conversely, the amount
  51.    of silence between notes. */
  52. #define LEGATO  1.0
  53. #define NORMAL  0.875
  54. #define STACCATO 0.75
  55.  
  56. /* Changing this definition changes the duration of the notes for the entire
  57.    song. */
  58. #define NOTE_DUR NORMAL
  59.  
  60. /* How much must we speed up the timer.  The value works fine for the tempo
  61.    I've defined here.  If you play a faster song, you might consider
  62.    increasing this value. */
  63. #define CLOCK_INC 4
  64.  
  65. #define NUM_NOTES 61
  66. static double notes[NUM_NOTES] =
  67.     {
  68. C1, C2, A1, G1, E1, G1, D1,
  69. C1, C2, A1, G1, E1, G1, GS1,
  70. A1, GS1, A1, E1, F1, G1, A1, F1, D1,
  71. A1, A1, A1, B1, C2, D2, B1, A1, G1, F1, D1,
  72. C1, C2, A1, G1, E1, G1, D1,
  73. C1, D1, E1, F1, G1, A1, A1, B1,
  74. C2, C2, C2, B1, A1, G1, FS1, G1, A1, B1, C2
  75.     };
  76. static double sizes[NUM_NOTES] =
  77.     {
  78. H, Q, Q, Q, Q, HP, HP,
  79. H, Q, Q, Q, Q, W, Q,
  80. Q, Q, Q, Q, Q, Q, H, Q, HP,
  81. H, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q,
  82. H, Q, Q, Q, Q, HP, HP,
  83. H, Q, Q, Q, Q, W, Q, Q,
  84. HP, HP, Q, Q, Q, Q, Q, Q, HP, HP, W
  85.     };
  86.  
  87. volatile long click = 0;
  88. void (interrupt far *orig_int)(void);  /* function pointer to the original interrupt
  89. */
  90.  
  91. void init_clock(void);
  92. void reset_clock(void);
  93. void sleep(double how_long);
  94. void sound(double freq, double duration);
  95.  
  96. void main(void)
  97.     {
  98.     int i;
  99.  
  100.     init_clock();
  101.     for(i = 0; i < NUM_NOTES; i++)
  102.         sound(notes[i], sizes[i]);
  103.     reset_clock();
  104.     }
  105.  
  106. void interrupt far new_int(void)
  107.     {
  108.     if((++click % CLOCK_INC) == 0)
  109.         (*orig_int)();
  110.     outp(0x20, 0x20);
  111.     }
  112.  
  113. void init_clock(void)
  114.     {
  115.     /*
  116.          Increase the 8253 timer's channel 0 output by a factor of CLOCK_INC.
  117.     */
  118.  
  119.     union
  120.         {
  121.         long divisor;
  122.         unsigned char c[2];
  123.         } count;
  124.  
  125.     /* Install the new interrupt routine. */
  126.  
  127.     orig_int = _dos_getvect(0x08);
  128.     _dos_setvect(0x08, new_int);
  129.  
  130.     /* Increase the timer speed. */
  131.     count.divisor = (long)65536 / CLOCK_INC;
  132.     outp(0x43, 0x36);  /* tell 8253 that count is coming */
  133.     outp(0x40, count.c[0]);  /* send low-order byte */
  134.     outp(0x40, count.c[1]);  /* send high-order byte */
  135.     }
  136.  
  137. void reset_clock(void)
  138.     {
  139. /*
  140.      Return clock to it's original speed.
  141. */
  142.  
  143. /* Reinstall the old interrupt routine. */
  144.     _dos_setvect(0x08, orig_int);
  145.  
  146.     /* Slow down the clock. */
  147.     outp(0x43, 0x36);  /* tell 8253 that count is coming */
  148.     outp(0x40, (char)0);  /* send low-order byte */
  149.     outp(0x40, (char)0);  /* send high-order byte */
  150.     }
  151.  
  152. void sleep(double how_long)
  153.     {
  154.     long i,
  155.          orig,
  156.          new;
  157.  
  158.     orig = click;
  159.     i = (long)((how_long * (18.2 * CLOCK_INC)) + orig);
  160.     new = click;
  161.     while(new < i)
  162.         new = click;
  163.     }
  164.  
  165. void sound(double freq, double duration)
  166.     {
  167.     /*
  168.         Beep the speaker using the specified frequency.
  169.     */
  170.  
  171.     double off,
  172.            play;
  173.     union
  174.         {
  175.         long divisor;
  176.         unsigned char c[2];
  177.         } count;
  178.     int p;
  179.  
  180.     play = duration * NOTE_DUR;
  181.     off = duration - play;
  182.  
  183.     if(freq != S)
  184.         count.divisor = (long)(1193180 / freq);  /* compute the proper count */
  185.     else
  186.         count.divisor = 0;
  187.     outp(0x43, 0xb6);  /* tell 8253 that count is coming */
  188.     outp(0x42, count.c[0]);  /* send low-order byte */
  189.     outp(0x42, count.c[1]);  /* send high-order byte */
  190.     p = inp(0x61);  /* get existing bit pattern */
  191.     if(freq != S)
  192.         outp(0x61, p | 3);  /* turn on bits 0 and 1 */
  193.     else
  194.         outp(0x61, p);
  195.  
  196.     sleep(play);
  197.  
  198.     outp(0x61, p);  /* restore original bits to turn off speaker */
  199.  
  200.     sleep(off);
  201.     }
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211. Figure D: Executing this program will play "Take Me Out to the Ball Game". To play music on a PC the 8253 timer chip must be reprogrammed; BALLGAME causes it to run four times faster than normal. However, it is written so as not to affect the time-of-day clock.