sfx.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* Sound effects system- PLAY, SFX, and bkground code */
  22. #include "meminter.h"
  23. #include <_null.h>
  24. #include "mod.h"
  25. #include "sfx.h"
  26. #include "data.h"
  27. #include <dos.h>
  28. #include "string.h"
  29. int note_freq[12]={//Frequencies of 6C thru 6B
  30. 2032,2152,2280,2416,2560,2712,2880,3048,3232,3424,3624,3840 };
  31. int sam_freq[12]={//Sample frequencies of 0C (C-~1) thru 0B (B-~1)
  32. 3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812 };
  33. noise far background[NOISEMAX]; //The sound queue itself
  34. int topindex=0; //Marks the top of the queue
  35. int backduration=0; //Keeps track of duration of sound
  36. int backindex=0; //Marks bottom of queue
  37. int sound_in_queue=0; //Tells if sound in queue
  38. void play_sfx(int sfxn) {
  39. if(sfxn>=NUM_SFX) return;
  40. if(custom_sfx_on) play_str(&custom_sfx[sfxn*69],1);
  41. else play_str(sfx_strs[sfxn],1);
  42. }
  43. //sfx_play=1 to NOT play non-digi unless queue empty
  44. void play_str(unsigned char far *str,char sfx_play) {
  45. int t1,oct=3,note=1,dur=18,t2,last_note=-1,digi_st=-1,digi_end;
  46. unsigned char chr;
  47. char nn[7]={ 10,12,1,3,5,6,8 };//Note trans. table from 1-7 (a-z) to 1-12
  48. if(!sfx_on) sfx_play=1;//SFX off
  49. else if(!sound_in_queue) sfx_play=0;
  50. //Now, if sfx_play, only play digi
  51. for(t1=0;t1<str_len(str);t1++) {
  52. chr=str[t1];
  53. if((chr>='a')&&(chr<='z')) chr-=32;
  54. if(chr=='-') {//Octave down
  55. if(oct>0) oct--;
  56. continue;
  57. }
  58. if(chr=='+') {//Octave up
  59. if(oct<6) oct++;
  60. continue;
  61. }
  62. if(chr=='X') {//Rest
  63. if(!sfx_play) submit_sound(F_REST,dur);
  64. continue;
  65. }
  66. if((chr>47)&&(chr<55)) oct=chr-48;//Set octave
  67. if(chr=='.') dur+=(dur>>1);//Dot (duration 150%)
  68. if(chr=='!') dur/=3;//Triplet (cut duration to 33%)
  69. if((chr>64)&&(chr<72)) {//Note
  70. note=nn[chr-65];//Convert to 1-12
  71. t2=oct;//Save old octave in case # or $ changes it
  72. if(str[t1+1]=='#') {//Increase if sharp
  73. t1++;
  74. if(++note==13) {//"B#":="+C-"
  75. note=1;
  76. if(++oct==7) oct=6;
  77. }
  78. }
  79. else if(str[t1+1]=='$') {//Decrease if flat
  80. t1++;
  81. if(--note==0) {//"C$":="-B+"
  82. note=12;
  83. if(--oct==-1) oct=0;
  84. }
  85. }
  86. //Digi
  87. if(digi_st>0) {
  88. str[digi_end]=0;
  89. play_sample(sam_freq[note-1]>>oct,&str[digi_st]);
  90. str[digi_end]='&';
  91. }
  92. else if(sfx_play) continue;
  93. else if(last_note==note) {
  94. if(dur<=9) {
  95. submit_sound(F_REST,1);
  96. play_note(note,oct,dur-1);
  97. }
  98. else {
  99. submit_sound(F_REST,2);
  100. play_note(note,oct,dur-2);
  101. }
  102. }
  103. else {
  104. play_note(note,oct,dur);
  105. last_note=note;
  106. }
  107. oct=t2;//Restore old octave
  108. }
  109. if(chr=='Z') dur=9;//64th notes
  110. if(chr=='T') dur=18;//32nd notes (default)
  111. if(chr=='S') dur=36;//16th
  112. if(chr=='I') dur=72;//8th
  113. if(chr=='Q') dur=144;//1/4
  114. if(chr=='H') dur=288;//1/2
  115. if(chr=='W') dur=576;//Whole
  116. if(chr=='&') {
  117. //Digitized
  118. digi_st=++t1;
  119. if(str[t1]==0) break;
  120. do {
  121. if(str[++t1]==0) break;
  122. if(str[t1]=='&') break;
  123. } while(1);
  124. if(str[t1]==0) break;
  125. digi_end=t1;
  126. }
  127. if(chr=='_') {
  128. digi_st=-1;
  129. if((music_on)&&(music_device<6)) break;
  130. }
  131. }
  132. }
  133. void clear_sfx_queue(void) {
  134. backindex=topindex=sound_in_queue=0;//queue pointers
  135. nosound();
  136. }
  137. void play_note(char note,char octave,int delay) {
  138. //Note is # 1-12
  139. //Octave #0-6
  140. submit_sound(note_freq[note-1]>>(6-octave),delay);
  141. }
  142. void submit_sound(int freq,int delay) {
  143. if((backindex==0)&&(topindex==NOISEMAX)) return;
  144. if(topindex!=(backindex-1)) {//Queue full?
  145. background[topindex].freq=freq;//No, put it in queue
  146. background[topindex++].duration=delay;
  147. if(topindex==NOISEMAX)
  148. topindex=0;//Wraparound
  149. sound_in_queue=1;//Note sound in queue
  150. }
  151. }
  152. void sound_system(void) {
  153. if(backduration) backduration--;//Sound is in progress
  154. else {
  155. if(sound_in_queue) {//Current sound finished, more?
  156. backduration=background[backindex].duration;//Yes, setup
  157. if(background[backindex].freq==F_REST) {
  158. if(sfx_on) nosound();//freq==1 for rest
  159. }
  160. else if(sfx_on) sound(background[backindex].freq);//Start sound
  161. backindex++;
  162. if(backindex==NOISEMAX)
  163. backindex=0;//Wraparound
  164. if(backindex==topindex)//If last sound reset queue pointers
  165. backindex=topindex=sound_in_queue=0;
  166. }
  167. else if(sfx_on) nosound();
  168. }
  169. }
  170. unsigned char far *sfx_strs[NUM_SFX]={
  171. "5c-gec-gec", // Gem
  172. "5c-gec-gec", // Magic Gem
  173. "cge-zcge", // Health
  174. "-c+c+c-g-g-g", // Ammo
  175. "6a#a#zx", // Coin
  176. "-cegeg+c-g+cecegeg+c", // Life
  177. "-cc#dd#e", // Lo Bomb
  178. "cc#dd#e", // Hi Bomb
  179. "4gec-g+ec-ge+c-gec", // Key
  180. "-gc#-a#a", // Full Keys
  181. "ceg+c-eg+ce-g+ceg", // Unlock
  182. "s1a#z+a#-a#x", // Can't Unlock
  183. "-a-a+e-e+c-c", // Invis. Wall
  184. "zax", // Forest
  185. "0a#+a#-a#b+b-b", // Gate Locked
  186. "0a+a-a+a-a", // Opening Gate
  187. "-g+g-g+g+g-g+g-g-g+g-g-tg+g", // Invinco Start
  188. "sc-cqxsg-g+a#-a#xx+g-g+a#-a#", // Invinco Beat
  189. "sc-cqxsg-g+f-f+d#-d#+c-ca#-a#2c-c", // Invinco End
  190. "0g+g-gd#+d#-d#",//19-Door locked
  191. "0g+gd#+d#",//Door opening
  192. "c-zgd#c-gd#c",//Hurt
  193. "a#e-a#e-a#e-a#e",//AUGH!
  194. "+c-gd#cd#c-gd#gd#c-g+c-gd#cd#c-gd#gd#c",//Death
  195. "ic1c+ca#+c1c+cx+d#1c+ca#+c1c+cx"
  196. "+c1c+ca#+c1c+cx+d#1c+c+fc1c+cx", //Game over
  197. "0c+c-c+c-c", //25-Gate closing
  198. "1d#x", //26-Push
  199. "2c+c+c2d#+d#+d#2g+g+g3cd#g", //27-Transport
  200. "z+c-c",// 28-shoot
  201. "1a+a+a", //29-break
  202. "-af#-f#a", //30-out of ammo
  203. "+f#", //31-ricochet
  204. "s-d-d-d", //32-out of bombs
  205. "c-aec-a",//33-place bomb (lo)
  206. "+c-aec-a",//34-place bomb (hi)
  207. "+g-ege-ege",//35-switch bomb type
  208. "1c+c0d#+d#-g+g-c#",//36-explosion
  209. "2cg+e+c2c#g#+f+c#2da+f#+d2d#a#+g+d#",//37-Entrance
  210. "cge+c-g+ecge+c-g+ec",//38-Pouch
  211. "zcd#gd#cd#gd#cd#gd#cd#gd#"
  212. "cfg#fcfg#fcfg#fcfg#f"
  213. "cga#gcga#gcga#gcga#g"
  214. "s+c",//39-ring/potion
  215. "z-a-a-aa-aa",//40-Empty chest
  216. "1c+c-c#+c#-d+d-d#+d#-e+e-ec",//41-Chest
  217. "c-gd#c-zd#gd#c",//42-Out of time
  218. "zc-d#g-cd#",//43-Fire ouch
  219. "cd#g+cd#g",//44-Stolen gem
  220. "z1d#+d#+d#",//45-Enemy HP down
  221. "z0ca#f+d#cf#",//46-Dragon fire
  222. "cg+c-eda+d-f#eb+e-g#",//47-Scroll/sign
  223. "1c+c+c+c+c",//48-Goop
  224. "" };//49-Unused
  225. unsigned char far *custom_sfx=NULL;
  226. char custom_sfx_on=0;//1 to turn on custom sfx
  227. char sfx_init(void) {
  228. custom_sfx=(unsigned char *)farmalloc(NUM_SFX*69);
  229. if(custom_sfx==NULL) return 1;
  230. return 0;
  231. }
  232. void sfx_exit(void) {
  233. if(custom_sfx!=NULL) farfree(custom_sfx);
  234. custom_sfx=NULL;
  235. }
  236. char is_playing(void) {
  237. return sound_in_queue;
  238. }