fixed loading screen. regression in blitfb
[dosdemo] / src / dos / audos.c
1 #ifndef NO_SOUND
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include "audio.h"
7 #include "midasdll.h"
8 #include "util.h"
9
10 #define SET_MUS_VOL(vol) \
11         do { \
12                 int mv = (vol) * vol_master >> 10; \
13                 MIDASsetMusicVolume(modplay, mv ? mv + 1 : 0); \
14         } while(0)
15
16 extern int force_snd_config;
17
18 static MIDASmodulePlayHandle modplay;
19 static struct au_module *curmod;
20
21 static int vol_master, vol_mus, vol_sfx;
22
23 int au_init(void)
24 {
25         modplay = 0;
26         curmod = 0;
27         vol_master = vol_mus = vol_sfx = 255;
28
29         MIDASstartup();
30
31         if(force_snd_config || (!MIDASloadConfig("sound.cfg") && !MIDASdetectSoundCard())) {
32                 if(MIDASconfig()) {
33                         if(!MIDASsaveConfig("sound.cfg")) {
34                                 fprintf(stderr, "failed to save sound card configuration\n");
35                         }
36                 }
37         }
38
39         MIDASinit();
40
41         MIDASstartBackgroundPlay(0);
42         return 0;
43 }
44
45 void au_shutdown(void)
46 {
47         printf("au_shutdown\n");
48         if(curmod) {
49                 au_stop_module(curmod);
50         }
51         MIDASstopBackgroundPlay();
52         MIDASclose();
53 }
54
55 struct au_module *au_load_module(const char *fname)
56 {
57         static MIDASmoduleInfo info;
58         struct au_module *mod;
59         char *name, *end;
60
61         if(!(mod = malloc(sizeof *mod))) {
62                 fprintf(stderr, "au_load_module: failed to allocate module\n");
63                 return 0;
64         }
65
66         if(!(mod->impl = MIDASloadModule((char*)fname))) {
67                 fprintf(stderr, "au_load_module: failed to load module: %s\n", fname);
68                 free(mod);
69                 return 0;
70         }
71
72         name = 0;
73         if(MIDASgetModuleInfo(mod->impl, &info)) {
74                 name = info.songName;
75                 end = name + strlen(name) - 1;
76                 while(end >= name && isspace(*end)) {
77                         *end-- = 0;
78                 }
79                 if(!*name) name = 0;
80         }
81
82         if(!name) {
83                 /* fallback to using the filename */
84                 if((name = strrchr(fname, '/')) || (name = strrchr(fname, '\\'))) {
85                         name++;
86                 } else {
87                         name = (char*)fname;
88                 }
89         }
90
91         if(!(mod->name = malloc(strlen(name) + 1))) {
92                 fprintf(stderr, "au_load_module: mod->name malloc failed\n");
93                 MIDASfreeModule(mod->impl);
94                 return 0;
95         }
96         strcpy(mod->name, name);
97
98         printf("loaded module \"%s\" (%s)\n", name, fname);
99         return mod;
100 }
101
102 void au_free_module(struct au_module *mod)
103 {
104         if(!mod) return;
105
106         if(mod == curmod) {
107                 au_stop_module(curmod);
108         }
109         MIDASfreeModule(mod->impl);
110         free(mod->name);
111         free(mod);
112 }
113
114 int au_play_module(struct au_module *mod)
115 {
116         if(curmod) {
117                 if(curmod == mod) return 0;
118                 au_stop_module(curmod);
119         }
120
121         if(!(modplay = MIDASplayModule(mod->impl, 1))) {
122                 fprintf(stderr, "au_play_module: failed to play module: %s\n", mod->name);
123                 return -1;
124         }
125         SET_MUS_VOL(vol_mus);
126         curmod = mod;
127         return 0;
128 }
129
130 void au_update(void)
131 {
132 }
133
134 int au_stop_module(struct au_module *mod)
135 {
136         if(mod && curmod != mod) return -1;
137         if(!curmod) return -1;
138
139         MIDASstopModule(modplay);
140         curmod = 0;
141         return 0;
142 }
143
144 int au_module_state(struct au_module *mod)
145 {
146         if(mod) {
147                 return curmod == mod ? AU_PLAYING : AU_STOPPED;
148         }
149         return curmod ? AU_PLAYING : AU_STOPPED;
150 }
151
152 int au_volume(int vol)
153 {
154         AU_VOLADJ(vol_master, vol);
155         if(vol != vol_master) {
156                 vol_master = vol;
157
158                 au_sfx_volume(vol_sfx);
159                 au_music_volume(vol_mus);
160         }
161         return vol_master;
162 }
163
164 int au_sfx_volume(int vol)
165 {
166         AU_VOLADJ(vol_sfx, vol);
167         vol_sfx = vol;
168
169         /* TODO set sfx volume */
170         return vol_sfx;
171 }
172
173
174 int au_music_volume(int vol)
175 {
176         AU_VOLADJ(vol_mus, vol);
177         vol_mus = vol;
178
179         if(curmod) {
180                 SET_MUS_VOL(vol);
181         }
182         return vol_mus;
183 }
184
185 /* when using MIDAS, we can't access the PIT directly, so we don't build timer.c
186  * and implement all the timer functions here, using MIDAS callbacks
187  */
188 static volatile unsigned long ticks;
189 static unsigned long tick_interval;
190
191 static void MIDAS_CALL midas_timer(void)
192 {
193         ticks++;
194 }
195
196 /* macro to divide and round to the nearest integer */
197 #define DIV_ROUND(a, b) \
198         ((a) / (b) + ((a) % (b)) / ((b) / 2))
199
200 void init_timer(int res_hz)
201 {
202         MIDASsetTimerCallbacks(res_hz * 1000, 0, midas_timer, 0, 0);
203         tick_interval = DIV_ROUND(1000, res_hz);
204 }
205
206 void reset_timer(void)
207 {
208         ticks = 0;
209 }
210
211 unsigned long get_msec(void)
212 {
213         return ticks * tick_interval;
214 }
215
216 void sleep_msec(unsigned long msec)
217 {
218         unsigned long wakeup_time = ticks + msec / tick_interval;
219         while(ticks < wakeup_time) {
220 #ifdef USE_HLT
221                 halt();
222 #endif
223         }
224 }
225
226 #else   /* NO_SOUND */
227 #include "audio.h"
228
229 static int vol_master, vol_mus, vol_sfx;
230
231 int au_init(void)
232 {
233         vol_master = vol_mus = vol_sfx = 255;
234         return 0;
235 }
236
237 void au_shutdown(void)
238 {
239         printf("au_shutdown\n");
240 }
241
242 struct au_module *au_load_module(const char *fname)
243 {
244         return 0;
245 }
246
247 void au_free_module(struct au_module *mod)
248 {
249 }
250
251 int au_play_module(struct au_module *mod)
252 {
253         return -1;
254 }
255
256 void au_update(void)
257 {
258 }
259
260 int au_stop_module(struct au_module *mod)
261 {
262         return -1;
263 }
264
265 int au_module_state(struct au_module *mod)
266 {
267         return AU_STOPPED;
268 }
269
270 int au_volume(int vol)
271 {
272         AU_VOLADJ(vol_master, vol);
273         return vol_master;
274 }
275
276 int au_sfx_volume(int vol)
277 {
278         AU_VOLADJ(vol_sfx, vol);
279         return vol_sfx;
280 }
281
282
283 int au_music_volume(int vol)
284 {
285         AU_VOLADJ(vol_mus, vol);
286         return vol_mus;
287 }
288 #endif  /* NO_SOUND */