Improved Glulxercise test program
[projects/chimara/chimara.git] / interpreters / frotz / sound.c
1 /* sound.c - Sound effect function
2  *      Copyright (c) 1995-1997 Stefan Jokisch
3  *
4  * This file is part of Frotz.
5  *
6  * Frotz is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Frotz is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include "frotz.h"
22
23 #ifdef DJGPP
24 #include "djfrotz.h"
25 #endif
26
27 #define EFFECT_PREPARE 1
28 #define EFFECT_PLAY 2
29 #define EFFECT_STOP 3
30 #define EFFECT_FINISH_WITH 4
31
32 extern int direct_call (zword);
33
34 static zword routine = 0;
35
36 static int next_sample = 0;
37 static int next_volume = 0;
38
39 static bool locked = FALSE;
40 static bool playing = FALSE;
41
42 /*
43  * init_sound
44  *
45  * Initialize sound variables.
46  *
47  */
48
49 void init_sound (void)
50 {
51     locked = FALSE;
52     playing = FALSE;
53 } /* init_sound */
54
55
56 /*
57  * start_sample
58  *
59  * Call the IO interface to play a sample.
60  *
61  */
62
63 static void start_sample (int number, int volume, int repeats, zword eos)
64 {
65
66     static zbyte lh_repeats[] = {
67         0x00, 0x00, 0x00, 0x01, 0xff,
68         0x00, 0x01, 0x01, 0x01, 0x01,
69         0xff, 0x01, 0x01, 0xff, 0x00,
70         0xff, 0xff, 0xff, 0xff, 0xff
71     };
72
73     if (story_id == LURKING_HORROR)
74         repeats = lh_repeats[number];
75
76     os_start_sample (number, volume, repeats, eos);
77
78     routine = eos;
79     playing = TRUE;
80
81 }/* start_sample */
82
83 /*
84  * start_next_sample
85  *
86  * Play a sample that has been delayed until the previous sound effect has
87  * finished.  This is necessary for two samples in The Lurking Horror that
88  * immediately follow other samples.
89  *
90  */
91
92 static void start_next_sample (void)
93 {
94
95     if (next_sample != 0)
96         start_sample (next_sample, next_volume, 0, 0);
97
98     next_sample = 0;
99     next_volume = 0;
100
101 }/* start_next_sample */
102
103 /*
104  * end_of_sound
105  *
106  * Call the Z-code routine which was given as the last parameter of
107  * a sound_effect call. This function may be called from a hardware
108  * interrupt (which requires extremely careful programming).
109  *
110  */
111
112 void end_of_sound (void)
113 {
114
115 #if defined(DJGPP) && defined(SOUND_SUPPORT)
116     end_of_sound_flag = 0;
117 #endif
118
119     playing = FALSE;
120
121     if (!locked) {
122
123         if (story_id == LURKING_HORROR)
124             start_next_sample ();
125
126         direct_call (routine);
127
128     }
129
130 }/* end_of_sound */
131
132 /*
133  * z_sound_effect, load / play / stop / discard a sound effect.
134  *
135  *      zargs[0] = number of bleep (1 or 2) or sample
136  *      zargs[1] = operation to perform (samples only)
137  *      zargs[2] = repeats and volume (play sample only)
138  *      zargs[3] = end-of-sound routine (play sample only, optional)
139  *
140  * Note: Volumes range from 1 to 8, volume 255 is the default volume.
141  *       Repeats are stored in the high byte, 255 is infinite loop.
142  *
143  */
144
145 void z_sound_effect (void)
146 {
147     zword number = zargs[0];
148     zword effect = zargs[1];
149     zword volume = zargs[2];
150
151     /* By default play sound 1 at volume 8 */
152     if (zargc < 1)
153         number = 1;
154     if (zargc < 2)
155         effect = EFFECT_PLAY;
156     if (zargc < 3)
157         volume = 8;
158
159     if (number >= 3 || number == 0) {
160
161         locked = TRUE;
162
163         if (story_id == LURKING_HORROR && (number == 9 || number == 16)) {
164
165             if (effect == EFFECT_PLAY) {
166
167                 next_sample = number;
168                 next_volume = volume;
169
170                 locked = FALSE;
171
172                 if (!playing)
173                     start_next_sample ();
174
175             } else locked = FALSE;
176
177             return;
178
179         }
180
181         playing = FALSE;
182
183         switch (effect) {
184
185         case EFFECT_PREPARE:
186             os_prepare_sample (number);
187             break;
188         case EFFECT_PLAY:
189             start_sample (number, lo (volume), hi (volume), (zargc == 4) ? zargs[3] : 0);
190             break;
191         case EFFECT_STOP:
192             os_stop_sample (number);
193             break;
194         case EFFECT_FINISH_WITH:
195             os_finish_with_sample (number);
196             break;
197
198         }
199
200         locked = FALSE;
201
202     } else os_beep (number);
203
204 }/* z_sound_effect */