X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=libs%2Fmikmod%2Fdrivers%2Fdrv_ultra.c;fp=libs%2Fmikmod%2Fdrivers%2Fdrv_ultra.c;h=0000000000000000000000000000000000000000;hp=dbd0b7ce21ead6e641709f069634d79d920a7b3a;hb=b2c24e9d5b637bb78d18a377d9957c07d0759030;hpb=67c749060592270c9cd8b4f7dafe7d7c7a61a614 diff --git a/libs/mikmod/drivers/drv_ultra.c b/libs/mikmod/drivers/drv_ultra.c deleted file mode 100644 index dbd0b7c..0000000 --- a/libs/mikmod/drivers/drv_ultra.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* MikMod sound library - (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for - complete list. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -/*============================================================================== - - $Id$ - - Driver for Gravis Ultrasound cards using libGUS. - A subset of libGUS is provided for DOS/DJGPP and OS/2 - -==============================================================================*/ - -/* - - Written by Andy Lo A Foe - - Updated to work with later versions of both the ultrasound driver and - libmikmod by C. Ray C. - - Major fixes by Andrew Zabolotny - + Ported to OS/2 and DOS. - + Eight-bit samples are not converted to 16-bit anymore. - + Samples are no longer kept in normal memory. - + Removed sample 'unclick' logic... libGUS does unclick internally. - -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "mikmod_internals.h" - -#ifdef DRV_ULTRA - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_MEMORY_H -#include -#endif - -#ifdef MIKMOD_DYNAMIC -#include -#endif -#include -#include -#include - -#include - -#if !defined(GUS_INSTR_SIMPLE) || !defined(GUS_WAVE_BIDIR) -#error libgus version is too old -#endif -/* just in case */ -#ifndef LIBGUS_VERSION_MAJOR -#define LIBGUS_VERSION_MAJOR 0x0003 -#endif - -/* DOS/DJGPP and OS/2 libGUS'es have gus_get_voice_status() */ -#if defined(__EMX__) || defined(__DJGPP__) -#define HAVE_VOICE_STATUS -#else -#include -#endif - - -#ifdef MIKMOD_DYNAMIC -/* runtime link with libgus */ -static int (*_libgus_cards) (void); - -#if LIBGUS_VERSION_MAJOR < 0x0004 -static int (*_libgus_close) (int); -static int (*_libgus_do_flush) (void); -static void (*_libgus_do_tempo) (unsigned int); -static void (*_libgus_do_voice_frequency) (unsigned char, unsigned int); -static void (*_libgus_do_voice_pan) (unsigned char, unsigned short); -static void (*_libgus_do_voice_start) (unsigned char, unsigned int, - unsigned int, unsigned short, - unsigned short); -static void (*_libgus_do_voice_start_position) (unsigned char, unsigned int, - unsigned int, unsigned short, - unsigned short, unsigned int); -static void (*_libgus_do_voice_stop) (unsigned char, unsigned char); -static void (*_libgus_do_voice_volume) (unsigned char, unsigned short); -static void (*_libgus_do_wait) (unsigned int); -static int (*_libgus_get_handle) (void); -static int (*_libgus_info) (gus_info_t *, int); -static int (*_libgus_memory_alloc) (gus_instrument_t *); -static int (*_libgus_memory_free) (gus_instrument_t *); -static int (*_libgus_memory_free_size) (void); -static int (*_libgus_memory_pack) (void); -static int (*_libgus_open) (int, size_t, int); -static int (*_libgus_queue_flush) (void); -static int (*_libgus_queue_read_set_size) (int); -static int (*_libgus_queue_write_set_size) (int); -static int (*_libgus_reset) (int, unsigned int); -static int (*_libgus_select) (int); -static int (*_libgus_timer_start) (void); -static int (*_libgus_timer_stop) (void); -static int (*_libgus_timer_tempo) (int); -#else -static int (*_libgus_close) (void*); -static int (*_libgus_do_flush) (void*); -static void (*_libgus_do_tempo) (void*, unsigned int); -static void (*_libgus_do_voice_frequency) (void*, unsigned char, unsigned int); -static void (*_libgus_do_voice_pan) (void*, unsigned char,unsigned short); -static void (*_libgus_do_voice_start) (void*, unsigned char, unsigned int, - unsigned int, unsigned short, - unsigned short); -static void (*_libgus_do_voice_start_position) (void*, unsigned char, unsigned int, - unsigned int,unsigned short, - unsigned short, unsigned int); -static void (*_libgus_do_voice_stop) (void*, unsigned char, unsigned char); -static void (*_libgus_do_voice_volume) (void*, unsigned char, unsigned short); -static void (*_libgus_do_wait) (void*, unsigned int); -static int (*_libgus_get_file_descriptor) (void*); -static int (*_libgus_info) (void*, gus_info_t*, int); -static int (*_libgus_memory_alloc) (void*, gus_instrument_t*); -static int (*_libgus_memory_free) (void*, gus_instrument_t*); -static int (*_libgus_memory_free_size) (void*); -static int (*_libgus_memory_pack) (void*); -static int (*_libgus_open) (void**, int, int, size_t, int); -static int (*_libgus_queue_flush) (void*); -static int (*_libgus_queue_read_set_size) (void*, int); -static int (*_libgus_queue_write_set_size) (void*, int); -static int (*_libgus_reset) (void*, int, unsigned int); -static int (*_libgus_timer_start)(void*); -static int (*_libgus_timer_stop) (void*); -static int (*_libgus_timer_tempo) (void*, int); -#endif -#ifndef HAVE_RTLD_GLOBAL -#define RTLD_GLOBAL (0) -#endif -static void *libgus = NULL; - -#else -/* compile-time link with libgus */ -#define _libgus_cards gus_cards -#define _libgus_close gus_close -#define _libgus_do_flush gus_do_flush -#define _libgus_do_tempo gus_do_tempo -#define _libgus_do_voice_frequency gus_do_voice_frequency -#define _libgus_do_voice_pan gus_do_voice_pan -#define _libgus_do_voice_start gus_do_voice_start -#define _libgus_do_voice_start_position gus_do_voice_start_position -#define _libgus_do_voice_stop gus_do_voice_stop -#define _libgus_do_voice_volume gus_do_voice_volume -#define _libgus_do_wait gus_do_wait -#if LIBGUS_VERSION_MAJOR < 0x0004 -#define _libgus_get_handle gus_get_handle -#else -#define _libgus_get_file_descriptor gus_get_file_descriptor -#endif -#define _libgus_info gus_info -#define _libgus_memory_alloc gus_memory_alloc -#define _libgus_memory_free gus_memory_free -#define _libgus_memory_free_size gus_memory_free_size -#define _libgus_memory_pack gus_memory_pack -#define _libgus_open gus_open -#define _libgus_queue_flush gus_queue_flush -#define _libgus_queue_read_set_size gus_queue_read_set_size -#define _libgus_queue_write_set_size gus_queue_write_set_size -#define _libgus_reset gus_reset -#if LIBGUS_VERSION_MAJOR < 0x0004 -#define _libgus_select gus_select -#endif -#define _libgus_timer_start gus_timer_start -#define _libgus_timer_stop gus_timer_stop -#define _libgus_timer_tempo gus_timer_tempo -#endif - -#define libgus_cards _libgus_cards /* same between v3 and v4 */ -#define libgus_open _libgus_open /* different between v3 and v4: must use #ifdef */ -#define libgus_close _libgus_close /* different between v3 and v4: must use #ifdef */ -/* the following can be handled easily by macros: v4 only adds them the handle as the first param */ -#if LIBGUS_VERSION_MAJOR < 0x0004 -#define libgus_get_handle _libgus_get_handle /* only in v3 */ -#define libgus_do_flush _libgus_do_flush -#define libgus_do_tempo _libgus_do_tempo -#define libgus_do_voice_frequency _libgus_do_voice_frequency -#define libgus_do_voice_pan _libgus_do_voice_pan -#define libgus_do_voice_start _libgus_do_voice_start -#define libgus_do_voice_start_position _libgus_do_voice_start_position -#define libgus_do_voice_stop _libgus_do_voice_stop -#define libgus_do_voice_volume _libgus_do_voice_volume -#define libgus_do_wait _libgus_do_wait -#define libgus_info _libgus_info -#define libgus_memory_alloc _libgus_memory_alloc -#define libgus_memory_free _libgus_memory_free -#define libgus_memory_free_size _libgus_memory_free_size -#define libgus_memory_pack _libgus_memory_pack -#define libgus_queue_flush _libgus_queue_flush -#define libgus_queue_read_set_size _libgus_queue_read_set_size -#define libgus_queue_write_set_size _libgus_queue_write_set_size -#define libgus_reset _libgus_reset -#define libgus_select _libgus_select -#define libgus_timer_start _libgus_timer_start -#define libgus_timer_stop _libgus_timer_stop -#define libgus_timer_tempo _libgus_timer_tempo -#else -#define libgus_get_file_descriptor _libgus_get_file_descriptor /* only in v4 */ -#define libgus_do_flush() _libgus_do_flush(ultra_h) -#define libgus_do_tempo(t) _libgus_do_tempo(ultra_h,t) -#define libgus_do_voice_frequency(a,b) _libgus_do_voice_frequency(ultra_h,a,b) -#define libgus_do_voice_pan(a,b) _libgus_do_voice_pan(ultra_h,a,b) -#define libgus_do_voice_start(a,b,c,d,e) _libgus_do_voice_start(ultra_h,a,b,c,d,e) -#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) -#define libgus_do_voice_stop(a,b) _libgus_do_voice_stop(ultra_h,a,b) -#define libgus_do_voice_volume(a,b) _libgus_do_voice_volume(ultra_h,a,b) -#define libgus_do_wait(a) _libgus_do_wait(ultra_h,a) -#define libgus_info(a,b) _libgus_info(ultra_h,a,b) -#define libgus_memory_alloc(a) _libgus_memory_alloc(ultra_h,a) -#define libgus_memory_free(a) _libgus_memory_free(ultra_h,a) -#define libgus_memory_free_size() _libgus_memory_free_size(ultra_h) -#define libgus_memory_pack() _libgus_memory_pack(ultra_h) -#define libgus_queue_flush() _libgus_queue_flush(ultra_h) -#define libgus_queue_read_set_size(a) _libgus_queue_read_set_size(ultra_h,a) -#define libgus_queue_write_set_size(a) _libgus_queue_write_set_size(ultra_h,a) -#define libgus_reset(a,b) _libgus_reset(ultra_h,a,b) -#define libgus_timer_start() _libgus_timer_start(ultra_h) -#define libgus_timer_stop() _libgus_timer_stop(ultra_h) -#define libgus_timer_tempo(a) _libgus_timer_tempo(ultra_h,a) -#endif - -#define GUS_SAMPLES 256 /* Max. GUS samples loadable */ -#define GUS_CHANNELS 32 /* Max. GUS channels available */ -#define SIZE_OF_SEQBUF (8 * 1024) /* Size of the sequence buffer */ -#define ULTRA_PAN_MIDDLE (16383 >> 1) /* Middle balance position */ - -#define CH_FREQ 1 -#define CH_VOL 2 -#define CH_PAN 4 - -/* This structure holds the current state of a GUS voice channel. */ -typedef struct GUS_VOICE { - UBYTE kick; - UBYTE active; - UWORD flags; - SWORD handle; - ULONG start; - ULONG size; - ULONG reppos; - ULONG repend; - ULONG frq; - int vol; - int decvol; - int pan; - - int changes; -#ifndef HAVE_VOICE_STATUS - time_t started; -#endif -} GUS_VOICE; - -/* Global declarations follow */ - -static SAMPLE *samples[GUS_SAMPLES]; /* sample handles */ -static GUS_VOICE voices[GUS_CHANNELS]; /* channel status */ - -static int ultra_dev = 0; /* GUS index, if more than one card */ -#if LIBGUS_VERSION_MAJOR < 0x0004 -static int ultra_card = -1; /* returned by gus_open(ultra_dev,,) - must be same as ultra_dev */ -#else -static void* ultra_h = NULL; /* GUS handle */ -#endif -static int ultra_fd = -1; /* GUS file descriptor */ - - -#ifdef MIKMOD_DYNAMIC -static int Ultra_Link(void) -{ - if (libgus) - return 0; - - /* load libgus.so */ -#if LIBGUS_VERSION_MAJOR < 0x0004 - libgus = dlopen("libgus.so.3", RTLD_LAZY | RTLD_GLOBAL); -#else - libgus = dlopen("libgus.so.4", RTLD_LAZY | RTLD_GLOBAL); -#endif - if (!libgus) /* then this won't succeed either, but whatever.. */ - libgus = dlopen("libgus.so", RTLD_LAZY | RTLD_GLOBAL); - if (!libgus) - return 1; - - /* resolve function references */ -#define IMPORT_SYMBOL(x,ret,params) \ - if (!(_lib##x = (ret (*)params) dlsym(libgus, #x))) return 1 - - IMPORT_SYMBOL(gus_cards, int, (void)); -#if LIBGUS_VERSION_MAJOR < 0x0004 - IMPORT_SYMBOL(gus_close, int, (int)); - IMPORT_SYMBOL(gus_do_flush, int, (void)); - IMPORT_SYMBOL(gus_do_tempo, void, (unsigned int)); - IMPORT_SYMBOL(gus_do_voice_frequency, void, (unsigned char, unsigned int)); - IMPORT_SYMBOL(gus_do_voice_pan, void, (unsigned char, unsigned short)); - IMPORT_SYMBOL(gus_do_voice_start, void, (unsigned char, unsigned int, unsigned int, unsigned short, unsigned short)); - IMPORT_SYMBOL(gus_do_voice_start_position, void, (unsigned char, unsigned int, unsigned int, unsigned short, unsigned short, unsigned int)); - IMPORT_SYMBOL(gus_do_voice_stop, void, (unsigned char, unsigned char)); - IMPORT_SYMBOL(gus_do_voice_volume, void, (unsigned char, unsigned short)); - IMPORT_SYMBOL(gus_do_wait, void, (unsigned int)); - IMPORT_SYMBOL(gus_get_handle, int, (void)); - IMPORT_SYMBOL(gus_info, int, (gus_info_t *, int)); - IMPORT_SYMBOL(gus_memory_alloc, int, (gus_instrument_t *)); - IMPORT_SYMBOL(gus_memory_free, int, (gus_instrument_t *)); - IMPORT_SYMBOL(gus_memory_free_size, int, (void)); - IMPORT_SYMBOL(gus_memory_pack, int, (void)); - IMPORT_SYMBOL(gus_open, int, (int, size_t, int)); - IMPORT_SYMBOL(gus_queue_flush, int, (void)); - IMPORT_SYMBOL(gus_queue_read_set_size, int, (int)); - IMPORT_SYMBOL(gus_queue_write_set_size, int, (int)); - IMPORT_SYMBOL(gus_reset, int, (int, unsigned int)); - IMPORT_SYMBOL(gus_select, int, (int)); - IMPORT_SYMBOL(gus_timer_start, int, (void)); - IMPORT_SYMBOL(gus_timer_stop, int, (void)); - IMPORT_SYMBOL(gus_timer_tempo, int, (int)); -#else - IMPORT_SYMBOL(gus_close, int, (void*)); - IMPORT_SYMBOL(gus_do_flush, int, (void*)); - IMPORT_SYMBOL(gus_do_tempo, void, (void*, unsigned int)); - IMPORT_SYMBOL(gus_do_voice_frequency, void, (void*, unsigned char, unsigned int)); - IMPORT_SYMBOL(gus_do_voice_pan, void, (void*, unsigned char, unsigned short)); - IMPORT_SYMBOL(gus_do_voice_start, void, (void*, unsigned char, unsigned int, unsigned int, unsigned short, unsigned short)); - IMPORT_SYMBOL(gus_do_voice_start_position, void, (void*, unsigned char, unsigned int, unsigned int, unsigned short, unsigned short, unsigned int)); - IMPORT_SYMBOL(gus_do_voice_stop, void, (void*, unsigned char, unsigned char)); - IMPORT_SYMBOL(gus_do_voice_volume, void, (void*, unsigned char, unsigned short)); - IMPORT_SYMBOL(gus_do_wait, void, (void*, unsigned int)); - IMPORT_SYMBOL(gus_get_file_descriptor, int, (void*)); - IMPORT_SYMBOL(gus_info, int, (void*, gus_info_t *, int)); - IMPORT_SYMBOL(gus_memory_alloc, int, (void*, gus_instrument_t *)); - IMPORT_SYMBOL(gus_memory_free, int, (void*, gus_instrument_t *)); - IMPORT_SYMBOL(gus_memory_free_size, int, (void*)); - IMPORT_SYMBOL(gus_memory_pack, int, (void*)); - IMPORT_SYMBOL(gus_open, int, (void**, int, int, size_t, int)); - IMPORT_SYMBOL(gus_queue_flush, int, (void*)); - IMPORT_SYMBOL(gus_queue_read_set_size, int, (void*, int)); - IMPORT_SYMBOL(gus_queue_write_set_size, int, (void*, int)); - IMPORT_SYMBOL(gus_reset, int, (void*, int, unsigned int)); - IMPORT_SYMBOL(gus_timer_start, int, (void*)); - IMPORT_SYMBOL(gus_timer_stop, int, (void*)); - IMPORT_SYMBOL(gus_timer_tempo, int, (void*, int)); -#endif -#undef IMPORT_SYMBOL - - return 0; -} - -static void Ultra_Unlink(void) -{ - _libgus_cards = NULL; - _libgus_close = NULL; - _libgus_do_flush = NULL; - _libgus_do_tempo = NULL; - _libgus_do_voice_frequency = NULL; - _libgus_do_voice_pan = NULL; - _libgus_do_voice_start = NULL; - _libgus_do_voice_start_position = NULL; - _libgus_do_voice_stop = NULL; - _libgus_do_voice_volume = NULL; - _libgus_do_wait = NULL; -#if LIBGUS_VERSION_MAJOR < 0x0004 - _libgus_get_handle = NULL; -#else - _libgus_get_file_descriptor = NULL; -#endif - _libgus_info = NULL; - _libgus_memory_alloc = NULL; - _libgus_memory_free = NULL; - _libgus_memory_free_size = NULL; - _libgus_memory_pack = NULL; - _libgus_open = NULL; - _libgus_queue_flush = NULL; - _libgus_queue_read_set_size = NULL; - _libgus_queue_write_set_size = NULL; - _libgus_reset = NULL; -#if LIBGUS_VERSION_MAJOR < 0x0004 - _libgus_select = NULL; -#endif - _libgus_timer_start = NULL; - _libgus_timer_stop = NULL; - _libgus_timer_tempo = NULL; - - if (libgus) { - dlclose(libgus); - libgus = NULL; - } -} -#endif - -static void Ultra_CommandLine(const CHAR *cmdline) -{ - CHAR *ptr = MD_GetAtom("card", cmdline, 0); - - if (ptr) { - int buf = atoi(ptr); - - if (buf >= 0 && buf <= 8) - ultra_dev = buf; - MikMod_free(ptr); - } -#ifdef __DJGPP__ - ptr = MD_GetAtom("dma", cmdline, 0); - if (ptr) { - gus_dma_usage (atoi(ptr)); - MikMod_free(ptr); - } -#endif -} - -/* Checks for the presence of GUS cards */ -static BOOL Ultra_IsThere(void) -{ - BOOL retval; - -#ifdef MIKMOD_DYNAMIC - if (Ultra_Link()) - return 0; -#endif - retval = libgus_cards()? 1 : 0; -#ifdef MIKMOD_DYNAMIC - Ultra_Unlink(); -#endif - return retval; -} - -/* Load a new sample directly into GUS DRAM and return a handle */ -static SWORD Ultra_SampleLoad(struct SAMPLOAD *sload, int type) -{ - int handle; - SAMPLE *s = sload->sample; - gus_instrument_t instrument; - gus_layer_t layer; - gus_wave_t wave; - unsigned char *buffer; - unsigned int length, loopstart, loopend; - - /* Find empty slot to put sample in */ - for (handle = 0; handle < GUS_SAMPLES; handle++) - if (!samples[handle]) - break; - - if (handle == GUS_SAMPLES) { - _mm_errno = MMERR_OUT_OF_HANDLES; - return -1; - } - - /* Fill an gus_instrument_t structure and feed it to libgus. We can - download 8 and 16 bit, both signed and unsigned samples into GUS, so - don't bother much about formats here. */ - - /* convert position/length data from samples to bytes */ - length = s->length; - loopstart = s->loopstart; - loopend = s->loopend ? s->loopend : length; - /* sanity checks */ - if (loopend > length) - loopend = length; - if (loopstart > loopend) - loopstart = loopend; - if (s->flags & SF_16BITS) { - length <<= 1; - loopstart <<= 1; - loopend <<= 1; - } - - /* Load sample into normal memory */ - if (!(buffer = (unsigned char *) MikMod_malloc(length))) { - _mm_errno = MMERR_SAMPLE_TOO_BIG; - return -1; - } - - if (SL_Load(buffer, sload, s->length)) { - MikMod_free(buffer); - return -1; - } - - samples[handle] = s; - - memset(&wave, 0, sizeof(wave)); - memset(&layer, 0, sizeof(layer)); - memset(&instrument, 0, sizeof(instrument)); - - wave.format = - ((s->flags & SF_SIGNED) ? 0 : GUS_WAVE_INVERT) | - ((s->flags & SF_16BITS) ? GUS_WAVE_16BIT : 0) | - ((s->flags & SF_DELTA ) ? GUS_WAVE_DELTA : 0) | - ((s->flags & SF_LOOP ) ? GUS_WAVE_LOOP : 0) | - ((s->flags & SF_BIDI ) ? GUS_WAVE_BIDIR : 0); - wave.begin.ptr = buffer; - wave.loop_start = loopstart << 4; - wave.loop_end = loopend << 4; - wave.size = length; - - layer.wave = &wave; - - instrument.mode = layer.mode = wave.mode = GUS_INSTR_SIMPLE; - instrument.number.instrument = handle; - instrument.info.layer = &layer; - - /* Download the sample to GUS RAM */ - if (libgus_memory_alloc(&instrument)) { - MikMod_free(buffer); - _mm_errno = MMERR_SAMPLE_TOO_BIG; - return -1; - } - - MikMod_free(buffer); - return handle; -} - -/* Discards a sample from the GUS memory and mark handle as free */ -static void Ultra_SampleUnload(SWORD handle) -{ - gus_instrument_t instrument; - - if (handle >= GUS_SAMPLES || handle < 0 || !samples[handle]) - return; - - memset(&instrument, 0, sizeof(instrument)); - instrument.mode = GUS_INSTR_SIMPLE; - instrument.number.instrument = handle; - libgus_memory_free(&instrument); - samples[handle] = NULL; -} - -/* Reports available sample space */ -static ULONG Ultra_SampleSpace(int type) -{ - libgus_memory_pack(); - return (libgus_memory_free_size()); -} - -/* Reports the size of a sample */ -static ULONG Ultra_SampleLength(int type, SAMPLE *s) -{ - if (!s) - return 0; - - if (s->flags & SF_16BITS) - return ((s->length << 1) + 31) & ~31; - else - return ( s->length + 15) & ~15; -} - -/* Initializes the driver */ -static int Ultra_Init_internal(void) -{ - gus_info_t info; - -#if LIBGUS_VERSION_MAJOR < 0x0004 - if ((ultra_card = libgus_open(ultra_dev, SIZE_OF_SEQBUF, 0)) < 0) { - _mm_errno = (errno == ENOMEM)? MMERR_OUT_OF_MEMORY : MMERR_INVALID_DEVICE; - return 1; - } - libgus_select(ultra_card); - ultra_fd = libgus_get_handle(); -#else - if (libgus_open(&ultra_h, ultra_dev, 0, SIZE_OF_SEQBUF, GUS_OPEN_FLAG_NONE) < 0) { - _mm_errno = (errno == ENOMEM)? MMERR_OUT_OF_MEMORY : MMERR_INVALID_DEVICE; - return 1; - } - ultra_fd = libgus_get_file_descriptor(ultra_h); -#endif - - /* We support only 16-bit stereo with 44K mixing frequency. On UltraSound - Classic mixing frequency depends on number of channels, on Interwave it - is always 44KHz. */ - md_mode |= DMODE_16BITS | DMODE_STEREO; - md_mixfreq = info.mixing_freq; - - libgus_info(&info, 0); -#ifdef MIKMOD_DEBUG - switch (info.version) { - case 0x24: - fputs("GUS 2.4", stderr); - break; - case 0x35: - fputs("GUS 3.7 (flipped)", stderr); - break; - case 0x37: - fputs("GUS 3.7", stderr); - break; - case 0x90: - fputs("GUS ACE", stderr); - break; - case 0xa0: - fputs("GUS MAX 10", stderr); - break; - case 0xa1: - fputs("GUS MAX 11", stderr); - break; - case 0x100: - fputs("Interwave/GUS PnP", stderr); - break; - default: - fprintf(stderr, "Unknown GUS type %x", info.version); - break; - } - fprintf(stderr, " with %dKb RAM on board\n", info.memory_size >> 10); -#endif - - /* Zero the voice states and sample handles */ - memset (&voices, 0, sizeof (voices)); - memset (&samples, 0, sizeof (samples)); - - return 0; -} - -static int Ultra_Init(void) -{ -#ifdef MIKMOD_DYNAMIC - if (Ultra_Link()) { - _mm_errno = MMERR_DYNAMIC_LINKING; - return 1; - } -#endif - return Ultra_Init_internal(); -} - -/* Closes the driver */ -static void Ultra_Exit_internal(void) -{ -#if LIBGUS_VERSION_MAJOR < 0x0004 - if (ultra_card >= 0) { - ultra_card = -1; - libgus_close(ultra_dev); - } -#else - if (ultra_h) { - libgus_close(ultra_h); - ultra_h = NULL; - } -#endif - ultra_fd = -1; -} - -static void Ultra_Exit(void) -{ - Ultra_Exit_internal(); -#ifdef MIKMOD_DYNAMIC - Ultra_Unlink(); -#endif -} - -/* Poor man's reset function */ -static int Ultra_Reset(void) -{ - Ultra_Exit_internal(); - return Ultra_Init_internal(); -} - -static int Ultra_SetNumVoices(void) -{ - return 0; -} - -/* Module player tick function */ -static void UltraPlayer(void) -{ - int channel, panning; - struct GUS_VOICE *voice; - static BOOL ultra_pause = 1; /* paused status */ - - md_player(); - - if (ultra_pause != Player_Paused()) - if ((ultra_pause = Player_Paused())) - for (channel = 0, voice = voices; channel < md_numchn; - channel++, voice++) { - libgus_do_voice_volume (channel, 0); - voices->changes |= (CH_VOL | CH_FREQ | CH_PAN); - } - - if (ultra_pause) - return; - - for (channel = 0, voice = voices; channel < md_numchn; channel++, voice++) { - panning = (voice->pan == PAN_SURROUND) ? - ULTRA_PAN_MIDDLE : (voice->pan << 6); - - if (voice->kick) { - voice->kick = 0; - voice->decvol = voice->vol; - if (voice->start > 0) - libgus_do_voice_start_position(channel, voice->handle, - voice->frq, voice->vol << 6, panning, voice->start << 4); - else - libgus_do_voice_start(channel, voice->handle, voice->frq, - voice->vol << 6, voice->pan << 6); - } else { - if (voice->changes & CH_FREQ) - libgus_do_voice_frequency(channel, voice->frq); - if (voice->changes & CH_VOL) - libgus_do_voice_volume(channel, voice->vol << 6); - if (voice->changes & CH_PAN) - libgus_do_voice_pan(channel, panning); - if (voice->decvol) - voice->decvol -= 4; - } - voice->changes = 0; - } -} - -/* Play sound */ -#if defined(__DJGPP__) || defined(__EMX__) -static void Ultra_Callback(void) -{ - UltraPlayer(); - libgus_do_flush(); -} - -static void Ultra_Update(void) -{ - static UWORD ultra_bpm = 0; /* current GUS tempo */ - - /* All real work is done during GF1 timer 1 interrupt */ - if (ultra_bpm != md_bpm) { - libgus_do_tempo((md_bpm * 50) / 125); - ultra_bpm = md_bpm; - } -} - -#else -static void Ultra_Update(void) -{ - fd_set write_fds; - int need_write; - static UWORD ultra_bpm = 0; /* current GUS tempo */ - - if (ultra_bpm != md_bpm) { - libgus_do_tempo((md_bpm * 50) / 125); - ultra_bpm = md_bpm; - } - - UltraPlayer(); - - do { - need_write = libgus_do_flush(); - - FD_ZERO(&write_fds); - do { - FD_SET(ultra_fd, &write_fds); - - select(ultra_fd + 1, NULL, &write_fds, NULL, NULL); - } while (!FD_ISSET(ultra_fd, &write_fds)); - } while(need_write > 0); - - /* Wait so that all voice commands gets executed */ - libgus_do_wait (1); -} - -#endif - -/* Start playback */ -static int Ultra_PlayStart(void) -{ - int t; - gus_info_t info; - - for (t = 0; t < md_numchn; t++) { - voices[t].flags = 0; - voices[t].handle = 0; - voices[t].size = 0; - voices[t].start = 0; - voices[t].reppos = 0; - voices[t].repend = 0; - voices[t].changes = 0; - voices[t].kick = 0; - voices[t].frq = 10000; - voices[t].vol = 0; - voices[t].pan = ULTRA_PAN_MIDDLE; - voices[t].active = 0; - } - -#if LIBGUS_VERSION_MAJOR < 0x0004 - libgus_select(ultra_card); -#endif - if (libgus_reset(md_numchn, 0) < 0) { - _mm_errno = MMERR_GUS_RESET; - return 1; - } - - /* Query mixing frequency */ - libgus_info(&info, 0); - md_mixfreq = info.mixing_freq; - - libgus_queue_write_set_size(1024); - libgus_queue_read_set_size(128); - - if (libgus_timer_start() < 0) { - _mm_errno = MMERR_GUS_TIMER; - return 1; - } - -#if defined(__DJGPP__) || defined(__EMX__) - gus_timer_callback(Ultra_Callback); -#endif - - libgus_timer_tempo(50); - - for (t = 0; t < md_numchn; t++) { - libgus_do_voice_pan(t, ULTRA_PAN_MIDDLE); - libgus_do_voice_volume(t, 0 << 8); - } - - libgus_do_flush(); - - return 0; -} - -/* Stop playback */ -static void Ultra_PlayStop(void) -{ - int voice; - - libgus_queue_flush(); - libgus_timer_stop(); - libgus_queue_write_set_size(0); - libgus_queue_read_set_size(0); - for(voice = 0; voice < md_numchn; voice++) - libgus_do_voice_stop(voice, 0); - -#if defined(__DJGPP__) || defined(__EMX__) - gus_timer_callback(NULL); -#endif - - libgus_do_flush(); -} - -/* Set the volume for the given voice */ -static void Ultra_VoiceSetVolume(UBYTE voice, UWORD vol) -{ - if (voice < md_numchn) - if (vol != voices[voice].vol) { - voices[voice].decvol = - voices[voice].vol = vol; - voices[voice].changes |= CH_VOL; - } -} - -/* Returns the volume of the given voice */ -static UWORD Ultra_VoiceGetVolume(UBYTE voice) -{ - return (voice < md_numchn) ? voices[voice].vol : 0; -} - -/* Set the pitch for the given voice */ -static void Ultra_VoiceSetFrequency(UBYTE voice, ULONG frq) -{ - if (voice < md_numchn) - if (frq != voices[voice].frq) { - voices[voice].frq = frq; - voices[voice].changes |= CH_FREQ; - } -} - -/* Returns the frequency of the given voice */ -static ULONG Ultra_VoiceGetFrequency(UBYTE voice) -{ - return (voice < md_numchn) ? voices[voice].frq : 0; -} - -/* Set the panning position for the given voice */ -static void Ultra_VoiceSetPanning(UBYTE voice, ULONG pan) -{ - if (voice < md_numchn) - if (pan != voices[voice].pan) { - voices[voice].pan = pan; - voices[voice].changes |= CH_PAN; - } -} - -/* Returns the panning of the given voice */ -static ULONG Ultra_VoiceGetPanning(UBYTE voice) -{ - return (voice < md_numchn) ? voices[voice].pan : 0; -} - -/* Start a new sample on a voice */ -static void Ultra_VoicePlay(UBYTE voice, SWORD handle, ULONG start, - ULONG size, ULONG reppos, ULONG repend, - UWORD flags) -{ - if ((voice >= md_numchn) || (start >= size)) - return; - - if (flags & SF_LOOP) - if (repend > size) - repend = size; - - voices[voice].flags = flags; - voices[voice].handle = handle; - voices[voice].start = start; - voices[voice].size = size; - voices[voice].reppos = reppos; - voices[voice].repend = repend; - voices[voice].kick = 1; - voices[voice].active = 1; -#ifndef HAVE_VOICE_STATUS - voices[voice].started = time(NULL); -#endif -} - -/* Stops a voice */ -static void Ultra_VoiceStop(UBYTE voice) -{ - if (voice < md_numchn) - voices[voice].active = 0; -} - -/* Returns whether a voice is stopped */ -static BOOL Ultra_VoiceStopped(UBYTE voice) -{ - if (voice >= md_numchn) - return 1; - -#ifdef HAVE_VOICE_STATUS - if (voices[voice].active) - return gus_get_voice_status(voice) ? 0 : 1; - else - return 1; -#else - if (voices[voice].active) { - /* is sample looping ? */ - if (voices[voice].flags & (SF_LOOP | SF_BIDI)) - return 0; - else - if (time(NULL) - voices[voice].started >= - ((voices[voice].size - voices[voice].start + md_mixfreq -1) - / md_mixfreq)) { - voices[voice].active = 0; - return 1; - } - return 0; - } else - return 1; -#endif -} - -/* Returns current voice position */ -static SLONG Ultra_VoiceGetPosition(UBYTE voice) -{ - /* NOTE This information can not be determined. */ - return -1; -} - -/* Returns voice real volume */ -static ULONG Ultra_VoiceRealVolume(UBYTE voice) -{ - int retval = 0; - if (!Ultra_VoiceStopped (voice)) { - /* NOTE This information can not be accurately determined. */ - retval = (voices [voice].decvol) << 8; - if (retval > 0xffff) retval = 0xffff; - } - return retval; -} - -MDRIVER drv_ultra = { - NULL, - "Gravis Ultrasound native mode", - "Gravis Ultrasound native mode driver v1.2", - 0, (GUS_CHANNELS)-1, - "ultra", -#ifdef __DJGPP__ - "dma:b:1:Use DMA for transferring samples into GUS DRAM\n" -#endif - "card:r:0,8,0:Soundcard number\n", - - Ultra_CommandLine, - Ultra_IsThere, - Ultra_SampleLoad, - Ultra_SampleUnload, - Ultra_SampleSpace, - Ultra_SampleLength, - Ultra_Init, - Ultra_Exit, - Ultra_Reset, - Ultra_SetNumVoices, - Ultra_PlayStart, - Ultra_PlayStop, - Ultra_Update, - NULL, - Ultra_VoiceSetVolume, - Ultra_VoiceGetVolume, - Ultra_VoiceSetFrequency, - Ultra_VoiceGetFrequency, - Ultra_VoiceSetPanning, - Ultra_VoiceGetPanning, - Ultra_VoicePlay, - Ultra_VoiceStop, - Ultra_VoiceStopped, - Ultra_VoiceGetPosition, - Ultra_VoiceRealVolume -}; -#else - -MISSING(drv_ultra); - -#endif /* DRV_ULTRA */ - -/* ex:set ts=8: */