home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / msc / chap_6 / black6.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-13  |  10.6 KB  |  454 lines

  1.  
  2. // BLACK6.C - Library Module
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17.  
  18.  
  19. #include "black6.h"
  20.  
  21. // G L O B A L S  ////////////////////////////////////////////////////////////
  22.  
  23.  
  24.  
  25. // F U N C T I O N S /////////////////////////////////////////////////////////
  26.  
  27. int Sound_Load(char *filename, sound_ptr the_sound,int translate)
  28. {
  29. // this function will load a sound from disk into memory and pre-format
  30. // it in preparation to be played
  31.  
  32. unsigned char far *temp_ptr;   // temporary pointer used to load sound
  33. unsigned char far *sound_ptr;  // pointer to sound data
  34.  
  35. unsigned int segment,          // segment of sound data memory
  36.              paragraphs,       // number of 16 byte paragraphs sound takes up
  37.              bytes_read,       // used to track numbr of bytes read by DOS
  38.              size_of_file,     // the total size of the VOC file in bytes
  39.              header_length;    // the length of the header portion of VOC file
  40.  
  41. int sound_handle;              // DOS file handle
  42.  
  43.  
  44. // open the sound file, use DOS file and memory allocation to make sure
  45. // memory is on a 16 byte or paragraph boundary
  46.  
  47. if (_dos_open(filename, _O_RDONLY, &sound_handle)!=0)
  48.    {
  49.    printf("\nSound System - Couldn't open %s",filename);
  50.    return(0);
  51.  
  52.    } // end if file not found
  53.  
  54. // compute number of paragraphs that sound file needs
  55.  
  56. size_of_file = _filelength(sound_handle);
  57.  
  58. paragraphs = 1 + (size_of_file)/16;
  59.  
  60. // allocate the memory on a paragraph boundary
  61.  
  62. _dos_allocmem(paragraphs,&segment);
  63.  
  64. // point data pointer to allocated data area
  65.  
  66. _FP_SEG(sound_ptr) = segment;
  67. _FP_OFF(sound_ptr) = 0;
  68.  
  69. // alias pointer to memory storage area
  70.  
  71. temp_ptr = sound_ptr;
  72.  
  73. // read in blocks of 16k until file is loaded
  74.  
  75. do
  76.  {
  77.  // load next block
  78.  
  79.  _dos_read(sound_handle,temp_ptr, 0x4000, &bytes_read);
  80.  
  81.  // adjust pointer
  82.  
  83.  temp_ptr += bytes_read;
  84.  
  85.  } while(bytes_read==0x4000);
  86.  
  87. // close the file
  88.  
  89. _dos_close(sound_handle);
  90.  
  91. // make sure it's a voc file, test for "Creative"
  92.  
  93. if ((sound_ptr[0] != 'C') || (sound_ptr[1] != 'r'))
  94.    {
  95.  
  96.    printf("\n%s is not a VOC file!",filename);
  97.  
  98.    // de-allocate the memory
  99.  
  100.    _dos_freemem(_FP_SEG(sound_ptr));
  101.  
  102.    // return failure
  103.  
  104.    return(0);
  105.  
  106.    } // end if voc file
  107.  
  108.    // compute start of sound data;
  109.  
  110.    header_length = (unsigned int)sound_ptr[20];
  111.  
  112.    // point buffer pointer to start of VOC file in memory
  113.  
  114.    the_sound->buffer       = sound_ptr;
  115.  
  116.    // set up the SNDSTRUC for DIGIPAK
  117.  
  118.    the_sound->SS.sound     = (unsigned char far*)(sound_ptr+header_length+4);
  119.  
  120.    the_sound->SS.sndlen    = (unsigned short)(size_of_file - header_length);
  121.  
  122.    the_sound->SS.IsPlaying = (short far *)&the_sound->status;
  123.  
  124.    the_sound->SS.frequency = (short)((long)(-1000000) /
  125.                                 ((int)sound_ptr[header_length+4]-256));
  126.  
  127.    // now format data for sound card if requested
  128.  
  129.    if (translate)
  130.        Sound_Translate(the_sound);
  131.  
  132. // return success
  133.  
  134. return(1);
  135.  
  136. } // end Sound_Load
  137.  
  138. //////////////////////////////////////////////////////////////////////////////
  139.  
  140. void Sound_Unload(sound_ptr the_sound)
  141. {
  142.  
  143. // this functions deletes the sound from memory
  144.  
  145. _dos_freemem(_FP_SEG(the_sound->buffer));
  146.  
  147. the_sound->buffer=NULL;
  148.  
  149. } // end Sound_Unload
  150.  
  151. //////////////////////////////////////////////////////////////////////////////
  152.  
  153. void Sound_Translate(sound_ptr the_sound)
  154. {
  155. // this function calls the DIGIPAK function massage audio to translate
  156. // the raw audio data into the proper format for the sound card that
  157. // the sound system is running on.
  158.  
  159. unsigned char far *buffer;
  160.  
  161. buffer = (unsigned char far*)&the_sound->SS;
  162.  
  163. _asm
  164.    {
  165.    push ds         ; save DS and SI on stack
  166.    push si
  167.    mov ax, 068Ah   ; function 3: MassageAudio
  168.    lds si, buffer  ; move address of sound in DS:SI
  169.    int 66h         ; call DIGIPAK
  170.    pop si          ; restore DS and SI from stack
  171.    pop ds
  172.  
  173.    } // end inline assembly
  174.  
  175. } // end Sound_Translate
  176.  
  177. ///////////////////////////////////////////////////////////////////////////////
  178.  
  179. void Sound_Play(sound_ptr the_sound)
  180. {
  181. // ths function will the sound pointed to in the sent sound structure
  182.  
  183. unsigned char far *buffer;
  184.  
  185. buffer = (unsigned char far*)&the_sound->SS;
  186.  
  187. _asm
  188.    {
  189.    push ds         ; save DS and SI on stack
  190.    push si
  191.    mov ax, 068Bh   ; function 4: DigPlay2
  192.    lds si, buffer  ; move address of sound in DS:SI
  193.    int 66h         ; call DIGIPAK
  194.    pop si          ; restore DS and SI from stack
  195.    pop ds
  196.  
  197.    } // end inline assembly
  198.  
  199. } // end Sound_Play
  200.  
  201. //////////////////////////////////////////////////////////////////////////////
  202.  
  203. int Sound_Status(void)
  204. {
  205. // this function will return the status of DIGIPAK i.e. is a sound playing
  206. // or not
  207.  
  208. _asm
  209.    {
  210.    mov ax, 0689h   ; function 2: SoundStatus
  211.    int 66h         ; call DIGIPAK
  212.  
  213.    } // end inline assembly
  214.  
  215. // on exit AX will be used as the return value, if 1 then a sound is playing
  216. // 0 if a sound is not playing
  217.  
  218. } // end Sound_Status
  219.  
  220. //////////////////////////////////////////////////////////////////////////////
  221.  
  222. void Sound_Stop(void)
  223. {
  224. // this function will stop a currently playing sound
  225.  
  226. _asm
  227.    {
  228.    mov ax, 068Fh   ; function 8: StopSound
  229.    int 66h         ; call DIGIPAK
  230.  
  231.    } // end inline assembly
  232.  
  233. } // end Sound_Stop
  234.  
  235. //////////////////////////////////////////////////////////////////////////////
  236.  
  237. int Music_Load(char *filename, music_ptr the_music)
  238. {
  239. // this function will load a xmidi file from disk into memory and register it
  240.  
  241. unsigned char far *temp_ptr;   // temporary pointer used to load music
  242. unsigned char far *xmidi_ptr;   // pointer to xmidi data
  243.  
  244. unsigned int segment,          // segment of music data memory
  245.              paragraphs,       // number of 16 byte paragraphs music takes up
  246.              bytes_read;       // used to track numbr of bytes read by DOS
  247.  
  248. long         size_of_file;     // the total size of the xmidi file in bytes
  249.  
  250. int xmidi_handle;              // DOS file handle
  251.  
  252. // open the extended xmidi file, use DOS file and memory allocation to make sure
  253. // memory is on a 16 byte or paragraph boundary
  254.  
  255. if (_dos_open(filename, _O_RDONLY, &xmidi_handle)!=0)
  256.    {
  257.    printf("\nMusic System - Couldn't open %s",filename);
  258.    return(0);
  259.  
  260.    } // end if file not found
  261.  
  262. // compute number of paragraphs that sound file needs
  263.  
  264. size_of_file = _filelength(xmidi_handle);
  265.  
  266. paragraphs = 1 + (size_of_file)/16;
  267.  
  268. // allocate the memory on a paragraph boundary
  269.  
  270. _dos_allocmem(paragraphs,&segment);
  271.  
  272. // point data pointer to allocated data area
  273.  
  274. _FP_SEG(xmidi_ptr) = segment;
  275. _FP_OFF(xmidi_ptr) = 0;
  276.  
  277. // alias pointer to memory storage area
  278.  
  279. temp_ptr = xmidi_ptr;
  280.  
  281. // read in blocks of 16k until file is loaded
  282.  
  283. do
  284.  {
  285.  // load next block
  286.  
  287.  _dos_read(xmidi_handle,temp_ptr, 0x4000, &bytes_read);
  288.  
  289.  // adjust pointer
  290.  
  291.  temp_ptr += bytes_read;
  292.  
  293.  } while(bytes_read==0x4000);
  294.  
  295. // close the file
  296.  
  297. _dos_close(xmidi_handle);
  298.  
  299. // set up the music structure
  300.  
  301. the_music->buffer = xmidi_ptr;
  302. the_music->size   = size_of_file;
  303. the_music->status = 0;
  304.  
  305. // now register the xmidi file with MIDIPAK
  306.  
  307. if ((the_music->register_info = Music_Register(the_music))==XMIDI_UNREGISTERED)
  308.    {
  309.    // delete the memory
  310.  
  311.    Music_Unload(the_music);
  312.  
  313.    // return an error
  314.  
  315.    return(0);
  316.  
  317.    } // end if couldn't register xmidi file
  318.  
  319. // else return success
  320.  
  321. return(1);
  322.  
  323. } // end Music_Load
  324.  
  325. /////////////////////////////////////////////////////////////////////////////
  326.  
  327. void Music_Unload(music_ptr the_music)
  328. {
  329.  
  330. // this functions deletes the xmidi file data from memory
  331.  
  332. _dos_freemem(_FP_SEG(the_music->buffer));
  333.  
  334. the_music->buffer=NULL;
  335.  
  336. } // end Music_Unload
  337.  
  338. ///////////////////////////////////////////////////////////////////////////////
  339.  
  340. int Music_Register(music_ptr the_music)
  341. {
  342.  
  343. // this function registers the xmidi music with MIDIPAK, so that it can be
  344. // played
  345.  
  346. unsigned int xmid_off,   // offset and segment of midi file
  347.              xmid_seg,
  348.              length_low, // length of midi file in bytes
  349.              length_hi;
  350.  
  351. // extract segment and offset of music buffer
  352.  
  353. xmid_off = _FP_OFF((the_music->buffer));
  354. xmid_seg = _FP_SEG((the_music->buffer));
  355.  
  356. // extract the low word and high word of xmidi file length
  357.  
  358. length_low = the_music->size;
  359. length_hi  = (the_music->size) >> 16;
  360.  
  361. // call MIDIPAK
  362.  
  363. _asm
  364.    {
  365.    push si           ; save si and di
  366.    push di
  367.  
  368.    mov ax,704h       ; function #5: RegisterXmidi
  369.  
  370.    mov bx,xmid_off   ; offset of xmidi data
  371.  
  372.    mov cx,xmid_seg   ; segment of xmidi data
  373.  
  374.    mov si,length_low ; low word of xmidi length
  375.    mov di,length_hi  ; hi word of xmidi length
  376.  
  377.    int 66h           ; call MIDIPAK
  378.    pop di            ; restore si and di
  379.    pop si
  380.  
  381.    } // end inline assembly
  382.  
  383. // return value will be in AX
  384.  
  385. } // end Music_Register
  386.  
  387. ///////////////////////////////////////////////////////////////////////////////
  388.  
  389. void Music_Stop(void)
  390. {
  391. // this function will stop the song currently playing
  392.  
  393. _asm
  394.    {
  395.    mov ax,705h    ; function #6: MidiStop
  396.    int 66h        ; call MIDIPAK
  397.  
  398.    } // end inline assembly
  399.  
  400. } // end Music_Stop
  401.  
  402. ///////////////////////////////////////////////////////////////////////////////
  403.  
  404. int Music_Play(music_ptr the_music,int sequence)
  405. {
  406. // this function plays a xmidi file from memory
  407.  
  408. _asm
  409.    {
  410.    mov ax,702h        ; function #3: PlaySequence
  411.    mov bx, sequence   ; which sequence to play 0,1,2....
  412.    int 66h            ; call MIDIPAK
  413.  
  414.    } // end inline assembly
  415.  
  416. // return value is in AX, 1 success, 0 sequence not available
  417.  
  418. } // end Music_Play
  419.  
  420. ///////////////////////////////////////////////////////////////////////////////
  421.  
  422. void Music_Resume(void)
  423. {
  424. // this function resumes a previously stopped xmidi sequence
  425.  
  426. _asm
  427.    {
  428.    mov ax,70Bh        ; function #12: ResumePlaying
  429.    int 66h            ; call MIDIPAK
  430.  
  431.    } // end inline assembly
  432.  
  433. } // end Music_Resume
  434.  
  435. ///////////////////////////////////////////////////////////////////////////////
  436.  
  437. int Music_Status(void)
  438. {
  439. // this function returns the status of a playing sequence
  440.  
  441. _asm
  442.    {
  443.    mov ax,70Ch        ; function #13: SequenceStatus
  444.    int 66h            ; call MIDIPAK
  445.  
  446.    } // end inline assembly
  447.  
  448. // return value is in AX
  449.  
  450. } // end Music_Status
  451.  
  452. ///////////////////////////////////////////////////////////////////////////////
  453.  
  454.