1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
25 Driver for Gravis Ultrasound cards using libGUS.
26 A subset of libGUS is provided for DOS/DJGPP and OS/2
28 ==============================================================================*/
32 Written by Andy Lo A Foe <andy@alsa-project.org>
34 Updated to work with later versions of both the ultrasound driver and
35 libmikmod by C. Ray C. <crayc@pyro.net>
37 Major fixes by Andrew Zabolotny <bit@eltech.ru>
38 + Ported to OS/2 and DOS.
39 + Eight-bit samples are not converted to 16-bit anymore.
40 + Samples are no longer kept in normal memory.
41 + Removed sample 'unclick' logic... libGUS does unclick internally.
49 #include "mikmod_internals.h"
69 #if !defined(GUS_INSTR_SIMPLE) || !defined(GUS_WAVE_BIDIR)
70 #error libgus version is too old
73 #ifndef LIBGUS_VERSION_MAJOR
74 #define LIBGUS_VERSION_MAJOR 0x0003
77 /* DOS/DJGPP and OS/2 libGUS'es have gus_get_voice_status() */
78 #if defined(__EMX__) || defined(__DJGPP__)
79 #define HAVE_VOICE_STATUS
86 /* runtime link with libgus */
87 static int (*_libgus_cards) (void);
89 #if LIBGUS_VERSION_MAJOR < 0x0004
90 static int (*_libgus_close) (int);
91 static int (*_libgus_do_flush) (void);
92 static void (*_libgus_do_tempo) (unsigned int);
93 static void (*_libgus_do_voice_frequency) (unsigned char, unsigned int);
94 static void (*_libgus_do_voice_pan) (unsigned char, unsigned short);
95 static void (*_libgus_do_voice_start) (unsigned char, unsigned int,
96 unsigned int, unsigned short,
98 static void (*_libgus_do_voice_start_position) (unsigned char, unsigned int,
99 unsigned int, unsigned short,
100 unsigned short, unsigned int);
101 static void (*_libgus_do_voice_stop) (unsigned char, unsigned char);
102 static void (*_libgus_do_voice_volume) (unsigned char, unsigned short);
103 static void (*_libgus_do_wait) (unsigned int);
104 static int (*_libgus_get_handle) (void);
105 static int (*_libgus_info) (gus_info_t *, int);
106 static int (*_libgus_memory_alloc) (gus_instrument_t *);
107 static int (*_libgus_memory_free) (gus_instrument_t *);
108 static int (*_libgus_memory_free_size) (void);
109 static int (*_libgus_memory_pack) (void);
110 static int (*_libgus_open) (int, size_t, int);
111 static int (*_libgus_queue_flush) (void);
112 static int (*_libgus_queue_read_set_size) (int);
113 static int (*_libgus_queue_write_set_size) (int);
114 static int (*_libgus_reset) (int, unsigned int);
115 static int (*_libgus_select) (int);
116 static int (*_libgus_timer_start) (void);
117 static int (*_libgus_timer_stop) (void);
118 static int (*_libgus_timer_tempo) (int);
120 static int (*_libgus_close) (void*);
121 static int (*_libgus_do_flush) (void*);
122 static void (*_libgus_do_tempo) (void*, unsigned int);
123 static void (*_libgus_do_voice_frequency) (void*, unsigned char, unsigned int);
124 static void (*_libgus_do_voice_pan) (void*, unsigned char,unsigned short);
125 static void (*_libgus_do_voice_start) (void*, unsigned char, unsigned int,
126 unsigned int, unsigned short,
128 static void (*_libgus_do_voice_start_position) (void*, unsigned char, unsigned int,
129 unsigned int,unsigned short,
130 unsigned short, unsigned int);
131 static void (*_libgus_do_voice_stop) (void*, unsigned char, unsigned char);
132 static void (*_libgus_do_voice_volume) (void*, unsigned char, unsigned short);
133 static void (*_libgus_do_wait) (void*, unsigned int);
134 static int (*_libgus_get_file_descriptor) (void*);
135 static int (*_libgus_info) (void*, gus_info_t*, int);
136 static int (*_libgus_memory_alloc) (void*, gus_instrument_t*);
137 static int (*_libgus_memory_free) (void*, gus_instrument_t*);
138 static int (*_libgus_memory_free_size) (void*);
139 static int (*_libgus_memory_pack) (void*);
140 static int (*_libgus_open) (void**, int, int, size_t, int);
141 static int (*_libgus_queue_flush) (void*);
142 static int (*_libgus_queue_read_set_size) (void*, int);
143 static int (*_libgus_queue_write_set_size) (void*, int);
144 static int (*_libgus_reset) (void*, int, unsigned int);
145 static int (*_libgus_timer_start)(void*);
146 static int (*_libgus_timer_stop) (void*);
147 static int (*_libgus_timer_tempo) (void*, int);
149 #ifndef HAVE_RTLD_GLOBAL
150 #define RTLD_GLOBAL (0)
152 static void *libgus = NULL;
155 /* compile-time link with libgus */
156 #define _libgus_cards gus_cards
157 #define _libgus_close gus_close
158 #define _libgus_do_flush gus_do_flush
159 #define _libgus_do_tempo gus_do_tempo
160 #define _libgus_do_voice_frequency gus_do_voice_frequency
161 #define _libgus_do_voice_pan gus_do_voice_pan
162 #define _libgus_do_voice_start gus_do_voice_start
163 #define _libgus_do_voice_start_position gus_do_voice_start_position
164 #define _libgus_do_voice_stop gus_do_voice_stop
165 #define _libgus_do_voice_volume gus_do_voice_volume
166 #define _libgus_do_wait gus_do_wait
167 #if LIBGUS_VERSION_MAJOR < 0x0004
168 #define _libgus_get_handle gus_get_handle
170 #define _libgus_get_file_descriptor gus_get_file_descriptor
172 #define _libgus_info gus_info
173 #define _libgus_memory_alloc gus_memory_alloc
174 #define _libgus_memory_free gus_memory_free
175 #define _libgus_memory_free_size gus_memory_free_size
176 #define _libgus_memory_pack gus_memory_pack
177 #define _libgus_open gus_open
178 #define _libgus_queue_flush gus_queue_flush
179 #define _libgus_queue_read_set_size gus_queue_read_set_size
180 #define _libgus_queue_write_set_size gus_queue_write_set_size
181 #define _libgus_reset gus_reset
182 #if LIBGUS_VERSION_MAJOR < 0x0004
183 #define _libgus_select gus_select
185 #define _libgus_timer_start gus_timer_start
186 #define _libgus_timer_stop gus_timer_stop
187 #define _libgus_timer_tempo gus_timer_tempo
190 #define libgus_cards _libgus_cards /* same between v3 and v4 */
191 #define libgus_open _libgus_open /* different between v3 and v4: must use #ifdef */
192 #define libgus_close _libgus_close /* different between v3 and v4: must use #ifdef */
193 /* the following can be handled easily by macros: v4 only adds them the handle as the first param */
194 #if LIBGUS_VERSION_MAJOR < 0x0004
195 #define libgus_get_handle _libgus_get_handle /* only in v3 */
196 #define libgus_do_flush _libgus_do_flush
197 #define libgus_do_tempo _libgus_do_tempo
198 #define libgus_do_voice_frequency _libgus_do_voice_frequency
199 #define libgus_do_voice_pan _libgus_do_voice_pan
200 #define libgus_do_voice_start _libgus_do_voice_start
201 #define libgus_do_voice_start_position _libgus_do_voice_start_position
202 #define libgus_do_voice_stop _libgus_do_voice_stop
203 #define libgus_do_voice_volume _libgus_do_voice_volume
204 #define libgus_do_wait _libgus_do_wait
205 #define libgus_info _libgus_info
206 #define libgus_memory_alloc _libgus_memory_alloc
207 #define libgus_memory_free _libgus_memory_free
208 #define libgus_memory_free_size _libgus_memory_free_size
209 #define libgus_memory_pack _libgus_memory_pack
210 #define libgus_queue_flush _libgus_queue_flush
211 #define libgus_queue_read_set_size _libgus_queue_read_set_size
212 #define libgus_queue_write_set_size _libgus_queue_write_set_size
213 #define libgus_reset _libgus_reset
214 #define libgus_select _libgus_select
215 #define libgus_timer_start _libgus_timer_start
216 #define libgus_timer_stop _libgus_timer_stop
217 #define libgus_timer_tempo _libgus_timer_tempo
219 #define libgus_get_file_descriptor _libgus_get_file_descriptor /* only in v4 */
220 #define libgus_do_flush() _libgus_do_flush(ultra_h)
221 #define libgus_do_tempo(t) _libgus_do_tempo(ultra_h,t)
222 #define libgus_do_voice_frequency(a,b) _libgus_do_voice_frequency(ultra_h,a,b)
223 #define libgus_do_voice_pan(a,b) _libgus_do_voice_pan(ultra_h,a,b)
224 #define libgus_do_voice_start(a,b,c,d,e) _libgus_do_voice_start(ultra_h,a,b,c,d,e)
225 #define libgus_do_voice_start_position(a,b,c,d,e,f) _libgus_do_voice_start_position(ultra_h,a,b,c,d,e,f)
226 #define libgus_do_voice_stop(a,b) _libgus_do_voice_stop(ultra_h,a,b)
227 #define libgus_do_voice_volume(a,b) _libgus_do_voice_volume(ultra_h,a,b)
228 #define libgus_do_wait(a) _libgus_do_wait(ultra_h,a)
229 #define libgus_info(a,b) _libgus_info(ultra_h,a,b)
230 #define libgus_memory_alloc(a) _libgus_memory_alloc(ultra_h,a)
231 #define libgus_memory_free(a) _libgus_memory_free(ultra_h,a)
232 #define libgus_memory_free_size() _libgus_memory_free_size(ultra_h)
233 #define libgus_memory_pack() _libgus_memory_pack(ultra_h)
234 #define libgus_queue_flush() _libgus_queue_flush(ultra_h)
235 #define libgus_queue_read_set_size(a) _libgus_queue_read_set_size(ultra_h,a)
236 #define libgus_queue_write_set_size(a) _libgus_queue_write_set_size(ultra_h,a)
237 #define libgus_reset(a,b) _libgus_reset(ultra_h,a,b)
238 #define libgus_timer_start() _libgus_timer_start(ultra_h)
239 #define libgus_timer_stop() _libgus_timer_stop(ultra_h)
240 #define libgus_timer_tempo(a) _libgus_timer_tempo(ultra_h,a)
243 #define GUS_SAMPLES 256 /* Max. GUS samples loadable */
244 #define GUS_CHANNELS 32 /* Max. GUS channels available */
245 #define SIZE_OF_SEQBUF (8 * 1024) /* Size of the sequence buffer */
246 #define ULTRA_PAN_MIDDLE (16383 >> 1) /* Middle balance position */
252 /* This structure holds the current state of a GUS voice channel. */
253 typedef struct GUS_VOICE {
268 #ifndef HAVE_VOICE_STATUS
273 /* Global declarations follow */
275 static SAMPLE *samples[GUS_SAMPLES]; /* sample handles */
276 static GUS_VOICE voices[GUS_CHANNELS]; /* channel status */
278 static int ultra_dev = 0; /* GUS index, if more than one card */
279 #if LIBGUS_VERSION_MAJOR < 0x0004
280 static int ultra_card = -1; /* returned by gus_open(ultra_dev,,) - must be same as ultra_dev */
282 static void* ultra_h = NULL; /* GUS handle */
284 static int ultra_fd = -1; /* GUS file descriptor */
287 #ifdef MIKMOD_DYNAMIC
288 static int Ultra_Link(void)
294 #if LIBGUS_VERSION_MAJOR < 0x0004
295 libgus = dlopen("libgus.so.3", RTLD_LAZY | RTLD_GLOBAL);
297 libgus = dlopen("libgus.so.4", RTLD_LAZY | RTLD_GLOBAL);
299 if (!libgus) /* then this won't succeed either, but whatever.. */
300 libgus = dlopen("libgus.so", RTLD_LAZY | RTLD_GLOBAL);
304 /* resolve function references */
305 #define IMPORT_SYMBOL(x,ret,params) \
306 if (!(_lib##x = (ret (*)params) dlsym(libgus, #x))) return 1
308 IMPORT_SYMBOL(gus_cards, int, (void));
309 #if LIBGUS_VERSION_MAJOR < 0x0004
310 IMPORT_SYMBOL(gus_close, int, (int));
311 IMPORT_SYMBOL(gus_do_flush, int, (void));
312 IMPORT_SYMBOL(gus_do_tempo, void, (unsigned int));
313 IMPORT_SYMBOL(gus_do_voice_frequency, void, (unsigned char, unsigned int));
314 IMPORT_SYMBOL(gus_do_voice_pan, void, (unsigned char, unsigned short));
315 IMPORT_SYMBOL(gus_do_voice_start, void, (unsigned char, unsigned int, unsigned int, unsigned short, unsigned short));
316 IMPORT_SYMBOL(gus_do_voice_start_position, void, (unsigned char, unsigned int, unsigned int, unsigned short, unsigned short, unsigned int));
317 IMPORT_SYMBOL(gus_do_voice_stop, void, (unsigned char, unsigned char));
318 IMPORT_SYMBOL(gus_do_voice_volume, void, (unsigned char, unsigned short));
319 IMPORT_SYMBOL(gus_do_wait, void, (unsigned int));
320 IMPORT_SYMBOL(gus_get_handle, int, (void));
321 IMPORT_SYMBOL(gus_info, int, (gus_info_t *, int));
322 IMPORT_SYMBOL(gus_memory_alloc, int, (gus_instrument_t *));
323 IMPORT_SYMBOL(gus_memory_free, int, (gus_instrument_t *));
324 IMPORT_SYMBOL(gus_memory_free_size, int, (void));
325 IMPORT_SYMBOL(gus_memory_pack, int, (void));
326 IMPORT_SYMBOL(gus_open, int, (int, size_t, int));
327 IMPORT_SYMBOL(gus_queue_flush, int, (void));
328 IMPORT_SYMBOL(gus_queue_read_set_size, int, (int));
329 IMPORT_SYMBOL(gus_queue_write_set_size, int, (int));
330 IMPORT_SYMBOL(gus_reset, int, (int, unsigned int));
331 IMPORT_SYMBOL(gus_select, int, (int));
332 IMPORT_SYMBOL(gus_timer_start, int, (void));
333 IMPORT_SYMBOL(gus_timer_stop, int, (void));
334 IMPORT_SYMBOL(gus_timer_tempo, int, (int));
336 IMPORT_SYMBOL(gus_close, int, (void*));
337 IMPORT_SYMBOL(gus_do_flush, int, (void*));
338 IMPORT_SYMBOL(gus_do_tempo, void, (void*, unsigned int));
339 IMPORT_SYMBOL(gus_do_voice_frequency, void, (void*, unsigned char, unsigned int));
340 IMPORT_SYMBOL(gus_do_voice_pan, void, (void*, unsigned char, unsigned short));
341 IMPORT_SYMBOL(gus_do_voice_start, void, (void*, unsigned char, unsigned int, unsigned int, unsigned short, unsigned short));
342 IMPORT_SYMBOL(gus_do_voice_start_position, void, (void*, unsigned char, unsigned int, unsigned int, unsigned short, unsigned short, unsigned int));
343 IMPORT_SYMBOL(gus_do_voice_stop, void, (void*, unsigned char, unsigned char));
344 IMPORT_SYMBOL(gus_do_voice_volume, void, (void*, unsigned char, unsigned short));
345 IMPORT_SYMBOL(gus_do_wait, void, (void*, unsigned int));
346 IMPORT_SYMBOL(gus_get_file_descriptor, int, (void*));
347 IMPORT_SYMBOL(gus_info, int, (void*, gus_info_t *, int));
348 IMPORT_SYMBOL(gus_memory_alloc, int, (void*, gus_instrument_t *));
349 IMPORT_SYMBOL(gus_memory_free, int, (void*, gus_instrument_t *));
350 IMPORT_SYMBOL(gus_memory_free_size, int, (void*));
351 IMPORT_SYMBOL(gus_memory_pack, int, (void*));
352 IMPORT_SYMBOL(gus_open, int, (void**, int, int, size_t, int));
353 IMPORT_SYMBOL(gus_queue_flush, int, (void*));
354 IMPORT_SYMBOL(gus_queue_read_set_size, int, (void*, int));
355 IMPORT_SYMBOL(gus_queue_write_set_size, int, (void*, int));
356 IMPORT_SYMBOL(gus_reset, int, (void*, int, unsigned int));
357 IMPORT_SYMBOL(gus_timer_start, int, (void*));
358 IMPORT_SYMBOL(gus_timer_stop, int, (void*));
359 IMPORT_SYMBOL(gus_timer_tempo, int, (void*, int));
366 static void Ultra_Unlink(void)
368 _libgus_cards = NULL;
369 _libgus_close = NULL;
370 _libgus_do_flush = NULL;
371 _libgus_do_tempo = NULL;
372 _libgus_do_voice_frequency = NULL;
373 _libgus_do_voice_pan = NULL;
374 _libgus_do_voice_start = NULL;
375 _libgus_do_voice_start_position = NULL;
376 _libgus_do_voice_stop = NULL;
377 _libgus_do_voice_volume = NULL;
378 _libgus_do_wait = NULL;
379 #if LIBGUS_VERSION_MAJOR < 0x0004
380 _libgus_get_handle = NULL;
382 _libgus_get_file_descriptor = NULL;
385 _libgus_memory_alloc = NULL;
386 _libgus_memory_free = NULL;
387 _libgus_memory_free_size = NULL;
388 _libgus_memory_pack = NULL;
390 _libgus_queue_flush = NULL;
391 _libgus_queue_read_set_size = NULL;
392 _libgus_queue_write_set_size = NULL;
393 _libgus_reset = NULL;
394 #if LIBGUS_VERSION_MAJOR < 0x0004
395 _libgus_select = NULL;
397 _libgus_timer_start = NULL;
398 _libgus_timer_stop = NULL;
399 _libgus_timer_tempo = NULL;
408 static void Ultra_CommandLine(const CHAR *cmdline)
410 CHAR *ptr = MD_GetAtom("card", cmdline, 0);
415 if (buf >= 0 && buf <= 8)
420 ptr = MD_GetAtom("dma", cmdline, 0);
422 gus_dma_usage (atoi(ptr));
428 /* Checks for the presence of GUS cards */
429 static BOOL Ultra_IsThere(void)
433 #ifdef MIKMOD_DYNAMIC
437 retval = libgus_cards()? 1 : 0;
438 #ifdef MIKMOD_DYNAMIC
444 /* Load a new sample directly into GUS DRAM and return a handle */
445 static SWORD Ultra_SampleLoad(struct SAMPLOAD *sload, int type)
448 SAMPLE *s = sload->sample;
449 gus_instrument_t instrument;
452 unsigned char *buffer;
453 unsigned int length, loopstart, loopend;
455 /* Find empty slot to put sample in */
456 for (handle = 0; handle < GUS_SAMPLES; handle++)
457 if (!samples[handle])
460 if (handle == GUS_SAMPLES) {
461 _mm_errno = MMERR_OUT_OF_HANDLES;
465 /* Fill an gus_instrument_t structure and feed it to libgus. We can
466 download 8 and 16 bit, both signed and unsigned samples into GUS, so
467 don't bother much about formats here. */
469 /* convert position/length data from samples to bytes */
471 loopstart = s->loopstart;
472 loopend = s->loopend ? s->loopend : length;
474 if (loopend > length)
476 if (loopstart > loopend)
478 if (s->flags & SF_16BITS) {
484 /* Load sample into normal memory */
485 if (!(buffer = (unsigned char *) MikMod_malloc(length))) {
486 _mm_errno = MMERR_SAMPLE_TOO_BIG;
490 if (SL_Load(buffer, sload, s->length)) {
497 memset(&wave, 0, sizeof(wave));
498 memset(&layer, 0, sizeof(layer));
499 memset(&instrument, 0, sizeof(instrument));
502 ((s->flags & SF_SIGNED) ? 0 : GUS_WAVE_INVERT) |
503 ((s->flags & SF_16BITS) ? GUS_WAVE_16BIT : 0) |
504 ((s->flags & SF_DELTA ) ? GUS_WAVE_DELTA : 0) |
505 ((s->flags & SF_LOOP ) ? GUS_WAVE_LOOP : 0) |
506 ((s->flags & SF_BIDI ) ? GUS_WAVE_BIDIR : 0);
507 wave.begin.ptr = buffer;
508 wave.loop_start = loopstart << 4;
509 wave.loop_end = loopend << 4;
514 instrument.mode = layer.mode = wave.mode = GUS_INSTR_SIMPLE;
515 instrument.number.instrument = handle;
516 instrument.info.layer = &layer;
518 /* Download the sample to GUS RAM */
519 if (libgus_memory_alloc(&instrument)) {
521 _mm_errno = MMERR_SAMPLE_TOO_BIG;
529 /* Discards a sample from the GUS memory and mark handle as free */
530 static void Ultra_SampleUnload(SWORD handle)
532 gus_instrument_t instrument;
534 if (handle >= GUS_SAMPLES || handle < 0 || !samples[handle])
537 memset(&instrument, 0, sizeof(instrument));
538 instrument.mode = GUS_INSTR_SIMPLE;
539 instrument.number.instrument = handle;
540 libgus_memory_free(&instrument);
541 samples[handle] = NULL;
544 /* Reports available sample space */
545 static ULONG Ultra_SampleSpace(int type)
547 libgus_memory_pack();
548 return (libgus_memory_free_size());
551 /* Reports the size of a sample */
552 static ULONG Ultra_SampleLength(int type, SAMPLE *s)
557 if (s->flags & SF_16BITS)
558 return ((s->length << 1) + 31) & ~31;
560 return ( s->length + 15) & ~15;
563 /* Initializes the driver */
564 static int Ultra_Init_internal(void)
568 #if LIBGUS_VERSION_MAJOR < 0x0004
569 if ((ultra_card = libgus_open(ultra_dev, SIZE_OF_SEQBUF, 0)) < 0) {
570 _mm_errno = (errno == ENOMEM)? MMERR_OUT_OF_MEMORY : MMERR_INVALID_DEVICE;
573 libgus_select(ultra_card);
574 ultra_fd = libgus_get_handle();
576 if (libgus_open(&ultra_h, ultra_dev, 0, SIZE_OF_SEQBUF, GUS_OPEN_FLAG_NONE) < 0) {
577 _mm_errno = (errno == ENOMEM)? MMERR_OUT_OF_MEMORY : MMERR_INVALID_DEVICE;
580 ultra_fd = libgus_get_file_descriptor(ultra_h);
583 /* We support only 16-bit stereo with 44K mixing frequency. On UltraSound
584 Classic mixing frequency depends on number of channels, on Interwave it
586 md_mode |= DMODE_16BITS | DMODE_STEREO;
587 md_mixfreq = info.mixing_freq;
589 libgus_info(&info, 0);
591 switch (info.version) {
593 fputs("GUS 2.4", stderr);
596 fputs("GUS 3.7 (flipped)", stderr);
599 fputs("GUS 3.7", stderr);
602 fputs("GUS ACE", stderr);
605 fputs("GUS MAX 10", stderr);
608 fputs("GUS MAX 11", stderr);
611 fputs("Interwave/GUS PnP", stderr);
614 fprintf(stderr, "Unknown GUS type %x", info.version);
617 fprintf(stderr, " with %dKb RAM on board\n", info.memory_size >> 10);
620 /* Zero the voice states and sample handles */
621 memset (&voices, 0, sizeof (voices));
622 memset (&samples, 0, sizeof (samples));
627 static int Ultra_Init(void)
629 #ifdef MIKMOD_DYNAMIC
631 _mm_errno = MMERR_DYNAMIC_LINKING;
635 return Ultra_Init_internal();
638 /* Closes the driver */
639 static void Ultra_Exit_internal(void)
641 #if LIBGUS_VERSION_MAJOR < 0x0004
642 if (ultra_card >= 0) {
644 libgus_close(ultra_dev);
648 libgus_close(ultra_h);
655 static void Ultra_Exit(void)
657 Ultra_Exit_internal();
658 #ifdef MIKMOD_DYNAMIC
663 /* Poor man's reset function */
664 static int Ultra_Reset(void)
666 Ultra_Exit_internal();
667 return Ultra_Init_internal();
670 static int Ultra_SetNumVoices(void)
675 /* Module player tick function */
676 static void UltraPlayer(void)
678 int channel, panning;
679 struct GUS_VOICE *voice;
680 static BOOL ultra_pause = 1; /* paused status */
684 if (ultra_pause != Player_Paused())
685 if ((ultra_pause = Player_Paused()))
686 for (channel = 0, voice = voices; channel < md_numchn;
687 channel++, voice++) {
688 libgus_do_voice_volume (channel, 0);
689 voices->changes |= (CH_VOL | CH_FREQ | CH_PAN);
695 for (channel = 0, voice = voices; channel < md_numchn; channel++, voice++) {
696 panning = (voice->pan == PAN_SURROUND) ?
697 ULTRA_PAN_MIDDLE : (voice->pan << 6);
701 voice->decvol = voice->vol;
702 if (voice->start > 0)
703 libgus_do_voice_start_position(channel, voice->handle,
704 voice->frq, voice->vol << 6, panning, voice->start << 4);
706 libgus_do_voice_start(channel, voice->handle, voice->frq,
707 voice->vol << 6, voice->pan << 6);
709 if (voice->changes & CH_FREQ)
710 libgus_do_voice_frequency(channel, voice->frq);
711 if (voice->changes & CH_VOL)
712 libgus_do_voice_volume(channel, voice->vol << 6);
713 if (voice->changes & CH_PAN)
714 libgus_do_voice_pan(channel, panning);
723 #if defined(__DJGPP__) || defined(__EMX__)
724 static void Ultra_Callback(void)
730 static void Ultra_Update(void)
732 static UWORD ultra_bpm = 0; /* current GUS tempo */
734 /* All real work is done during GF1 timer 1 interrupt */
735 if (ultra_bpm != md_bpm) {
736 libgus_do_tempo((md_bpm * 50) / 125);
742 static void Ultra_Update(void)
746 static UWORD ultra_bpm = 0; /* current GUS tempo */
748 if (ultra_bpm != md_bpm) {
749 libgus_do_tempo((md_bpm * 50) / 125);
756 need_write = libgus_do_flush();
760 FD_SET(ultra_fd, &write_fds);
762 select(ultra_fd + 1, NULL, &write_fds, NULL, NULL);
763 } while (!FD_ISSET(ultra_fd, &write_fds));
764 } while(need_write > 0);
766 /* Wait so that all voice commands gets executed */
773 static int Ultra_PlayStart(void)
778 for (t = 0; t < md_numchn; t++) {
780 voices[t].handle = 0;
783 voices[t].reppos = 0;
784 voices[t].repend = 0;
785 voices[t].changes = 0;
787 voices[t].frq = 10000;
789 voices[t].pan = ULTRA_PAN_MIDDLE;
790 voices[t].active = 0;
793 #if LIBGUS_VERSION_MAJOR < 0x0004
794 libgus_select(ultra_card);
796 if (libgus_reset(md_numchn, 0) < 0) {
797 _mm_errno = MMERR_GUS_RESET;
801 /* Query mixing frequency */
802 libgus_info(&info, 0);
803 md_mixfreq = info.mixing_freq;
805 libgus_queue_write_set_size(1024);
806 libgus_queue_read_set_size(128);
808 if (libgus_timer_start() < 0) {
809 _mm_errno = MMERR_GUS_TIMER;
813 #if defined(__DJGPP__) || defined(__EMX__)
814 gus_timer_callback(Ultra_Callback);
817 libgus_timer_tempo(50);
819 for (t = 0; t < md_numchn; t++) {
820 libgus_do_voice_pan(t, ULTRA_PAN_MIDDLE);
821 libgus_do_voice_volume(t, 0 << 8);
830 static void Ultra_PlayStop(void)
834 libgus_queue_flush();
836 libgus_queue_write_set_size(0);
837 libgus_queue_read_set_size(0);
838 for(voice = 0; voice < md_numchn; voice++)
839 libgus_do_voice_stop(voice, 0);
841 #if defined(__DJGPP__) || defined(__EMX__)
842 gus_timer_callback(NULL);
848 /* Set the volume for the given voice */
849 static void Ultra_VoiceSetVolume(UBYTE voice, UWORD vol)
851 if (voice < md_numchn)
852 if (vol != voices[voice].vol) {
853 voices[voice].decvol =
854 voices[voice].vol = vol;
855 voices[voice].changes |= CH_VOL;
859 /* Returns the volume of the given voice */
860 static UWORD Ultra_VoiceGetVolume(UBYTE voice)
862 return (voice < md_numchn) ? voices[voice].vol : 0;
865 /* Set the pitch for the given voice */
866 static void Ultra_VoiceSetFrequency(UBYTE voice, ULONG frq)
868 if (voice < md_numchn)
869 if (frq != voices[voice].frq) {
870 voices[voice].frq = frq;
871 voices[voice].changes |= CH_FREQ;
875 /* Returns the frequency of the given voice */
876 static ULONG Ultra_VoiceGetFrequency(UBYTE voice)
878 return (voice < md_numchn) ? voices[voice].frq : 0;
881 /* Set the panning position for the given voice */
882 static void Ultra_VoiceSetPanning(UBYTE voice, ULONG pan)
884 if (voice < md_numchn)
885 if (pan != voices[voice].pan) {
886 voices[voice].pan = pan;
887 voices[voice].changes |= CH_PAN;
891 /* Returns the panning of the given voice */
892 static ULONG Ultra_VoiceGetPanning(UBYTE voice)
894 return (voice < md_numchn) ? voices[voice].pan : 0;
897 /* Start a new sample on a voice */
898 static void Ultra_VoicePlay(UBYTE voice, SWORD handle, ULONG start,
899 ULONG size, ULONG reppos, ULONG repend,
902 if ((voice >= md_numchn) || (start >= size))
909 voices[voice].flags = flags;
910 voices[voice].handle = handle;
911 voices[voice].start = start;
912 voices[voice].size = size;
913 voices[voice].reppos = reppos;
914 voices[voice].repend = repend;
915 voices[voice].kick = 1;
916 voices[voice].active = 1;
917 #ifndef HAVE_VOICE_STATUS
918 voices[voice].started = time(NULL);
923 static void Ultra_VoiceStop(UBYTE voice)
925 if (voice < md_numchn)
926 voices[voice].active = 0;
929 /* Returns whether a voice is stopped */
930 static BOOL Ultra_VoiceStopped(UBYTE voice)
932 if (voice >= md_numchn)
935 #ifdef HAVE_VOICE_STATUS
936 if (voices[voice].active)
937 return gus_get_voice_status(voice) ? 0 : 1;
941 if (voices[voice].active) {
942 /* is sample looping ? */
943 if (voices[voice].flags & (SF_LOOP | SF_BIDI))
946 if (time(NULL) - voices[voice].started >=
947 ((voices[voice].size - voices[voice].start + md_mixfreq -1)
949 voices[voice].active = 0;
958 /* Returns current voice position */
959 static SLONG Ultra_VoiceGetPosition(UBYTE voice)
961 /* NOTE This information can not be determined. */
965 /* Returns voice real volume */
966 static ULONG Ultra_VoiceRealVolume(UBYTE voice)
969 if (!Ultra_VoiceStopped (voice)) {
970 /* NOTE This information can not be accurately determined. */
971 retval = (voices [voice].decvol) << 8;
972 if (retval > 0xffff) retval = 0xffff;
977 MDRIVER drv_ultra = {
979 "Gravis Ultrasound native mode",
980 "Gravis Ultrasound native mode driver v1.2",
984 "dma:b:1:Use DMA for transferring samples into GUS DRAM\n"
986 "card:r:0,8,0:Soundcard number\n",
1002 Ultra_VoiceSetVolume,
1003 Ultra_VoiceGetVolume,
1004 Ultra_VoiceSetFrequency,
1005 Ultra_VoiceGetFrequency,
1006 Ultra_VoiceSetPanning,
1007 Ultra_VoiceGetPanning,
1011 Ultra_VoiceGetPosition,
1012 Ultra_VoiceRealVolume
1018 #endif /* DRV_ULTRA */