dropping SDL for the cross-platform version almost done
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Jun 2020 04:08:58 +0000 (07:08 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 16 Jun 2020 04:08:58 +0000 (07:08 +0300)
24 files changed:
GNUmakefile
libs/mikmod/config.h
libs/mikmod/drivers/dos/dosdma.c [deleted file]
libs/mikmod/drivers/dos/dosdma.h [deleted file]
libs/mikmod/drivers/dos/dosgus.c [deleted file]
libs/mikmod/drivers/dos/dosgus.h [deleted file]
libs/mikmod/drivers/dos/dosirq.c [deleted file]
libs/mikmod/drivers/dos/dosirq.h [deleted file]
libs/mikmod/drivers/dos/dossb.c [deleted file]
libs/mikmod/drivers/dos/dossb.h [deleted file]
libs/mikmod/drivers/dos/doswss.c [deleted file]
libs/mikmod/drivers/dos/doswss.h [deleted file]
libs/mikmod/drivers/dos/libgus.h [deleted file]
libs/mikmod/drivers/drv_alsa.c [new file with mode: 0644]
libs/mikmod/drivers/drv_ds.c [new file with mode: 0644]
libs/mikmod/drivers/drv_sb.c [deleted file]
libs/mikmod/drivers/drv_sgi.c [new file with mode: 0644]
libs/mikmod/drivers/drv_ultra.c [deleted file]
libs/mikmod/drivers/drv_wss.c [deleted file]
libs/mikmod/posix/strcasecmp.c [deleted file]
libs/mikmod/posix/strccmp.c [new file with mode: 0644]
src/cfgopt.c
src/cfgopt.h
src/demo.h

index a6c9936..c6e94c2 100644 (file)
@@ -1,4 +1,5 @@
-src = $(wildcard src/*.c) $(wildcard src/scr/*.c) $(wildcard src/glut/*.c)
+src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) \
+         $(wildcard src/glut/*.c)
 asmsrc = $(wildcard src/*.asm)
 obj = $(src:.c=.o) $(asmsrc:.asm=.o)
 dep = $(obj:.o=.d)
index 24caf3c..1872753 100644 (file)
@@ -1,87 +1,51 @@
+#ifndef MIKMOD_CONFIG_H_
+#define MIKMOD_CONFIG_H_
+
+#define HAVE_INTTYPES_H 1
 #define HAVE_LIMITS_H 1
+#define HAVE_MALLOC_H 1
 #define HAVE_MEMCMP 1
+#define HAVE_MEMORY_H 1
+#define HAVE_POSIX_MEMALIGN 1
+#define HAVE_SETENV 1
 #define HAVE_STDLIB_H 1
+#define HAVE_STRINGS_H 1
 #define HAVE_STRING_H 1
 #define HAVE_STRSTR 1
 
-#ifdef DOS
-#define DRV_SB 1
-#define DRV_ULTRA 1
-#define DRV_WSS 1
-
-#define HAVE_UNISTD_H 1
-#define HAVE_FCNTL_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_IOCTL_H 1
+#if !defined(_MSC_VER) || _MSC_VER >= 1800
+#define HAVE_STDINT_H 1
+#define HAVE_SNPRINTF 1
 #endif
 
-#if defined(__unix__) || defined(__APPLE__)
-#define DRV_SDL 1
-
+#ifdef __unix__
+#define HAVE_DLFCN_H 1
+#define HAVE_RTLD_GLOBAL 1
 #define HAVE_FCNTL_H 1
-#define HAVE_INTTYPES_H 1
 #define HAVE_SYS_IOCTL_H 1
-#define HAVE_SNPRINTF 1
 #define HAVE_SYS_STAT_H 1
 #define HAVE_SYS_TYPES_H 1
 #define HAVE_SYS_WAIT_H 1
 #define HAVE_UNISTD_H 1
-#define HAVE_POSIX_MEMALIGN 1
 #define HAVE_PTHREAD 1
-#define HAVE_SETENV 1
-#define HAVE_SRANDOM 1
-
-#define MIKMOD_UNIX 1
 #endif
 
+#define STDC_HEADERS 1
 
-#if defined(WIN32)
-#define DRV_SDL 1
-
-#define HAVE_WINDOWS_H 1
-#define HAVE_MALLOC_H 1
-
-#define NO_SDL_CONFIG 1
+#ifdef __linux__
+#define DRV_ALSA       1
 #endif
 
-#undef MIKMOD_DEBUG
-
-/* disable the high quality mixer (build only with the standart mixer) */
-#undef NO_HQMIXER
-
-/* Name of package */
-#undef PACKAGE
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Version number of package */
-#undef VERSION
+#ifdef __FreeBSD__
+#define DRV_OSS                1
+#endif
 
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-   significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-#  define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-#  undef WORDS_BIGENDIAN
-# endif
+#ifdef __sgi__
+#define DRV_SGI                1
 #endif
 
-/* Define to `__inline__' or `__inline' if that's what the C compiler
-   calls it, or to nothing if 'inline' is not supported under any name.  */
-#if !defined(__cplusplus) && defined(_MSC_VER)
-#define inline __inline
+#ifdef _WIN32
+#define DRV_DS 1
 #endif
+
+#endif /* MIKMOD_CONFIG_H_ */
diff --git a/libs/mikmod/drivers/dos/dosdma.c b/libs/mikmod/drivers/dos/dosdma.c
deleted file mode 100644 (file)
index e232c30..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
-    Implementation of DMA routines on DOS
-    Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
-
-    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 library 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "dosdma.h"
-
-#include <go32.h> /* includes sys/version.h (djgpp >= 2.02) */
-#include <dos.h>
-#include <dpmi.h>
-#include <sys/nearptr.h>
-#include <malloc.h>
-#include "mikmod.h" /* for MikMod_malloc() & co */
-
-/* BUG WARNING:  there is an error in DJGPP libraries <= 2.01:
- * src/libc/dpmi/api/d0102.s loads the selector and allocsize
- * arguments in the wrong order.  DJGPP >= 2.02 have it fixed. */
-#if (!defined(__DJGPP_MINOR__) || (__DJGPP_MINOR__+0) < 2)
-#warning __dpmi_resize_dos_memory() from DJGPP <= 2.01 is broken!
-#endif
-
-__dma_regs dma[8] = {
-/* *INDENT-OFF* */
-       {DMA_ADDR_0, DMA_PAGE_0, DMA_SIZE_0,
-        DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},
-       {DMA_ADDR_1, DMA_PAGE_1, DMA_SIZE_1,
-        DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},
-
-       {DMA_ADDR_2, DMA_PAGE_2, DMA_SIZE_2,
-        DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},
-       {DMA_ADDR_3, DMA_PAGE_3, DMA_SIZE_3,
-        DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},
-
-       {DMA_ADDR_4,          0, DMA_SIZE_4,
-        DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},
-       {DMA_ADDR_5, DMA_PAGE_5, DMA_SIZE_5,
-        DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},
-
-       {DMA_ADDR_6, DMA_PAGE_6, DMA_SIZE_6,
-        DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},
-       {DMA_ADDR_7, DMA_PAGE_7, DMA_SIZE_7,
-        DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG}
-/* *INDENT-ON* */
-};
-
-static int __initialized = 0;
-static int __buffer_count = 0;
-static __dpmi_meminfo __locked_data;
-
-int dma_initialize()
-{
-       if (!__djgpp_nearptr_enable())
-               return 0;
-
-       /* Trick: Avoid re-setting DS selector limit on each memory allocation
-          call */
-       __djgpp_selector_limit = 0xffffffff;
-
-       __locked_data.address = __djgpp_base_address + (unsigned long)&dma;
-       __locked_data.size = sizeof(dma);
-       if (__dpmi_lock_linear_region(&__locked_data))
-               return 0;
-
-       return (__initialized = 1);
-}
-
-void dma_finalize()
-{
-       if (!__initialized)
-               return;
-       __dpmi_unlock_linear_region(&__locked_data);
-       __djgpp_nearptr_disable();
-}
-
-dma_buffer *dma_allocate(unsigned int channel, unsigned int size)
-{
-       int parsize = (size + 15) >> 4; /* size in paragraphs */
-       int par = 0;                            /* Real-mode paragraph */
-       int selector = 0;                       /* Protected-mode selector */
-       int mask = channel <= 3 ? 0xfff : 0x1fff;       /* Alignment mask in para. */
-       int allocsize = parsize;        /* Allocated size in paragraphs */
-       int count;                                      /* Try count */
-       int bound = 0;                          /* Nearest bound address */
-       int maxsize;                            /* Maximal possible block size */
-       dma_buffer *buffer = NULL;
-       __dpmi_meminfo buff_info, struct_info;
-
-       if (!dma_initialize())
-               return NULL;
-
-       /* Loop until we'll get a properly aligned memory block */
-       for (count = 8; count; count--) {
-               int resize = (selector != 0);
-
-               /* Try first to resize (possibly previously) allocated block */
-               if (resize) {
-                       maxsize = (bound + parsize) - par;
-                       if (maxsize > parsize * 2)
-                               maxsize = parsize * 2;
-                       if (maxsize == allocsize)
-                               resize = 0;
-                       else {
-                               allocsize = maxsize;
-                               if (__dpmi_resize_dos_memory(selector, allocsize, &maxsize) !=
-                                       0) resize = 0;
-                       }
-               }
-
-               if (!resize) {
-                       if (selector)
-                               __dpmi_free_dos_memory(selector), selector = 0;
-                       par = __dpmi_allocate_dos_memory(allocsize, &selector);
-               }
-
-               if ((par == 0) || (par == -1))
-                       goto exit;
-
-               /* If memory block contains a properly aligned portion, quit loop */
-               bound = (par + mask + 1) & ~mask;
-               if (par + parsize <= bound)
-                       break;
-               if (bound + parsize <= par + allocsize) {
-                       par = bound;
-                       break;
-               }
-       }
-       if (!count) {
-               __dpmi_free_dos_memory(selector);
-               goto exit;
-       }
-
-       buffer = (dma_buffer *) MikMod_malloc(sizeof(dma_buffer));
-       buffer->linear = (unsigned char *)(__djgpp_conventional_base + bound * 16);
-       buffer->physical = bound * 16;
-       buffer->size = parsize * 16;
-       buffer->selector = selector;
-       buffer->channel = channel;
-
-       buff_info.address = buffer->physical;
-       buff_info.size = buffer->size;
-       /*
-          Don't pay attention to return code since under plain DOS it often
-          returns error (at least under HIMEM/CWSDPMI and EMM386/DPMI)
-        */
-       __dpmi_lock_linear_region(&buff_info);
-
-       /* Lock the DMA buffer control structure as well */
-       struct_info.address = __djgpp_base_address + (unsigned long)buffer;
-       struct_info.size = sizeof(dma_buffer);
-       if (__dpmi_lock_linear_region(&struct_info)) {
-               __dpmi_unlock_linear_region(&buff_info);
-               __dpmi_free_dos_memory(selector);
-               MikMod_free(buffer);
-               buffer = NULL;
-               goto exit;
-       }
-
-  exit:
-       if (buffer)
-               __buffer_count++;
-       else if (--__buffer_count == 0)
-               dma_finalize();
-       return buffer;
-}
-
-void dma_free(dma_buffer * buffer)
-{
-       __dpmi_meminfo buff_info;
-
-       if (!buffer)
-               return;
-
-       buff_info.address = buffer->physical;
-       buff_info.size = buffer->size;
-       __dpmi_unlock_linear_region(&buff_info);
-
-       __dpmi_free_dos_memory(buffer->selector);
-       MikMod_free(buffer);
-
-       if (--__buffer_count == 0)
-               dma_finalize();
-}
-
-void dma_start(dma_buffer * buffer, unsigned long count, unsigned char mode)
-{
-       /* Disable interrupts */
-       int old_ints = disable();
-       dma_disable(buffer->channel);
-       dma_set_mode(buffer->channel, mode);
-       dma_clear_ff(buffer->channel);
-       dma_set_addr(buffer->channel, buffer->physical);
-       dma_clear_ff(buffer->channel);
-       dma_set_count(buffer->channel, count);
-       dma_enable(buffer->channel);
-       /* Re-enable interrupts */
-       if (old_ints)
-               enable();
-}
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dosdma.h b/libs/mikmod/drivers/dos/dosdma.h
deleted file mode 100644 (file)
index 882c9ac..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-    Interface for DMA routines on DOS
-    Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
-
-    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 library 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __DOSDMA_H__
-#define __DOSDMA_H__
-
-#include <pc.h>
-
-#define DMA1_BASE              0x00    /* 8 bit slave DMA, channels 0..3 */
-#define DMA2_BASE              0xC0    /* 16 bit master DMA, ch 4(=slave input)..7 */
-
-#define DMA1_CMD_REG           0x08    /* command register (w) */
-#define DMA1_STAT_REG          0x08    /* status register (r) */
-#define DMA1_REQ_REG           0x09    /* request register (w) */
-#define DMA1_MASK_REG          0x0A    /* single-channel mask (w) */
-#define DMA1_MODE_REG          0x0B    /* mode register (w) */
-#define DMA1_CLEAR_FF_REG      0x0C    /* clear pointer flip-flop (w) */
-#define DMA1_TEMP_REG          0x0D    /* Temporary Register (r) */
-#define DMA1_RESET_REG         0x0D    /* Master Clear (w) */
-#define DMA1_CLR_MASK_REG      0x0E    /* Clear Mask */
-#define DMA1_MASK_ALL_REG      0x0F    /* all-channels mask (w) */
-
-#define DMA2_CMD_REG           0xD0    /* command register (w) */
-#define DMA2_STAT_REG          0xD0    /* status register (r) */
-#define DMA2_REQ_REG           0xD2    /* request register (w) */
-#define DMA2_MASK_REG          0xD4    /* single-channel mask (w) */
-#define DMA2_MODE_REG          0xD6    /* mode register (w) */
-#define DMA2_CLEAR_FF_REG      0xD8    /* clear pointer flip-flop (w) */
-#define DMA2_TEMP_REG          0xDA    /* Temporary Register (r) */
-#define DMA2_RESET_REG         0xDA    /* Master Clear (w) */
-#define DMA2_CLR_MASK_REG      0xDC    /* Clear Mask */
-#define DMA2_MASK_ALL_REG      0xDE    /* all-channels mask (w) */
-
-#define DMA_ADDR_0      0x00   /* DMA address registers */
-#define DMA_ADDR_1      0x02
-#define DMA_ADDR_2      0x04
-#define DMA_ADDR_3      0x06
-#define DMA_ADDR_4      0xC0
-#define DMA_ADDR_5      0xC4
-#define DMA_ADDR_6      0xC8
-#define DMA_ADDR_7      0xCC
-
-#define DMA_SIZE_0             0x01    /* DMA transfer size registers */
-#define DMA_SIZE_1             0x03
-#define DMA_SIZE_2             0x05
-#define DMA_SIZE_3             0x07
-#define DMA_SIZE_4             0xC2
-#define DMA_SIZE_5             0xC6
-#define DMA_SIZE_6             0xCA
-#define DMA_SIZE_7             0xCE
-
-#define DMA_PAGE_0      0x87   /* DMA page registers */
-#define DMA_PAGE_1      0x83
-#define DMA_PAGE_2      0x81
-#define DMA_PAGE_3      0x82
-#define DMA_PAGE_5      0x8B
-#define DMA_PAGE_6      0x89
-#define DMA_PAGE_7      0x8A
-
-#define DMA_MODE_AUTOINIT      0x10    /* Auto-init mode bit */
-#define DMA_MODE_READ          0x44    /* I/O to memory, no autoinit, increment, single mode */
-#define DMA_MODE_WRITE         0x48    /* memory to I/O, no autoinit, increment, single mode */
-#define DMA_MODE_CASCADE       0xC0    /* pass thru DREQ->HRQ, DACK<-HLDA only */
-
-/* Indexable specific DMA registers */
-typedef struct __dma_regs_s {
-       unsigned char addr;                     /* DMA transfer address register */
-       unsigned char page;                     /* DMA page register */
-       unsigned char size;                     /* DMA transfer size register */
-       unsigned char mask;                     /* DMA mask/unmask register */
-       unsigned char flip;                     /* DMA flip-flop reset register */
-       unsigned char mode;                     /* DMA mode register */
-} __dma_regs;
-
-extern __dma_regs dma[8];
-
-/* Enable a specific DMA channel */
-static inline void dma_enable(unsigned int channel)
-{
-       outportb(dma[channel].mask, channel & 3);
-}
-
-/* Disable a specific DMA channel */
-static inline void dma_disable(unsigned int channel)
-{
-       outportb(dma[channel].mask, (channel & 3) | 0x04);
-}
-
-/* Clear the 'DMA Flip Flop' flag */
-static inline void dma_clear_ff(unsigned int channel)
-{
-       outportb(dma[channel].flip, 0);
-}
-
-/* Set mode for a specific DMA channel */
-static inline void dma_set_mode(unsigned int channel, char mode)
-{
-       outportb(dma[channel].mode, mode | (channel & 3));
-}
-
-/* Set DMA page register */
-static inline void dma_set_page(unsigned int channel, char page)
-{
-       if (channel > 3)
-               page &= 0xfe;
-       outportb(dma[channel].page, page);
-}
-
-/*
-  Set transfer address & page bits for specific DMA channel.
-  Assumes dma flipflop is clear.
-*/
-static inline void dma_set_addr(unsigned int channel, unsigned int address)
-{
-       unsigned char dma_reg = dma[channel].addr;
-       dma_set_page(channel, address >> 16);
-       if (channel <= 3) {
-               outportb(dma_reg, (address) & 0xff);
-               outportb(dma_reg, (address >> 8) & 0xff);
-       } else {
-               outportb(dma_reg, (address >> 1) & 0xff);
-               outportb(dma_reg, (address >> 9) & 0xff);
-       }
-}
-
-/*
-  Set transfer size for a specific DMA channel.
-  Assumes dma flip-flop is clear.
-*/
-static inline void dma_set_count(unsigned int channel, unsigned int count)
-{
-       unsigned char dma_reg = dma[channel].size;
-       count--;                                        /* number of DMA transfers is bigger by one */
-       if (channel > 3)
-               count >>= 1;
-       outportb(dma_reg, (count) & 0xff);
-       outportb(dma_reg, (count >> 8) & 0xff);
-}
-
-/*
-  Query the number of bytes left to transfer.
-  Assumes DMA flip-flop is clear.
-*/
-static inline int dma_get_count(unsigned int channel)
-{
-       unsigned char dma_reg = dma[channel].size;
-
-       /* using short to get 16-bit wrap around */
-       unsigned short count;
-       count = inportb(dma_reg);
-       count |= inportb(dma_reg) << 8;
-       count++;
-       return (channel <= 3) ? count : (count << 1);
-}
-
-typedef struct dma_buffer_s {
-       unsigned char *linear;          /* Linear address */
-       unsigned long physical;         /* Physical address */
-       unsigned long size;                     /* Buffer size */
-       unsigned short selector;        /* The selector assigned to this memory */
-       unsigned char channel;          /* The DMA channel */
-} dma_buffer;
-
-/* Allocate a block of memory suitable for using as a DMA buffer */
-extern dma_buffer *dma_allocate(unsigned int channel, unsigned int size);
-/* Deallocate a DMA buffer */
-extern void dma_free(dma_buffer * buffer);
-/* Start DMA transfer to or from given buffer */
-extern void dma_start(dma_buffer * buffer, unsigned long count,
-                                         unsigned char mode);
-
-#endif /* __DOSDMA_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dosgus.c b/libs/mikmod/drivers/dos/dosgus.c
deleted file mode 100644 (file)
index 637b526..0000000
+++ /dev/null
@@ -1,1907 +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.
-*/
-
-/*==============================================================================
-
-  Driver for GUS cards under DOS
-  Written by Andrew Zabolotny <bit@eltech.ru>
-
-==============================================================================*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef DRV_ULTRA
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dos.h>
-#include <dpmi.h>
-#include <sys/farptr.h>
-#include <sys/nearptr.h>
-#include <go32.h>
-#include <string.h>
-
-#include "dosgus.h"
-#include "mikmod.h" /* for MikMod_malloc() & co */
-
-/********************************************* Private variables/routines *****/
-
-/* The Gravis Ultrasound state/info */
-__gus_state gus;
-
-/* Try to avoid holes in DRAM less than this size */
-#define DRAM_HOLE_THRESHOLD    8192
-/* If hole is larger than that, create a free block describing it */
-#define DRAM_SPLIT_THRESHOLD   64
-/* The size of DMA buffer used for RAM->DRAM transfers */
-#define GF1_DMA_BUFFER_SIZE    8192
-
-/* Debug macro: useful to change screen locations when some event occurs */
-#ifdef MIKMOD_DEBUG
-#  define DEBUG_PRINT(x) printf x;
-#  define DEBUG_OFS(addr, attr)                        \
-   {                                           \
-     unsigned short x;                         \
-     _dosmemgetw (0xb8780 + addr*2, 1, &x);    \
-     if ((x >> 8) != attr) x = '0';            \
-     x = ((x + 1) & 0xff) | (attr << 8);       \
-     _dosmemputw (&x, 1, 0xb8780 + addr*2);    \
-   }
-#else
-#  define DEBUG_PRINT(x)
-#  define DEBUG_OFS(addr, attr)
-#endif
-
-static unsigned short __gus_volume_table[512] = {
-       0x0000, 0x7000, 0x7ff0, 0x8800, 0x8ff0, 0x9400, 0x9800, 0x9c00,
-       0x9ff0, 0xa200, 0xa400, 0xa600, 0xa800, 0xaa00, 0xac00, 0xae00,
-       0xaff0, 0xb100, 0xb200, 0xb300, 0xb400, 0xb500, 0xb600, 0xb700,
-       0xb800, 0xb900, 0xba00, 0xbb00, 0xbc00, 0xbd00, 0xbe00, 0xbf00,
-       0xbff0, 0xc080, 0xc100, 0xc180, 0xc200, 0xc280, 0xc300, 0xc380,
-       0xc400, 0xc480, 0xc500, 0xc580, 0xc600, 0xc680, 0xc700, 0xc780,
-       0xc800, 0xc880, 0xc900, 0xc980, 0xca00, 0xca80, 0xcb00, 0xcb80,
-       0xcc00, 0xcc80, 0xcd00, 0xcd80, 0xce00, 0xce80, 0xcf00, 0xcf80,
-       0xcff0, 0xd040, 0xd080, 0xd0c0, 0xd100, 0xd140, 0xd180, 0xd1c0,
-       0xd200, 0xd240, 0xd280, 0xd2c0, 0xd300, 0xd340, 0xd380, 0xd3c0,
-       0xd400, 0xd440, 0xd480, 0xd4c0, 0xd500, 0xd540, 0xd580, 0xd5c0,
-       0xd600, 0xd640, 0xd680, 0xd6c0, 0xd700, 0xd740, 0xd780, 0xd7c0,
-       0xd800, 0xd840, 0xd880, 0xd8c0, 0xd900, 0xd940, 0xd980, 0xd9c0,
-       0xda00, 0xda40, 0xda80, 0xdac0, 0xdb00, 0xdb40, 0xdb80, 0xdbc0,
-       0xdc00, 0xdc40, 0xdc80, 0xdcc0, 0xdd00, 0xdd40, 0xdd80, 0xddc0,
-       0xde00, 0xde40, 0xde80, 0xdec0, 0xdf00, 0xdf40, 0xdf80, 0xdfc0,
-       0xdff0, 0xe020, 0xe040, 0xe060, 0xe080, 0xe0a0, 0xe0c0, 0xe0e0,
-       0xe100, 0xe120, 0xe140, 0xe160, 0xe180, 0xe1a0, 0xe1c0, 0xe1e0,
-       0xe200, 0xe220, 0xe240, 0xe260, 0xe280, 0xe2a0, 0xe2c0, 0xe2e0,
-       0xe300, 0xe320, 0xe340, 0xe360, 0xe380, 0xe3a0, 0xe3c0, 0xe3e0,
-       0xe400, 0xe420, 0xe440, 0xe460, 0xe480, 0xe4a0, 0xe4c0, 0xe4e0,
-       0xe500, 0xe520, 0xe540, 0xe560, 0xe580, 0xe5a0, 0xe5c0, 0xe5e0,
-       0xe600, 0xe620, 0xe640, 0xe660, 0xe680, 0xe6a0, 0xe6c0, 0xe6e0,
-       0xe700, 0xe720, 0xe740, 0xe760, 0xe780, 0xe7a0, 0xe7c0, 0xe7e0,
-       0xe800, 0xe820, 0xe840, 0xe860, 0xe880, 0xe8a0, 0xe8c0, 0xe8e0,
-       0xe900, 0xe920, 0xe940, 0xe960, 0xe980, 0xe9a0, 0xe9c0, 0xe9e0,
-       0xea00, 0xea20, 0xea40, 0xea60, 0xea80, 0xeaa0, 0xeac0, 0xeae0,
-       0xeb00, 0xeb20, 0xeb40, 0xeb60, 0xeb80, 0xeba0, 0xebc0, 0xebe0,
-       0xec00, 0xec20, 0xec40, 0xec60, 0xec80, 0xeca0, 0xecc0, 0xece0,
-       0xed00, 0xed20, 0xed40, 0xed60, 0xed80, 0xeda0, 0xedc0, 0xede0,
-       0xee00, 0xee20, 0xee40, 0xee60, 0xee80, 0xeea0, 0xeec0, 0xeee0,
-       0xef00, 0xef20, 0xef40, 0xef60, 0xef80, 0xefa0, 0xefc0, 0xefe0,
-       0xeff0, 0xf010, 0xf020, 0xf030, 0xf040, 0xf050, 0xf060, 0xf070,
-       0xf080, 0xf090, 0xf0a0, 0xf0b0, 0xf0c0, 0xf0d0, 0xf0e0, 0xf0f0,
-       0xf100, 0xf110, 0xf120, 0xf130, 0xf140, 0xf150, 0xf160, 0xf170,
-       0xf180, 0xf190, 0xf1a0, 0xf1b0, 0xf1c0, 0xf1d0, 0xf1e0, 0xf1f0,
-       0xf200, 0xf210, 0xf220, 0xf230, 0xf240, 0xf250, 0xf260, 0xf270,
-       0xf280, 0xf290, 0xf2a0, 0xf2b0, 0xf2c0, 0xf2d0, 0xf2e0, 0xf2f0,
-       0xf300, 0xf310, 0xf320, 0xf330, 0xf340, 0xf350, 0xf360, 0xf370,
-       0xf380, 0xf390, 0xf3a0, 0xf3b0, 0xf3c0, 0xf3d0, 0xf3e0, 0xf3f0,
-       0xf400, 0xf410, 0xf420, 0xf430, 0xf440, 0xf450, 0xf460, 0xf470,
-       0xf480, 0xf490, 0xf4a0, 0xf4b0, 0xf4c0, 0xf4d0, 0xf4e0, 0xf4f0,
-       0xf500, 0xf510, 0xf520, 0xf530, 0xf540, 0xf550, 0xf560, 0xf570,
-       0xf580, 0xf590, 0xf5a0, 0xf5b0, 0xf5c0, 0xf5d0, 0xf5e0, 0xf5f0,
-       0xf600, 0xf610, 0xf620, 0xf630, 0xf640, 0xf650, 0xf660, 0xf670,
-       0xf680, 0xf690, 0xf6a0, 0xf6b0, 0xf6c0, 0xf6d0, 0xf6e0, 0xf6f0,
-       0xf700, 0xf710, 0xf720, 0xf730, 0xf740, 0xf750, 0xf760, 0xf770,
-       0xf780, 0xf790, 0xf7a0, 0xf7b0, 0xf7c0, 0xf7d0, 0xf7e0, 0xf7f0,
-       0xf800, 0xf810, 0xf820, 0xf830, 0xf840, 0xf850, 0xf860, 0xf870,
-       0xf880, 0xf890, 0xf8a0, 0xf8b0, 0xf8c0, 0xf8d0, 0xf8e0, 0xf8f0,
-       0xf900, 0xf910, 0xf920, 0xf930, 0xf940, 0xf950, 0xf960, 0xf970,
-       0xf980, 0xf990, 0xf9a0, 0xf9b0, 0xf9c0, 0xf9d0, 0xf9e0, 0xf9f0,
-       0xfa00, 0xfa10, 0xfa20, 0xfa30, 0xfa40, 0xfa50, 0xfa60, 0xfa70,
-       0xfa80, 0xfa90, 0xfaa0, 0xfab0, 0xfac0, 0xfad0, 0xfae0, 0xfaf0,
-       0xfb00, 0xfb10, 0xfb20, 0xfb30, 0xfb40, 0xfb50, 0xfb60, 0xfb70,
-       0xfb80, 0xfb90, 0xfba0, 0xfbb0, 0xfbc0, 0xfbd0, 0xfbe0, 0xfbf0,
-       0xfc00, 0xfc10, 0xfc20, 0xfc30, 0xfc40, 0xfc50, 0xfc60, 0xfc70,
-       0xfc80, 0xfc90, 0xfca0, 0xfcb0, 0xfcc0, 0xfcd0, 0xfce0, 0xfcf0,
-       0xfd00, 0xfd10, 0xfd20, 0xfd30, 0xfd40, 0xfd50, 0xfd60, 0xfd70,
-       0xfd80, 0xfd90, 0xfda0, 0xfdb0, 0xfdc0, 0xfdd0, 0xfde0, 0xfdf0,
-       0xfe00, 0xfe10, 0xfe20, 0xfe30, 0xfe40, 0xfe50, 0xfe60, 0xfe70,
-       0xfe80, 0xfe90, 0xfea0, 0xfeb0, 0xfec0, 0xfed0, 0xfee0, 0xfef0,
-       0xff00, 0xff10, 0xff20, 0xff30, 0xff40, 0xff50, 0xff60, 0xff70,
-       0xff80, 0xff90, 0xffa0, 0xffb0, 0xffc0, 0xffd0, 0xffe0, 0xfff0
-};
-
-/* Wait a bit for GUS before doing something
- * Mark function as volatile: don't allow it to be inlined.
- * It *should* be slow, no need to make it work faster :-)
- */
-#if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
-# define _func_noinline volatile /* match original code */
-# define _func_noclone
-#else
-/* avoid warnings from newer gcc:
- * "function definition has qualified void return type" and
- * function return types not compatible due to 'volatile' */
-# define _func_noinline __attribute__((__noinline__))
-# if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
-#  define _func_noclone
-# else
-#  define _func_noclone __attribute__((__noclone__))
-# endif
-#endif
-_func_noinline
-_func_noclone
- void __gus_delay()
-{
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-       inportb(GF1_MIX_CTRL);
-}
-
-static void __gus_stop_controller(unsigned char gf1reg)
-{
-       register unsigned char value = __gus_inregb(gf1reg);
-       __gus_outregb(gf1reg, (value | GF1VC_STOPPED | GF1VC_STOP) &
-                      ~(GF1VC_IRQ_PENDING | GF1VC_IRQ));
-}
-
-/* Returns 1 if volume is already at given position */
-static boolean __gus_volume_ramp_to(unsigned short volume,
-                                    unsigned char rate,
-                                    unsigned char vol_ctrl)
-{
-       int svol = __gus_inregw(GF1R_VOLUME) & 0xfff0;
-       int evol = volume;
-
-       /* First of all, disable volume ramp */
-       __gus_stop_controller(GF1R_VOLUME_CONTROL);
-
-       /* If voice is stopped, set the volume to zero and return */
-       if (__gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED) {
-               __gus_outregw(GF1R_VOLUME, 0);
-               return 1;
-       }
-
-       /* Avoid clicks when volume ramp goes too high or too low */
-       if (svol < 0x0400)
-               svol = 0x0400;
-       if (svol > 0xfc00)
-               svol = 0xfc00;
-       if (evol < 0x0400)
-               evol = 0x0400;
-       if (evol > 0xfc00)
-               evol = 0xfc00;
-
-       /* Adjust start/end positions */
-       if (svol > evol) {
-               unsigned short tmp = evol;
-               evol = svol;
-               svol = tmp;
-               vol_ctrl |= GF1VL_BACKWARD;
-       }
-
-       /* If we already are (near) the target volume, quit */
-       if (evol - svol < 0x1000) {
-               __gus_outregw(GF1R_VOLUME, volume);
-               return 1;
-       }
-
-       __gus_outregb(GF1R_VOLUME_START, svol >> 8);
-       __gus_outregb(GF1R_VOLUME_END, evol >> 8);
-       __gus_outregb(GF1R_VOLUME_RATE, rate);
-       __gus_outregb_slow(GF1R_VOLUME_CONTROL, vol_ctrl);
-       return 0;
-}
-
-static inline void __gus_stop_voice()
-{
-       __gus_stop_controller(GF1R_VOICE_CONTROL);
-       __gus_outregb_slow(GF1R_VOICE_CONTROL, GF1VC_STOPPED | GF1VC_STOP);
-}
-
-/* The GUS IRQ handler */
-static void gf1_irq()
-{
-       unsigned char irq_source;       /* The contents of GF1_IRQ_STATUS register */
-       boolean timer_cb = 0;           /* Call timer callback function */
-
-       DEBUG_OFS(0, 0xCE)
-       gus.eow_ignore = 0;
-       while ((irq_source = inportb(GF1_IRQ_STATUS))) {
-               DEBUG_OFS(1, 0xCE)
-
-                 if (irq_source & GF1M_IRQ_DMA_COMPLETE) {
-                       DEBUG_OFS(4, 0x9F)
-                         /* reset the IRQ pending bit */
-                         __gus_inregb(GF1R_DMA_CONTROL);
-                       gus.dma_active = 0;
-
-                       if (gus.dma_callback)
-                               gus.dma_callback();
-               }
-
-               if (irq_source & (GF1M_IRQ_WAVETABLE | GF1M_IRQ_ENVELOPE)) {
-                       unsigned char vcirq;
-                       unsigned int done_mask = 0;
-
-                       /* IRQ bits are inverse (i.e. 0 = IRQ pending) */
-                       while ((vcirq = __gus_inregb(GF1R_IRQ_SOURCE) ^
-                               (GF1IRQ_WAVE | GF1IRQ_VOLUME)) &
-                               (GF1IRQ_WAVE | GF1IRQ_VOLUME)) {
-                               unsigned long voice = (vcirq & 0x1f);
-                               unsigned char voice_ctl, volume_ctl;
-                               unsigned int voice_mask = (1 << voice);
-
-                               /* Don't handle more than one IRQ from same voice */
-                               if (done_mask & voice_mask)
-                                       continue;
-
-                               done_mask |= voice_mask;
-
-                               /* Read voice/volume selection registers */
-                               __gus_select_voice(voice);
-                               voice_ctl = __gus_inregb(GF1R_VOICE_CONTROL);
-                               volume_ctl = __gus_inregb(GF1R_VOLUME_CONTROL);
-
-                               if ((vcirq & GF1IRQ_WAVE) && (gus.wt_callback)
-                                       && !(gus.eow_ignore & voice_mask)) {
-                                       DEBUG_OFS(5, 0xAF)
-                                       gus.wt_callback(voice, voice_ctl, volume_ctl);
-                               }
-
-                               if ((vcirq & GF1IRQ_VOLUME) && (gus.vl_callback)) {
-                                       DEBUG_OFS(6, 0xAF)
-                                       gus.vl_callback(voice, voice_ctl, volume_ctl);
-                               }
-                       }
-               }
-
-               /* Reset timers that sent this IRQ */
-               if (irq_source & (GF1M_IRQ_TIMER1 | GF1M_IRQ_TIMER2)) {
-                       unsigned char timer_ctl = gus.timer_ctl_reg;
-
-                       if (irq_source & GF1M_IRQ_TIMER1)
-                               timer_ctl &= ~GF1M_TIMER1;
-
-                       if (irq_source & GF1M_IRQ_TIMER2)
-                               timer_ctl &= ~GF1M_TIMER2;
-
-                       __gus_outregb_slow(GF1R_TIMER_CONTROL, timer_ctl);
-                       __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
-               }
-
-               if (irq_source & GF1M_IRQ_TIMER1)
-                       if (--gus.t1_countdown == 0) {
-                               gus.t1_countdown = gus.t1_multiple;
-                               gus.t1_ticks++;
-
-                               DEBUG_OFS(2, 0xCF)
-
-                               if (gus.t1_callback) {
-                                       timer_cb = 1;
-                                       gus.t1_callback();
-                               }
-                       }
-
-               if (irq_source & GF1M_IRQ_TIMER2)
-                       if (--gus.t2_countdown == 0) {
-                               gus.t2_countdown = gus.t2_multiple;
-                               gus.t2_ticks++;
-
-                               DEBUG_OFS(3, 0xCF)
-
-                               if (gus.t2_callback)
-                                       gus.t2_callback();
-                       }
-#if 0
-               /* The following are not used and implemented yet */
-               if (irq_source & (GF1M_IRQ_MIDI_TX | GF1M_IRQ_MIDI_RX)) {
-               }
-#endif
-       }
-
-       irq_ack(gus.gf1_irq);
-
-       if (timer_cb && gus.timer_callback)
-               gus.timer_callback();
-}
-
-static void gf1_irq_end()
-{
-}
-
-static boolean __gus_detect()
-{
-       /* A relatively relaxed autodetection;
-          We don't count on DRAM: GUS PnP could not have it
-          (although its anyway bad for us)
-        */
-       __gus_select_voice(0);
-       __gus_stop_voice();
-       __gus_outregw(GF1R_FREQUENCY, 0x1234);
-       __gus_outregw(GF1R_VOLUME, 0x5670);
-       return ((__gus_inregw(GF1R_FREQUENCY) & 0xfffe) == 0x1234)
-         && ((__gus_inregw(GF1R_VOLUME) & 0xfff0) == 0x5670);
-}
-
-static void __gus_reset(boolean reset_io_dma)
-{
-       static unsigned char irqctl[16] = { 0, 0, 1, 3, 0, 2, 0, 4, 0, 0, 0, 5, 6, 0, 0, 7 };
-       static unsigned char dmactl[8] = { 0, 1, 0, 2, 0, 3, 4, 5 };
-       unsigned char irqtmp, dmatmp;
-
-       /* Disable interrupts while resetting to avoid spurious IRQs */
-       int i, timer, old_ints = disable();
-
-       /* Stop the timer so that GUS IRQ won't clobber registers */
-       timer = (gus.timer_ctl_reg & GF1M_TIMER1);
-       if (timer)
-               gus_timer_stop();
-
-       gus.dma_active = 0;
-
-       __gus_outregb(GF1R_RESET, 0);
-       for (i = 0; i < 10; i++)
-               __gus_delay();
-       __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET);
-       for (i = 0; i < 10; i++)
-               __gus_delay();
-
-       outportb(GF1_MIDI_CTRL, GF1M_MIDI_RESET);
-       for (i = 0; i < 10; i++)
-               __gus_delay();
-       outportb(GF1_MIDI_CTRL, 0);
-
-       /* Reset all IRQ sources */
-       __gus_outregb(GF1R_DMA_CONTROL, 0);
-       __gus_outregb(GF1R_TIMER_CONTROL, 0);
-       __gus_outregb(GF1R_SAMPLE_CONTROL, 0);
-
-       /* Reset all voices */
-       gus_reset(gus.voices, gus.dynmask);
-
-       /* Flush any pending IRQs */
-       inportb(GF1_IRQ_STATUS);
-       __gus_inregb(GF1R_DMA_CONTROL);
-       __gus_inregb(GF1R_SAMPLE_CONTROL);
-       __gus_inregb(GF1R_IRQ_SOURCE);
-
-       if (reset_io_dma) {
-               /* Now set up the GUS card to required IRQs and DMAs */
-               if (gus.irq[0] == gus.irq[1])
-                       irqtmp = irqctl[gus.irq[0]] | GF1M_IRQ_EQUAL;
-               else
-                       irqtmp = irqctl[gus.irq[0]] | (irqctl[gus.irq[1]] << 3);
-
-               if (gus.dma[0] == gus.dma[1])
-                       dmatmp = dmactl[gus.dma[0]] | GF1M_DMA_EQUAL;
-               else
-                       dmatmp = dmactl[gus.dma[0]] | (dmactl[gus.dma[1]] << 3);
-
-               /* Reset IRQs if possible */
-               gus.mixer =
-                 GF1M_MIXER_NO_LINE_IN | GF1M_MIXER_NO_OUTPUT | GF1M_MIXER_GF1_IRQ;
-               if (gus.version >= GUS_CARD_VERSION_CLASSIC1) {
-                       outportb(GF1_REG_CTRL, 0x05);
-                       outportb(GF1_MIX_CTRL, gus.mixer);
-                       outportb(GF1_IRQ_CTRL, 0x00);   /* Reset IRQs */
-                       outportb(GF1_REG_CTRL, 0x00);
-               }
-
-               /* Set up DMA channels: NEVER disable MIXER_GF1_IRQ in the future */
-               outportb(GF1_MIX_CTRL, gus.mixer);
-               outportb(GF1_IRQ_CTRL, dmatmp);
-
-               /* Set up IRQ channels */
-               outportb(GF1_MIX_CTRL, gus.mixer | GF1M_CONTROL_SELECT);
-               outportb(GF1_IRQ_CTRL, irqtmp);
-       }
-
-       __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET | GF1M_OUTPUT_ENABLE | GF1M_MASTER_IRQ);
-       __gus_delay();
-
-       /* Flush IRQs again */
-       inportb(GF1_IRQ_STATUS);
-       __gus_inregb(GF1R_DMA_CONTROL);
-       __gus_inregb(GF1R_SAMPLE_CONTROL);
-       __gus_inregb(GF1R_IRQ_SOURCE);
-
-       _irq_ack(gus.irq[0]);
-       _irq_ack(gus.irq[1]);
-
-       if (timer)
-               gus_timer_continue();
-
-       if (old_ints)
-               enable();
-
-       /* Enable output */
-       __gus_mixer_output(1);
-}
-
-/* Transfer a block of data from GUS DRAM to main RAM through port I/O */
-static void __gus_transfer_io_in(unsigned long address, unsigned char *source,
-                                 unsigned long size)
-{
-       while (size) {
-               register unsigned int size64k;
-
-               size64k = 0x10000 - (address & 0xffff);
-               if (size64k > size)
-                       size64k = size;
-               size -= size64k;
-
-               __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
-               while (size64k--) {
-                       __gus_outregw(GF1R_DRAM_LOW, address++);
-                       *source++ = inportb(GF1_DRAM);
-               }
-       }
-}
-
-/* Transfer a block of data into GUS DRAM through port I/O */
-static void __gus_transfer_io(unsigned long address, unsigned char *source,
-                              unsigned long size, int flags)
-{
-       while (size) {
-               register unsigned int size64k;
-
-               size64k = 0x10000 - (address & 0xffff);
-               if (size64k > size)
-                       size64k = size;
-               size -= size64k;
-
-               __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
-               if (flags & GUS_WAVE_INVERT)
-                       if (flags & GUS_WAVE_16BIT)
-                               while (size64k-- && size64k--) {
-                                       __gus_outregw(GF1R_DRAM_LOW, address++);
-                                       outportb(GF1_DRAM, *source++);
-                                       __gus_outregw(GF1R_DRAM_LOW, address++);
-                                       outportb(GF1_DRAM, (*source++) ^ 0x80);
-                       } else
-                               while (size64k--) {
-                                       __gus_outregw(GF1R_DRAM_LOW, address++);
-                                       outportb(GF1_DRAM, (*source++) ^ 0x80);
-               } else
-                       while (size64k--) {
-                               __gus_outregw(GF1R_DRAM_LOW, address++);
-                               outportb(GF1_DRAM, *source++);
-                       }
-       }
-}
-
-/* Wait for DMA transfer to finish between 8-9 1/18sec timer ticks */
-static int __gus_wait_dma()
-{
-       unsigned long timer;
-       _farsetsel(_dos_ds);
-       timer = _farnspeekl(0x46c);
-       while (gus.dma_active)
-               if (_farnspeekl(0x46c) - timer > 8) {
-                       /* Force DMA abort since something went wrong */
-                       __gus_reset(0);
-                       return -1;
-               }
-
-       return 0;
-}
-
-/* Transfer a block of data into GUS DRAM through DMA controller */
-static void __gus_transfer_dma(unsigned long address, unsigned char *source,
-                               unsigned long size, int flags)
-{
-       unsigned char dma_control;
-       unsigned long bytes_left;
-       unsigned long cur_size;
-       unsigned long dest_addr;
-
-       if ((gus.dma[0] > 3) || (flags & GUS_WAVE_16BIT))
-               size = (size + 1) & ~1;
-
-       bytes_left = size;
-       while (bytes_left) {
-               __gus_wait_dma();
-
-               cur_size = gus.dma_buff->size;
-               if (cur_size > bytes_left)
-                       cur_size = bytes_left;
-               bytes_left -= cur_size;
-               dest_addr = address;
-
-               if (gus.dma_buff->linear != source)
-                       memmove(gus.dma_buff->linear, source, cur_size);
-               source += cur_size;
-               address += cur_size;
-
-               /* Disable GUS -> DMA tie */
-               __gus_outregb(GF1R_DMA_CONTROL, 0);
-               __gus_delay();
-
-               /* Set up the DMA */
-               dma_start(gus.dma_buff, cur_size, DMA_MODE_WRITE);
-               gus.dma_active = 1;
-
-               /* Reset the DMA IRQ pending bit if set */
-               __gus_inregb(GF1R_DMA_CONTROL);
-
-               /* The 16-bit DMA channels needs a slightly different approach */
-               dma_control = GF1M_DMAR_ENABLE | GF1M_DMAR_IRQ_ENABLE | gus.dma_rate;
-               if (gus.dma[0] > 3) {
-                       dest_addr = __gus_convert_addr16(dest_addr);
-                       dma_control |= GF1M_DMAR_CHAN16;
-               }
-
-               __gus_outregw(GF1R_DMA_ADDRESS, dest_addr >> 4);
-
-               if (flags & GUS_WAVE_16BIT)
-                       dma_control |= GF1M_DMAR_DATA16;
-               if (flags & GUS_WAVE_INVERT)
-                       dma_control |= GF1M_DMAR_TOGGLE_SIGN;
-
-               /* Tell GUS to start transfer */
-               __gus_outregb(GF1R_DMA_CONTROL, dma_control);
-       }
-}
-
-static void __gus_detect_version()
-{
-       unsigned char tmp;
-
-       switch (gus.version = inportb(GF1_REVISION)) {
-         case 5:
-               gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
-               gus.ics = 1;
-               gus.ics_flipped = 1;
-               break;
-         case 6:
-         case 7:
-         case 8:
-         case 9:
-               gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
-               gus.ics = 1;
-               break;
-         case 10:
-               gus.version = GUS_CARD_VERSION_MAX;
-               gus.codec = 1;
-               break;
-         case 11:
-               gus.version = GUS_CARD_VERSION_MAX1;
-               gus.codec = 1;
-               break;
-         case 0x30:
-               gus.version = GUS_CARD_VERSION_ACE;
-               break;
-         case 0x50:
-               gus.version = GUS_CARD_VERSION_EXTREME;
-               break;
-         case 0xff:
-               /* Pre-3.7 board */
-               outportb(GF1_REG_CTRL, 0x20);
-               tmp = inportb(GF1_REG_CTRL);
-               if ((tmp != 0xff) && (tmp & 0x06))
-                       gus.version = GUS_CARD_VERSION_CLASSIC1;
-               else
-                       gus.version = GUS_CARD_VERSION_CLASSIC;
-               break;
-         default:
-               /* Hmm... unknown revision. Assume a safe Classic model */
-#ifdef MIKMOD_DEBUG
-               fprintf(stderr, "libgus: Unknown board revision (%02x)\n",
-                               gus.version);
-#endif
-               gus.version = GUS_CARD_VERSION_CLASSIC;
-               break;
-       }
-}
-
-static void __gus_detect_transfer()
-{
-       unsigned char *outbuff, *inbuff;
-       unsigned int i, j, seed = 0x13243546;
-       __gus_transfer_func func;
-
-#define TRANSFER_SIZE  0x4000
-
-       outbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
-       inbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
-
-       /* Suppose we have an malfunctioning GUS */
-       gus.transfer = NULL;
-
-       for (i = (gus.dma_buff ? 0 : 4); i <= 4; i++) {
-               switch (i) {
-                 case 0:
-                       gus.dma_rate = GF1M_DMAR_RATE0;
-                       func = __gus_transfer_dma;
-                       break;
-                 case 1:
-                       gus.dma_rate = GF1M_DMAR_RATE1;
-                       func = __gus_transfer_dma;
-                       break;
-                 case 2:
-                       gus.dma_rate = GF1M_DMAR_RATE2;
-                       func = __gus_transfer_dma;
-                       break;
-                 case 3:
-                       gus.dma_rate = GF1M_DMAR_RATE3;
-                       func = __gus_transfer_dma;
-                       break;
-                 case 4:
-                       func = __gus_transfer_io;
-                       break;
-               }
-
-               /* Fill data array each time with pseudo-random values */
-               for (j = 0; j < TRANSFER_SIZE; j++)
-                       outbuff[j] = seed, seed =
-                         ((seed + 358979323) ^ (seed >> 16)) * 314159265;
-
-               /* Transfer the random array to GUS */
-               /* Poke a security fence around dest block */
-               __gus_poke(0x100 - 1, 0xAA);
-               __gus_poke(0x100 - 2, 0x55);
-               __gus_poke(0x100 + TRANSFER_SIZE + 0, 0xAA);
-               __gus_poke(0x100 + TRANSFER_SIZE + 1, 0x55);
-
-               func(0x100, outbuff, TRANSFER_SIZE, 0);
-
-               if (__gus_wait_dma() == 0) {
-                       /* Check if the security fence was not damaged */
-                       if ((__gus_peek(0x100 - 1) != 0xAA)
-                               || (__gus_peek(0x100 - 2) != 0x55)
-                               || (__gus_peek(0x100 + TRANSFER_SIZE + 0) != 0xAA)
-                               || (__gus_peek(0x100 + TRANSFER_SIZE + 1) != 0x55))
-                               continue;
-
-                       /* Now check if GUS DRAM really data that we expects to be transferred */
-                       __gus_transfer_io_in(0x100, inbuff, TRANSFER_SIZE);
-                       if (memcmp(outbuff, inbuff, TRANSFER_SIZE) == 0) {
-                               gus.transfer = func;
-                               break;
-                       }
-               }
-       }
-
-#undef TRANSFER_SIZE
-
-       MikMod_free(inbuff);
-       MikMod_free(outbuff);
-}
-
-static void __gus_detect_memory()
-{
-       unsigned int size;
-       for (size = 0; size < 1024; size += 256) {
-               __gus_poke(size * 1024, 0xaa);
-               if (__gus_peek(size * 1024) != 0xaa)
-                       break;
-               __gus_poke(size * 1024, 0x55);
-               if (__gus_peek(size * 1024) != 0x55)
-                       break;
-       }
-       gus.ram = size;
-}
-
-static void __gus_init()
-{
-       char *gusenv = getenv("ULTRASND");
-
-       memset((void *)&gus, 0, sizeof(gus));
-       gus.cmd_voice = -1;
-
-       if (!gusenv)
-               return;
-
-       sscanf(gusenv, "%x,%d,%d,%d,%d", &gus.port, &gus.dma[0], &gus.dma[1],
-                  &gus.irq[0], &gus.irq[1]);
-
-       /* A relaxed sanity check */
-       if ((gus.port < 0x100) || (gus.port > 0x1000)
-               || (gus.irq[0] < 2) || (gus.irq[0] > 15)
-               || (gus.irq[1] < 2) || (gus.irq[1] > 15)
-               || (gus.dma[0] < 0) || (gus.dma[0] > 7)
-               || (gus.dma[1] < 0) || (gus.dma[1] > 7))
-               return;
-
-       gus.voices = 32;
-       gus.timer_ctl = GF1M_MASK_TIMER1 | GF1M_MASK_TIMER2;
-
-       /* Detect if the card is really there */
-       if (__gus_detect() == 0)
-               return;
-
-       /* Detect the version of Gravis Ultrasound */
-       __gus_detect_version();
-
-       /* Reset the card */
-       __gus_reset(1);
-
-       /* Detect the amount of on-board memory */
-       __gus_detect_memory();
-
-       gus.ok = 1;
-}
-
-static void __gus_kick(gus_wave_t * wave, unsigned int wave_offset)
-{
-       unsigned char vc;
-
-       vc = GF1VC_IRQ;
-       if (wave->format & GUS_WAVE_16BIT)
-               vc |= GF1VC_DATA16;
-       if (wave->format & GUS_WAVE_BACKWARD)
-               vc |= GF1VC_BACKWARD;
-       if (wave->format & GUS_WAVE_LOOP) {
-               vc |= GF1VC_LOOP_ENABLE;
-               if (wave->format & GUS_WAVE_BIDIR)
-                       vc |= GF1VC_BI_LOOP;
-       }
-       __gus_set_loop_start(vc, (wave->begin.memory << 4) + wave->loop_start);
-       if (wave->format & GUS_WAVE_LOOP)
-               __gus_set_loop_end(vc, (wave->begin.memory << 4) + wave->loop_end);
-       else
-               __gus_set_loop_end(vc, (wave->begin.memory + wave->size) << 4);
-       __gus_set_current(vc, (wave->begin.memory << 4) + wave_offset + 100);
-       __gus_outregb_slow(GF1R_VOICE_CONTROL, vc);
-}
-
-/* Timer 1 callback function (updates voices) */
-static void __gus_timer_update()
-{
-       gus_wave_t *wave;
-       unsigned long wave_offset;
-       unsigned char *src, *top;
-       unsigned int vmask = (1 << gus.cur_voice);
-
-       if (!gus.cmd_pool_ready)
-               return;
-
-       __gus_select_voice(gus.cur_voice);
-       wave_offset = 0;
-       src = gus.cmd_pool;
-       top = gus.cmd_pool + gus.cmd_pool_top;
-
-#define GET_B  *src
-#define GET_W  *((unsigned short *)src)
-#define GET_L  *((unsigned long *)src)
-
-       while (src < top) {
-               __gus_delay();
-               switch (GET_B++) {
-                 case PCMD_VOICE:
-                       __gus_select_voice(gus.cur_voice = GET_B++);
-                       vmask = (1 << gus.cur_voice);
-                       break;
-                 case PCMD_FREQ:
-               /*      __gus_outregw(GF1R_FREQUENCY, GET_W++);*/
-                       __gus_outregw(GF1R_FREQUENCY, *(unsigned short *)src);
-                       src += 2;
-                       break;
-                 case PCMD_PAN:
-                       __gus_outregb(GF1R_BALANCE, GET_B++);
-                       break;
-                 case PCMD_VOLUME:
-                       __gus_volume_ramp_to(gus.cur_vol[gus.cur_voice] =
-                                                       /*       GET_W++, GUS_VOLCHANGE_RAMP, GF1VL_IRQ);*/
-                                                 *(unsigned short *)src, GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
-                                                               src += 2;
-                       break;
-                 case PCMD_VOLUME_PREPARE:
-               /*      gus.cur_vol[gus.cur_voice] = GET_W++;*/
-                       gus.cur_vol[gus.cur_voice] = *(unsigned short *)src;
-                       src += 2;
-                       break;
-                 case PCMD_OFFSET:
-               /*      wave_offset = GET_L++;*/
-                       wave_offset = *(unsigned long *)src;
-                       src += 4;
-                       break;
-                 case PCMD_START:
-               /*      wave = (gus_wave_t *) GET_L++;*/
-                       wave = (gus_wave_t *) *(unsigned long *)src;
-                       src += 4;
-                       gus.cur_wave[gus.cur_voice] = wave;
-                       gus.kick_offs[gus.cur_voice] = wave_offset;
-                       if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ)) {
-                               __gus_kick(wave, wave_offset);
-                               __gus_volume_ramp_to(gus.cur_vol[gus.cur_voice],
-                                                                        GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
-                       } else
-                               gus.voice_kick[gus.cur_voice] = 1;
-                       wave_offset = 0;
-                       gus.eow_ignore |= vmask;
-                       break;
-                 case PCMD_STOP:
-                       /* If volume is close to nothing, abort immediately instead of
-                          ramping */
-                       gus.cur_vol[gus.cur_voice] = 0;
-                       gus.cur_wave[gus.cur_voice] = NULL;
-                       if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))
-                               __gus_stop_voice();
-                       break;
-                 case PCMD_STOP_LOOP:
-                       __gus_outregb_slow(GF1R_VOICE_CONTROL,
-                                                          (__gus_inregb(GF1R_VOICE_CONTROL) | GF1VC_IRQ)
-                                                          & ~GF1VC_LOOP_ENABLE);
-                       __gus_outregb_slow(GF1R_VOLUME_CONTROL,
-                                                          __gus_inregb(GF1R_VOLUME_CONTROL) &
-                                                          ~GF1VL_ROLLOVER);
-                       break;
-                 default:
-                       /* Alarm! Break out immediately */
-                       src = top;
-                       break;
-               }
-       }
-
-#undef GET_B
-#undef GET_W
-#undef GET_L
-
-       gus.cmd_pool_ready = 0;
-       gus.cmd_pool_top = 0;
-}
-
-static void __gus_wavetable_update(unsigned int voice, unsigned int voice_ctl,
-                                                                  unsigned int volume_ctl)
-{
-       gus_wave_t *wave = gus.cur_wave[voice];
-
-       if (!wave || !(wave->format & GUS_WAVE_LOOP)) {
-               __gus_stop_voice();
-               gus.cur_wave[voice] = NULL;
-               gus.cur_vol[voice] = 0;
-               if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))
-                       __gus_stop_voice();
-       }
-}
-
-static void __gus_volume_update(unsigned int voice, unsigned int voice_ctl,
-                                                               unsigned int volume_ctl)
-{
-       __gus_volume_ramp_to(gus.cur_vol[voice], GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
-       if (!gus.cur_wave[voice])
-               __gus_stop_voice();
-       else if (gus.voice_kick[voice])
-               __gus_kick(gus.cur_wave[voice], gus.kick_offs[voice]);
-       gus.voice_kick[voice] = 0;
-}
-
-/***************************************************** GUS memory manager *****/
-
-/* Mark all GUS memory as available */
-static void __gus_mem_clear()
-{
-       __gus_mcb *cur = gus.mcb;
-
-       while (cur) {
-               __gus_mcb *next = cur->next;
-               if (cur != gus.mcb)
-                       MikMod_free(cur);
-               cur = next;
-       }
-
-       if (!gus.mcb)
-               gus.mcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
-
-       gus.mcb->next = gus.mcb->prev = NULL;
-       gus.mcb->addr = 0;
-       gus.mcb->size = gus.ram * 1024;
-       gus.mcb->free = 1;
-}
-
-/* Return amount of free memory */
-static unsigned int __gus_mem_get_free()
-{
-       __gus_mcb *cur = gus.mcb;
-       unsigned int size = 0;
-
-       if (!gus.open)
-               return gus.ram * 1024;
-
-       while (cur) {
-               if (cur->free)
-                       size += cur->size;
-               cur = cur->next;
-       }
-
-       return size;
-}
-
-/* Return largest size for a 8-bit sample */
-static unsigned int __gus_mem_get_free_8()
-{
-       __gus_mcb *cur = gus.mcb;
-       unsigned int size = 0;
-
-       if (!gus.open)
-               return 0;
-
-       while (cur) {
-               if (cur->free && (cur->size > size))
-                       size = cur->size;
-               cur = cur->next;
-       }
-
-       return size;
-}
-
-/* Return largest size for a 16-bit sample */
-static unsigned int __gus_mem_get_free_16()
-{
-       __gus_mcb *cur = gus.mcb;
-       unsigned int size = 0;
-
-       if (!gus.open)
-               return 0;
-
-       while (cur) {
-               if (cur->free) {
-                       unsigned int size16 = cur->size;
-                       unsigned int tmp;
-                       /* 16-bit samples cannot cross 256K boundaries */
-                       tmp = 0x40000 - (cur->addr & 0x3ffff);
-                       if (size16 > tmp)
-                               size16 = tmp;
-                       /* 16-bit samples should be aligned on a 32-byte boundary */
-                       size16 -= (32 - cur->addr) & 0x1f;
-
-                       if (size16 > size)
-                               size = size16;
-
-                       /* Now try vice versa: skip a portion of aligned memory */
-                       size16 =
-                         (cur->addr + cur->size) - ((cur->addr + 0x3ffff) & ~0x3ffff);
-                       if ((size16 < 0x7fffffff) && (size16 > size))
-                               size = size16;
-               }
-               cur = cur->next;
-       }
-
-       return size;
-}
-
-/* Allocate a segment of GUS DRAM for a sample with given bits per sample.
- * The algorithm tries to find the smallest free block that fits requested
- * size; but if found free block is larger by some (large) delta than
- * requested block size, the largest possible block is preffered.
- */
-static unsigned int __gus_mem_alloc(unsigned int size, int bits16)
-{
-       __gus_mcb *cur = gus.mcb;
-       __gus_mcb *best_max = NULL, *best_min = NULL;
-       unsigned int best_max_delta = 0, best_min_delta = 0xffffffff;
-       unsigned int best_max_prefix = 0, best_min_prefix = 0;
-       unsigned int memaddr, memsize;
-
-       if (!gus.open || !size || (bits16 && size > 0x40000))
-               return -1;
-
-       /* Round block size up to nearest acceptable DMA bound */
-       if (bits16)
-               size = (size + 0x1f) & ~0x1f;
-       else
-               size = (size + 0x0f) & ~0x0f;
-
-       while (cur) {
-               if (cur->free) {
-                       unsigned char fits = 0;
-
-                       memsize = cur->size;
-                       memaddr = cur->addr;
-
-                       if (bits16) {
-                               /* 16-bit samples cannot cross 256K boundaries */
-                               unsigned int tmp = 256 * 1024 - (memaddr & 0x3ffff);
-                               if (memsize > tmp)
-                                       memsize = tmp;
-                               /* 16-bit samples should be aligned on a 32-byte boundary */
-                               memsize -= (32 - memaddr) & 0x1f;
-                               memaddr = (memaddr + 0x1f) & ~0x1f;
-                       }
-
-                       /* If block fits, analyze it */
-                       if (size <= memsize)
-                               fits = 1;
-                       /* Look if we still can complete the request by creating a free
-                          block */
-                       else if (size <= cur->size) {
-                               /* Align start address to next 256k boundary */
-                               unsigned int endaddr = cur->addr + cur->size;
-                               memaddr = (cur->addr + 0x3ffff) & ~0x3ffff;
-                               /* Can we split current block by inserting a free block at the
-                                  beginning? */
-                               if ((memaddr < endaddr) && (memaddr + size <= endaddr))
-                                       fits = 1;
-                       }
-
-                       if (fits) {
-                               unsigned int size_delta = cur->size - size;
-                               unsigned int size_prefix = memaddr - cur->addr;
-                               if (size_delta < best_min_delta)
-                                       best_min = cur, best_min_delta =
-                                         size_delta, best_min_prefix = size_prefix;
-                               if (size_delta > best_max_delta)
-                                       best_max = cur, best_max_delta =
-                                         size_delta, best_max_prefix = size_prefix;
-                       }
-               }
-
-               cur = cur->next;
-       }
-
-       if (!best_min)
-               return -1;
-
-       /* If minimal block that fits is too large, use largest block that fits */
-       /* But if using the maximal block is going to create a small hole, forget
-          it */
-       if ((best_max_prefix == 0)
-               || (best_max_prefix >= DRAM_HOLE_THRESHOLD)
-               || (best_min_prefix != 0))
-               if (
-                       ((best_min_delta < DRAM_HOLE_THRESHOLD) &&
-                        (best_max_delta >= DRAM_HOLE_THRESHOLD)) ||
-                       ((best_min_prefix > 0) && (best_min_prefix < DRAM_HOLE_THRESHOLD)
-                        && ((best_max_prefix == 0) ||
-                                (best_max_prefix > best_min_prefix))) ||
-                       ((best_min_prefix != 0) && (best_max_prefix == 0))) {
-                       best_min = best_max;
-                       best_min_delta = best_max_delta;
-                       best_min_prefix = best_max_prefix;
-               }
-
-       /* Compute the DRAM address to return */
-       memaddr = best_min->addr + best_min_prefix;
-       if (bits16)
-               memaddr = (memaddr + 0x1f) & ~0x1f;
-       else
-               memaddr = (memaddr + 0x0f) & ~0x0f;
-
-       /* If we have a considerable hole at the beginning of sample,
-          create a free node describing the hole */
-       if (memaddr - best_min->addr >= DRAM_SPLIT_THRESHOLD) {
-               __gus_mcb *newmcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
-               newmcb->prev = best_min->prev;
-               newmcb->next = best_min;
-               newmcb->addr = best_min->addr;
-               newmcb->size = memaddr - best_min->addr;
-               newmcb->free = 1;
-               best_min->addr = memaddr;
-               best_min->size -= newmcb->size;
-               best_min->prev = newmcb;
-               if (newmcb->prev)
-                       newmcb->prev->next = newmcb;
-       }
-
-       /* Compute the size of hole at the end of block */
-       memsize = (best_min->addr + best_min->size) - (memaddr + size);
-
-       /* Split the block if the block is larger than requested amount */
-       if (memsize > DRAM_SPLIT_THRESHOLD) {
-               /* The next node cannot be free since free blocks are always glued
-                  together */
-               __gus_mcb *newmcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
-               best_min->size -= memsize;
-               newmcb->prev = best_min;
-               newmcb->next = best_min->next;
-               newmcb->addr = best_min->addr + best_min->size;
-               newmcb->size = memsize;
-               newmcb->free = 1;
-               if (best_min->next)
-                       best_min->next->prev = newmcb;
-               best_min->next = newmcb;
-       }
-       best_min->free = 0;
-
-       return memaddr;
-}
-
-static void __gus_mem_free(unsigned int addr)
-{
-       __gus_mcb *cur = gus.mcb;
-       while (cur) {
-               if (!cur->free && (cur->addr <= addr) &&
-                       (cur->addr + cur->size > addr)) {
-                       cur->free = 1;
-
-                       /* If next block is free as well, link them together */
-                       if (cur->next && cur->next->free) {
-                               __gus_mcb *next = cur->next;
-                               cur->size += next->size;
-                               cur->next = next->next;
-                               if (next->next)
-                                       next->next->prev = cur;
-                               MikMod_free(next);
-                       }
-
-                       /* If previous block is free, link current block with it */
-                       if (cur->prev && cur->prev->free) {
-                               cur->prev->size += cur->size;
-                               cur->prev->next = cur->next;
-                               if (cur->next)
-                                       cur->next->prev = cur->prev;
-                               MikMod_free(cur);
-                       }
-                       return;
-               }
-               cur = cur->next;
-       }
-}
-
-static void __gus_mem_pack()
-{
-}
-
-#ifdef MIKMOD_DEBUG
-
-/* Debug dump of GUS DRAM heap */
-void __gus_mem_dump()
-{
-       __gus_mcb *cur = gus.mcb;
-       fprintf(stderr, "/-- Offset --+-- Prev --+-- Size --+-- Free --\\\n");
-       while (cur) {
-               fprintf(stderr, "|  %08X  | %08X |  %6d  |   %s    |\n",
-                               cur->addr, cur->prev ? cur->prev->addr : -1, cur->size,
-                               cur->free ? "yes" : " no");
-               cur = cur->next;
-       }
-       fprintf(stderr, "\\------------+----------+----------+----------/\n");
-}
-
-#endif
-
-/************************************************** Middle-level routines *****/
-
-static int __gus_instrument_free(gus_instrument_t * instrument)
-{
-       gus_instrument_t **cur_instr;
-       gus_layer_t *cur_layer;
-       gus_wave_t *cur_wave, *wave_head;
-
-       /* Remove the instrument from the list of registered instruments */
-       cur_instr = (gus_instrument_t **) & gus.instr;
-       while (*cur_instr) {
-               if (*cur_instr == instrument) {
-                       *cur_instr = instrument->next;
-                       goto instr_loaded;
-               }
-               cur_instr = &(*cur_instr)->next;
-       }
-       return -1;
-
-instr_loaded:
-       wave_head = NULL;
-       for (cur_layer = instrument->info.layer; cur_layer;
-                cur_layer = cur_layer->next)
-               /* Free all waves */
-               for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {
-                       if (!wave_head)
-                               wave_head = cur_wave;
-                       if (cur_wave->begin.memory != (unsigned int)-1)
-                               __gus_mem_free(cur_wave->begin.memory);
-               }
-       if (wave_head)
-               MikMod_free(wave_head);
-
-       MikMod_free(instrument->info.layer);
-       if (instrument->name)
-               MikMod_free(instrument->name);
-       MikMod_free(instrument);
-       return 0;
-}
-
-static gus_instrument_t *__gus_instrument_get(int program)
-{
-       gus_instrument_t *cur_instr = (gus_instrument_t *) gus.instr;
-       while (cur_instr) {
-               if (cur_instr->number.instrument == program)
-                       return cur_instr;
-               cur_instr = cur_instr->next;
-       }
-       return NULL;
-}
-
-static gus_instrument_t *__gus_instrument_copy(gus_instrument_t * instrument)
-{
-       gus_instrument_t **cur_instr, *instr;
-       gus_layer_t *cur_layer, *dest_layer;
-       gus_wave_t *cur_wave, *dest_wave;
-       unsigned int waves, layers;
-
-       if (!instrument || !instrument->info.layer || !gus.open)
-               return NULL;
-
-       if (__gus_instrument_get(instrument->number.instrument))
-               return NULL;
-
-       instr = (gus_instrument_t *) MikMod_malloc(sizeof(gus_instrument_t));
-       *instr = *instrument;
-
-       if (instrument->name)
-               instr->name = MikMod_strdup(instrument->name);
-
-       /* Make a copy of all layers at once */
-       for (layers = 0, cur_layer = instrument->info.layer; cur_layer; layers++)
-               cur_layer = cur_layer->next;
-
-       if (!(dest_layer = instr->info.layer = (gus_layer_t *) MikMod_malloc(sizeof(gus_layer_t) * layers))) {
-               if (instr->name)
-                       MikMod_free(instr->name);
-               MikMod_free(instr);
-               return NULL;
-       }
-       for (waves = 0, cur_layer = instrument->info.layer; cur_layer;
-                cur_layer = cur_layer->next) {
-               *dest_layer = *cur_layer;
-               dest_layer->wave = NULL;
-               /* Count the total number of waves */
-               for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next)
-                       waves++;
-               if (cur_layer->next)
-                       dest_layer->next = dest_layer + 1;
-               else
-                       dest_layer->next = NULL;
-               dest_layer++;
-       }
-
-       /* Allocate memory for waves */
-       if (!(dest_wave = (gus_wave_t *) MikMod_malloc(sizeof(gus_wave_t) * waves))) {
-               MikMod_free(instr->info.layer);
-               if (instr->name)
-                       MikMod_free(instr->name);
-               MikMod_free(instr);
-               return NULL;
-       }
-       for (cur_layer = instrument->info.layer, dest_layer = instr->info.layer;
-            cur_layer; cur_layer = cur_layer->next, dest_layer = dest_layer->next)
-               /* Copy all waves */
-               for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {
-                       if (!dest_layer->wave)
-                               dest_layer->wave = dest_wave;
-
-                       *dest_wave = *cur_wave;
-                       /* Mark DRAM address as unallocated */
-                       dest_wave->begin.memory = -1;
-
-                       if (cur_wave->next)
-                               dest_wave->next = (dest_wave + 1);
-                       else
-                               dest_wave->next = NULL;
-                       dest_wave++;
-               }
-
-       /* Insert the instrument into list of registered instruments */
-       cur_instr = (gus_instrument_t **) & gus.instr;
-       while (*cur_instr)
-               cur_instr = &(*cur_instr)->next;
-       *cur_instr = instr;
-
-       return instr;
-}
-
-static void __gus_instruments_clear()
-{
-       gus_instrument_t *next_instr, *cur_instr = (gus_instrument_t *) gus.instr;
-       while (cur_instr) {
-               next_instr = cur_instr->next;
-               __gus_instrument_free(cur_instr);
-               cur_instr = next_instr;
-       }
-}
-
-/******************************************************* libGUS interface *****/
-
-/* return value: number of GUS cards installed in system */
-int gus_cards()
-{
-       if (!gus.ok)
-               __gus_init();
-       return gus.ok ? 1 : 0;
-}
-
-int gus_info(gus_info_t * info, int reread)
-{
-       if (!gus.ok)
-               __gus_init();
-       if (!gus.ok)
-               return -1;
-
-       strcpy((char *)info->id, "gus0");
-       info->flags = (gus.ram ? GUS_STRU_INFO_F_PCM : 0);
-       info->version = gus.version;
-       info->port = gus.port;
-       info->irq = gus.irq[0];
-       info->dma1 = gus.dma[0];
-       info->dma2 = gus.dma[1];
-
-       info->mixing_freq = gus.freq;
-
-       info->memory_size = gus.ram * 1024;
-       info->memory_free = __gus_mem_get_free();
-       info->memory_block_8 = __gus_mem_get_free_8();
-       info->memory_block_16 = __gus_mem_get_free_16();
-       return 0;
-}
-
-int gus_open(int card, size_t queue_buffer_size, int non_block)
-{
-       __dpmi_meminfo struct_info, pool_info;
-
-       if (!gus.ok)
-               __gus_init();
-
-       if (!gus.ok || gus.open || card != 0)
-               return -1;
-
-       /* Now lock the gus structure in memory */
-       struct_info.address = __djgpp_base_address + (unsigned long)&gus;
-       struct_info.size = sizeof(gus);
-       if (__dpmi_lock_linear_region(&struct_info))
-               return -1;
-
-       /* And hook the GF1 interrupt */
-       __irq_stack_count = 4;
-       gus.gf1_irq =
-         irq_hook(gus.irq[0], gf1_irq, (long)gf1_irq_end - (long)gf1_irq);
-       __irq_stack_count = 1;
-       if (!gus.gf1_irq) {
-               __dpmi_unlock_linear_region(&struct_info);
-               return -1;
-       }
-
-       /* Enable the interrupt */
-       irq_enable(gus.gf1_irq);
-       if (gus.irq[0] > 7)
-               _irq_enable(2);
-
-       /* Allocate a DMA buffer: if we fail, we just use I/O so don't fail */
-       if ((gus.transfer == NULL) || (gus.transfer == __gus_transfer_dma))
-               gus.dma_buff = dma_allocate(gus.dma[0], GF1_DMA_BUFFER_SIZE);
-       else
-               gus.dma_buff = NULL;
-
-       /* Detect the best available RAM -> DRAM transfer function */
-       if (!gus.transfer) {
-               __gus_detect_transfer();
-               if (gus.transfer != __gus_transfer_dma || !gus.transfer)
-                       dma_free(gus.dma_buff), gus.dma_buff = NULL;
-
-               /* If no transfer function worked, fail */
-               if (!gus.transfer) {
-                       if (gus.dma_buff) {
-                               dma_free(gus.dma_buff);
-                               gus.dma_buff = NULL;
-                       }
-                       __dpmi_unlock_linear_region(&struct_info);
-                       irq_unhook(gus.gf1_irq);
-                       gus.gf1_irq = NULL;
-                       return -1;
-               }
-       }
-
-       /* Allocate and lock command pool buffer */
-       if (queue_buffer_size < 64)
-               queue_buffer_size = 64;
-       if (queue_buffer_size > 16384)
-               queue_buffer_size = 16384;
-       gus.cmd_pool = (unsigned char *) MikMod_malloc(queue_buffer_size);
-       pool_info.address = __djgpp_base_address + (unsigned long)&gus.cmd_pool;
-       pool_info.size = sizeof(queue_buffer_size);
-       if (__dpmi_lock_linear_region(&pool_info)) {
-               if (gus.dma_buff) {
-                       dma_free(gus.dma_buff);
-                       gus.dma_buff = NULL;
-               }
-               __dpmi_unlock_linear_region(&struct_info);
-               irq_unhook(gus.gf1_irq);
-               gus.gf1_irq = NULL;
-               return -1;
-       }
-
-       gus.open++;
-
-       __gus_mem_clear();
-       gus.t1_callback = __gus_timer_update;
-       gus.wt_callback = __gus_wavetable_update;
-       gus.vl_callback = __gus_volume_update;
-       gus_do_tempo(60);                       /* Default is 60 Hz */
-
-       return 0;
-}
-
-int gus_close(int card)
-{
-       __dpmi_meminfo struct_info;
-
-       if (!gus.open || card != 0)
-               return -1;
-
-       /* First reset the card: disable any operation it can currently perform */
-       __gus_reset(0);
-
-       gus.open--;
-
-       /* Stop the timer */
-       gus_timer_stop();
-
-       /* Free DMA buffer if used */
-       if (gus.dma_buff) {
-               dma_free(gus.dma_buff);
-               gus.dma_buff = NULL;
-       }
-
-       /* And unhook the GF1 interrupt */
-       irq_unhook(gus.gf1_irq);
-       gus.gf1_irq = NULL;
-
-       /* Unlock the gus structure */
-       struct_info.address = __djgpp_base_address + (unsigned long)&gus;
-       struct_info.size = sizeof(gus);
-       __dpmi_unlock_linear_region(&struct_info);
-
-       __gus_mem_clear();
-       __gus_instruments_clear();
-
-       return 0;
-}
-
-int gus_select(int card)
-{
-       if (!gus.open || (card != 0))
-               return -1;
-
-       return 0;
-}
-
-/* return value: same as gus_reset function
-   note: this command doesn't change number of active voices and doesn't do
-   hardware reset */
-int gus_reset_engine_only()
-{
-       gus.timer_base = 100;
-       return 0;
-}
-
-int gus_reset(int voices, unsigned int channel_voices)
-{
-       static unsigned short freq_table[32 - 14 + 1] = {
-               44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843,
-               25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293
-       };
-       int voice;
-       int timer;
-
-       /* No support for dynamically allocated voices for now */
-       gus.dynmask = channel_voices;
-
-       if (voices < 14)
-               voices = 14;
-       if (voices > 32)
-               voices = 32;
-
-       /* Stop the timer so that GUS IRQ won't clobber registers */
-       timer = (gus.timer_ctl_reg & GF1M_TIMER1);
-       if (timer)
-               gus_timer_stop();
-
-       /* Stop all voices */
-       for (voice = 0; voice < 32; voice++) {
-               __gus_select_voice(voice);
-               __gus_stop_voice();
-               gus.cur_wave[voice] = NULL;
-               gus.cur_vol[voice] = 0;
-
-               __gus_delay();
-
-               /* Reset voice parameters to reasonable values */
-               __gus_set_current(0, 0);
-               __gus_set_loop_start(0, 0);
-               __gus_set_loop_end(0, 0);
-               __gus_outregw(GF1R_VOLUME, 0);
-               __gus_outregb(GF1R_VOLUME_RATE, 0);
-               __gus_outregb(GF1R_VOLUME_START, 0);
-               __gus_outregb(GF1R_VOLUME_END, 0);
-               __gus_outregb(GF1R_BALANCE, 0x7);
-       }
-
-       voice = (__gus_inregb(GF1R_VOICES) & 0x1f) + 1;
-
-       if (voice != voices) {
-               int reset = __gus_inregb(GF1R_RESET);
-               __gus_outregb(GF1R_RESET, reset & ~GF1M_OUTPUT_ENABLE);
-               __gus_delay();
-               __gus_outregb(GF1R_VOICES, 0xc0 | (voices - 1));
-               __gus_delay();
-               __gus_outregb(GF1R_RESET, reset);
-       }
-
-       /* Compute the discretization frequence */
-       gus.voices = voices;
-       if (gus.interwave)
-               gus.freq = 44100;
-       else
-               gus.freq = freq_table[voices - 14];
-
-       gus_reset_engine_only();
-
-       if (timer)
-               gus_timer_continue();
-
-       return gus.voices;
-}
-
-int gus_do_flush()
-{
-       DEBUG_PRINT(("gus_do_flush: top = %d\n", gus.cmd_pool_top))
-         gus.cmd_pool_ready = 1;
-       return 0;
-}
-
-/* set new tempo */
-void gus_do_tempo(unsigned int tempo)
-{
-       DEBUG_PRINT(("gus_do_tempo (%d)\n", tempo))
-         gus_timer_tempo(tempo);
-       gus_timer_start();
-}
-
-/* set voice frequency in Hz */
-void gus_do_voice_frequency(unsigned char voice, unsigned int freq)
-{
-       DEBUG_PRINT(("gus_do_voice_frequency (%d, %d)\n", voice, freq))
-         __pool_select_voice(voice);
-       __pool_command_w(PCMD_FREQ,
-                                        (((freq << 9) + (gus.freq >> 1)) / gus.freq) << 1);
-}
-
-/* set voice pan (0-16384) (full left - full right) */
-void gus_do_voice_pan(unsigned char voice, unsigned short pan)
-{
-       DEBUG_PRINT(("gus_do_voice_pan (%d, %d)\n", voice, pan))
-         pan >>= 10;
-       if (pan > 15)
-               pan = 15;
-       __pool_select_voice(voice);
-       __pool_command_b(PCMD_PAN, pan);
-}
-
-/* set voice volume level 0-16384 (linear) */
-void gus_do_voice_volume(unsigned char voice, unsigned short vol)
-{
-       DEBUG_PRINT(("gus_do_voice_volume (%d, %d)\n", voice, vol))
-         if (vol > 0x3fff)
-               vol = 0x3fff;
-       __pool_select_voice(voice);
-       __pool_command_w(PCMD_VOLUME, __gus_volume_table[vol >> 5]);
-}
-
-/* start voice
- *   voice    : voice #
- *   program  : program # or ~0 = current
- *   freq     : frequency in Hz
- *   volume   : volume level (0-16384) or ~0 = current
- *   pan      : pan level (0-16384) or ~0 = current
- */
-void gus_do_voice_start(unsigned char voice, unsigned int program,
-                                               unsigned int freq, unsigned short volume,
-                                               unsigned short pan)
-{
-       gus_do_voice_start_position(voice, program, freq, volume, pan, 0);
-}
-
-/* start voice
- *   voice    : voice #
- *   program  : program # or ~0 = current
- *   freq     : frequency in Hz
- *   volume   : volume level (0-16384) or ~0 = current
- *   pan      : pan level (0-16384) or ~0 = current
- *   position : offset to wave in bytes * 16 (lowest 4 bits - fraction)
- */
-void gus_do_voice_start_position(unsigned char voice, unsigned int program,
-                                                                unsigned int freq, unsigned short volume,
-                                                                unsigned short pan, unsigned int position)
-{
-       gus_instrument_t *instrument;
-       gus_wave_t *wave;
-
-       DEBUG_PRINT(
-                               ("gus_do_voice_start_position (%d, %d, pos: %d)\n", voice,
-                                program, position))
-
-         instrument = __gus_instrument_get(program);
-
-       if (!instrument
-               || !instrument->info.layer
-               || !instrument->info.layer->wave
-               || instrument->flags == GUS_INSTR_F_NOT_FOUND
-               || instrument->flags == GUS_INSTR_F_NOT_LOADED) return;
-
-       gus_do_voice_frequency(voice, freq);
-       gus_do_voice_pan(voice, pan);
-
-       /* We have to set volume different way, to avoid unneeded work in handler */
-       if (volume > 0x3fff)
-               volume = 0x3fff;
-       __pool_command_w(PCMD_VOLUME_PREPARE, __gus_volume_table[volume >> 5]);
-
-       switch (instrument->mode) {
-         case GUS_INSTR_SIMPLE:
-               wave = instrument->info.layer->wave;
-               if (position)
-                       __pool_command_l(PCMD_OFFSET, position);
-               __pool_command_l(PCMD_START, (unsigned long)wave);
-               break;
-       }
-}
-
-/* stop voice
- *   mode = 0 : stop voice now
- *   mode = 1 : disable wave loop and finish it
- */
-void gus_do_voice_stop(unsigned char voice, unsigned char mode)
-{
-       __pool_select_voice(voice);
-       if (mode)
-               __pool_command(PCMD_STOP_LOOP);
-       else
-               __pool_command(PCMD_STOP);
-}
-
-/* wait x ticks - this command is block separator
-   all commands between blocks are interpreted in the begining of one tick */
-void gus_do_wait(unsigned int ticks)
-{
-       DEBUG_PRINT(("gus_do_wait (%d)\n", ticks))
-
-         ticks += gus.t1_ticks;
-       while ((int)(ticks - gus.t1_ticks) > 0);
-}
-
-int gus_get_voice_status(int voice)
-{
-       __gus_select_voice(voice);
-       return __gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED ? 0 : 1;
-}
-
-/* return value: file handle (descriptor) for /dev/gus */
-int gus_get_handle()
-{
-       /* Return stdout handle so that select() will "work" with it */
-       return 0;
-}
-
-/* return value: zero if instrument was successfully allocated */
-int gus_memory_alloc(gus_instrument_t * instrument)
-{
-       gus_instrument_t *instr = __gus_instrument_copy(instrument);
-       gus_layer_t *cur_layer;
-       gus_wave_t *cur_wave;
-
-       DEBUG_PRINT(("gus_memory_alloc (%d)\n", instrument->number.instrument))
-
-         if (!instr)
-               return -1;
-
-       for (cur_layer = instr->info.layer; cur_layer;
-                cur_layer = cur_layer->next) for (cur_wave = cur_layer->wave;
-                                                                                  cur_wave;
-                                                                                  cur_wave = cur_wave->next) {
-                       if (cur_layer->mode == GUS_INSTR_SIMPLE) {
-                               cur_wave->begin.memory = __gus_mem_alloc(cur_wave->size,
-                                                                                                                cur_wave->format &
-                                                                                                                GUS_WAVE_16BIT);
-                               if (cur_wave->begin.memory == (unsigned int)-1) {
-                                       __gus_instrument_free(instr);
-                                       return -1;
-                               }
-                               gus.transfer(cur_wave->begin.memory, cur_wave->begin.ptr,
-                                                        cur_wave->size, cur_wave->format);
-                       } else if (cur_layer->mode == GUS_INSTR_PATCH)
-                               /* not supported yet */ ;
-               }
-
-       return 0;
-}
-
-/* return value: zero if instrument was successfully removed */
-int gus_memory_free(gus_instrument_t * instrument)
-{
-       gus_instrument_t *cur_instr = gus.instr;
-
-       DEBUG_PRINT(("gus_memory_free (%d)\n", instrument->number.instrument))
-
-         for (; cur_instr; cur_instr = cur_instr->next)
-               if (cur_instr->number.instrument == instrument->number.instrument)
-                       return __gus_instrument_free(cur_instr);
-
-       return -1;
-}
-
-/* return value: unused gus memory in bytes */
-int gus_memory_free_size()
-{
-       return __gus_mem_get_free();
-}
-
-/* return value: zero if success */
-int gus_memory_pack()
-{
-       __gus_mem_pack();
-       return 0;
-}
-
-/* return value: gus memory size in bytes */
-int gus_memory_size()
-{
-       return gus.ram * 1024;
-}
-
-/* return value: current largest free block for 8-bit or 16-bit wave */
-int gus_memory_free_block(int w_16bit)
-{
-       return w_16bit ? __gus_mem_get_free_16() : __gus_mem_get_free_8();
-}
-
-/* input value:        see to GUS_DOWNLOAD_MODE_XXXX constants (gus.h)
-   return value: zero if samples & instruments was successfully removed        from
-   GF1 memory manager */
-int gus_memory_reset(int mode)
-{
-       __gus_mem_clear();
-       __gus_instruments_clear();
-       return 0;
-}
-
-/* return value: zero if command queue was successfully flushed */
-int gus_queue_flush()
-{
-       return 0;
-}
-
-/* input value: echo buffer size in items (if 0 - erase echo buffer) */
-int gus_queue_read_set_size(int items)
-{
-       return 0;
-}
-
-/* input value: write queue size in items (each item have 8 bytes) */
-int gus_queue_write_set_size(int items)
-{
-       return 0;
-}
-
-/* return value: zero if successfull */
-int gus_timer_start()
-{
-       gus.timer_ctl_reg |= GF1M_TIMER1;
-       __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
-
-       gus.timer_ctl = gus.timer_ctl & ~GF1M_MASK_TIMER1;
-       outportb(GF1_TIMER_CTRL, 0x04);
-       outportb(GF1_TIMER_DATA, gus.timer_ctl | GF1M_START_TIMER1);
-       return 0;
-}
-
-/* return value: zero if timer was stoped */
-int gus_timer_stop()
-{
-       gus.timer_ctl_reg &= ~GF1M_TIMER1;
-       __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
-
-       gus.timer_ctl = gus.timer_ctl | GF1M_MASK_TIMER1;
-       outportb(GF1_TIMER_CTRL, 0x04);
-       outportb(GF1_TIMER_DATA, gus.timer_ctl);
-       return 0;
-}
-
-/* return value: zero if setup was success */
-int gus_timer_tempo(int ticks)
-{
-       unsigned int counter;
-
-       /* Limit ticks per second to 1..1000 range */
-       if (ticks < 1)
-               ticks = 1;
-       if (ticks > 1000)
-               ticks = 1000;
-
-       /* GF1 timer1 period is 80 usecs, 12500 times per second */
-       counter = 1250000 / (ticks * gus.timer_base);
-       gus.t1_multiple = 1;
-       while (counter > 255) {
-               counter >>= 1;
-               gus.t1_multiple <<= 1;
-       }
-       gus.t1_countdown = gus.t1_multiple;
-       __gus_outregb(GF1R_TIMER1, 256 - counter);
-       return 0;
-}
-
-/* return value: zero if timer will be continue */
-int gus_timer_continue()
-{
-       return gus_timer_start();
-}
-
-/* return value: zero if setup was success (default timebase = 100) */
-int gus_timer_base(int base)
-{
-       gus.timer_base = base;
-       return 0;
-}
-
-void gus_timer_callback(void (*timer_callback) ())
-{
-       gus.timer_callback = timer_callback;
-}
-
-void gus_convert_delta(unsigned int type, unsigned char *dest,
-                                          unsigned char *src, size_t size)
-{
-       if (!(type & GUS_WAVE_DELTA))
-               return;
-
-       /* This doesn't depend much on wave signedness, since addition/subtraction
-          do not depend on operand signedness */
-       if (type & GUS_WAVE_16BIT) {
-               unsigned short delta = type & GUS_WAVE_UNSIGNED ? 0x8000 : 0;
-               while (size--) {
-                       delta = *(unsigned short *)dest = *(unsigned short *)src + delta;
-                       src += sizeof(unsigned short);
-                       dest += sizeof(unsigned short);
-               }
-       } else {
-               unsigned char delta = type & GUS_WAVE_UNSIGNED ? 0x80 : 0;
-               while (size--) {
-                       delta = *(unsigned char *)dest = *(unsigned char *)src + delta;
-                       src++;
-                       dest++;
-               }
-       }
-}
-
-int gus_dma_usage (int use)
-{
-       if (gus.dma_buff)
-               return -1;
-       gus.transfer = __gus_transfer_io;
-       return 0;
-}
-
-#endif /* DRV_ULTRA */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dosgus.h b/libs/mikmod/drivers/dos/dosgus.h
deleted file mode 100644 (file)
index ae3488a..0000000
+++ /dev/null
@@ -1,514 +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$
-
-  libGUS-alike definitions for DOS
-
-==============================================================================*/
-
-#ifndef __DOSGUS_H__
-#define __DOSGUS_H__
-
-#include <pc.h>
-#include "dosdma.h"
-#include "dosirq.h"
-#include "libgus.h"
-
-/* Private header file for a libGUS-alike library for DOS */
-
-#define JOYSTICK_TIMER                 (gus.port+0x201)        /* 201 */
-#define JOYSTICK_DATA                  (gus.port+0x201)        /* 201 */
-
-#define GF1_MIDI_CTRL                  (gus.port+0x100)        /* 3X0 */
-#define GF1_MIDI_DATA                  (gus.port+0x101)        /* 3X1 */
-
-#define GF1_VOICESEL                   (gus.port+0x102)        /* 3X2 */
-#define GF1_REGSEL                     (gus.port+0x103)        /* 3X3 */
-#define GF1_DATA                       (gus.port+0x104)        /* 3X4 */
-#define GF1_DATA_LOW                   (gus.port+0x104)        /* 3X4 */
-#define GF1_DATA_HIGH                  (gus.port+0x105)        /* 3X5 */
-#define GF1_IRQ_STATUS                 (gus.port+0x006)        /* 2X6 */
-#define GF1_DRAM                       (gus.port+0x107)        /* 3X7 */
-
-#define GF1_MIX_CTRL                   (gus.port+0x000)        /* 2X0 */
-#define GF1_TIMER_CTRL                 (gus.port+0x008)        /* 2X8 */
-#define GF1_TIMER_DATA                 (gus.port+0x009)        /* 2X9 */
-#define GF1_IRQ_CTRL                   (gus.port+0x00B)        /* 2XB */
-#define GF1_REG_CTRL                   (gus.port+0x00F)        /* 2XF */
-
-#define GF1_REVISION                   (gus.port+0x506)        /* 7X6 */
-
-/* The GF1 hardware clock rate */
-#define CLOCK_RATE                     9878400L
-
-/* GF1 voice-independent registers */
-#define        GF1R_DMA_CONTROL                0x41
-#define        GF1R_DMA_ADDRESS                0x42
-#define        GF1R_DRAM_LOW                   0x43
-#define        GF1R_DRAM_HIGH                  0x44
-
-#define        GF1R_TIMER_CONTROL              0x45
-#define        GF1R_TIMER1                     0x46
-#define        GF1R_TIMER2                     0x47
-
-#define        GF1R_SAMPLE_RATE                0x48
-#define        GF1R_SAMPLE_CONTROL             0x49
-
-#define        GF1R_JOYSTICK                   0x4B
-#define        GF1R_RESET                      0x4C
-
-/* GF1 voice-specific registers */
-#define        GF1R_VOICE_CONTROL              0x00
-#define        GF1R_FREQUENCY                  0x01
-#define        GF1R_START_HIGH                 0x02
-#define        GF1R_START_LOW                  0x03
-#define        GF1R_END_HIGH                   0x04
-#define        GF1R_END_LOW                    0x05
-#define        GF1R_VOLUME_RATE                0x06
-#define        GF1R_VOLUME_START               0x07
-#define        GF1R_VOLUME_END                 0x08
-#define        GF1R_VOLUME                     0x09
-#define        GF1R_ACC_HIGH                   0x0a
-#define        GF1R_ACC_LOW                    0x0b
-#define        GF1R_BALANCE                    0x0c
-#define        GF1R_VOLUME_CONTROL             0x0d
-#define        GF1R_VOICES                     0x0e
-#define        GF1R_IRQ_SOURCE                 0x0f
-
-/* Add this to above registers for reading */
-#define GF1R_READ_MASK                 0x80
-
-/* MIDI */
-#define        GF1M_MIDI_RESET                 0x03
-#define        GF1M_MIDI_ENABLE_XMIT           0x20
-#define        GF1M_MIDI_ENABLE_RCV            0x80
-
-#define        GF1M_MIDI_RCV_FULL              0x01
-#define        GF1M_MIDI_XMIT_EMPTY            0x02
-#define        GF1M_MIDI_FRAME_ERR             0x10
-#define        GF1M_MIDI_OVERRUN               0x20
-#define        GF1M_MIDI_IRQ_PEND              0x80
-
-/* Joystick */
-#define        GF1M_JOY_POSITION               0x0f
-#define        GF1M_JOY_BUTTONS                0xf0
-
-/* GF1_IRQ_STATUS (port 2X6) */
-#define        GF1M_IRQ_MIDI_TX                0x01    /* pending MIDI xmit IRQ */
-#define        GF1M_IRQ_MIDI_RX                0x02    /* pending MIDI recv IRQ */
-#define        GF1M_IRQ_TIMER1                 0x04    /* general purpose timer */
-#define        GF1M_IRQ_TIMER2                 0x08    /* general purpose timer */
-#define        GF1M_IRQ_WAVETABLE              0x20    /* pending wavetable IRQ */
-#define        GF1M_IRQ_ENVELOPE               0x40    /* pending volume envelope IRQ */
-#define        GF1M_IRQ_DMA_COMPLETE           0x80    /* pending dma transfer complete IRQ */
-
-/* GF1_MIX_CTRL (port 2X0) */
-#define        GF1M_MIXER_NO_LINE_IN           0x01    /* 0: enable */
-#define        GF1M_MIXER_NO_OUTPUT            0x02    /* 0: enable */
-#define        GF1M_MIXER_MIC_IN               0x04    /* 1: enable */
-#define        GF1M_MIXER_GF1_IRQ              0x08    /* 1: enable */
-#define GF1M_GF1_COMBINED_IRQ          0x10    /* 1: IRQ1 == IRQ2 */
-#define        GF1M_MIDI_LOOPBACK              0x20    /* 1: enable loop back */
-#define        GF1M_CONTROL_SELECT             0x40    /* 0: DMA latches; 1: IRQ latches */
-
-/* Timer data register (2X9) */
-#define GF1M_START_TIMER1              0x01
-#define GF1M_START_TIMER2              0x02
-#define GF1M_MASK_TIMER1               0x20
-#define GF1M_MASK_TIMER2               0x40
-#define GF1M_TIMER_CLRIRQ              0x80
-
-/* IRQ/DMA control register (2XB) */
-#define GF1M_IRQ_EQUAL                 0x40
-#define GF1M_DMA_EQUAL                 0x40
-
-/* (0x41) DMA control register bits */
-#define        GF1M_DMAR_ENABLE                0x01    /* 1: go */
-#define        GF1M_DMAR_READ                  0x02    /* 1: read (->RAM), 0: write (->DRAM) */
-#define        GF1M_DMAR_CHAN16                0x04    /* 1: 16 bit, 0: 8 bit DMA channel */
-#define        GF1M_DMAR_RATE                  0x18    /* 00: fast, 11: slow */
-#define        GF1M_DMAR_IRQ_ENABLE            0x20    /* 1: enable */
-#define        GF1M_DMAR_IRQ_PENDING           0x40    /* R: DMA irq pending */
-#define        GF1M_DMAR_DATA16                0x40    /* W: 0: 8 bits; 1: 16 bits per sample */
-#define        GF1M_DMAR_TOGGLE_SIGN           0x80    /* W: 1: invert high bit */
-
-/* DMA transfer rate divisors */
-#define        GF1M_DMAR_RATE0                 0x00    /* Fastest DMA xfer (~650khz) */
-#define        GF1M_DMAR_RATE1                 0x08    /* fastest / 2 */
-#define        GF1M_DMAR_RATE2                 0x10    /* fastest / 4 */
-#define        GF1M_DMAR_RATE3                 0x18    /* Slowest DMA xfer (fastest / 8) */
-
-/* (0x45) Timer Control */
-#define GF1M_TIMER1                    0x04    /* Enable timer 1 IRQ */
-#define GF1M_TIMER2                    0x08    /* Enable timer 2 IRQ */
-
-/* (0x49) Sampling (ADC) control register */
-#define        GF1M_DMAW_ENABLE                0x01    /* 1: Start sampling */
-#define        GF1M_DMAW_MODE                  0x02    /* 0: mono, 1: stereo */
-#define        GF1M_DMAW_CHAN16                0x04    /* 0: 8 bit, 1: 16 bit */
-#define        GF1M_DMAW_IRQ_ENABLE            0x20    /* 1: enable IRQ */
-#define        GF1M_DMAW_IRQ_PENDING           0x40    /* 1: irq pending */
-#define        GF1M_DMAW_TOGGLE_SIGN           0x80    /* 1: invert sign bit */
-
-/* (0x4C) GF1 reset register */
-#define        GF1M_MASTER_RESET               0x01    /* 0: hold in reset */
-#define        GF1M_OUTPUT_ENABLE              0x02    /* 1: enable output */
-#define        GF1M_MASTER_IRQ                 0x04    /* 1: master IRQ enable */
-
-/* (0x0,0x80) Voice control register - GF1R_VOICE_CONTROL */
-#define        GF1VC_STOPPED                   0x01    /* 1: voice has stopped */
-#define        GF1VC_STOP                      0x02    /* 1: stop voice */
-#define        GF1VC_DATA16                    0x04    /* 0: 8 bit, 1: 16 bit */
-#define        GF1VC_LOOP_ENABLE               0x08    /* 1: enable */
-#define        GF1VC_BI_LOOP                   0x10    /* 1: bi directional looping */
-#define        GF1VC_IRQ                       0x20    /* 1: enable voice's wave irq */
-#define        GF1VC_BACKWARD                  0x40    /* 0: increasing, 1: decreasing */
-#define        GF1VC_IRQ_PENDING               0x80    /* 1: wavetable irq pending */
-
-/* (0x01,0x81) Frequency control */
-/* Bit 0       - Unused */
-/* Bits        1-9     - Fractional portion */
-/* Bits        10-15   - Integer portion */
-
-/* (0x02,0x82) Accumulator start address - GF1R_START_HIGH */
-/* Bits        0-11    - HIGH 12 bits of address */
-/* Bits        12-15   - Unused */
-
-/* (0x03,0x83) Accumulator start address - GF1R_START_LOW */
-/* Bits        0-4     - Unused */
-/* Bits        5-8     - Fractional portion */
-/* Bits        9-15    - Low 7 bits of integer portion */
-
-/* (0x04,0x84) Accumulator end address - GF1R_END_HIGH */
-/* Bits        0-11    - HIGH 12 bits of address */
-/* Bits        12-15   - Unused */
-
-/* (0x05,0x85) Accumulator end address - GF1R_END_LOW */
-/* Bits        0-4     - Unused */
-/* Bits        5-8     - Fractional portion */
-/* Bits        9-15    - Low 7 bits of integer portion */
-
-/* (0x06,0x86) Volume Envelope control register - GF1R_VOLUME_RATE */
-#define        GF1VL_RATE_MANTISSA             0x3f
-#define        GF1VL_RATE_RANGE                0xC0
-
-/* (0x07,0x87) Volume envelope start - GF1R_VOLUME_START */
-#define        GF1VL_START_MANT                0x0F
-#define        GF1VL_START_EXP                 0xF0
-
-/* (0x08,0x88) Volume envelope end - GF1R_VOLUME_END */
-#define        GF1VL_END_MANT                  0x0F
-#define        GF1VL_END_EXP                   0xF0
-
-/* (0x09,0x89) Current volume register - GF1R_VOLUME */
-/* Bits        0-3     - Unused */
-/* Bits        4-11    - Mantissa of current volume */
-/* Bits        10-15   - Exponent of current volume */
-
-/* (0x0A,0x8A) Accumulator value (high) */
-/* Bits        0-12    - HIGH 12 bits of current position (a19-a7) */
-
-/* (0x0B,0x8B) Accumulator value (low) */
-/* Bits        0-8     - Fractional portion */
-/* Bits        9-15    - Integer portion of low adress (a6-a0) */
-
-/* (0x0C,0x8C) Pan (balance) position */
-/* Bits        0-3     - Balance position 0=full left, 0x0f=full right */
-
-/* (0x0D,0x8D) Volume control register - GF1R_VOLUME_CONTROL */
-#define        GF1VL_STOPPED                   0x01    /* volume has stopped */
-#define        GF1VL_STOP                      0x02    /* stop volume */
-#define        GF1VL_ROLLOVER                  0x04    /* Roll PAST end & gen IRQ */
-#define        GF1VL_LOOP_ENABLE               0x08    /* 1: enable */
-#define        GF1VL_BI_LOOP                   0x10    /* 1: bi directional looping */
-#define        GF1VL_IRQ                       0x20    /* 1: enable voice's volume irq */
-#define        GF1VL_BACKWARD                  0x40    /* 0: increasing, 1: decreasing */
-#define        GF1VL_IRQ_PENDING               0x80    /* 1: wavetable irq pending */
-
-/* (0x0E,0x8E) Number of active voices */
-/* Bits        0-5     - Number of active voices - 1 */
-
-/* (0x0F,0x8F) Sources of IRQs */
-/* Bits        0-4     - interrupting voice number */
-/* Bit 5       - Always a 1 */
-#define        GF1IRQ_VOLUME                   0x40    /* individual voice irq bit */
-#define        GF1IRQ_WAVE                     0x80    /* individual waveform irq bit */
-
-/* Commands are pooled and executed ON TIMER (1st timer) interrupt.
- * Currently there is a limit on the number of commands that you can
- * issue between gus_do_flush (...); this should not be an issue however
- * because each voice has a limited (little) set of parameters that
- * you can change (freq, vol, pan... what else?)
- *
- * The pool is a pseudo-CPU code that gets executed once per timer interrupt.
- */
-
-/* Below are definitions for commands placed in GUS command pool */
-#define PCMD_NOP                       0x00    /* Traditionally ... */
-#define PCMD_VOICE                     0x01    /* +B: select voice */
-#define PCMD_START                     0x02    /* +L: start voice */
-#define PCMD_STOP                      0x03    /*     stop voice */
-#define PCMD_FREQ                      0x04    /* +W: set frequence */
-#define PCMD_VOLUME                    0x05    /* +W: set volume */
-#define PCMD_VOLUME_PREPARE            0x06    /* +W: prepare to set volume on (soon to follow) kick */
-#define PCMD_PAN                       0x07    /* +B: set panning */
-#define PCMD_OFFSET                    0x08    /* +L: set DRAM offset */
-#define PCMD_STOP_LOOP                 0x09    /*     stop looping */
-
-#define GUS_VOLCHANGE_RAMP             0x20    /* Volume change ramp speed */
-
-/* Definition for the boolean type */
-typedef unsigned char boolean;
-/* Prototype for functions that do block transfers to GUS DRAM:
-   flags can contain any of the following bits:
-   GUS_WAVE_16BIT    - sample is 16-bit
-   GUS_WAVE_UNSIGNED - do not invert sign bit while downloading
- */
-typedef void (*__gus_transfer_func) (unsigned long address,
-                                     unsigned char *source,
-                                     unsigned long size, int flags);
-typedef void (*__gus_callback) ();
-typedef void (*__gus_callback_3) (unsigned int, unsigned int, unsigned int);
-
-/* Structure used to keep track of all on-board GUS memory */
-typedef struct __struct_gus_mcb {
-       struct __struct_gus_mcb *next;          /* Next MCB in chain */
-       struct __struct_gus_mcb *prev;          /* Previous MCB in chain */
-       unsigned int addr;                      /* GUS DRAM address */
-       unsigned int size;                      /* Memory block size */
-       int free;                               /* 1: block is free */
-} __gus_mcb;
-
-/* Structure defining overall GUS state/information */
-typedef struct __gus_state_s {
-       unsigned int port;                      /* Base I/O port (0x220, 0x240, ...) */
-       unsigned int irq[2];                    /* GF1 IRQ and MIDI IRQ */
-       unsigned int dma[2];                    /* Play / record DMA */
-       unsigned int ram;                       /* Memory size (K), i.e. 256, 1024 etc */
-       unsigned int version;                   /* GUS version (see GUS_CARD_VERSION_XXX in libgus.h */
-       unsigned int freq;                      /* Current mixing frequency */
-       unsigned int voices;                    /* Active voices (14-32) */
-       unsigned int dynmask;                   /* Dynamically allocated voices mask */
-       unsigned int timer_base;                /* The relative timer speed in percents (def: 100) */
-       volatile unsigned int t1_ticks;         /* Incremented per each timer1 tick */
-       volatile unsigned int t2_ticks;         /* Incremented per each timer2 tick */
-       volatile unsigned int t1_countdown;     /* t1_callback is called when this reaches zero */
-       volatile unsigned int t2_countdown;     /* t2_callback is called when this reaches zero */
-       unsigned int t1_multiple;               /* Timer1 handler is called once per such many ticks */
-       unsigned int t2_multiple;               /* Timer2 handler is called once per such many ticks */
-       struct irq_handle *gf1_irq;             /* The interrupt handler for GF1 events */
-       dma_buffer *dma_buff;                   /* Pre-allocated DMA buffer */
-       __gus_callback dma_callback;            /* Routine called at end of DMA transfers */
-       __gus_callback t1_callback;             /* Routine called on Timer1 events */
-       __gus_callback t2_callback;             /* Routine called on Timer1 events */
-       __gus_callback timer_callback;          /* Called once per TEMPO ticks */
-       __gus_callback_3 wt_callback;           /* Routine called on WaveTable events */
-       __gus_callback_3 vl_callback;           /* Routine called on Volume ramp events */
-       __gus_mcb *mcb;                         /* Chained list of memory control blocks */
-       __gus_transfer_func transfer;           /* Best working function for DRAM transfer */
-       gus_instrument_t *instr;                /* The list of registered instruments */
-       unsigned short mixer;                   /* Current mixer register state */
-       unsigned char dma_rate;                 /* One of GF1M_DMAR_RATEX constants defined above */
-       unsigned char timer_ctl;                /* Timer control register value (2x8/2x9) */
-       unsigned char timer_ctl_reg;            /* Timer control register value (GF1/0x45) */
-       boolean ok;                             /* Is the information below okay? */
-       boolean open;                           /* 1 if between gus_open() and gus_close() */
-       boolean ics;                            /* Is it equipped with an ICS mixer? */
-       boolean ics_flipped;                    /* rev 5 (3.7) has flipped R/L mixer */
-       boolean codec;                          /* Is it equipped with a GUS MAX codec? */
-       boolean interwave;                      /* GUS InterWave card */
-       volatile boolean dma_active;            /* DMA is transferring data */
-       volatile boolean cmd_pool_ready;        /* Flush cmd_pool during timer interrupt */
-       unsigned char cmd_voice;                /* Pool selection index cache */
-       unsigned int cmd_pool_top;              /* Command pool top */
-       unsigned char *cmd_pool;                /* Async commands pool */
-       /* The following data is for private use only by interrupt routines! */
-       gus_wave_t *cur_wave[32];               /* Currently played waves */
-       boolean voice_kick[32];                 /* Kick wave on next volume ramp IRQ */
-       unsigned int kick_offs[32];             /* Sample start position on kick */
-       unsigned short cur_vol[32];             /* Current voice volumes */
-       unsigned int cur_voice;                 /* Current voice */
-       unsigned int eow_ignore;                /* Temp ignore end-of-wave IRQ for these voices */
-} __gus_state;
-
-extern __gus_state gus;
-extern void __gus_delay();
-
-static unsigned long __gus_convert_addr16(unsigned long address)
-{
-       return ((address & 0x0003ffff) >> 1) | (address & ~0x0003ffff);
-}
-
-/* The XXX_slow routines cannot be used outside IRQ handler! */
-static inline void __gus_outregb_slow(unsigned char reg, unsigned char value)
-{
-       outportb(GF1_REGSEL, reg);
-       outportb(GF1_DATA_HIGH, value);
-       __gus_delay();
-       outportb(GF1_DATA_HIGH, value);
-}
-
-static inline void __gus_outregw_slow(unsigned char reg, unsigned short value)
-{
-       outportb(GF1_REGSEL, reg);
-       outportw(GF1_DATA, value);
-       __gus_delay();
-       outportw(GF1_DATA, value);
-}
-
-static inline void __gus_outregb(unsigned char reg, unsigned char value)
-{
-       outportb(GF1_REGSEL, reg);
-       outportb(GF1_DATA_HIGH, value);
-}
-
-static inline void __gus_outregw(unsigned char reg, unsigned short value)
-{
-       outportb(GF1_REGSEL, reg);
-       outportw(GF1_DATA, value);
-}
-
-static inline unsigned char __gus_inregb(unsigned char reg)
-{
-       if (reg < 0x10)
-               reg |= GF1R_READ_MASK;
-       outportb(GF1_REGSEL, reg);
-       return inportb(GF1_DATA_HIGH);
-}
-
-static inline unsigned short __gus_inregw(unsigned char reg)
-{
-       if (reg < 0x10)
-               reg |= GF1R_READ_MASK;
-       outportb(GF1_REGSEL, reg);
-       return inportw(GF1_DATA);
-}
-
-static inline void __gus_set_dram_address(unsigned int address)
-{
-       __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
-       __gus_outregw(GF1R_DRAM_LOW, address);
-}
-
-static inline unsigned char __gus_peek(unsigned int address)
-{
-       __gus_set_dram_address(address);
-       return inportb(GF1_DRAM);
-}
-
-static inline void __gus_poke(unsigned int address, unsigned char value)
-{
-       __gus_set_dram_address(address);
-       outportb(GF1_DRAM, value);
-}
-
-static inline void __gus_select_voice(unsigned char voice)
-{
-       outportb(GF1_VOICESEL, voice);
-}
-
-static inline void __gus_set_current(unsigned char mode,
-                                     unsigned long address)
-{
-       if (mode & GF1VC_DATA16)
-               address = __gus_convert_addr16(address);
-       __gus_outregw_slow(GF1R_ACC_HIGH, address >> 11);
-       __gus_outregw_slow(GF1R_ACC_LOW, address << 5);
-}
-
-static inline void __gus_set_loop_start(unsigned char mode,
-                                                                               unsigned long address)
-{
-       if (mode & GF1VC_DATA16)
-               address = __gus_convert_addr16(address);
-       __gus_outregw_slow(GF1R_START_HIGH, address >> 11);
-       __gus_outregw_slow(GF1R_START_LOW, address << 5);
-}
-
-static inline void __gus_set_loop_end(unsigned char mode,
-                                      unsigned long address)
-{
-       address--;
-       if (mode & GF1VC_DATA16)
-               address = __gus_convert_addr16(address);
-       __gus_outregw_slow(GF1R_END_HIGH, address >> 11);
-       __gus_outregw_slow(GF1R_END_LOW, address << 5);
-}
-
-static inline void __gus_mixer_output(boolean state)
-{
-       if (state)
-               gus.mixer &= ~GF1M_MIXER_NO_OUTPUT;
-       else
-               gus.mixer |= GF1M_MIXER_NO_OUTPUT;
-       outportb(GF1_MIX_CTRL, gus.mixer);
-       /* Dummy read to avoid touching DMA latches */
-       __gus_inregb(GF1R_BALANCE);
-}
-
-/* Inline routines for working with command pools */
-
-/* WARNING: no bounds checking due to performance reasons */
-#define __POOL_VALUE(type,value)                                                               \
-  *((unsigned type *)&gus.cmd_pool [gus.cmd_pool_top]) = value;        \
-  gus.cmd_pool_top += sizeof (type);
-
-static inline void __pool_command(unsigned char command)
-{
-       __POOL_VALUE(char, command);
-}
-
-static inline void __pool_command_b(unsigned char command, unsigned char arg)
-{
-       __POOL_VALUE(char, command);
-       __POOL_VALUE(char, arg);
-}
-
-static inline void __pool_command_w(unsigned char command, unsigned short arg)
-{
-       __POOL_VALUE(char, command);
-       __POOL_VALUE(short, arg);
-}
-
-static inline void __pool_command_l(unsigned char command, unsigned long arg)
-{
-       __POOL_VALUE(char, command);
-       __POOL_VALUE(long, arg);
-}
-
-static inline void __pool_select_voice(unsigned char voice)
-{
-       if (gus.cmd_voice != voice)
-               __pool_command_b(PCMD_VOICE, gus.cmd_voice = voice);
-}
-
-#undef __POOL_VALUE
-
-#ifdef DEBUG
-/* Debug dump of GUS DRAM heap */
-extern void __gus_mem_dump();
-#endif
-
-#endif /* __DOSGUS_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dosirq.c b/libs/mikmod/drivers/dos/dosirq.c
deleted file mode 100644 (file)
index 9b0e21f..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
-    Implementation of IRQ routines on DOS
-    Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
-
-    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 library 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "dosirq.h"
-
-#include <dpmi.h>
-#include <go32.h>
-#include <dos.h>
-#include <sys/nearptr.h>
-#include <malloc.h>
-#include <string.h>
-#include "mikmod.h" /* for MikMod_malloc() & co */
-
-unsigned int __irq_stack_size = 0x4000;
-unsigned int __irq_stack_count = 1;
-
-static void __int_stub_template (void)
-{
-/* *INDENT-OFF* */
-       asm("   pushal\n"
-               "       pushl   %ds\n"
-               "       pushl   %es\n"
-               "       pushl   %fs\n"
-               "       pushl   %gs\n"
-               "       movw    $0x1234,%ax\n"          /* Get DPMI data selector */
-               "       movw    %ax,%ds\n"                      /* Set DS and ES to data selector */
-               "       movw    %ax,%es\n"
-               "       movl    $0x12345678,%ebx\n"     /* Interrupt stack top */
-               "       movl    (%ebx),%ecx\n"
-               "       movl    %ecx,%edx\n"
-               "       subl    $0x12345678,%ecx\n"     /* Subtract irq_stack_count */
-               "       movl    %ecx,(%ebx)\n"
-               "       movw    %ss,%si\n"                      /* Save old SS:ESP */
-               "       movl    %esp,%edi\n"
-               "       movl    %edx,%esp\n"            /* Set SS:ESP to interrupt stack */
-               "       movw    %ax,%ss\n"
-               "       pushl   %esi\n"
-               "       pushl   %edi\n"
-               "       pushl   %ebx\n"
-               "       pushl   %edx\n"
-               "       call    1f\n"                           /* Call user interrupt handler */
-               "1:     popl    %edx\n"
-               "       popl    %ebx\n"
-               "       movl    %edx,(%ebx)\n"
-               "       popl    %edi\n"
-               "       popl    %esi\n"
-               "       movl    %edi,%esp\n"            /* Restore old SS:ESP */
-               "       movw    %si,%ss\n"
-               "       popl    %gs\n"
-               "       popl    %fs\n"
-               "       popl    %es\n"
-               "       popl    %ds\n"
-               "       popal\n"
-               "       iret\n");
-/* *INDENT-ON* */
-}
-
-#include <stdio.h>
-
-static int _allocate_iret_wrapper(_go32_dpmi_seginfo * info)
-{
-       unsigned char *irqtpl = (unsigned char *)__int_stub_template;
-       unsigned char *irqend, *irqwrapper, *tmp;
-       __dpmi_meminfo handler_info;
-       unsigned int wrappersize;
-
-       /* First, skip until pushal */
-       while (*irqtpl != 0x60)
-               irqtpl++;
-       /* Now find the iret */
-       irqend = irqtpl;
-       while (*irqend++ != 0xcf);
-
-       wrappersize = 4 + __irq_stack_size * __irq_stack_count + 4 +
-         ((long)irqend - (long)irqtpl);
-       irqwrapper = (unsigned char *) MikMod_malloc(wrappersize);
-       /* Lock the wrapper */
-       handler_info.address = __djgpp_base_address + (unsigned long)irqwrapper;
-       handler_info.size = wrappersize;
-       if (__dpmi_lock_linear_region(&handler_info)) {
-               MikMod_free(irqwrapper);
-               return -1;
-       }
-
-       /* First comes the interrupt wrapper size */
-       *(unsigned long *)irqwrapper = wrappersize;
-
-       /* Next comes the interrupt stack */
-       tmp = irqwrapper + 4 + __irq_stack_size * __irq_stack_count;
-
-       /* The following dword is interrupt stack pointer */
-       *((void **)tmp) = tmp;
-       tmp += 4;
-
-       /* Now comes the interrupt wrapper itself */
-       memcpy(tmp, irqtpl, irqend - irqtpl);
-       *(unsigned short *)(tmp + 9) = _my_ds();
-       *(unsigned long *)(tmp + 16) = (unsigned long)tmp - 4;
-       *(unsigned long *)(tmp + 26) = __irq_stack_size;
-       *(unsigned long *)(tmp + 46) =
-         info->pm_offset - (unsigned long)(tmp + 50);
-
-       info->pm_offset = (unsigned long)tmp;
-       info->pm_selector = _my_cs();
-
-       return 0;
-}
-
-static void _free_iret_wrapper(_go32_dpmi_seginfo * info)
-{
-       __dpmi_meminfo handler_info;
-
-       info->pm_offset -= 4 + __irq_stack_size * __irq_stack_count + 4;
-
-       handler_info.address = __djgpp_base_address + info->pm_offset;
-       handler_info.size = *(unsigned long *)info->pm_offset;
-       __dpmi_unlock_linear_region(&handler_info);
-
-       MikMod_free((void *)info->pm_offset);
-}
-
-struct irq_handle *irq_hook(int irqno, void (*handler)(), unsigned long size)
-{
-       int interrupt;
-       struct irq_handle *irq;
-       __dpmi_version_ret version;
-       __dpmi_meminfo handler_info, struct_info;
-       _go32_dpmi_seginfo info;
-       unsigned long old_sel, old_ofs;
-
-       __dpmi_get_version(&version);
-       if (irqno < 8)
-               interrupt = version.master_pic + irqno;
-       else
-               interrupt = version.slave_pic + (irqno - 8);
-
-       if (_go32_dpmi_get_protected_mode_interrupt_vector(interrupt, &info))
-               return NULL;
-
-       old_sel = info.pm_selector;
-       old_ofs = info.pm_offset;
-
-       info.pm_offset = (unsigned long)handler;
-       if (_allocate_iret_wrapper(&info))
-               return NULL;
-
-       /* Lock the interrupt handler in memory */
-       handler_info.address = __djgpp_base_address + (unsigned long)handler;
-       handler_info.size = size;
-       if (__dpmi_lock_linear_region(&handler_info)) {
-               _free_iret_wrapper(&info);
-               return NULL;
-       }
-
-       irq = (struct irq_handle *) MikMod_malloc(sizeof(struct irq_handle));
-       irq->c_handler = handler;
-       irq->handler_size = size;
-       irq->handler = info.pm_offset;
-       irq->prev_selector = old_sel;
-       irq->prev_offset = old_ofs;
-       irq->int_num = interrupt;
-       irq->irq_num = irqno;
-       irq->pic_base = irqno < 8 ? PIC1_BASE : PIC2_BASE;
-
-       struct_info.address = __djgpp_base_address + (unsigned long)irq;
-       struct_info.size = sizeof(struct irq_handle);
-       if (__dpmi_lock_linear_region(&struct_info)) {
-               MikMod_free(irq);
-               __dpmi_unlock_linear_region(&handler_info);
-               _free_iret_wrapper(&info);
-               return NULL;
-       }
-
-       _go32_dpmi_set_protected_mode_interrupt_vector(interrupt, &info);
-
-       irq->pic_mask = irq_state(irq);
-       return irq;
-}
-
-void irq_unhook(struct irq_handle *irq)
-{
-       _go32_dpmi_seginfo info;
-       __dpmi_meminfo mem_info;
-
-       if (!irq)
-               return;
-
-       /* Restore the interrupt vector */
-       irq_disable(irq);
-       info.pm_offset = irq->prev_offset;
-       info.pm_selector = irq->prev_selector;
-       _go32_dpmi_set_protected_mode_interrupt_vector(irq->int_num, &info);
-
-       /* Unlock the interrupt handler */
-       mem_info.address = __djgpp_base_address + (unsigned long)irq->c_handler;
-       mem_info.size = irq->handler_size;
-       __dpmi_unlock_linear_region(&mem_info);
-
-       /* Unlock the irq_handle structure */
-       mem_info.address = __djgpp_base_address + (unsigned long)irq;
-       mem_info.size = sizeof(struct irq_handle);
-       __dpmi_unlock_linear_region(&mem_info);
-
-       info.pm_offset = irq->handler;
-       _free_iret_wrapper(&info);
-
-       /* If IRQ was enabled before we hooked, restore enabled state */
-       if (irq->pic_mask)
-               irq_enable(irq);
-       else
-               irq_disable(irq);
-
-       MikMod_free(irq);
-}
-
-/*---------------------------------------------- IRQ detection mechanism -----*/
-static struct irq_handle *__irqs[16];
-static int (*__irq_confirm) (int irqno);
-static volatile unsigned int __irq_mask;
-static volatile unsigned int __irq_count[16];
-
-#define DECLARE_IRQ_HANDLER(irqno)                                                     \
-static void __irq##irqno##_handler ()                                          \
-{                                                                                                                      \
-  if (irq_check (__irqs [irqno]) && __irq_confirm (irqno))     \
-  {                                                                                                                    \
-    __irq_count [irqno]++;                                                                     \
-    __irq_mask |= (1 << irqno);                                                                \
-  }                                                                                                                    \
-  irq_ack (__irqs [irqno]);                                                                    \
-}
-
-/* *INDENT-OFF* */
-DECLARE_IRQ_HANDLER(0)
-DECLARE_IRQ_HANDLER(1)
-DECLARE_IRQ_HANDLER(2)
-DECLARE_IRQ_HANDLER(3)
-DECLARE_IRQ_HANDLER(4)
-DECLARE_IRQ_HANDLER(5)
-DECLARE_IRQ_HANDLER(6)
-DECLARE_IRQ_HANDLER(7)
-DECLARE_IRQ_HANDLER(8)
-DECLARE_IRQ_HANDLER(9)
-DECLARE_IRQ_HANDLER(10)
-DECLARE_IRQ_HANDLER(11)
-DECLARE_IRQ_HANDLER(12)
-DECLARE_IRQ_HANDLER(13)
-DECLARE_IRQ_HANDLER(14)
-DECLARE_IRQ_HANDLER(15)
-/* *INDENT-ON* */
-
-static void (*__irq_handlers[16]) () = {
-       __irq0_handler, __irq1_handler, __irq2_handler, __irq3_handler,
-         __irq4_handler, __irq5_handler, __irq6_handler, __irq7_handler,
-         __irq8_handler, __irq9_handler, __irq10_handler, __irq11_handler,
-         __irq12_handler, __irq13_handler, __irq14_handler, __irq15_handler};
-
-void irq_detect_start(unsigned int irqs, int (*irq_confirm) (int irqno))
-{
-       int i;
-
-       __irq_mask = 0;
-       __irq_confirm = irq_confirm;
-       memset(&__irqs, 0, sizeof(__irqs));
-       memset((void *) &__irq_count, 0, sizeof(__irq_count));
-
-       /* Hook all specified IRQs */
-       for (i = 1; i <= 15; i++)
-               if (irqs & (1 << i)) {
-                       __irqs[i] = irq_hook(i, __irq_handlers[i], 200);
-                       /* Enable the interrupt */
-                       irq_enable(__irqs[i]);
-               }
-       /* Enable IRQ2 if we need at least one IRQ above 7 */
-       if (irqs & 0xff00)
-               _irq_enable(2);
-}
-
-void irq_detect_end()
-{
-       int i;
-       for (i = 15; i >= 1; i--)
-               if (__irqs[i])
-                       irq_unhook(__irqs[i]);
-}
-
-int irq_detect_get(int irqno, unsigned int *irqmask)
-{
-       int oldirq = disable();
-       int count = __irq_count[irqno];
-       *irqmask = __irq_mask;
-       __irq_mask = 0;
-       if (oldirq)
-               enable();
-       return count;
-}
-
-void irq_detect_clear()
-{
-       int oldirq = disable();
-       memset((void *) &__irq_count, 0, sizeof(__irq_count));
-       __irq_mask = 0;
-       if (oldirq)
-               enable();
-}
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dosirq.h b/libs/mikmod/drivers/dos/dosirq.h
deleted file mode 100644 (file)
index eaf60a1..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-    Interface for IRQ routines on DOS
-    Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
-
-    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 library 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __DOSIRQ_H__
-#define __DOSIRQ_H__
-
-#include <pc.h>
-
-#define PIC1_BASE      0x20            /* PIC1 base */
-#define PIC2_BASE      0xA0            /* PIC2 base */
-
-struct irq_handle {
-       void (*c_handler) ();           /* The real interrupt handler */
-       unsigned long handler_size;     /* The size of interrupt handler */
-       unsigned long handler;          /* Interrupt wrapper address */
-       unsigned long prev_selector;    /* Selector of previous handler */
-       unsigned long prev_offset;      /* Offset of previous handler */
-       unsigned char irq_num;          /* IRQ number */
-       unsigned char int_num;          /* Interrupt number */
-       unsigned char pic_base;         /* PIC base (0x20 or 0xA0) */
-       unsigned char pic_mask;         /* Old PIC mask state */
-};
-
-/* Return the enabled state for specific IRQ */
-static inline unsigned char irq_state(struct irq_handle * irq)
-{
-       return ((~inportb(irq->pic_base + 1)) & (0x01 << (irq->irq_num & 7)));
-}
-
-/* Acknowledge the end of interrupt */
-static inline void _irq_ack(int irqno)
-{
-       outportb(irqno > 7 ? PIC2_BASE : PIC1_BASE, 0x60 | (irqno & 7));
-       /* For second controller we also should acknowledge first controller */
-       if (irqno > 7)
-               outportb(PIC1_BASE, 0x20);      /* 0x20, 0x62? */
-}
-
-/* Acknowledge the end of interrupt */
-static inline void irq_ack(struct irq_handle * irq)
-{
-       outportb(irq->pic_base, 0x60 | (irq->irq_num & 7));
-       /* For second controller we also should acknowledge first controller */
-       if (irq->pic_base != PIC1_BASE)
-               outportb(PIC1_BASE, 0x20);      /* 0x20, 0x62? */
-}
-
-/* Mask (disable) the particular IRQ given his ordinal */
-static inline void _irq_disable(int irqno)
-{
-       unsigned int port_no = (irqno < 8 ? PIC1_BASE : PIC2_BASE) + 1;
-       outportb(port_no, inportb(port_no) | (1 << (irqno & 7)));
-}
-
-/* Unmask (enable) the particular IRQ given its ordinal */
-static inline void _irq_enable(int irqno)
-{
-       unsigned int port_no = (irqno < 8 ? PIC1_BASE : PIC2_BASE) + 1;
-       outportb(port_no, inportb(port_no) & ~(1 << (irqno & 7)));
-}
-
-/* Mask (disable) the particular IRQ given its irq_handle structure */
-static inline void irq_disable(struct irq_handle * irq)
-{
-       outportb(irq->pic_base + 1,
-                 inportb(irq->pic_base + 1) | (1 << (irq->irq_num & 7)));
-}
-
-/* Unmask (enable) the particular IRQ given its irq_handle structure */
-static inline void irq_enable(struct irq_handle * irq)
-{
-       outportb(irq->pic_base + 1,
-                 inportb(irq->pic_base + 1) & ~(1 << (irq->irq_num & 7)));
-}
-
-/* Check if a specific IRQ is pending: return 0 is no */
-static inline int irq_check(struct irq_handle * irq)
-{
-       outportb(irq->pic_base, 0x0B);  /* Read IRR vector */
-       return (inportb(irq->pic_base) & (1 << (irq->irq_num & 7)));
-}
-
-/* Hook a specific IRQ; NOTE: IRQ is disabled upon return, irq_enable() it */
-extern struct irq_handle *irq_hook(int irqno, void (*handler)(),
-                                   unsigned long size);
-/* Unhook a previously hooked IRQ */
-extern void irq_unhook(struct irq_handle * irq);
-/* Start IRQ detection process (IRQ list is given with irq mask) */
-/* irq_confirm should return "1" if the IRQ really comes from the device */
-extern void irq_detect_start(unsigned int irqs,
-                             int (*irq_confirm) (int irqno));
-/* Finish IRQ detection process */
-extern void irq_detect_end();
-/* Get the count of specific irqno that happened */
-extern int irq_detect_get(int irqno, unsigned int *irqmask);
-/* Clear IRQ counters */
-extern void irq_detect_clear();
-
-/* The size of interrupt stack */
-extern unsigned int __irq_stack_size;
-/* The number of nested interrupts that can be handled */
-extern unsigned int __irq_stack_count;
-
-#endif /* __DOSIRQ_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dossb.c b/libs/mikmod/drivers/dos/dossb.c
deleted file mode 100644 (file)
index 344ac85..0000000
+++ /dev/null
@@ -1,575 +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.
-*/
-
-/*==============================================================================
-
-  Sound Blaster I/O routines, common for SB8, SBPro and SB16
-  Written by Andrew Zabolotny <bit@eltech.ru>
-
-==============================================================================*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef DRV_SB
-
-#include <stdlib.h>
-#include <dpmi.h>
-#include <go32.h>
-#include <dos.h>
-#include <sys/nearptr.h>
-#include <sys/farptr.h>
-#include <string.h>
-
-#include "dossb.h"
-
-/********************************************* Private variables/routines *****/
-
-__sb_state sb;
-
-/* Wait for SoundBlaster for some time */
-#if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
-# define _func_noinline volatile /* match original code */
-# define _func_noclone
-#else
-/* avoid warnings from newer gcc:
- * "function definition has qualified void return type" and
- * function return types not compatible due to 'volatile' */
-# define _func_noinline __attribute__((__noinline__))
-# if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
-#  define _func_noclone
-# else
-#  define _func_noclone __attribute__((__noclone__))
-# endif
-#endif
-_func_noinline
-_func_noclone
- void __sb_wait()
-{
-       inportb(SB_DSP_RESET);
-       inportb(SB_DSP_RESET);
-       inportb(SB_DSP_RESET);
-       inportb(SB_DSP_RESET);
-       inportb(SB_DSP_RESET);
-       inportb(SB_DSP_RESET);
-}
-
-static void sb_irq()
-{
-       /* Make sure its not a spurious IRQ */
-       if (!irq_check(sb.irq_handle))
-               return;
-
-       sb.irqcount++;
-
-       /* Acknowledge DMA transfer is complete */
-       if (sb.mode & SBMODE_16BITS)
-               __sb_dsp_ack_dma16();
-       else
-               __sb_dsp_ack_dma8();
-
-       /* SoundBlaster 1.x cannot do autoinit ... */
-       if (sb.dspver < SBVER_20)
-               __sb_dspreg_outwlh(SBDSP_DMA_PCM8, (sb.dma_buff->size >> 1) - 1);
-
-       /* Send EOI */
-       irq_ack(sb.irq_handle);
-
-       enable();
-       if (sb.timer_callback)
-               sb.timer_callback();
-}
-
-static void sb_irq_end()
-{
-}
-
-static boolean __sb_reset()
-{
-       /* Disable the output */
-       sb_output(FALSE);
-
-       /* Clear pending ints if any */
-       __sb_dsp_ack_dma8();
-       __sb_dsp_ack_dma16();
-
-       /* Reset the DSP */
-       outportb(SB_DSP_RESET, SBM_DSP_RESET);
-       __sb_wait();
-       __sb_wait();
-       outportb(SB_DSP_RESET, 0);
-
-       /* Now wait for AA coming from datain port */
-       if (__sb_dsp_in() != 0xaa)
-               return FALSE;
-
-       /* Finally, get the DSP version */
-       if ((sb.dspver = __sb_dsp_version()) == 0xffff)
-               return FALSE;
-       /* Check again */
-       if (sb.dspver != __sb_dsp_version())
-               return FALSE;
-
-       return TRUE;
-}
-
-/***************************************************** SB detection stuff *****/
-
-static int __sb_irq_irqdetect(int irqno)
-{
-       __sb_dsp_ack_dma8();
-       return 1;
-}
-
-static void __sb_irq_dmadetect()
-{
-       /* Make sure its not a spurious IRQ */
-       if (!irq_check(sb.irq_handle))
-               return;
-
-       sb.irqcount++;
-
-       /* Acknowledge DMA transfer is complete */
-       if (sb.mode & SBMODE_16BITS)
-               __sb_dsp_ack_dma16();
-       else
-               __sb_dsp_ack_dma8();
-
-       /* Send EOI */
-       irq_ack(sb.irq_handle);
-}
-
-static boolean __sb_detect()
-{
-       /* First find the port number */
-       if (!sb.port) {
-               int i;
-               for (i = 5; i >= 0; i--) {
-                       sb.port = 0x210 + i * 0x10;
-                       if (__sb_reset())
-                               break;
-               }
-               if (i < 0) {
-                       sb.port = 0;
-                       return FALSE;
-               }
-       }
-
-       /* Now detect the IRQ and DMA numbers */
-       if (!sb.irq) {
-               unsigned int irqmask, sbirqmask, sbirqcount;
-               unsigned long timer;
-
-               /* IRQ can be one of 2,3,5,7,10 */
-               irq_detect_start(0x04ac, __sb_irq_irqdetect);
-
-               /* Prepare timeout counter */
-               _farsetsel(_dos_ds);
-               timer = _farnspeekl(0x46c);
-
-               sbirqmask = 0;
-               sbirqcount = 10;                /* Emit 10 SB irqs */
-
-               /* Tell SoundBlaster to emit IRQ for 8-bit transfers */
-               __sb_dsp_out(SBDSP_GEN_IRQ8);
-               __sb_wait();
-               for (;;) {
-                       irq_detect_get(0, &irqmask);
-                       if (irqmask) {
-                               sbirqmask |= irqmask;
-                               if (!--sbirqcount)
-                                       break;
-                               __sb_dsp_out(SBDSP_GEN_IRQ8);
-                       }
-                       if (_farnspeekl(0x46c) - timer >= 9)    /* Wait ~1/2 secs */
-                               break;
-               }
-               if (sbirqmask)
-                       for (sb.irq = 15; sb.irq > 0; sb.irq--)
-                               if (irq_detect_get(sb.irq, &irqmask) == 10)
-                                       break;
-
-               irq_detect_end();
-               if (!sb.irq)
-                       return FALSE;
-       }
-
-       /* Detect the 8-bit and 16-bit DMAs */
-       if (!sb.dma8 || ((sb.dspver >= SBVER_16) && !sb.dma16)) {
-               static int __dma8[] = { 0, 1, 3 };
-               static int __dma16[] = { 5, 6, 7 };
-               int *dma;
-
-               sb_output(FALSE);
-               /* Temporary hook SB IRQ */
-               sb.irq_handle = irq_hook(sb.irq, __sb_irq_dmadetect, 200);
-               irq_enable(sb.irq_handle);
-               if (sb.irq > 7)
-                       _irq_enable(2);
-
-               /* Start a short DMA transfer and check if IRQ happened */
-               for (;;) {
-                       int i;
-                       unsigned int timer, oldcount;
-
-                       if (!sb.dma8)
-                               dma = &sb.dma8;
-                       else if ((sb.dspver >= SBVER_16) && !sb.dma16)
-                               dma = &sb.dma16;
-                       else
-                               break;
-
-                       for (i = 0; i < 3; i++) {
-                               boolean success = 1;
-
-                               *dma = (dma == &sb.dma8) ? __dma8[i] : __dma16[i];
-                               oldcount = sb.irqcount;
-
-                               dma_disable(*dma);
-                               dma_set_mode(*dma, DMA_MODE_WRITE);
-                               dma_clear_ff(*dma);
-                               dma_set_count(*dma, 2);
-                               dma_enable(*dma);
-
-                               __sb_dspreg_out(SBDSP_SET_TIMING, 206); /* 20KHz */
-                               if (dma == &sb.dma8) {
-                                       sb.mode = 0;
-                                       __sb_dspreg_outwlh(SBDSP_DMA_PCM8, 1);
-                               } else {
-                                       sb.mode = SBMODE_16BITS;
-                                       __sb_dspreg_out(SBDSP_DMA_GENERIC16, 0);
-                                       __sb_dsp_out(0);
-                                       __sb_dsp_out(1);
-                               }
-
-                               _farsetsel(_dos_ds);
-                               timer = _farnspeekl(0x46c);
-
-                               while (oldcount == sb.irqcount)
-                                       if (_farnspeekl(0x46c) - timer >= 2) {
-                                               success = 0;
-                                               break;
-                                       }
-                               dma_disable(*dma);
-                               if (success)
-                                       break;
-                               *dma = 0;
-                       }
-                       if (!*dma)
-                               break;
-               }
-
-               irq_unhook(sb.irq_handle);
-               sb.irq_handle = NULL;
-               if (!sb.dma8 || ((sb.dspver >= SBVER_16) && !sb.dma16))
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-/*************************************************** High-level interface *****/
-
-/* Detect whenever SoundBlaster is present and fill "sb" structure */
-boolean sb_detect()
-{
-       char *env;
-
-       /* Try to find the port and DMA from environment */
-       env = getenv("BLASTER");
-
-       while (env && *env) {
-               /* Skip whitespace */
-               while ((*env == ' ') || (*env == '\t'))
-                       env++;
-               if (!*env)
-                       break;
-
-               switch (*env++) {
-                 case 'A':
-                 case 'a':
-                       if (!sb.port)
-                               sb.port = strtol(env, &env, 16);
-                       break;
-                 case 'E':
-                 case 'e':
-                       if (!sb.aweport)
-                               sb.aweport = strtol(env, &env, 16);
-                       break;
-                 case 'I':
-                 case 'i':
-                       if (!sb.irq)
-                               sb.irq = strtol(env, &env, 10);
-                       break;
-                 case 'D':
-                 case 'd':
-                       if (!sb.dma8)
-                               sb.dma8 = strtol(env, &env, 10);
-                       break;
-                 case 'H':
-                 case 'h':
-                       if (!sb.dma16)
-                               sb.dma16 = strtol(env, &env, 10);
-                       break;
-                 default:
-                       /* Skip other values (H == MIDI, T == model, any other?) */
-                       while (*env && (*env != ' ') && (*env != '\t'))
-                               env++;
-                       break;
-               }
-       }
-
-       /* Try to detect missing sound card parameters */
-       __sb_detect();
-
-       if (!sb.port || !sb.irq || !sb.dma8)
-               return FALSE;
-
-       if (!__sb_reset())
-               return FALSE;
-
-       if ((sb.dspver >= SBVER_16) && !sb.dma16)
-               return FALSE;
-
-       if (sb.dspver >= SBVER_PRO)
-               sb.caps |= SBMODE_STEREO;
-       if (sb.dspver >= SBVER_16 && sb.dma16)
-               sb.caps |= SBMODE_16BITS;
-       if (sb.dspver < SBVER_20)
-               sb.maxfreq_mono = 22222;
-       else
-               sb.maxfreq_mono = 45454;
-       if (sb.dspver <= SBVER_16)
-               sb.maxfreq_stereo = 22727;
-       else
-               sb.maxfreq_stereo = 45454;
-
-       sb.ok = 1;
-       return TRUE;
-}
-
-/* Reset SoundBlaster */
-void sb_reset()
-{
-       sb_stop_dma();
-       __sb_reset();
-}
-
-/* Start working with SoundBlaster */
-boolean sb_open()
-{
-       __dpmi_meminfo struct_info;
-
-       if (!sb.ok)
-               if (!sb_detect())
-                       return FALSE;
-
-       if (sb.open)
-               return FALSE;
-
-       /* Now lock the sb structure in memory */
-       struct_info.address = __djgpp_base_address + (unsigned long)&sb;
-       struct_info.size = sizeof(sb);
-       if (__dpmi_lock_linear_region(&struct_info))
-               return FALSE;
-
-       /* Hook the SB IRQ */
-       sb.irq_handle = irq_hook(sb.irq, sb_irq, (long)sb_irq_end - (long)sb_irq);
-       if (!sb.irq_handle) {
-               __dpmi_unlock_linear_region(&struct_info);
-               return FALSE;
-       }
-
-       /* Enable the interrupt */
-       irq_enable(sb.irq_handle);
-       if (sb.irq > 7)
-               _irq_enable(2);
-
-       sb.open++;
-
-       return TRUE;
-}
-
-/* Finish working with SoundBlaster */
-boolean sb_close()
-{
-       __dpmi_meminfo struct_info;
-       if (!sb.open)
-               return FALSE;
-
-       sb.open--;
-
-       /* Stop/free DMA buffer */
-       sb_stop_dma();
-
-       /* Unhook IRQ */
-       irq_unhook(sb.irq_handle);
-       sb.irq_handle = NULL;
-
-       /* Unlock the sb structure */
-       struct_info.address = __djgpp_base_address + (unsigned long)&sb;
-       struct_info.size = sizeof(sb);
-       __dpmi_unlock_linear_region(&struct_info);
-
-       return TRUE;
-}
-
-/* Enable/disable stereo DSP mode */
-/* Enable/disable speaker output */
-void sb_output(boolean enable)
-{
-       __sb_dsp_out(enable ? SBDSP_SPEAKER_ENA : SBDSP_SPEAKER_DIS);
-}
-
-/* Start playing from DMA buffer */
-boolean sb_start_dma(unsigned char mode, unsigned int freq)
-{
-       int dmachannel = (mode & SBMODE_16BITS) ? sb.dma16 : sb.dma8;
-       int dmabuffsize;
-       unsigned int tc = 0;            /* timing constant (<=sbpro only) */
-
-       /* Stop DMA transfer if it is enabled */
-       sb_stop_dma();
-
-       /* Sanity check */
-       if ((mode & SBMODE_MASK & sb.caps) != (mode & SBMODE_MASK))
-               return FALSE;
-
-       /* Check this SB can perform at requested frequency */
-       if (((mode & SBMODE_STEREO) && (freq > sb.maxfreq_stereo))
-               || (!(mode & SBMODE_STEREO) && (freq > sb.maxfreq_mono)))
-               return FALSE;
-
-       /* Check the timing constant here to avoid failing later */
-       if (sb.dspver < SBVER_16) {
-               /* SBpro cannot do signed transfer */
-               if (mode & SBMODE_SIGNED)
-                       return FALSE;
-
-               /* Old SBs have a different way on setting DMA timing constant */
-               tc = freq;
-               if (mode & SBMODE_STEREO)
-                       tc *= 2;
-               tc = 1000000 / tc;
-               if (tc > 255)
-                       return FALSE;
-       }
-
-       sb.mode = mode;
-
-       /* Get a DMA buffer enough for a 1/4sec interval... 4K <= dmasize <= 32K */
-       dmabuffsize = freq;
-       if (mode & SBMODE_STEREO)
-               dmabuffsize *= 2;
-       if (mode & SBMODE_16BITS)
-               dmabuffsize *= 2;
-       dmabuffsize >>= 2;
-       if (dmabuffsize < 4096)
-               dmabuffsize = 4096;
-       if (dmabuffsize > 32768)
-               dmabuffsize = 32768;
-       dmabuffsize = (dmabuffsize + 255) & 0xffffff00;
-
-       sb.dma_buff = dma_allocate(dmachannel, dmabuffsize);
-       if (!sb.dma_buff)
-               return FALSE;
-
-       /* Fill DMA buffer with silence */
-       dmabuffsize = sb.dma_buff->size;
-       if (mode & SBMODE_SIGNED)
-               memset(sb.dma_buff->linear, 0, dmabuffsize);
-       else
-               memset(sb.dma_buff->linear, 0x80, dmabuffsize);
-
-       /* Prime DMA for transfer */
-       dma_start(sb.dma_buff, dmabuffsize, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
-
-       /* Tell SoundBlaster to start transfer */
-       if (sb.dspver >= SBVER_16) {    /* SB16 */
-               __sb_dspreg_outwhl(SBDSP_SET_RATE, freq);
-
-               /* Start DMA->DAC transfer */
-               __sb_dspreg_out(SBM_GENDAC_AUTOINIT | SBM_GENDAC_FIFO |
-                                               ((mode & SBMODE_16BITS) ? SBDSP_DMA_GENERIC16 :
-                                                SBDSP_DMA_GENERIC8),
-                                               ((mode & SBMODE_SIGNED) ? SBM_GENDAC_SIGNED : 0) |
-                                               ((mode & SBMODE_STEREO) ? SBM_GENDAC_STEREO : 0));
-
-               /* Write the length of transfer */
-               dmabuffsize = (dmabuffsize >> 2) - 1;
-               __sb_dsp_out(dmabuffsize);
-               __sb_dsp_out(dmabuffsize >> 8);
-       } else {
-               __sb_dspreg_out(SBDSP_SET_TIMING, 256 - tc);
-               dmabuffsize = (dmabuffsize >> 1) - 1;
-               if (sb.dspver >= SBVER_20) {    /* SB 2.0/Pro */
-                       /* Set stereo mode */
-                       __sb_stereo((mode & SBMODE_STEREO) ? TRUE : FALSE);
-                       __sb_dspreg_outwlh(SBDSP_SET_DMA_BLOCK, dmabuffsize);
-                       if (sb.dspver >= SBVER_PRO)
-                               __sb_dsp_out(SBDSP_HS_DMA_DAC8_AUTO);
-                       else
-                               __sb_dsp_out(SBDSP_DMA_PCM8_AUTO);
-               } else {                                /* Original SB */
-                       /* Start DMA->DAC transfer */
-                       __sb_dspreg_outwlh(SBDSP_DMA_PCM8, dmabuffsize);
-               }
-       }
-
-       return TRUE;
-}
-
-/* Stop playing from DMA buffer */
-void sb_stop_dma()
-{
-       if (!sb.dma_buff)
-               return;
-
-       if (sb.mode & SBMODE_16BITS)
-               __sb_dsp_out(SBDSP_DMA_HALT16);
-       else
-               __sb_dsp_out(SBDSP_DMA_HALT8);
-
-       dma_disable(sb.dma_buff->channel);
-       dma_free(sb.dma_buff);
-       sb.dma_buff = NULL;
-}
-
-/* Query current position/total size of the DMA buffer */
-void sb_query_dma(unsigned int *dma_size, unsigned int *dma_pos)
-{
-       unsigned int dma_left;
-       *dma_size = sb.dma_buff->size;
-       /* It can happen we try to read DMA count when HI/LO bytes will be
-          inconsistent */
-       for (;;) {
-               unsigned int dma_left_test;
-               dma_clear_ff(sb.dma_buff->channel);
-               dma_left_test = dma_get_count(sb.dma_buff->channel);
-               dma_left = dma_get_count(sb.dma_buff->channel);
-               if ((dma_left >= dma_left_test) && (dma_left - dma_left_test < 10))
-                       break;
-       }
-       *dma_pos = *dma_size - dma_left;
-}
-
-#endif /* DRV_SB */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/dossb.h b/libs/mikmod/drivers/dos/dossb.h
deleted file mode 100644 (file)
index cb8dc70..0000000
+++ /dev/null
@@ -1,341 +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$
-
-  SoundBlaster and compatible soundcards definitions
-
-==============================================================================*/
-
-#ifndef __DOSSB_H__
-#define __DOSSB_H__
-
-#include "dosdma.h"
-#include "dosirq.h"
-
-#define SB_FM_LEFT_STATUS              (sb.port + 0x00)        /* (r) Left FM status */
-#define SB_FM_LEFT_REGSEL              (sb.port + 0x00)        /* (w) Left FM register select */
-#define SB_FM_LEFT_DATA                        (sb.port + 0x01)        /* (w) Left FM data */
-#define SB_FM_RIGHT_STATUS             (sb.port + 0x02)        /* (r) Right FM status */
-#define SB_FM_RIGHT_REGSEL             (sb.port + 0x02)        /* (w) Right FM register select */
-#define SB_FM_RIGHT_DATA               (sb.port + 0x03)        /* (w) Right FM data */
-#define SB_MIXER_REGSEL                        (sb.port + 0x04)        /* (w) Mixer register select */
-#define SB_MIXER_DATA                  (sb.port + 0x05)        /* (rw)Mixer data */
-#define SB_DSP_RESET                   (sb.port + 0x06)        /* (w) DSP reset */
-#define SB_FM_STATUS                   (sb.port + 0x08)        /* (r) FM status */
-#define SB_FM_REGSEL                   (sb.port + 0x08)        /* (w) FM register select */
-#define SB_FM_DATA                     (sb.port + 0x09)        /* (w) FM data */
-#define SB_DSP_DATA_IN                 (sb.port + 0x0a)        /* (r) DSP data input */
-#define SB_DSP_DATA_OUT                        (sb.port + 0x0c)        /* (w) DSP data output */
-#define SB_DSP_DATA_OUT_STATUS         (sb.port + 0x0c)        /* (r) DSP data output status */
-#define SB_DSP_TIMER_IRQ               (sb.port + 0x0d)        /* (r) clear timer IRQ? */
-#define SB_DSP_DATA_IN_STATUS          (sb.port + 0x0e)        /* (r) DSP data input status */
-#define SB_DSP_DMA8_IRQ                        (sb.port + 0x0e)        /* (r) Acknowledge 8-bit DMA transfer */
-#define SB_DSP_DMA16_IRQ               (sb.port + 0x0f)        /* (r) Acknowledge 16-bit DMA transfer */
-
-/* DSP commands */
-#define SBDSP_ASP_STATUS               0x03    /* ASP Status (SB16ASP) */
-#define SBDSP_STATUS_OLD               0x04    /* DSP Status (Obsolete) (SB2.0-Pro2) */
-#define SBDSP_DIRECT_DAC               0x10    /* Direct DAC, 8-bit (SB) */
-#define SBDSP_DMA_PCM8                 0x14    /* DMA DAC, 8-bit (SB) */
-#define SBDSP_DMA_ADPCM2               0x16    /* DMA DAC, 2-bit ADPCM (SB) */
-#define SBDSP_DMA_ADPCM2R              0x17    /* DMA DAC, 2-bit ADPCM Reference (SB) */
-#define SBDSP_DMA_PCM8_AUTO            0x1C    /* Auto-Initialize DMA DAC, 8-bit (SB2.0) */
-#define SBDSP_DMA_ADPCM2R_AUTO         0x1F    /* Auto-Initialize DMA DAC, 2-bit ADPCM Reference (SB2.0) */
-#define SBDSP_DIRECT_ADC               0x20    /* Direct ADC, 8-bit (SB) */
-#define SBDSP_DMA_ADC8                 0x24    /* DMA ADC, 8-bit (SB) */
-#define SBDSP_DIRECT_ADC8_BURST                0x28    /* Direct ADC, 8-bit (Burst) (SB-Pro2) */
-#define SBDSP_DMA_ADC8_AUTO            0x2C    /* Auto-Initialize DMA ADC, 8-bit (SB2.0) */
-#define SBDSP_MIDI_READ_POLL           0x30    /* MIDI Read Poll (SB) */
-#define SBDSP_MIDI_READ_IRQ            0x31    /* MIDI Read Interrupt (SB) */
-#define SBDSP_MIDI_READ_TIME           0x32    /* MIDI Read Timestamp Poll (SB???) */
-#define SBDSP_MIDI_READ_TIME_IRQ       0x33    /* MIDI Read Timestamp Interrupt (SB???) */
-#define SBDSP_MIDI_RW_POLL             0x34    /* MIDI Read Poll + Write Poll (UART) (SB2.0) */
-#define SBDSP_MIDI_RW_IRQ              0x35    /* MIDI Read Interrupt + Write Poll (UART) (SB2.0???) */
-#define SBDSP_MIDI_RW_TIME_IRQ         0x37    /* MIDI Read Timestamp Interrupt + Write Poll (UART) (SB2.0???) */
-#define SBDSP_MIDI_WRITE_POLL          0x38    /* MIDI Write Poll (SB) */
-#define SBDSP_SET_TIMING               0x40    /* Set Time Constant (SB) */
-#define SBDSP_SET_RATE                 0x41    /* Set Sample Rate, Hz (SB16) */
-#define SBDSP_DMA_CONT8_AUTO           0x45    /* Continue Auto-Initialize DMA, 8-bit (SB16) */
-#define SBDSP_DMA_CONT16_AUTO          0x47    /* Continue Auto-Initialize DMA, 16-bit (SB16) */
-#define SBDSP_SET_DMA_BLOCK            0x48    /* Set DMA Block Size (SB2.0) */
-#define SBDSP_DMA_ADPCM4               0x74    /* DMA DAC, 4-bit ADPCM (SB) */
-#define SBDSP_DMA_ADPCM4_REF           0x75    /* DMA DAC, 4-bit ADPCM Reference (SB) */
-#define SBDSP_DMA_ADPCM26              0x76    /* DMA DAC, 2.6-bit ADPCM (SB) */
-#define SBDSP_DMA_ADPCM26_REF          0x77    /* DMA DAC, 2.6-bit ADPCM Reference (SB) */
-#define SBDSP_DMA_ADPCM4R_AUTO         0x7D    /* Auto-Initialize DMA DAC, 4-bit ADPCM Reference (SB2.0) */
-#define SBDSP_DMA_ADPCM26R_AUTO                0x7F    /* Auto-Initialize DMA DAC, 2.6-bit ADPCM Reference (SB2.0) */
-#define SBDSP_DISABLE_DAC              0x80    /* Silence DAC (SB) */
-#define SBDSP_HS_DMA_DAC8_AUTO         0x90    /* Auto-Initialize DMA DAC, 8-bit (High Speed) (SB2.0-Pro2) */
-#define SBDSP_HS_DMA_ADC8_AUTO         0x98    /* Auto-Initialize DMA ADC, 8-bit (High Speed) (SB2.0-Pro2) */
-#define SBDSP_STEREO_ADC_DIS           0xA0    /* Disable Stereo Input Mode (SBPro Only) */
-#define SBDSP_STEREO_ADC_ENA           0xA8    /* Enable Stereo Input Mode (SBPro Only) */
-#define SBDSP_DMA_GENERIC16            0xB0    /* Generic DAC/ADC DMA (16-bit) (SB16) */
-#define SBDSP_DMA_GENERIC8             0xC0    /* Generic DAC/ADC DMA (8-bit) (SB16) */
-#define SBDSP_DMA_HALT8                        0xD0    /* Halt DMA Operation, 8-bit (SB) */
-#define SBDSP_SPEAKER_ENA              0xD1    /* Enable Speaker (SB) */
-#define SBDSP_SPEAKER_DIS              0xD3    /* Disable Speaker (SB) */
-#define SBDSP_DMA_CONT8                        0xD4    /* Continue DMA Operation, 8-bit (SB) */
-#define SBDSP_DMA_HALT16               0xD5    /* Halt DMA Operation, 16-bit (SB16) */
-#define SBDSP_DMA_CONT16               0xD6    /* Continue DMA Operation, 16-bit (SB16) */
-#define SBDSP_SPEAKER_STATUS           0xD8    /* Speaker Status (SB) */
-#define SBDSP_DMA_EXIT16_AUTO          0xD9    /* Exit Auto-Initialize DMA Operation, 16-bit (SB16) */
-#define SBDSP_DMA_EXIT8_AUTO           0xDA    /* Exit Auto-Initialize DMA Operation, 8-bit (SB2.0) */
-#define SBDSP_IDENTIFY                 0xE0    /* DSP Identification (SB2.0) */
-#define SBDSP_VERSION                  0xE1    /* DSP Version (SB) */
-#define SBDSP_COPYRIGHT                        0xE3    /* DSP Copyright (SBPro2???) */
-#define SBDSP_WRITE_TEST               0xE4    /* Write Test Register (SB2.0) */
-#define SBDSP_READ_TEST                        0xE8    /* Read Test Register (SB2.0) */
-#define SBDSP_SINE_GEN                 0xF0    /* Sine Generator (SB) */
-#define SBDSP_AUX_STATUS_PRO           0xF1    /* DSP Auxiliary Status (Obsolete) (SB-Pro2) */
-#define SBDSP_GEN_IRQ8                 0xF2    /* IRQ Request, 8-bit (SB) */
-#define SBDSP_GEN_IRQ16                        0xF3    /* IRQ Request, 16-bit (SB16) */
-#define SBDSP_STATUS                   0xFB    /* DSP Status (SB16) */
-#define SBDSP_AUX_STATUS_16            0xFC    /* DSP Auxiliary Status (SB16) */
-#define SBDSP_CMD_STATUS               0xFD    /* DSP Command Status (SB16) */
-
-/* Mixer commands */
-#define SBMIX_RESET                    0x00    /* Reset                        Write       SBPro */
-#define SBMIX_STATUS                   0x01    /* Status                       Read        SBPro */
-#define SBMIX_MASTER_LEVEL1            0x02    /* Master Volume                Read/Write  SBPro Only */
-#define SBMIX_DAC_LEVEL                        0x04    /* DAC Level                    Read/Write  SBPro */
-#define SBMIX_FM_OUTPUT                        0x06    /* FM Output Control            Read/Write  SBPro Only */
-#define SBMIX_MIC_LEVEL                        0x0A    /* Microphone Level             Read/Write  SBPro */
-#define SBMIX_INPUT_SELECT             0x0C    /* Input/Filter Select          Read/Write  SBPro Only */
-#define SBMIX_OUTPUT_SELECT            0x0E    /* Output/Stereo Select         Read/Write  SBPro Only */
-#define SBMIX_FM_LEVEL                 0x22    /* Master Volume                Read/Write  SBPro */
-#define SBMIX_MASTER_LEVEL             0x26    /* FM Level                     Read/Write  SBPro */
-#define SBMIX_CD_LEVEL                 0x28    /* CD Audio Level               Read/Write  SBPro */
-#define SBMIX_LINEIN_LEVEL             0x2E    /* Line In Level                Read/Write  SBPro */
-#define SBMIX_MASTER_LEVEL_L           0x30    /* Master Volume Left           Read/Write  SB16 */
-#define SBMIX_MASTER_LEVEL_R           0x31    /* Master Volume Right          Read/Write  SB16 */
-#define SBMIX_DAC_LEVEL_L              0x32    /* DAC Level Left               Read/Write  SB16 */
-#define SBMIX_DAC_LEVEL_R              0x33    /* DAC Level Right              Read/Write  SB16 */
-#define SBMIX_FM_LEVEL_L               0x34    /* FM Level Left                Read/Write  SB16 */
-#define SBMIX_FM_LEVEL_R               0x35    /* FM Level Right               Read/Write  SB16 */
-#define SBMIX_CD_LEVEL_L               0x36    /* CD Audio Level Left          Read/Write  SB16 */
-#define SBMIX_CD_LEVEL_R               0x37    /* CD Audio Level Right         Read/Write  SB16 */
-#define SBMIX_LINEIN_LEVEL_L           0x38    /* Line In Level Left           Read/Write  SB16 */
-#define SBMIX_LINEIN_LEVEL_R           0x39    /* Line In Level Right          Read/Write  SB16 */
-#define SBMIX_MIC_LEVEL_16             0x3A    /* Microphone Level             Read/Write  SB16 */
-#define SBMIX_PCSPK_LEVEL              0x3B    /* PC Speaker Level             Read/Write  SB16 */
-#define SBMIX_OUTPUT_CONTROL           0x3C    /* Output Control               Read/Write  SB16 */
-#define SBMIX_INPUT_CONTROL_L          0x3D    /* Input Control Left           Read/Write  SB16 */
-#define SBMIX_INPUT_CONTROL_R          0x3E    /* Input Control Right          Read/Write  SB16 */
-#define SBMIX_INPUT_GAIN_L             0x3F    /* Input Gain Control Left      Read/Write  SB16 */
-#define SBMIX_INPUT_GAIN_R             0x40    /* Input Gain Control Right     Read/Write  SB16 */
-#define SBMIX_OUTPUT_GAIN_L            0x41    /* Output Gain Control Left     Read/Write  SB16 */
-#define SBMIX_OUTPUT_GAIN_R            0x42    /* Output Gain Control Right    Read/Write  SB16 */
-#define SBMIX_AGC_CONTROL              0x43    /* Automatic Gain Control (AGC) Read/Write  SB16 */
-#define SBMIX_TREBLE_L                 0x44    /* Treble Left                  Read/Write  SB16 */
-#define SBMIX_TREBLE_R                 0x45    /* Treble Right                 Read/Write  SB16 */
-#define SBMIX_BASS_L                   0x46    /* Bass Left                    Read/Write  SB16 */
-#define SBMIX_BASS_R                   0x47    /* Bass Right                   Read/Write  SB16 */
-#define SBMIX_IRQ_SELECT               0x80    /* IRQ Select                   Read/Write  SB16 */
-#define SBMIX_DMA_SELECT               0x81    /* DMA Select                   Read/Write  SB16 */
-#define SBMIX_IRQ_STATUS               0x82    /* IRQ Status                   Read        SB16 */
-
-/* SB_DSP_DATA_OUT_STATUS and SB_DSP_DATA_IN_STATUS bits */
-#define SBM_DSP_READY                  0x80
-
-/* SB_DSP_RESET / SBMIX_RESET */
-#define SBM_DSP_RESET                  0x01
-
-/* SBMIX_OUTPUT_SELECT */
-#define SBM_MIX_STEREO                 0x02
-#define SBM_MIX_FILTER                 0x20
-
-/* SBDSP_DMA_GENERIC16/SBDSP_DMA_GENERIC8 */
-#define SBM_GENDAC_FIFO                        0x02
-#define SBM_GENDAC_AUTOINIT            0x04
-#define SBM_GENDAC_ADC                 0x08
-/* Second (mode) byte */
-#define SBM_GENDAC_SIGNED              0x10
-#define SBM_GENDAC_STEREO              0x20
-
-/* DSP version masks */
-#define SBVER_10                       0x0100  /* Original SoundBlaster */
-#define SBVER_15                       0x0105  /* SoundBlaster 1.5 */
-#define SBVER_20                       0x0200  /* SoundBlaster 2.0 */
-#define SBVER_PRO                      0x0300  /* SoundBlaster Pro */
-#define SBVER_PRO2                     0x0301  /* SoundBlaster Pro 2 */
-#define SBVER_16                       0x0400  /* SoundBlaster 16 */
-#define SBVER_AWE32                    0x040c  /* SoundBlaster AWE32 */
-
-typedef unsigned char boolean;
-
-#ifndef FALSE
-#define FALSE                          0
-#define TRUE                           1
-#endif
-
-/* Play mode bits */
-#define SBMODE_16BITS                  0x0001
-#define SBMODE_STEREO                  0x0002
-#define SBMODE_SIGNED                  0x0004
-
-/* Mask for capabilities that never change */
-#define SBMODE_MASK                    (SBMODE_16BITS | SBMODE_STEREO)
-
-/* You can fill some members of this struct (i.e. port,irq,dma) before
- * calling sb_detect() or sb_open()... this will ignore environment settings.
- */
-typedef struct __sb_state_s {
-       boolean ok;                     /* Are structure contents valid? */
-       int port, aweport;              /* sb/awe32 base port */
-       int irq;                        /* SoundBlaster IRQ */
-       int dma8, dma16;                /* 8-bit and 16-bit DMAs */
-       int maxfreq_mono;               /* Maximum discretization frequency / mono mode */
-       int maxfreq_stereo;             /* Maximum discretization frequency / stereo mode */
-       unsigned short dspver;          /* DSP version number */
-       struct irq_handle *irq_handle;  /* The interrupt handler */
-       dma_buffer *dma_buff;           /* Pre-allocated DMA buffer */
-       unsigned char caps;             /* SoundBlaster capabilities (SBMODE_XXX) */
-       unsigned char mode;             /* Current SB mode (SBMODE_XXX) */
-       boolean open;                   /* Whenever the card has been opened */
-       volatile int irqcount;          /* Incremented on each IRQ... for diagnostics */
-       void (*timer_callback) ();      /* Called TWICE per buffer play */
-} __sb_state;
-
-extern __sb_state sb;
-
-extern void __sb_wait();
-
-static inline boolean __sb_dsp_ready_in()
-{
-       int count;
-       for (count = 10000; count >= 0; count--)
-               if (inportb(SB_DSP_DATA_IN_STATUS) & SBM_DSP_READY)
-                       return TRUE;
-       return FALSE;
-}
-
-static inline boolean __sb_dsp_ready_out()
-{
-       int count;
-       for (count = 10000; count >= 0; count--)
-               if ((inportb(SB_DSP_DATA_OUT_STATUS) & SBM_DSP_READY) == 0)
-                       return TRUE;
-       return FALSE;
-}
-
-static inline void __sb_dsp_out(unsigned char reg)
-{
-       __sb_dsp_ready_out();
-       outportb(SB_DSP_DATA_OUT, reg);
-}
-
-static inline unsigned char __sb_dsp_in()
-{
-       __sb_dsp_ready_in();
-       return inportb(SB_DSP_DATA_IN);
-}
-
-static inline void __sb_dspreg_out(unsigned char reg, unsigned char val)
-{
-       __sb_dsp_out(reg);
-       __sb_dsp_out(val);
-}
-
-static inline void __sb_dspreg_outwlh(unsigned char reg, unsigned short val)
-{
-       __sb_dsp_out(reg);
-       __sb_dsp_out(val);
-       __sb_dsp_out(val >> 8);
-}
-
-static inline void __sb_dspreg_outwhl(unsigned char reg, unsigned short val)
-{
-       __sb_dsp_out(reg);
-       __sb_dsp_out(val >> 8);
-       __sb_dsp_out(val);
-}
-
-static inline unsigned char __sb_dspreg_in(unsigned char reg)
-{
-       __sb_dsp_out(reg);
-       return __sb_dsp_in();
-}
-
-static inline void __sb_dsp_ack_dma8()
-{
-       inportb(SB_DSP_DMA8_IRQ);
-}
-
-static inline void __sb_dsp_ack_dma16()
-{
-       inportb(SB_DSP_DMA16_IRQ);
-}
-
-static inline unsigned short __sb_dsp_version()
-{
-       unsigned short ver;
-       __sb_dsp_out(SBDSP_VERSION);
-       __sb_dsp_ready_in();
-       ver = ((unsigned short)__sb_dsp_in()) << 8;
-       ver |= __sb_dsp_in();
-       return ver;
-}
-
-static inline void __sb_mixer_out(unsigned char reg, unsigned char val)
-{
-       outportb(SB_MIXER_REGSEL, reg);
-       outportb(SB_MIXER_DATA, val);
-}
-
-static inline unsigned char __sb_mixer_in(unsigned char reg)
-{
-       outportb(SB_MIXER_REGSEL, reg);
-       return inportb(SB_MIXER_DATA);
-}
-
-/* Enable stereo transfers: sbpro mode only */
-static inline void __sb_stereo(boolean stereo)
-{
-       unsigned char val = __sb_mixer_in(SBMIX_OUTPUT_SELECT);
-       if (stereo)
-               val |= SBM_MIX_STEREO;
-       else
-               val &= ~SBM_MIX_STEREO;
-       __sb_mixer_out(SBMIX_OUTPUT_SELECT, val);
-}
-
-/* Detect whenever SoundBlaster is present and fill "sb" structure */
-extern boolean sb_detect();
-/* Reset SoundBlaster */
-extern void sb_reset();
-/* Start working with SoundBlaster */
-extern boolean sb_open();
-/* Finish working with SoundBlaster */
-extern boolean sb_close();
-/* Enable/disable speaker output */
-extern void sb_output(boolean enable);
-/* Start playing from DMA buffer in either 8/16 bit mono/stereo */
-extern boolean sb_start_dma(unsigned char mode, unsigned int freq);
-/* Stop playing from DMA buffer */
-extern void sb_stop_dma();
-/* Query current position/total size of the DMA buffer */
-extern void sb_query_dma(unsigned int *dma_size, unsigned int *dma_pos);
-
-#endif /* __DOSSB_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/doswss.c b/libs/mikmod/drivers/dos/doswss.c
deleted file mode 100644 (file)
index 41cdf38..0000000
+++ /dev/null
@@ -1,577 +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.
-*/
-
-/*==============================================================================
-
-  Windows Sound System I/O routines (CS42XX, ESS18XX, GUS+DaughterBoard etc)
-  Written by Andrew Zabolotny <bit@eltech.ru>
-
-==============================================================================*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef DRV_WSS
-
-#include <stdlib.h>
-#include <dpmi.h>
-#include <go32.h>
-#include <dos.h>
-#include <sys/nearptr.h>
-#include <sys/farptr.h>
-#include <string.h>
-
-#include "doswss.h"
-
-/********************************************* Private variables/routines *****/
-
-__wss_state wss;
-
-/* WSS frequency rates... lower bit selects one of two frequency generators */
-static unsigned int wss_rates[14][2] = {
-       {5510, 0x00 | WSSM_XTAL2},
-       {6620, 0x0E | WSSM_XTAL2},
-       {8000, 0x00 | WSSM_XTAL1},
-       {9600, 0x0E | WSSM_XTAL1},
-       {11025, 0x02 | WSSM_XTAL2},
-       {16000, 0x02 | WSSM_XTAL1},
-       {18900, 0x04 | WSSM_XTAL2},
-       {22050, 0x06 | WSSM_XTAL2},
-       {27420, 0x04 | WSSM_XTAL1},
-       {32000, 0x06 | WSSM_XTAL1},
-       {33075, 0x0C | WSSM_XTAL2},
-       {37800, 0x08 | WSSM_XTAL2},
-       {44100, 0x0A | WSSM_XTAL2},
-       {48000, 0x0C | WSSM_XTAL1}
-};
-
-static void wss_irq()
-{
-       /* Make sure its not a spurious IRQ */
-       if (!irq_check(wss.irq_handle))
-               return;
-
-       wss.irqcount++;
-
-       /* Clear IRQ status */
-       outportb(WSS_STATUS, 0);
-
-       /* Write transfer count again */
-       __wss_outreg(WSSR_COUNT_LOW, wss.samples & 0xff);
-       __wss_outreg(WSSR_COUNT_HIGH, wss.samples >> 8);
-       irq_ack(wss.irq_handle);
-
-       enable();
-       if (wss.timer_callback)
-               wss.timer_callback();
-}
-
-static void wss_irq_end()
-{
-}
-
-/* WSS accepts some conventional values instead of frequency in Hz... */
-static unsigned char __wss_getrate(unsigned int *freq)
-{
-       int i, best = -1, delta = 0xffff;
-
-       for (i = 0; i < 14; i++) {
-               int newdelta = abs(wss_rates[i][0] - *freq);
-               if (newdelta < delta)
-                       best = i, delta = newdelta;
-       }
-
-       *freq = wss_rates[best][0];
-       return wss_rates[best][1];
-}
-
-/* Check if we really have a WSS compatible card on given address */
-static boolean __wss_ping()
-{
-       /* Disable CODEC operations first */
-       __wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-       /* Now put some harmless values in registers and check them */
-       __wss_outreg(WSSR_COUNT_LOW, 0xaa);
-       __wss_outreg(WSSR_COUNT_HIGH, 0x55);
-       return (__wss_inreg(WSSR_COUNT_LOW) == 0xaa)
-         && (__wss_inreg(WSSR_COUNT_HIGH) == 0x55);
-}
-
-static boolean __wss_reset()
-{
-       int count;
-
-       /* Disable output */
-       wss_output(FALSE);
-
-       /* Now select the test/initialization register */
-       count = 10000;
-       while (inportb(WSS_ADDR) != WSSR_TEST_INIT) {
-               outportb(WSS_ADDR, WSSR_TEST_INIT);
-               if (!--count)
-                       return FALSE;
-       }
-
-       count = 10000;
-       while (inportb(WSS_DATA) & WSSM_CALIB_IN_PROGRESS) {
-               outportb(WSS_ADDR, WSSR_TEST_INIT);
-               if (!--count)
-                       return FALSE;
-       }
-
-       /* Enable playback IRQ */
-       __wss_regbit_set(WSSR_PIN_CTRL, WSSM_IRQ_ENABLE);
-       __wss_outreg(WSSR_IRQ_STATUS, WSSM_PLAYBACK_IRQ);
-
-       /* Clear IRQ status */
-       outportb(WSS_STATUS, 0);
-
-       return TRUE;
-}
-
-static boolean __wss_setformat(unsigned char format)
-{
-       int count;
-
-       outportb(WSS_ADDR, WSSM_MCE | WSSR_PLAY_FORMAT);
-       outportb(WSS_DATA, format);
-       inportb(WSS_DATA);                      /* ERRATA SHEETS ... */
-       inportb(WSS_DATA);                      /* ERRATA SHEETS ... */
-
-       /* Wait end of syncronization ... */
-       if (!__wss_wait())
-               return FALSE;
-
-       /* Turn off the ModeChangeEnable bit: do it until it works */
-       count = 10000;
-       while (inportb(WSS_ADDR) != WSSR_PLAY_FORMAT) {
-               outportb(WSS_ADDR, WSSR_PLAY_FORMAT);
-               if (!--count)
-                       return FALSE;
-       }
-
-       return __wss_reset();
-}
-
-/**************************************************** WSS detection stuff *****/
-
-static int __wss_irq_irqdetect(int irqno)
-{
-       unsigned char status = inportb(WSS_STATUS);
-       /* Clear IRQ status */
-       outportb(WSS_STATUS, 0);
-       /* Reset transfer counter */
-       __wss_outreg(WSSR_COUNT_LOW, 0);
-       __wss_outreg(WSSR_COUNT_HIGH, 0);
-       return (status & WSSM_INT);
-}
-
-static boolean __wss_detect()
-{
-       /* First find the port number */
-       if (!wss.port) {
-               static unsigned int wss_ports[] =
-                 { 0x32c, 0x530, 0x604, 0xE80, 0xF40 };
-               int i;
-               for (i = 0; i < 5; i++) {
-                       wss.port = wss_ports[i];
-                       if (__wss_ping())
-                               break;
-               }
-               if (i < 0) {
-                       wss.port = 0;
-                       return FALSE;
-               }
-       }
-
-       /* Now disable output */
-       wss_output(FALSE);
-
-       /* Detect the DMA channel */
-       if (!wss.dma) {
-               static int __dma[] = { 0, 1, 3 };
-               int i;
-
-               /* Enable playback IRQ */
-               __wss_regbit_set(WSSR_PIN_CTRL, WSSM_IRQ_ENABLE);
-               __wss_outreg(WSSR_IRQ_STATUS, WSSM_PLAYBACK_IRQ);
-
-               /* Start a short DMA transfer and check if DMA count is zero */
-               for (i = 0; i < 3; i++) {
-                       unsigned int timer, status, freq = 44100;
-
-                       wss.dma = __dma[i];
-
-                       dma_disable(wss.dma);
-                       dma_set_mode(wss.dma, DMA_MODE_WRITE);
-                       dma_clear_ff(wss.dma);
-                       dma_set_count(wss.dma, 10);
-                       dma_enable(wss.dma);
-
-                       /* Clear IRQ status */
-                       outportb(WSS_STATUS, 0);
-
-                       __wss_setformat(__wss_getrate(&freq));
-                       __wss_outreg(WSSR_COUNT_LOW, 1);
-                       __wss_outreg(WSSR_COUNT_HIGH, 0);
-                       /* Tell codec to start transfer */
-                       __wss_regbit_set(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-
-                       _farsetsel(_dos_ds);
-                       timer = _farnspeekl(0x46c);
-
-                       while (_farnspeekl(0x46c) - timer <= 2)
-                               if (dma_get_count(wss.dma) == 0)
-                                       break;
-                       __wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-                       dma_disable(wss.dma);
-
-                       /* Now check if DMA transfer count is zero and an IRQ is pending */
-                       status = inportb(WSS_STATUS);
-                       outportb(WSS_STATUS, 0);
-                       if ((dma_get_count(wss.dma) == 0) && (status & WSSM_INT))
-                               break;
-
-                       wss.dma = 0;
-               }
-
-               if (!wss.dma)
-                       return FALSE;
-       }
-
-       /* Now detect the IRQ number */
-       if (!wss.irq) {
-               unsigned int i, irqmask, freq = 5510;
-               unsigned long timer, delta = 0x7fffffff;
-
-               /* IRQ can be one of 2,3,5,7,10 */
-               irq_detect_start(0x04ac, __wss_irq_irqdetect);
-
-               dma_disable(wss.dma);
-               dma_set_mode(wss.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
-               dma_clear_ff(wss.dma);
-               dma_set_count(wss.dma, 1);
-               dma_enable(wss.dma);
-
-               __wss_setformat(__wss_getrate(&freq));
-
-               /* Clear IRQ status */
-               outportb(WSS_STATUS, 0);
-
-               __wss_outreg(WSSR_COUNT_LOW, 0);
-               __wss_outreg(WSSR_COUNT_HIGH, 0);
-
-               /* Prepare timeout counter */
-               _farsetsel(_dos_ds);
-               timer = _farnspeekl(0x46c);
-               while (timer == _farnspeekl(0x46c));
-               timer = _farnspeekl(0x46c);
-
-               /* Reset all IRQ counters */
-               irq_detect_clear();
-
-               /* Tell codec to start transfer */
-               __wss_regbit_set(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-
-               /* Now wait 1/18 seconds */
-               while (timer == _farnspeekl(0x46c));
-               __wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-               dma_disable(wss.dma);
-
-               /* Given frequency 5510Hz, a buffer size of 1 byte and a time interval
-                  of 1/18.2 second, we should have received about 302 interrupts */
-               for (i = 2; i <= 10; i++) {
-                       int count = abs(302 - irq_detect_get(i, &irqmask));
-                       if (count < delta)
-                               wss.irq = i, delta = count;
-               }
-               if (delta > 150)
-                       wss.irq = 0;
-
-               irq_detect_end();
-               if (!wss.irq)
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-/*************************************************** High-level interface *****/
-
-/* Detect whenever WSS is present and fill "wss" structure */
-boolean wss_detect()
-{
-       char *env;
-
-       /* Try to find the port and DMA from environment */
-       env = getenv("WSS");
-
-       while (env && *env) {
-               /* Skip whitespace */
-               while ((*env == ' ') || (*env == '\t'))
-                       env++;
-               if (!*env)
-                       break;
-
-               switch (*env++) {
-                 case 'A':
-                 case 'a':
-                       if (!wss.port)
-                               wss.port = strtol(env, &env, 16);
-                       break;
-                 case 'I':
-                 case 'i':
-                       if (!wss.irq)
-                               wss.irq = strtol(env, &env, 10);
-                       break;
-                 case 'D':
-                 case 'd':
-                       if (!wss.dma)
-                               wss.dma = strtol(env, &env, 10);
-                       break;
-                 default:
-                       /* Skip other values */
-                       while (*env && (*env != ' ') && (*env != '\t'))
-                               env++;
-                       break;
-               }
-       }
-
-       /* Try to fill the gaps in wss hardware parameters */
-       __wss_detect();
-
-       if (!wss.port || !wss.irq || !wss.dma)
-               return FALSE;
-
-       if (!__wss_ping())
-               return FALSE;
-
-       if (!__wss_reset())
-               return FALSE;
-
-       wss.ok = 1;
-       return TRUE;
-}
-
-/* Reset WSS */
-void wss_reset()
-{
-       wss_stop_dma();
-       __wss_reset();
-}
-
-/* Open WSS for usage */
-boolean wss_open()
-{
-       __dpmi_meminfo struct_info;
-
-       if (!wss.ok)
-               if (!wss_detect())
-                       return FALSE;
-
-       if (wss.open)
-               return FALSE;
-
-       /* Now lock the wss structure in memory */
-       struct_info.address = __djgpp_base_address + (unsigned long)&wss;
-       struct_info.size = sizeof(wss);
-       if (__dpmi_lock_linear_region(&struct_info))
-               return FALSE;
-
-       /* Hook the WSS IRQ */
-       wss.irq_handle =
-         irq_hook(wss.irq, wss_irq, (long)wss_irq_end - (long)wss_irq);
-       if (!wss.irq_handle) {
-               __dpmi_unlock_linear_region(&struct_info);
-               return FALSE;
-       }
-
-       /* Enable the interrupt */
-       irq_enable(wss.irq_handle);
-       if (wss.irq > 7)
-               _irq_enable(2);
-
-       wss.open++;
-
-       return TRUE;
-}
-
-/* Finish working with WSS */
-boolean wss_close()
-{
-       __dpmi_meminfo struct_info;
-       if (!wss.open)
-               return FALSE;
-
-       wss.open--;
-
-       /* Stop/free DMA buffer */
-       wss_stop_dma();
-
-       /* Unhook IRQ */
-       irq_unhook(wss.irq_handle);
-       wss.irq_handle = NULL;
-
-       /* Unlock the wss structure */
-       struct_info.address = __djgpp_base_address + (unsigned long)&wss;
-       struct_info.size = sizeof(wss);
-       __dpmi_unlock_linear_region(&struct_info);
-
-       return TRUE;
-}
-
-/* Adjust frequency rate to nearest WSS available */
-unsigned int wss_adjust_freq(unsigned int freq)
-{
-       __wss_getrate(&freq);
-       return freq;
-}
-
-/* Enable/disable speaker output */
-/* Start playing from DMA buffer in either 8/16 bit mono/stereo */
-boolean wss_start_dma(unsigned char mode, unsigned int freq)
-{
-       int dmabuffsize;
-       unsigned char format;
-
-       /* Stop DMA transfer if it is enabled */
-       wss_stop_dma();
-
-       /* Sanity check: we support only 8-bit unsigned and 16-bit signed formats */
-       if (((mode & WSSMODE_16BITS) && !(mode & WSSMODE_SIGNED))
-               || (!(mode & WSSMODE_16BITS) && (mode & WSSMODE_SIGNED)))
-               return FALSE;
-
-       /* Find the nearest frequency divisor (rate) */
-       format = __wss_getrate(&freq);
-       wss.mode = mode;
-
-       /* Get a DMA buffer enough for a 1sec interval... 4K <= dmasize <= 32K */
-       dmabuffsize = freq;
-       if (mode & WSSMODE_STEREO)
-               dmabuffsize *= 2;
-       if (mode & WSSMODE_16BITS)
-               dmabuffsize *= 2;
-       dmabuffsize >>= 2;
-       if (dmabuffsize < 4096)
-               dmabuffsize = 4096;
-       if (dmabuffsize > 32768)
-               dmabuffsize = 32768;
-       dmabuffsize = (dmabuffsize + 255) & 0xffffff00;
-
-       wss.dma_buff = dma_allocate(wss.dma, dmabuffsize);
-       if (!wss.dma_buff)
-               return FALSE;
-
-       /* Fill DMA buffer with silence */
-       dmabuffsize = wss.dma_buff->size;
-       if (mode & WSSMODE_SIGNED)
-               memset(wss.dma_buff->linear, 0, dmabuffsize);
-       else
-               memset(wss.dma_buff->linear, 0x80, dmabuffsize);
-
-       /* Check data size and build a WSSR_PLAY_FORMAT value accordingly */
-       wss.samples = dmabuffsize;
-       if (mode & WSSMODE_16BITS) {
-               wss.samples >>= 1;
-               format |= WSSM_16BITS;
-       }
-
-       if (mode & WSSMODE_STEREO) {
-               wss.samples >>= 1;
-               format |= WSSM_STEREO;
-       }
-
-       if (!__wss_setformat(format)) {
-               wss_stop_dma();
-               return FALSE;
-       }
-
-       /* Prime DMA for transfer */
-       dma_start(wss.dma_buff, dmabuffsize, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
-
-       /* Tell codec how many samples to transfer */
-       wss.samples = (wss.samples >> 1) - 1;
-       __wss_outreg(WSSR_COUNT_LOW, wss.samples & 0xff);
-       __wss_outreg(WSSR_COUNT_HIGH, wss.samples >> 8);
-
-       /* Tell codec to start transfer */
-       __wss_regbit_set(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-
-       return TRUE;
-}
-
-/* Stop playing from DMA buffer */
-void wss_stop_dma()
-{
-       if (!wss.dma_buff)
-               return;
-
-       __wss_regbit_reset(WSSR_IFACE_CTRL, WSSM_PLAYBACK_ENABLE);
-       dma_disable(wss.dma);
-       dma_free(wss.dma_buff);
-       wss.dma_buff = NULL;
-}
-
-/* Query current position/total size of the DMA buffer */
-void wss_query_dma(unsigned int *dma_size, unsigned int *dma_pos)
-{
-       unsigned int dma_left;
-       *dma_size = wss.dma_buff->size;
-       /* It can happen we try to read DMA count when HI/LO bytes will be
-          inconsistent */
-       for (;;) {
-               unsigned int dma_left_test;
-               dma_clear_ff(wss.dma);
-               dma_left_test = dma_get_count(wss.dma);
-               dma_left = dma_get_count(wss.dma);
-               if ((dma_left >= dma_left_test) && (dma_left - dma_left_test < 10))
-                       break;
-       }
-       *dma_pos = *dma_size - dma_left;
-}
-
-void wss_output(boolean enable)
-{
-       if (enable)
-               wss.curlevel = wss.level;
-       else
-               wss.curlevel = 0x3f;
-
-       __wss_outreg(WSSR_MASTER_L, wss.curlevel);
-       __wss_outreg(WSSR_MASTER_R, wss.curlevel);
-}
-
-void wss_level(int level)
-{
-       if (level < 0)
-               level = 0;
-       if (level > 63)
-               level = 63;
-       wss.curlevel = wss.level = level ^ 63;
-
-       __wss_outreg(WSSR_MASTER_L, wss.curlevel);
-       __wss_outreg(WSSR_MASTER_R, wss.curlevel);
-}
-
-#endif /* DRV_WSS */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/doswss.h b/libs/mikmod/drivers/dos/doswss.h
deleted file mode 100644 (file)
index ae77bb5..0000000
+++ /dev/null
@@ -1,217 +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$
-
-  Windows Sound System and compatible soundcards definitions
-
-==============================================================================*/
-
-#ifndef __DOSWSS_H__
-#define __DOSWSS_H__
-
-#include "dosdma.h"
-#include "dosirq.h"
-
-#define WSS_ADDR                       (wss.port + 0x04)
-#define WSS_DATA                       (wss.port + 0x05)
-#define WSS_STATUS                     (wss.port + 0x06)
-#define WSS_PIO                                (wss.port + 0x07)
-
-/* WSS_ADDR: Bits 0-4 select an internal register to read/write */
-#define WSSR_INPUT_L                   0x00    /* Left input control register */
-#define WSSR_INPUT_R                   0x01    /* RIght input control register */
-#define WSSR_AUX1_L                    0x02    /* Left Aux #1 input control */
-#define WSSR_AUX1_R                    0x03    /* Right Aux #1 input control */
-#define WSSR_CD_L                      0x04    /* Left Aux #2 input control */
-#define WSSR_CD_R                      0x05    /* Right Aux #2 input control */
-#define WSSR_MASTER_L                  0x06    /* Left output control */
-#define WSSR_MASTER_R                  0x07    /* Right output control */
-#define WSSR_PLAY_FORMAT               0x08    /* Clock and data format */
-#define WSSR_IFACE_CTRL                        0x09    /* Interface control */
-#define WSSR_PIN_CTRL                  0x0a    /* Pin control */
-#define WSSR_TEST_INIT                 0x0b    /* Test and initialization */
-#define WSSR_MISC_INFO                 0x0c    /* Miscellaneaous information */
-#define WSSR_LOOPBACK                  0x0d    /* Digital Mix */
-#define WSSR_COUNT_HIGH                        0x0e    /* Playback Upper Base Count */
-#define WSSR_COUNT_LOW                 0x0f    /* Playback Lower Base Count */
-#define WSSR_ALT_FEATURE_1             0x10    /* alternate #1 feature enable */
-#define WSSR_ALT_FEATURE_2             0x11    /* alternate #2 feature enable */
-#define WSSR_LINE_IN_L                 0x12    /* left line input control */
-#define WSSR_LINE_IN_R                 0x13    /* right line input control */
-#define WSSR_TIMER_LOW                 0x14    /* timer low byte */
-#define WSSR_TIMER_HIGH                        0x15    /* timer high byte */
-#define WSSR_IRQ_STATUS                        0x18    /* irq status register */
-#define WSSR_MONO_IO_CTRL              0x1a    /* mono input/output control */
-#define WSSR_REC_FORMAT                        0x1c    /* record format */
-#define WSSR_REC_COUNT_HIGH            0x1e    /* record upper count */
-#define WSSR_REC_COUNT_LOW             0x1f    /* record lower count */
-
-/* WSS_ADDR bits 7-5 definition */
-#define WSSM_INIT                      0x80    /* Codec is initializing */
-#define WSSM_MCE                       0x40    /* Mode change enable */
-#define WSSM_TRD                       0x20    /* Transfer Request Disable */
-/* bits 4-0 are indirect register address (0-15) */
-
-/* WSS_STATUS bit masks */
-#define WSSM_CUL                       0x80    /* Capture data upper/lower byte */
-#define WSSM_CLR                       0x40    /* Capture left/right sample */
-#define WSSM_CRDY                      0x20    /* Capture data read */
-#define WSSM_SOUR                      0x10    /* Playback over/under run error */
-#define WSSM_PUL                       0x08    /* Playback upper/lower byte */
-#define WSSM_PLR                       0x04    /* Playback left/right sample */
-#define WSSM_PRDY                      0x02    /* Playback data register read */
-#define WSSM_INT                       0x01    /* interrupt status */
-
-/* Definitions for output level registers */
-#define WSSM_MUTE                      0x80    /* Mute this output source */
-/* bits 5-0 are left output attenuation select (0-63) */
-/* bits 5-0 are right output attenuation select (0-63) */
-
-/* Definitions for clock and data format register (WSSR_PLAY_FORMAT) */
-#define WSSM_STEREO                    0x10    /* stero mode */
-#define WSSM_ULAW_8                    0x20    /* 8-bit U-law companded */
-#define WSSM_16BITS                    0x40    /* 16 bit twos complement data - little endian */
-#define WSSM_ALAW_8                    0x60    /* 8-bit A-law companded */
-#define WSSM_16BITS_BE                 0xc0    /* 16-bit twos complement data - big endian */
-#define WSSM_ADPCM_16                  0xa0    /* 16-bit ADPCM */
-/* Bits 3-1 define frequency divisor */
-#define WSSM_XTAL1                     0x00    /* 24.576 crystal */
-#define WSSM_XTAL2                     0x01    /* 16.9344 crystal */
-
-/* Definitions for interface control register (WSSR_IFACE_CTRL) */
-#define WSSM_CAPTURE_PIO               0x80    /* Capture PIO enable */
-#define WSSM_PLAYBACK_PIO              0x40    /* Playback PIO enable */
-#define WSSM_AUTOCALIB                 0x08    /* auto calibrate */
-#define WSSM_SINGLE_DMA                        0x04    /* Use single DMA channel */
-#define WSSM_PLAYBACK_ENABLE           0x01    /* playback enable */
-
-/* Definitions for Pin control register (WSSR_PIN_CTRL) */
-#define WSSM_IRQ_ENABLE                        0x02    /* interrupt enable */
-#define WSSM_XCTL1                     0x40    /* external control #1 */
-#define WSSM_XCTL0                     0x80    /* external control #0 */
-
-/* Definitions for WSSR_TEST_INIT register */
-#define WSSM_CALIB_IN_PROGRESS 0x20    /* auto calibrate in progress */
-
-/* Definitions for misc control register (WSR_MISC_INFO) */
-#define WSSM_MODE2                     0x40    /* MODE 2 */
-#define WSSM_MODE3                     0x6c    /* MODE 3 - enhanced mode */
-
-/* Definitions for codec irq status (WSSR_IRQ_STATUS) */
-#define WSSM_PLAYBACK_IRQ              0x10
-#define WSSM_RECORD_IRQ                        0x20
-#define WSSM_TIMER_IRQ                 0x40
-
-typedef unsigned char boolean;
-
-#ifndef FALSE
-#define FALSE                          0
-#define TRUE                           1
-#endif
-
-/* Play mode bits */
-#define WSSMODE_16BITS                 0x0001
-#define WSSMODE_STEREO                 0x0002
-#define WSSMODE_SIGNED                 0x0004
-
-/* You can fill some members of this struct (i.e. port,irq,dma) before
- * calling wss_detect() or wss_open()... this will ignore environment settings.
- */
-typedef struct __wss_state_s {
-       boolean ok;                     /* Set if this structure is properly filled */
-       int port;                       /* Base codec port */
-       int irq;                        /* codec IRQ */
-       int dma;                        /* codec DMA */
-       struct irq_handle *irq_handle;  /* The interrupt handler */
-       dma_buffer *dma_buff;           /* Pre-allocated DMA buffer */
-       unsigned char mode;             /* Current WSS mode (WSSMODE_XXX) */
-       boolean open;                   /* Whenever the card has been opened */
-       int samples;                    /* Number of samples in DMA buffer */
-       unsigned char level;            /* Output level (63..0): doesn't change when mute */
-       unsigned char curlevel;         /* Current output level (63(min)..0(max)) */
-       volatile int irqcount;          /* Incremented on each IRQ... for diagnostics */
-       void (*timer_callback) ();      /* Called TWICE per buffer play */
-} __wss_state;
-
-extern __wss_state wss;
-
-/* Wait until codec finishes initialization */
-static inline boolean __wss_wait()
-{
-       int count;
-       for (count = 10000; count >= 0; count--)
-               if (!(inportb(WSS_ADDR) & WSSM_INIT))
-                       return TRUE;
-       return FALSE;
-}
-
-static inline void __wss_outreg(unsigned char reg, unsigned char val)
-{
-       outportb(WSS_ADDR, reg);
-       outportb(WSS_DATA, val);
-}
-
-static inline unsigned char __wss_inreg(unsigned char reg)
-{
-       outportb(WSS_ADDR, reg);
-       return inportb(WSS_DATA);
-}
-
-/* Set some bits in a specific register */
-static inline void __wss_regbit_set(unsigned char reg, unsigned char mask)
-{
-       outportb(WSS_ADDR, reg);
-       outportb(WSS_DATA, inportb(WSS_DATA) | mask);
-}
-
-/* Reset some bits in a specific register */
-static inline void __wss_regbit_reset(unsigned char reg, unsigned char mask)
-{
-       outportb(WSS_ADDR, reg);
-       outportb(WSS_DATA, inportb(WSS_DATA) & ~mask);
-}
-
-/* Detect whenever WSS is present and fill "wss" structure */
-extern boolean wss_detect();
-/* Reset WSS */
-extern void wss_reset();
-/* Open WSS for usage */
-extern boolean wss_open();
-/* Finish working with WSS */
-extern boolean wss_close();
-/* Enable/disable speaker output */
-extern void wss_output(boolean enable);
-/* Adjust frequency rate to nearest WSS available */
-extern unsigned int wss_adjust_freq(unsigned int freq);
-/* Start playing from DMA buffer in either 8/16 bit mono/stereo */
-extern boolean wss_start_dma(unsigned char mode, unsigned int freq);
-/* Stop playing from DMA buffer */
-extern void wss_stop_dma();
-/* Query current position/total size of the DMA buffer */
-extern void wss_query_dma(unsigned int *dma_size, unsigned int *dma_pos);
-/* Set output level (0(min)-63(max)) */
-extern void wss_level(int level);
-
-#endif /* __DOSWSS_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/dos/libgus.h b/libs/mikmod/drivers/dos/libgus.h
deleted file mode 100644 (file)
index 0d66ee9..0000000
+++ /dev/null
@@ -1,402 +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$
-
-  Linux libGUS-alike library for DOS, used by drv_ultra.c under DOS.
-
-==============================================================================*/
-
-/*
-       Current limitations:
-       - Only a subset of libgus is supported
-       - Only one GUS card is supported (due to the fact that ULTRASND environment
-         variable is used)
-       - No Interwawe support (if IW works the old way, it's ok).
-*/
-
-#ifndef __LIBGUS_H__
-#define __LIBGUS_H__
-
-#include <stddef.h>
-
-#define __LITTLE_ENDIAN
-
-typedef struct _gus_info_t gus_info_t;
-typedef struct _gus_instrument_t gus_instrument_t;
-typedef struct _gus_wave_t gus_wave_t;
-typedef struct _gus_layer_t gus_layer_t;
-
-#define GUS_CARD_VERSION_CLASSIC       0x0024  /* revision 2.4 */
-#define GUS_CARD_VERSION_CLASSIC1      0x0034  /* revision 3.4? */
-#define GUS_CARD_VERSION_CLASSIC_ICS   0x0037  /* revision 3.7 (ICS mixer) */
-#define GUS_CARD_VERSION_EXTREME       0x0050  /* GUS Extreme */
-#define GUS_CARD_VERSION_ACE           0x0090  /* GUS ACE */
-#define GUS_CARD_VERSION_MAX           0x00a0  /* GUS MAX - revision 10 */
-#define GUS_CARD_VERSION_MAX1          0x00a1  /* GUS MAX - revision 11 */
-#define GUS_CARD_VERSION_PNP           0x0100  /* GUS Plug & Play */
-
-#define GUS_STRU_INFO_F_DB16           0x00000001      /* 16-bit daughter board present */
-#define GUS_STRU_INFO_F_PCM            0x00000004      /* GF1 PCM during SYNTH enabled */
-#define GUS_STRU_INFO_F_ENHANCED       0x00000008      /* InterWave - enhanced mode */
-#define GUS_STRU_INFO_F_DAEMON         0x00000010      /* instrument daemon is present */
-
-struct _gus_info_t {
-       unsigned char id[8];            /* id of this card (warning! maybe unterminated!!!) */
-
-       unsigned int flags;             /* some info flags - see to GUS_STRU_INFO_F_XXXX */
-       unsigned int version;           /* see to GUS_CARD_VERSION_XXXX constants */
-
-       unsigned short port;
-       unsigned short irq;
-       unsigned short dma1;            /* DMA1 - GF1 download & codec record */
-       unsigned short dma2;            /* DMA2 - GF1 record & codec playback */
-
-       unsigned int mixing_freq;       /* mixing frequency in Hz */
-
-       unsigned int memory_size;       /* in bytes */
-       unsigned int memory_free;       /* in bytes */
-       unsigned int memory_block_8;    /* largest free 8-bit block in memory */
-       unsigned int memory_block_16;   /* largest free 16-bit block in memory */
-};
-
-/* struct gus_instrument_t - mode */
-
-#define GUS_INSTR_SIMPLE       0x00    /* simple format - for MOD players */
-#define GUS_INSTR_PATCH                0x01    /* old GF1 patch format */
-#define GUS_INSTR_COUNT                2
-
-#define GUS_INSTR_F_NORMAL     0x0000  /* normal mode */
-#define GUS_INSTR_F_NOT_FOUND  0x0001  /* instrument can't be loaded */
-#define GUS_INSTR_F_ALIAS      0x0002  /* alias */
-#define GUS_INSTR_F_NOT_LOADED 0x00ff  /* instrument not loaded (not found) */
-
-#define GUS_INSTR_E_NONE       0x0000  /* exclusion mode - none */
-#define GUS_INSTR_E_SINGLE     0x0001  /* exclude single - single note from this instrument */
-#define GUS_INSTR_E_MULTIPLE   0x0002  /* exclude multiple - stop only same note from this instrument */
-
-#define GUS_INSTR_L_NONE       0x0000  /* not layered */
-#define GUS_INSTR_L_ON         0x0001  /* layered */
-#define GUS_INSTR_L_VELOCITY   0x0002  /* layered by velocity */
-#define GUS_INSTR_L_FREQUENCY  0x0003  /* layered by frequency */
-
-struct _gus_instrument_t {
-       union {
-               unsigned int instrument;/* instrument number */
-       } number;
-
-       char *name;                     /* name of this instrument or NULL */
-
-       unsigned int mode:8,            /* see to GUS_INSTR_XXXX */
-           flags:8,                    /* see to GUS_INSTR_F_XXXX */
-           exclusion:4,                /* see to GUS_INSTR_E_XXXX */
-           layer:4;                    /* see to GUS_INSTR_L_XXXX */
-       unsigned short exclusion_group; /* 0 - none, 1-65535 */
-
-       struct {
-               unsigned char effect1:4,/* use global effect if available */
-                   effect2:4;          /* use global effect if available */
-               unsigned char effect1_depth;/* 0-127 */
-               unsigned char effect2_depth;/* 0-127 */
-       } patch;
-
-       union {
-               gus_layer_t *layer;     /* first layer */
-               unsigned int alias;     /* pointer to instrument */
-       } info;
-       gus_instrument_t *next;         /* next instrument */
-};
-
-struct _gus_layer_t {
-       unsigned char mode;             /* see to GUS_INSTR_XXXX constants */
-
-       gus_wave_t *wave;
-       gus_layer_t *next;
-};
-
-/* bits for format variable in gus_wave_t */
-
-#define GUS_WAVE_16BIT          0x0001 /* 16-bit wave */
-#define GUS_WAVE_UNSIGNED       0x0002 /* unsigned wave */
-#define GUS_WAVE_INVERT         0x0002 /* same as unsigned wave */
-#define GUS_WAVE_BACKWARD       0x0004 /* forward mode */
-#define GUS_WAVE_LOOP           0x0008 /* loop mode */
-#define GUS_WAVE_BIDIR          0x0010 /* bidirectional mode */
-#define GUS_WAVE_ULAW           0x0020 /* uLaw compressed wave */
-#define GUS_WAVE_RAM            0x0040 /* wave is _preloaded_ in RAM (it is used for ROM simulation) */
-#define GUS_WAVE_ROM            0x0080 /* wave is in ROM */
-#define GUS_WAVE_DELTA          0x0100
-
-#define GUS_WAVE_PATCH_ENVELOPE 0x01   /* envelopes on */
-#define GUS_WAVE_PATCH_SUSTAIN  0x02   /* sustain mode */
-
-struct _gus_wave_t {
-       unsigned char mode;             /* see to GUS_INSTR_XXXX constants */
-       unsigned char format;           /* see to GUS_WAVE_XXXX constants */
-       unsigned int size;              /* size of waveform in bytes */
-       unsigned int start;             /* start offset in bytes * 16 (lowest 4 bits - fraction) */
-       unsigned int loop_start;        /* bits loop start offset in bytes * 16 (lowest 4 bits - fraction) */
-       unsigned int loop_end;          /* loop start offset in bytes * 16 (lowest 4 bits - fraction) */
-       unsigned short loop_repeat;     /* loop repeat - 0 = forever */
-       struct {
-               unsigned int memory;    /* begin of waveform in GUS's memory */
-               unsigned char *ptr;     /* pointer to waveform in system memory */
-       } begin;
-
-       struct {
-               unsigned char flags;
-               unsigned int sample_rate;
-               unsigned int low_frequency;/* low frequency range for this waveform */
-               unsigned int high_frequency;/* high frequency range for this waveform */
-               unsigned int root_frequency;/* root frequency for this waveform */
-               signed short tune;
-               unsigned char balance;
-               unsigned char envelope_rate[6];
-               unsigned char envelope_offset[6];
-               unsigned char tremolo_sweep;
-               unsigned char tremolo_rate;
-               unsigned char tremolo_depth;
-               unsigned char vibrato_sweep;
-               unsigned char vibrato_rate;
-               unsigned char vibrato_depth;
-               unsigned short scale_frequency;
-               unsigned short scale_factor;/* 0-2048 or 0-2 */
-       } patch;
-
-       gus_wave_t *next;
-};
-
-/* defines for gus_memory_reset () */
-#define GUS_DOWNLOAD_MODE_NORMAL 0x0000
-#define GUS_DOWNLOAD_MODE_TEST  0x0001
-
-/*
-    A subset of libgus functions (used by MikMod Ultrasound driver)
-*/
-int gus_cards(void);
-  /*
-   * return value:      number of GUS cards installed in system or
-   *                    zero if driver isn't installed
-   */
-int gus_close(int card);
-  /*
-   * close file (gus synthesizer) previously opened with gusOpen function
-   * return value:      zero if success
-   */
-int gus_do_flush(void);
-  /*
-   * return value:      zero if command queue was successfully flushed
-   *                    in non block mode - number of written bytes
-   */
-void gus_do_tempo(unsigned int tempo);
-  /*
-   * set new tempo
-   */
-void gus_do_voice_frequency(unsigned char voice, unsigned int freq);
-  /*
-   * set voice frequency in Hz
-   */
-void gus_do_voice_pan(unsigned char voice, unsigned short pan);
-  /*
-   * set voice pan (0-16384) (full left - full right)
-   */
-void gus_do_voice_start(unsigned char voice, unsigned int program,
-                        unsigned int freq, unsigned short volume,
-                        unsigned short pan);
-  /*
-   * start voice
-   *            voice    : voice #
-   *            program  : program # or ~0 = current
-   *            freq     : frequency in Hz
-   *            volume   : volume level (0-16384) or ~0 = current
-   *            pan      : pan level (0-16384) or ~0 = current
-   */
-void gus_do_voice_start_position(unsigned char voice, unsigned int program,
-                                 unsigned int freq, unsigned short volume,
-                                 unsigned short pan, unsigned int position);
-  /*
-   * start voice
-   *            voice    : voice #
-   *            program  : program # or ~0 = current
-   *            freq     : frequency in Hz
-   *            volume   : volume level (0-16384) or ~0 = current
-   *            pan      : pan level (0-16384) or ~0 = current
-   *            position : offset to wave in bytes * 16 (lowest 4 bits - fraction)
-   */
-void gus_do_voice_stop(unsigned char voice, unsigned char mode);
-  /*
-   * stop voice
-   *            mode = 0 : stop voice now
-   *            mode = 1 : disable wave loop and finish it
-   */
-void gus_do_voice_volume(unsigned char voice, unsigned short vol);
-  /*
-   * set voice volume level 0-16384 (linear)
-   */
-void gus_do_wait(unsigned int ticks);
-  /*
-   * wait x ticks - this command is block separator
-   * all commands between blocks are interpreted in the begining of one tick
-   */
-int gus_get_voice_status(int voice);
-  /*
-   * THIS IS NOT A FUNCTION OF ORIGINAL libGUS!
-   * Return voice status: -1 on error, 0 if voice stopped, 1 if playing
-   */
-int gus_get_handle(void);
-  /*
-   * return value:      file handle (descriptor) for /dev/gus
-   */
-int gus_info(gus_info_t * info, int reread);
-  /*
-   * return value:      filled info variable with actual values
-   *                    (look at gus.h header file for more informations)
-   * version field:     0x0024  - GUS revision 2.4
-   *                    0x0035  - GUS revision 3.7 with flipped mixer channels
-   *                    0x0037  - GUS revision 3.7
-   *                    0x0090  - GUS ACE
-   *                    0x00a0  - GUS MAX revision 10
-   *                    0x00a1  - GUS MAX revision 11
-   *                    0x0100  - InterWave (full version)
-   * flags field:       see to GUS_STRU_INFO_F_???? constants (gus.h header file)
-   * port field:        port number (for example 0x220)
-   * irq field:         irq number (for example 11)
-   * dma1 field:        dma1 number (for example 5)
-   * dma2 field:        dma2 number (for example 6)
-   * note:              dma1 and dma2 could be same in case of only one dma channel used
-   */
-int gus_memory_alloc(gus_instrument_t * instrument);
-  /*
-   * input value:       look at gus.h for more details about gus_instrument_t structure
-   * return value:      zero if instrument was successfully allocated
-   */
-int gus_memory_free(gus_instrument_t * instrument);
-  /*
-   * input value:       look at gus.h for more details about gus_instrument_t structure
-   * return value:      zero if instrument was successfully removed
-   */
-int gus_memory_size(void);
-  /*
-   * return value:  gus memory size in bytes
-   */
-int gus_memory_free_size(void);
-  /*
-   * return value:      unused gus memory in bytes
-   * warning:           reset function must be called before
-   */
-int gus_memory_free_block(int w_16bit);
-  /*
-   * return value:  current largest free block for 8-bit or 16-bit wave
-   */
-int gus_memory_pack(void);
-  /*
-   * return value:      zero if success
-   */
-int gus_memory_reset(int mode);
-  /*
-   * input value:   see to GUS_DOWNLOAD_MODE_XXXX constants (gus.h)
-   * return value:  zero if samples & instruments was successfully removed
-   *            from GF1 memory manager
-   */
-
-int gus_open(int card, size_t queue_buffer_size, int non_block);
-  /*
-   * input values:      card number,
-   *                    size of command queue buffer (512-1MB)
-   *                    buffer is allocated dynamically,
-   *                    non block mode
-   * return value:      zero if success
-   * note 1:            this function must be called as first
-   *                    open file /dev/gus
-   * note 2:            you can open more cards with one process
-   */
-int gus_queue_flush(void);
-  /*
-   * return value:      zero if command queue was successfully flushed
-   */
-int gus_queue_read_set_size(int items);
-  /*
-   * input value:       echo buffer size in items (if 0 - erase echo buffer)
-   */
-int gus_queue_write_set_size(int items);
-  /*
-   * input value:       write queue size in items (each item have 8 bytes)
-   */
-int gus_reset(int voices, unsigned int channel_voices);
-  /*
-   * input values:      active voices and channel voices (for dynamic allocation)
-   * return value:      number of active voices if reset was successfull (GF1 chip active)
-   */
-int gus_reset_engine_only(void);
-  /*
-   * return value:  same as gus_reset function
-   * note:      this command doesn't change number of active
-   *            voices and doesn't do hardware reset
-   */
-int gus_select(int card);
-  /*
-   * select specified card
-   * return value:      zero if success
-   */
-int gus_timer_start(void);
-  /*
-   * return value:      zero if successfull
-   */
-int gus_timer_stop(void);
-  /*
-   * return value:      zero if timer was stoped
-   */
-int gus_timer_continue(void);
-  /*
-   * return value:  zero if timer will be continue
-   */
-int gus_timer_tempo(int ticks);
-  /*
-   * return value:      zero if setup was success
-   */
-int gus_timer_base(int base);
-  /*
-   * return value:  zero if setup was success (default timebase = 100)
-   */
-
-void gus_convert_delta(unsigned int type, unsigned char *dest,
-                       unsigned char *src, size_t size);
-  /*
-   * note: dest and src pointers can be equal
-   */
-
-void gus_timer_callback(void (*timer_callback) ());
-  /*
-   * Set a callback to be called once per tempo tick
-   */
-
-int gus_dma_usage (int use);
-  /*
-   * Tell GUS library to use/to not use DMA for sample transfer.
-   * In some environments/on some hardware platforms you will need
-   * to disable DMA in order to function properly. You should call
-   * this function before opening the card.
-   */
-
-#endif /* __LIBGUS_H__ */
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/drv_alsa.c b/libs/mikmod/drivers/drv_alsa.c
new file mode 100644 (file)
index 0000000..d18d15f
--- /dev/null
@@ -0,0 +1,490 @@
+/*     MikMod sound library
+       (c) 1998, 1999, 2000 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 Advanced Linux Sound Architecture (ALSA)
+
+==============================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mikmod_internals.h"
+
+#ifdef DRV_ALSA
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#ifdef MIKMOD_DYNAMIC
+#include <dlfcn.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <alsa/asoundlib.h>
+#if defined(SND_LIB_VERSION) && (SND_LIB_VERSION >= 0x20000)
+#undef DRV_ALSA
+#endif
+
+#if defined(SND_LIB_VERSION) && (SND_LIB_VERSION < 0x600)
+#error ALSA Version too old. Please upgrade your Linux distribution.
+#endif
+#endif /* DRV_ALSA */
+
+#ifdef DRV_ALSA
+
+#ifdef MIKMOD_DYNAMIC
+/* runtime link with libasound */
+#ifndef HAVE_RTLD_GLOBAL
+#define RTLD_GLOBAL (0)
+#endif
+static int (*alsa_pcm_subformat_mask_malloc)(snd_pcm_subformat_mask_t **);
+static const char * (*alsa_strerror)(int);
+static int (*alsa_pcm_resume)(snd_pcm_t *);
+static int (*alsa_pcm_prepare)(snd_pcm_t *);
+static int (*alsa_pcm_hw_params_any)(snd_pcm_t *, snd_pcm_hw_params_t *);
+static int (*alsa_pcm_hw_params)(snd_pcm_t *, snd_pcm_hw_params_t *);
+static int (*alsa_pcm_hw_params_current)(snd_pcm_t *, snd_pcm_hw_params_t *);
+static int (*alsa_pcm_hw_params_set_access)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
+static int (*alsa_pcm_hw_params_set_format)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
+static int (*alsa_pcm_hw_params_set_rate_near)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
+static int (*alsa_pcm_hw_params_set_channels_near)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *);
+static int (*alsa_pcm_hw_params_set_buffer_time_near)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
+static int (*alsa_pcm_hw_params_set_period_time_near)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
+static int (*alsa_pcm_hw_params_get_buffer_size)(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
+static int (*alsa_pcm_hw_params_get_period_size)(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
+static int (*alsa_pcm_sw_params_sizeof)(void);
+static int (*alsa_pcm_hw_params_sizeof)(void);
+static int (*alsa_pcm_open)(snd_pcm_t**, const char *, int, int);
+static int (*alsa_pcm_close)(snd_pcm_t*);
+static int (*alsa_pcm_drain)(snd_pcm_t*);
+static int (*alsa_pcm_drop)(snd_pcm_t*);
+static int (*alsa_pcm_start)(snd_pcm_t *);
+static snd_pcm_sframes_t (*alsa_pcm_writei)(snd_pcm_t*,const void*,snd_pcm_uframes_t);
+
+static void* libasound = NULL;
+
+#else
+/* compile-time link with libasound */
+#define alsa_pcm_subformat_mask_malloc         snd_pcm_subformat_mask_malloc
+#define alsa_strerror                          snd_strerror
+#define alsa_pcm_hw_params_any                 snd_pcm_hw_params_any
+#define alsa_pcm_hw_params                     snd_pcm_hw_params
+#define alsa_pcm_hw_params_current             snd_pcm_hw_params_current
+#define alsa_pcm_hw_params_set_access          snd_pcm_hw_params_set_access
+#define alsa_pcm_hw_params_set_format          snd_pcm_hw_params_set_format
+#define alsa_pcm_hw_params_set_rate_near       snd_pcm_hw_params_set_rate_near
+#define alsa_pcm_hw_params_set_channels_near   snd_pcm_hw_params_set_channels_near
+#define alsa_pcm_hw_params_set_buffer_time_near        snd_pcm_hw_params_set_buffer_time_near
+#define alsa_pcm_hw_params_set_period_time_near        snd_pcm_hw_params_set_period_time_near
+#define alsa_pcm_hw_params_get_buffer_size     snd_pcm_hw_params_get_buffer_size
+#define alsa_pcm_hw_params_get_period_size     snd_pcm_hw_params_get_period_size
+#define alsa_pcm_resume                                snd_pcm_resume
+#define alsa_pcm_prepare                       snd_pcm_prepare
+#define alsa_pcm_close                         snd_pcm_close
+#define alsa_pcm_drain                         snd_pcm_drain
+#define alsa_pcm_drop                          snd_pcm_drop
+#define alsa_pcm_start                         snd_pcm_start
+#define alsa_pcm_open                          snd_pcm_open
+#define alsa_pcm_writei                                snd_pcm_writei
+#endif /* MIKMOD_DYNAMIC */
+
+#if defined(MIKMOD_DEBUG)
+# define dbgprint                      fprintf
+#elif defined (__GNUC__) && !(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
+# define dbgprint(f, fmt, args...)     do {} while (0)
+#else
+# define dbgprint(f, ...)              do {} while (0)
+#endif
+static BOOL enabled = 0;
+static snd_pcm_t *pcm_h = NULL;
+static SBYTE *audiobuffer = NULL;
+static snd_pcm_sframes_t period_size;
+static int bytes_written = 0, bytes_played = 0;
+static int global_frame_size;
+
+#ifdef MIKMOD_DYNAMIC
+static int ALSA_Link(void)
+{
+       if (libasound) return 0;
+
+       /* load libasound.so */
+       libasound = dlopen("libasound.so.2",RTLD_LAZY|RTLD_GLOBAL);
+       if (!libasound) libasound = dlopen("libasound.so",RTLD_LAZY|RTLD_GLOBAL);
+       if (!libasound) return 1;
+
+       if (!(alsa_pcm_subformat_mask_malloc = (int (*)(snd_pcm_subformat_mask_t **))
+                                                dlsym(libasound,"snd_pcm_subformat_mask_malloc"))) return 1;
+       if (!(alsa_strerror = (const char* (*)(int))
+                                                dlsym(libasound,"snd_strerror"))) return 1;
+       if (!(alsa_pcm_prepare = (int (*)(snd_pcm_t *))
+                                                dlsym(libasound,"snd_pcm_prepare"))) return 1;
+       if (!(alsa_pcm_sw_params_sizeof = (int (*)(void))
+                                                dlsym(libasound,"snd_pcm_sw_params_sizeof"))) return 1;
+       if (!(alsa_pcm_hw_params_sizeof = (int (*)(void))
+                                                dlsym(libasound,"snd_pcm_hw_params_sizeof"))) return 1;
+       if (!(alsa_pcm_resume = (int (*)(snd_pcm_t *))
+                                                dlsym(libasound,"snd_pcm_resume"))) return 1;
+       if (!(alsa_pcm_hw_params_any = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *))
+                                                dlsym(libasound,"snd_pcm_hw_params_any"))) return 1;
+       if (!(alsa_pcm_hw_params = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *))
+                                                dlsym(libasound,"snd_pcm_hw_params"))) return 1;
+       if (!(alsa_pcm_hw_params_current = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *))
+                                                dlsym(libasound,"snd_pcm_hw_params_current"))) return 1;
+       if (!(alsa_pcm_hw_params_set_access = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_access"))) return 1;
+       if (!(alsa_pcm_hw_params_set_format = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_format"))) return 1;
+       if (!(alsa_pcm_hw_params_set_rate_near = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_rate_near"))) return 1;
+       if (!(alsa_pcm_hw_params_set_channels_near = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_channels_near"))) return 1;
+       if (!(alsa_pcm_hw_params_set_buffer_time_near = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_buffer_time_near"))) return 1;
+       if (!(alsa_pcm_hw_params_set_period_time_near = (int (*)(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *))
+                                                dlsym(libasound,"snd_pcm_hw_params_set_period_time_near"))) return 1;
+       if (!(alsa_pcm_hw_params_get_buffer_size = (int (*)(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *))
+                                                dlsym(libasound,"snd_pcm_hw_params_get_buffer_size"))) return 1;
+       if (!(alsa_pcm_hw_params_get_period_size = (int (*)(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *))
+                                                dlsym(libasound,"snd_pcm_hw_params_get_period_size"))) return 1;
+       if (!(alsa_pcm_open = (int (*)(snd_pcm_t**, const char *, int, int))
+                                                dlsym(libasound,"snd_pcm_open"))) return 1;
+       if (!(alsa_pcm_close = (int (*)(snd_pcm_t*))
+                                                dlsym(libasound,"snd_pcm_close"))) return 1;
+       if (!(alsa_pcm_drain = (int (*)(snd_pcm_t*))
+                                                dlsym(libasound,"snd_pcm_drain"))) return 1;
+       if (!(alsa_pcm_drop = (int (*)(snd_pcm_t*))
+                                                dlsym(libasound,"snd_pcm_drop"))) return 1;
+       if (!(alsa_pcm_start = (int (*)(snd_pcm_t *))
+                                                dlsym(libasound,"snd_pcm_start"))) return 1;
+       if (!(alsa_pcm_writei = (snd_pcm_sframes_t (*)(snd_pcm_t*,const void*,snd_pcm_uframes_t))
+                                                dlsym(libasound,"snd_pcm_writei"))) return 1;
+
+       return 0;
+}
+
+static void ALSA_Unlink(void)
+{
+       alsa_pcm_subformat_mask_malloc = NULL;
+       alsa_strerror = NULL;
+       alsa_pcm_resume = NULL;
+       alsa_pcm_prepare = NULL;
+       alsa_pcm_hw_params_any = NULL;
+       alsa_pcm_hw_params = NULL;
+       alsa_pcm_hw_params_current = NULL;
+       alsa_pcm_hw_params_set_access = NULL;
+       alsa_pcm_hw_params_set_format = NULL;
+       alsa_pcm_hw_params_set_rate_near = NULL;
+       alsa_pcm_hw_params_set_channels_near = NULL;
+       alsa_pcm_hw_params_set_buffer_time_near = NULL;
+       alsa_pcm_hw_params_set_period_time_near = NULL;
+       alsa_pcm_hw_params_get_buffer_size = NULL;
+       alsa_pcm_hw_params_get_period_size = NULL;
+       alsa_pcm_close = NULL;
+       alsa_pcm_drain = NULL;
+       alsa_pcm_drop = NULL;
+       alsa_pcm_start = NULL;
+       alsa_pcm_open = NULL;
+       alsa_pcm_writei = NULL;
+
+       if (libasound) {
+               dlclose(libasound);
+               libasound = NULL;
+       }
+}
+
+/* This is done to override the identifiers expanded
+ * in the macros provided by the ALSA includes which are
+ * not available.
+ * */
+#define snd_strerror                   alsa_strerror
+#define snd_pcm_sw_params_sizeof       alsa_pcm_sw_params_sizeof
+#define snd_pcm_hw_params_sizeof       alsa_pcm_hw_params_sizeof
+#endif /* MIKMOD_DYNAMIC */
+
+static void ALSA_CommandLine(const CHAR *cmdline)
+{
+               /* no options */
+}
+
+static BOOL ALSA_IsThere(void)
+{
+       snd_pcm_subformat_mask_t *ptr = NULL;
+       BOOL retval;
+
+#ifdef MIKMOD_DYNAMIC
+       if (ALSA_Link()) return 0;
+#endif
+       retval = (alsa_pcm_subformat_mask_malloc(&ptr) == 0) && (ptr != NULL);
+       free(ptr);
+#ifdef MIKMOD_DYNAMIC
+       ALSA_Unlink();
+#endif
+       return retval;
+}
+
+static int ALSA_Init_internal(void)
+{
+       snd_pcm_format_t pformat;
+       unsigned int btime = 250000;    /* 250ms */
+       unsigned int ptime = 50000;     /* 50ms */
+       snd_pcm_uframes_t psize;
+       snd_pcm_uframes_t bsize;
+       unsigned int rate, channels;
+       snd_pcm_hw_params_t * hwparams;
+       int err;
+
+       /* setup playback format structure */
+       pformat = (md_mode&DMODE_FLOAT)? SND_PCM_FORMAT_FLOAT :
+                       (md_mode&DMODE_16BITS)? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8;
+       channels = (md_mode&DMODE_STEREO)?2:1;
+       rate = md_mixfreq;
+
+#define MIKMOD_ALSA_DEVICE "default"
+       if ((err = alsa_pcm_open(&pcm_h, MIKMOD_ALSA_DEVICE, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+               _mm_errno = MMERR_OPENING_AUDIO;
+               goto END;
+       }
+
+       snd_pcm_hw_params_alloca(&hwparams);
+       err = alsa_pcm_hw_params_any(pcm_h, hwparams);
+       if (err < 0) {
+               _mm_errno = MMERR_ALSA_NOCONFIG;
+               goto END;
+       }
+
+       err = alsa_pcm_hw_params_set_access(pcm_h, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+       if (!err) err = alsa_pcm_hw_params_set_format(pcm_h, hwparams, pformat);
+       if (!err) err = alsa_pcm_hw_params_set_rate_near(pcm_h, hwparams, &rate, NULL);
+       if (!err) err = alsa_pcm_hw_params_set_channels_near(pcm_h, hwparams, &channels);
+       if (!err) err = alsa_pcm_hw_params_set_buffer_time_near(pcm_h, hwparams, &btime, NULL);
+       if (!err) err = alsa_pcm_hw_params_set_period_time_near(pcm_h, hwparams, &ptime, NULL);
+       if (!err) err = alsa_pcm_hw_params(pcm_h, hwparams);
+       if (err < 0) {
+               _mm_errno = MMERR_ALSA_SETPARAMS;
+               goto END;
+       }
+
+       if (rate != md_mixfreq) {
+               _mm_errno = MMERR_ALSA_SETRATE;
+               goto END;
+       }
+       if (!(md_mode&DMODE_STEREO) && channels != 1) {
+               _mm_errno = MMERR_ALSA_SETCHANNELS;
+               goto END;
+       }
+       if ((md_mode&DMODE_STEREO) && channels != 2) {
+               _mm_errno = MMERR_ALSA_SETCHANNELS;
+               goto END;
+       }
+
+       err = alsa_pcm_hw_params_current(pcm_h, hwparams);
+       if (!err) err = alsa_pcm_hw_params_get_buffer_size(hwparams, &bsize);
+       if (!err) err = alsa_pcm_hw_params_get_period_size(hwparams, &psize, NULL);
+       if (err < 0) {
+               _mm_errno = MMERR_ALSA_BUFFERSIZE;
+               goto END;
+       }
+
+       period_size = psize;
+       global_frame_size = channels *
+                               ((md_mode&DMODE_FLOAT)? 4 : (md_mode&DMODE_16BITS)? 2 : 1);
+
+       if (!(audiobuffer=(SBYTE*)MikMod_malloc(period_size * global_frame_size))) {
+               _mm_errno = MMERR_OUT_OF_MEMORY;
+               goto END;
+       }
+
+       /* sound device is ready to work */
+       if (!VC_Init()) {
+               enabled = 1;
+               return 0;
+       }
+END:
+       alsa_pcm_close(pcm_h);
+       pcm_h = NULL;
+       return 1;
+}
+
+static int ALSA_Init(void)
+{
+#ifdef HAVE_SSE2
+/* TODO : Detect SSE2, then set  md_mode |= DMODE_SIMDMIXER;*/
+#endif
+#ifdef MIKMOD_DYNAMIC
+       if (ALSA_Link()) {
+               _mm_errno=MMERR_DYNAMIC_LINKING;
+               return 1;
+       }
+#endif
+       return ALSA_Init_internal();
+}
+
+static void ALSA_Exit_internal(void)
+{
+       enabled = 0;
+       VC_Exit();
+       if (pcm_h) {
+               alsa_pcm_drain(pcm_h);
+               alsa_pcm_close(pcm_h);
+               pcm_h = NULL;
+       }
+       MikMod_free(audiobuffer);
+       audiobuffer = NULL;
+}
+
+static void ALSA_Exit(void)
+{
+       ALSA_Exit_internal();
+#ifdef MIKMOD_DYNAMIC
+       ALSA_Unlink();
+#endif
+}
+
+/* Underrun and suspend recovery - from alsa-lib:test/pcm.c
+ */
+static int xrun_recovery(snd_pcm_t *handle, int err)
+{
+       if (err == -EPIPE) {    /* under-run */
+               err = alsa_pcm_prepare(handle);
+               if (err < 0)
+                       dbgprint(stderr, "Can't recover from underrun, prepare failed: %s\n", snd_strerror(err));
+               return 0;
+       }
+       else if (err == -ESTRPIPE) {
+               while ((err = alsa_pcm_resume(handle)) == -EAGAIN)
+                       sleep(1);       /* wait until the suspend flag is released */
+               if (err < 0) {
+                       err = alsa_pcm_prepare(handle);
+                       if (err < 0)
+                               dbgprint(stderr, "Can't recover from suspend, prepare failed: %s\n", snd_strerror(err));
+               }
+               return 0;
+       }
+       return err;
+}
+
+static void ALSA_Update(void)
+{
+       int err;
+
+       if (!enabled) return;
+
+       if (bytes_written == 0 || bytes_played == bytes_written) {
+               bytes_written = VC_WriteBytes(audiobuffer,period_size * global_frame_size);
+               bytes_played = 0;
+       }
+
+       while (bytes_played < bytes_written)
+       {
+               err = alsa_pcm_writei(pcm_h, &audiobuffer[bytes_played], (bytes_written - bytes_played) / global_frame_size);
+               if (err == -EAGAIN)
+                       continue;
+               if (err < 0) {
+                       if ((err = xrun_recovery(pcm_h, err)) < 0) {
+                               _mm_errno = MMERR_ALSA_PCM_RECOVER;
+                               enabled = 0;
+                               dbgprint(stderr, "Write error: %s\n", alsa_strerror(err));
+                       }
+                       break;
+               }
+               bytes_played += err * global_frame_size;
+       }
+}
+
+static int ALSA_PlayStart(void)
+{
+       int err;
+
+       if (pcm_h == NULL) return 1;
+       err = alsa_pcm_prepare(pcm_h);
+       if (err == 0)
+           err = alsa_pcm_start(pcm_h);
+       if (err < 0) {
+               enabled = 0;
+               _mm_errno = MMERR_ALSA_PCM_START;
+               return 1;
+       }
+
+       return VC_PlayStart();
+}
+
+static void ALSA_PlayStop(void)
+{
+       VC_PlayStop();
+       if (pcm_h) alsa_pcm_drop(pcm_h);
+}
+
+static int ALSA_Reset(void)
+{
+       ALSA_Exit_internal();
+       return ALSA_Init_internal();
+}
+
+MIKMODAPI MDRIVER drv_alsa = {
+       NULL,
+       "ALSA",
+       "Advanced Linux Sound Architecture (ALSA) driver v1.11",
+       0,255,
+       "alsa",
+       NULL,
+       ALSA_CommandLine,
+       ALSA_IsThere,
+       VC_SampleLoad,
+       VC_SampleUnload,
+       VC_SampleSpace,
+       VC_SampleLength,
+       ALSA_Init,
+       ALSA_Exit,
+       ALSA_Reset,
+       VC_SetNumVoices,
+       ALSA_PlayStart,
+       ALSA_PlayStop,
+       ALSA_Update,
+       NULL,
+       VC_VoiceSetVolume,
+       VC_VoiceGetVolume,
+       VC_VoiceSetFrequency,
+       VC_VoiceGetFrequency,
+       VC_VoiceSetPanning,
+       VC_VoiceGetPanning,
+       VC_VoicePlay,
+       VC_VoiceStop,
+       VC_VoiceStopped,
+       VC_VoiceGetPosition,
+       VC_VoiceRealVolume
+};
+
+#else
+
+MISSING(drv_alsa);
+
+#endif
+
+/* ex:set ts=8: */
diff --git a/libs/mikmod/drivers/drv_ds.c b/libs/mikmod/drivers/drv_ds.c
new file mode 100644 (file)
index 0000000..69e4540
--- /dev/null
@@ -0,0 +1,417 @@
+/*     MikMod sound library
+       (c) 1998-2005 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 output on win32 platforms using DirectSound
+
+==============================================================================*/
+
+/*
+
+       Written by Brian McKinney <Brian.McKinney@colorado.edu>
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mikmod_internals.h"
+
+#ifdef DRV_DS
+
+#include <memory.h>
+#include <string.h>
+
+#define INITGUID
+#if !defined(__cplusplus) && !defined(CINTERFACE)
+#define CINTERFACE
+#endif
+#include <dsound.h>
+
+#ifdef __WATCOMC__
+/* If you encounter build failures from Open Watcom's dsound.h,
+ * see: https://github.com/open-watcom/open-watcom-v2/pull/313
+ */
+/* Open Watcom has broken __cdecl (leading underscore) name mangling for Windows
+ * internal var names. It is fixed in Open Watcom V2 fork as of May/2014:
+ * https://github.com/open-watcom/open-watcom-v2/commit/961ef1ff756f3ec5a7248cefcae00a6ecaa97ff4
+ * Therefore, we define and use a local copy of IID_IDirectSoundNotify here.
+ */
+#include <guiddef.h>
+DEFINE_GUID(IID_IDirectSoundNotify,0xB0210783,0x89cd,0x11d0,0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16);
+#endif
+
+/* PF_XMMI64_INSTRUCTIONS_AVAILABLE not in all SDKs */
+#ifndef PF_XMMI64_INSTRUCTIONS_AVAILABLE
+#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10
+#endif
+
+/* DSBCAPS_CTRLALL is not defined anymore with DirectX 7. Of course DirectSound
+   is a coherent, backwards compatible API... */
+#ifndef DSBCAPS_CTRLALL
+#define DSBCAPS_CTRLALL ( DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLVOLUME | \
+                                                 DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | \
+                                                 DSBCAPS_CTRL3D )
+#endif
+
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+#define WAVE_FORMAT_IEEE_FLOAT 0x0003
+#endif
+
+/* size of each buffer */
+#define FRAGSIZE 16
+/* buffer count */
+#define UPDATES  2
+
+static LPDIRECTSOUND pSoundCard = NULL;
+static LPDIRECTSOUNDBUFFER pPrimarySoundBuffer = NULL, pSoundBuffer = NULL;
+static LPDIRECTSOUNDNOTIFY pSoundBufferNotify = NULL;
+
+static HANDLE notifyUpdateHandle = NULL, updateBufferHandle = NULL;
+static BOOL threadInUse = FALSE;
+static int fragsize=1<<FRAGSIZE;
+static DWORD controlflags = DSBCAPS_CTRLALL & ~DSBCAPS_GLOBALFOCUS;
+
+static DWORD WINAPI updateBufferProc(LPVOID lpParameter)
+{
+       LPVOID pBlock1 = NULL, pBlock2 = NULL;
+       DWORD soundBufferCurrentPosition, blockBytes1, blockBytes2;
+       DWORD start;
+
+       while (threadInUse) {
+               if (WaitForSingleObject(notifyUpdateHandle,INFINITE)==WAIT_OBJECT_0) {
+
+                       if (!threadInUse) break;
+
+                       IDirectSoundBuffer_GetCurrentPosition
+                                               (pSoundBuffer,&soundBufferCurrentPosition,NULL);
+
+                       if (soundBufferCurrentPosition < fragsize)
+                               start = fragsize;
+                       else
+                               start = 0;
+
+                       if (IDirectSoundBuffer_Lock
+                                               (pSoundBuffer,start,fragsize,&pBlock1,&blockBytes1,
+                                                &pBlock2,&blockBytes2,0)==DSERR_BUFFERLOST) {
+                               IDirectSoundBuffer_Restore(pSoundBuffer);
+                               IDirectSoundBuffer_Lock
+                                               (pSoundBuffer,start,fragsize,&pBlock1,&blockBytes1,
+                                                &pBlock2,&blockBytes2,0);
+                       }
+
+                       MUTEX_LOCK(vars);
+                       if (Player_Paused_internal()) {
+                               VC_SilenceBytes((SBYTE*)pBlock1,(ULONG)blockBytes1);
+                               if (pBlock2)
+                                       VC_SilenceBytes((SBYTE*)pBlock2,(ULONG)blockBytes2);
+                       } else {
+                               VC_WriteBytes((SBYTE*)pBlock1,(ULONG)blockBytes1);
+                               if (pBlock2)
+                                       VC_WriteBytes((SBYTE*)pBlock2,(ULONG)blockBytes2);
+                       }
+                       MUTEX_UNLOCK(vars);
+
+                       IDirectSoundBuffer_Unlock
+                                               (pSoundBuffer,pBlock1,blockBytes1,pBlock2,blockBytes2);
+               }
+       }
+       return 0;
+}
+
+static void DS_CommandLine(const CHAR *cmdline)
+{
+       CHAR *ptr=MD_GetAtom("buffer",cmdline,0);
+
+       if (ptr) {
+               int buf=atoi(ptr);
+
+               if ((buf<12)||(buf>19)) buf=FRAGSIZE;
+               fragsize=1<<buf;
+
+               MikMod_free(ptr);
+       }
+
+       ptr=MD_GetAtom("globalfocus",cmdline,1);
+       if (ptr) {
+               controlflags |= DSBCAPS_GLOBALFOCUS;
+               MikMod_free(ptr);
+       } else
+               controlflags &= ~DSBCAPS_GLOBALFOCUS;
+}
+
+static BOOL DS_IsPresent(void)
+{
+       if(DirectSoundCreate(NULL,&pSoundCard,NULL)!=DS_OK)
+               return 0;
+       if (pSoundCard) {
+               IDirectSound_Release(pSoundCard);
+               pSoundCard = NULL;
+       }
+       return 1;
+}
+
+static int DS_Init(void)
+{
+       DSBUFFERDESC soundBufferFormat;
+       WAVEFORMATEX pcmwf;
+       DSBPOSITIONNOTIFY positionNotifications[2];
+       DWORD updateBufferThreadID;
+       LPVOID p = NULL;
+
+       if (DirectSoundCreate(NULL,&pSoundCard,NULL)!=DS_OK) {
+               _mm_errno=MMERR_OPENING_AUDIO;
+               return 1;
+       }
+
+       if (IDirectSound_SetCooperativeLevel
+                               (pSoundCard,GetForegroundWindow(),DSSCL_PRIORITY)!=DS_OK) {
+               _mm_errno=MMERR_DS_PRIORITY;
+               return 1;
+       }
+
+       memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC));
+       soundBufferFormat.dwSize = sizeof(DSBUFFERDESC);
+       soundBufferFormat.dwFlags = DSBCAPS_PRIMARYBUFFER;
+       soundBufferFormat.dwBufferBytes = 0;
+       soundBufferFormat.lpwfxFormat = NULL;
+
+       if (IDirectSound_CreateSoundBuffer
+                               (pSoundCard,&soundBufferFormat,&pPrimarySoundBuffer,NULL)!=DS_OK) {
+               _mm_errno=MMERR_DS_BUFFER;
+               return 1;
+       }
+
+       memset(&pcmwf,0,sizeof(WAVEFORMATEX));
+       pcmwf.wFormatTag     =(md_mode&DMODE_FLOAT)? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
+       pcmwf.nChannels      =(md_mode&DMODE_STEREO)?2:1;
+       pcmwf.nSamplesPerSec =md_mixfreq;
+       pcmwf.wBitsPerSample =(md_mode&DMODE_FLOAT)?32:(md_mode&DMODE_16BITS)?16:8;
+       pcmwf.nBlockAlign    =(pcmwf.wBitsPerSample * pcmwf.nChannels) / 8;
+       pcmwf.nAvgBytesPerSec=pcmwf.nSamplesPerSec*pcmwf.nBlockAlign;
+
+       if (IDirectSoundBuffer_SetFormat(pPrimarySoundBuffer,&pcmwf)!=DS_OK) {
+               _mm_errno=MMERR_DS_FORMAT;
+               return 1;
+       }
+       IDirectSoundBuffer_Play(pPrimarySoundBuffer,0,0,DSBPLAY_LOOPING);
+
+       memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC));
+       soundBufferFormat.dwSize        =sizeof(DSBUFFERDESC);
+       soundBufferFormat.dwFlags       =controlflags|DSBCAPS_GETCURRENTPOSITION2 ;
+       soundBufferFormat.dwBufferBytes =fragsize*UPDATES;
+       soundBufferFormat.lpwfxFormat   =&pcmwf;
+
+       if (IDirectSound_CreateSoundBuffer
+                               (pSoundCard,&soundBufferFormat,&pSoundBuffer,NULL)!=DS_OK) {
+               _mm_errno=MMERR_DS_BUFFER;
+               return 1;
+       }
+
+#ifdef __cplusplus
+       IDirectSoundBuffer_QueryInterface(pSoundBuffer, IID_IDirectSoundNotify,&p);
+#else
+       IDirectSoundBuffer_QueryInterface(pSoundBuffer,&IID_IDirectSoundNotify,&p);
+#endif
+       if (!p) {
+               _mm_errno=MMERR_DS_NOTIFY;
+               return 1;
+       }
+       pSoundBufferNotify = (LPDIRECTSOUNDNOTIFY) p;
+
+       notifyUpdateHandle=CreateEvent
+                               (NULL,FALSE,FALSE,TEXT("libmikmod DirectSound Driver positionNotify Event"));
+       if (!notifyUpdateHandle) {
+               _mm_errno=MMERR_DS_EVENT;
+               return 1;
+       }
+
+       updateBufferHandle=CreateThread
+                               (NULL,0,updateBufferProc,NULL,CREATE_SUSPENDED,&updateBufferThreadID);
+       if (!updateBufferHandle) {
+               _mm_errno=MMERR_DS_THREAD;
+               return 1;
+       }
+
+       memset(positionNotifications,0,2*sizeof(DSBPOSITIONNOTIFY));
+       positionNotifications[0].dwOffset    =0;
+       positionNotifications[0].hEventNotify=notifyUpdateHandle;
+       positionNotifications[1].dwOffset    =fragsize;
+       positionNotifications[1].hEventNotify=notifyUpdateHandle;
+       if (IDirectSoundNotify_SetNotificationPositions
+                               (pSoundBufferNotify,2,positionNotifications) != DS_OK) {
+               _mm_errno=MMERR_DS_UPDATE;
+               return 1;
+       }
+
+#if defined HAVE_SSE2
+       /* this test only works on Windows XP or later */
+       if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
+               md_mode|=DMODE_SIMDMIXER;
+       }
+#endif
+       return VC_Init();
+}
+
+static void DS_Exit(void)
+{
+       DWORD statusInfo;
+
+       if(updateBufferHandle) {
+               /* Signal thread to exit and wait for the exit */
+               if (threadInUse) {
+                       threadInUse = 0;
+                       MUTEX_UNLOCK(vars);
+                       SetEvent (notifyUpdateHandle);
+                       WaitForSingleObject (updateBufferHandle, INFINITE);
+                       MUTEX_LOCK(vars);
+               }
+
+               CloseHandle(updateBufferHandle),
+               updateBufferHandle = NULL;
+       }
+       if (notifyUpdateHandle) {
+               CloseHandle(notifyUpdateHandle),
+               notifyUpdateHandle = NULL;
+       }
+
+       if (pSoundBufferNotify) {
+               IDirectSoundNotify_Release(pSoundBufferNotify);
+               pSoundBufferNotify = NULL;
+       }
+       if(pSoundBuffer) {
+               if(IDirectSoundBuffer_GetStatus(pSoundBuffer,&statusInfo)==DS_OK)
+                       if(statusInfo&DSBSTATUS_PLAYING)
+                               IDirectSoundBuffer_Stop(pSoundBuffer);
+               IDirectSoundBuffer_Release(pSoundBuffer);
+               pSoundBuffer = NULL;
+       }
+
+       if(pPrimarySoundBuffer) {
+               if(IDirectSoundBuffer_GetStatus(pPrimarySoundBuffer,&statusInfo)==DS_OK)
+                       if(statusInfo&DSBSTATUS_PLAYING)
+                               IDirectSoundBuffer_Stop(pPrimarySoundBuffer);
+               IDirectSoundBuffer_Release(pPrimarySoundBuffer);
+               pPrimarySoundBuffer = NULL;
+       }
+
+       if (pSoundCard) {
+               IDirectSound_Release(pSoundCard);
+               pSoundCard = NULL;
+       }
+
+       VC_Exit();
+}
+
+static BOOL do_update = 0;
+
+static void DS_Update(void)
+{
+       LPVOID block;
+       DWORD bBytes;
+
+       /* Do first update in DS_Update() to be consistent with other
+          non threaded drivers. */
+       if (do_update && pSoundBuffer) {
+               do_update = 0;
+
+               if (IDirectSoundBuffer_Lock(pSoundBuffer, 0, fragsize, &block, &bBytes, NULL, NULL, 0)
+                                                                                       == DSERR_BUFFERLOST) {
+                       IDirectSoundBuffer_Restore (pSoundBuffer);
+                       IDirectSoundBuffer_Lock (pSoundBuffer, 0, fragsize, &block, &bBytes, NULL, NULL, 0);
+               }
+
+               if (Player_Paused_internal()) {
+                       VC_SilenceBytes ((SBYTE *)block, (ULONG)bBytes);
+               } else {
+                       VC_WriteBytes ((SBYTE *)block, (ULONG)bBytes);
+               }
+
+               IDirectSoundBuffer_Unlock (pSoundBuffer, block, bBytes, NULL, 0);
+
+               IDirectSoundBuffer_SetCurrentPosition(pSoundBuffer, 0);
+               IDirectSoundBuffer_Play(pSoundBuffer, 0, 0, DSBPLAY_LOOPING);
+
+               threadInUse=1;
+               ResumeThread (updateBufferHandle);
+       }
+}
+
+static void DS_PlayStop(void)
+{
+       do_update = 0;
+       if (pSoundBuffer)
+               IDirectSoundBuffer_Stop(pSoundBuffer);
+       VC_PlayStop();
+}
+
+static int DS_PlayStart(void)
+{
+       do_update = 1;
+       return VC_PlayStart();
+}
+
+MIKMODAPI MDRIVER drv_ds=
+{
+       NULL,
+       "DirectSound",
+       "DirectSound Driver (DX6+) v0.6",
+       0,255,
+       "ds",
+       "buffer:r:12,19,16:Audio buffer log2 size\n"
+               "globalfocus:b:0:Play if window does not have the focus\n",
+       DS_CommandLine,
+       DS_IsPresent,
+       VC_SampleLoad,
+       VC_SampleUnload,
+       VC_SampleSpace,
+       VC_SampleLength,
+       DS_Init,
+       DS_Exit,
+       NULL,
+       VC_SetNumVoices,
+       DS_PlayStart,
+       DS_PlayStop,
+       DS_Update,
+       NULL,
+       VC_VoiceSetVolume,
+       VC_VoiceGetVolume,
+       VC_VoiceSetFrequency,
+       VC_VoiceGetFrequency,
+       VC_VoiceSetPanning,
+       VC_VoiceGetPanning,
+       VC_VoicePlay,
+       VC_VoiceStop,
+       VC_VoiceStopped,
+       VC_VoiceGetPosition,
+       VC_VoiceRealVolume
+};
+
+#else
+
+MISSING(drv_ds);
+
+#endif
+
+/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/drv_sb.c b/libs/mikmod/drivers/drv_sb.c
deleted file mode 100644 (file)
index a0c65c6..0000000
+++ /dev/null
@@ -1,235 +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 SoundBlaster/Pro/16/AWE32 under DOS
-
-==============================================================================*/
-
-/*
-
-       Written by Andrew Zabolotny <bit@eltech.ru>
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef DRV_SB
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "mikmod_internals.h"
-
-#include "dossb.h"
-
-static void SB_CommandLine(const CHAR *cmdline)
-{
-       char *ptr, *end;
-
-       if ((ptr=MD_GetAtom("port",cmdline,0)) != NULL) {
-               sb.port = strtol(ptr, &end, 16);
-               MikMod_free(ptr);
-       }
-       if ((ptr=MD_GetAtom("irq",cmdline,0)) != NULL) {
-               sb.irq = strtol(ptr, &end, 10);
-               MikMod_free(ptr);
-       }
-       if ((ptr=MD_GetAtom("dma",cmdline,0)) != NULL) {
-               sb.dma8 = strtol(ptr, &end, 10);
-               MikMod_free(ptr);
-       }
-       if ((ptr=MD_GetAtom("hidma",cmdline,0)) != NULL) {
-               sb.dma16 = strtol(ptr, &end, 10);
-               MikMod_free(ptr);
-       }
-}
-
-static BOOL SB_IsThere(void)
-{
-       return sb_detect();
-}
-
-static int SB_Init(void)
-{
-       if (!sb_open()) {
-               _mm_errno = MMERR_INVALID_DEVICE;
-               return 1;
-       }
-
-       /* Adjust md_mode according to sound card capabilities */
-       if (!(sb.caps & SBMODE_STEREO))
-               md_mode &= ~DMODE_STEREO;
-       if (!(sb.caps & SBMODE_16BITS))
-               md_mode &= ~DMODE_16BITS;
-
-       if (md_mixfreq < 4000)
-               md_mixfreq = 4000;
-       if (md_mode & DMODE_STEREO) {
-               if (md_mixfreq > sb.maxfreq_stereo)
-                       md_mixfreq = sb.maxfreq_stereo;
-       } else {
-               if (md_mixfreq > sb.maxfreq_mono)
-                       md_mixfreq = sb.maxfreq_mono;
-       }
-
-       return VC_Init();
-}
-
-static void SB_Exit(void)
-{
-       VC_Exit();
-       sb_close();
-}
-
-/* The last buffer byte filled with sound */
-static unsigned int buff_tail = 0;
-
-static void SB_Callback(void)
-{
-       unsigned int dma_size, dma_pos;
-       ULONG (*mixer)(SBYTE *buf, ULONG todo);
-
-       sb_query_dma(&dma_size, &dma_pos);
-       /* There isn't much sense in filling less than 256 bytes */
-       dma_pos &= ~255;
-
-       /* If nothing to mix, quit */
-       if (buff_tail == dma_pos)
-               return;
-
-       if (Player_Paused_internal())
-               mixer = VC_SilenceBytes;
-       else
-               mixer = VC_WriteBytes;
-
-       /* If DMA pointer still didn't wrapped around ... */
-       if (dma_pos > buff_tail) {
-               buff_tail += mixer ((SBYTE *)(sb.dma_buff->linear + buff_tail), dma_pos - buff_tail);
-               /* If we arrived right to the DMA buffer end, jump to the beginning */
-               if (buff_tail >= dma_size)
-                       buff_tail = 0;
-       } else {
-               /* If wrapped around, fill first to the end of buffer */
-               mixer ((SBYTE *)(sb.dma_buff->linear + buff_tail), dma_size - buff_tail);
-               /* Now fill from buffer beginning to current DMA pointer */
-               buff_tail = mixer ((SBYTE *)sb.dma_buff->linear, dma_pos);
-       }
-}
-
-static void SB_Update(void)
-{
-       /* Do nothing: the real update is done during SB interrupts */
-}
-
-static int SB_PlayStart (void)
-{
-       if (VC_PlayStart())
-               return 1;
-
-       /* Enable speaker output */
-       sb_output(TRUE);
-
-       /* Set our routine to be called during SB IRQs */
-       buff_tail = 0;
-       sb.timer_callback = SB_Callback;
-
-       /* Start cyclic DMA transfer */
-       if (!sb_start_dma(((md_mode & DMODE_16BITS) ? SBMODE_16BITS | SBMODE_SIGNED : 0) |
-               ((md_mode & DMODE_STEREO) ? SBMODE_STEREO : 0), md_mixfreq))
-       {
-               _mm_errno = MMERR_DOSSB_STARTDMA;
-               return 1;
-       }
-
-       return 0;
-}
-
-static int SB_Reset(void)
-{
-       sb_reset();
-       VC_Exit();
-       return VC_Init();
-}
-
-static void SB_PlayStop(void)
-{
-       sb.timer_callback = NULL;
-       sb_output(FALSE);
-       sb_stop_dma();
-       VC_PlayStop();
-}
-
-MDRIVER drv_sb =
-{
-       NULL,
-       "Sound Blaster",
-       "Sound Blaster Orig/2.0/Pro/16 v1.0",
-       0, 255,
-       "sb",
-       "port:c:220,230,240,250,260,270,280,32C,530,604,E80,F40,220:Sound Blaster base I/O port\n"
-       "irq:c:2,3,5,7,10,5:Sound Blaster IRQ\n"
-       "dma:c:0,1,3,1:Sound Blaster 8 bit DMA channel\n"
-       "hidma:c:5,6,7,5:Sound Blaster 16 bit DMA channel (SB16/AWE32 only)\n",
-
-       SB_CommandLine,
-       SB_IsThere,
-       VC_SampleLoad,
-       VC_SampleUnload,
-       VC_SampleSpace,
-       VC_SampleLength,
-       SB_Init,
-       SB_Exit,
-       SB_Reset,
-       VC_SetNumVoices,
-       SB_PlayStart,
-       SB_PlayStop,
-       SB_Update,
-       NULL,
-       VC_VoiceSetVolume,
-       VC_VoiceGetVolume,
-       VC_VoiceSetFrequency,
-       VC_VoiceGetFrequency,
-       VC_VoiceSetPanning,
-       VC_VoiceGetPanning,
-       VC_VoicePlay,
-       VC_VoiceStop,
-       VC_VoiceStopped,
-       VC_VoiceGetPosition,
-       VC_VoiceRealVolume
-};
-
-#else /* DRV_SB */
-
-#include "mikmod_internals.h"
-MISSING(drv_sb);
-
-#endif
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/drv_sgi.c b/libs/mikmod/drivers/drv_sgi.c
new file mode 100644 (file)
index 0000000..4ad1c36
--- /dev/null
@@ -0,0 +1,229 @@
+/*     MikMod sound library
+       (c) 1998, 1999, 2000 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 output on SGI audio system (needs libaudio from the dmedia
+  package).
+
+==============================================================================*/
+
+/*
+
+       Written by Stephan Kanthak <kanthak@i6.informatik.rwth-aachen.de>
+
+       Fragment configuration:
+       =======================
+
+       You can use the driver options fragsize and bufsize to override the
+       default size of the audio buffer. If you experience crackles & pops,
+       try experimenting with these values.
+
+       Please read the SGI section of libmikmod's README file first before
+       contacting the author because there are some things to know about the
+       specials of the SGI audio driver.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mikmod_internals.h"
+
+#ifdef DRV_SGI
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <dmedia/audio.h>
+
+#define DEFAULT_SGI_BUFSIZE   40000
+#define DEFAULT_SGI_FRAGSIZE  (DEFAULT_SGI_BUFSIZE / 2)
+
+static ALconfig sgi_config;
+static ALport sgi_port;
+static int sample_factor;
+static int sgi_fragsize=DEFAULT_SGI_FRAGSIZE;
+static int sgi_bufsize=DEFAULT_SGI_BUFSIZE;
+static SBYTE *audiobuffer=NULL;
+
+static void SGI_CommandLine(const CHAR *cmdline)
+{
+       CHAR *ptr;
+
+       if ((ptr=MD_GetAtom("fragsize",cmdline,0)) != NULL) {
+               sgi_fragsize=atol(ptr);
+               MikMod_free(ptr);
+       } else sgi_fragsize=DEFAULT_SGI_FRAGSIZE;
+
+       if ((ptr=MD_GetAtom("bufsize",cmdline,0)) != NULL) {
+               sgi_bufsize=atol(ptr);
+               MikMod_free(ptr);
+       } else sgi_bufsize=DEFAULT_SGI_BUFSIZE;
+}
+
+static BOOL SGI_IsThere(void)
+{
+       ALseterrorhandler(0);
+       return(ALqueryparams(AL_DEFAULT_DEVICE,0,0))?1:0;
+}
+
+static int SGI_Init(void)
+{
+       long chpars[] = { AL_OUTPUT_RATE, AL_RATE_22050 };
+
+       switch(md_mixfreq) {
+               case 8000:
+                       chpars[1] = AL_RATE_8000;
+                       break;
+               case 11025:
+                       chpars[1] = AL_RATE_11025;
+                       break;
+               case 16000:
+                       chpars[1] = AL_RATE_16000;
+                       break;
+               case 22050:
+                       chpars[1] = AL_RATE_22050;
+                       break;
+               case 32000:
+                       chpars[1] = AL_RATE_32000;
+                       break;
+               case 44100:
+                       chpars[1] = AL_RATE_44100;
+                       break;
+               case 48000:
+                       chpars[1] = AL_RATE_48000;
+                       break;
+               default:
+                       _mm_errno=MMERR_SGI_SPEED;
+                       return 1;
+       }
+       ALseterrorhandler(0);
+       ALsetparams(AL_DEFAULT_DEVICE, chpars, 2);
+
+       if (!(sgi_config=ALnewconfig())) {
+               _mm_errno=MMERR_OPENING_AUDIO;
+               return 1;
+       }
+
+       if (md_mode&DMODE_16BITS) {
+               if (ALsetwidth(sgi_config,AL_SAMPLE_16)<0) {
+                       _mm_errno=MMERR_SGI_16BIT;
+                       return 1;
+               }
+               sample_factor = 1;
+       } else {
+               if (ALsetwidth(sgi_config,AL_SAMPLE_8)<0) {
+                       _mm_errno=MMERR_SGI_8BIT;
+                       return 1;
+               }
+               sample_factor = 0;
+       }
+
+       if (md_mode&DMODE_STEREO) {
+               if (ALsetchannels(sgi_config,AL_STEREO)<0) {
+                       _mm_errno=MMERR_SGI_STEREO;
+                       return 1;
+               }
+       } else {
+               if (ALsetchannels(sgi_config,AL_MONO)<0) {
+                       _mm_errno=MMERR_SGI_MONO;
+                       return 1;
+               }
+       }
+
+       if ((getenv("MM_SGI_FRAGSIZE"))&&(sgi_fragsize!=DEFAULT_SGI_FRAGSIZE))
+               sgi_fragsize=atol(getenv("MM_SGI_FRAGSIZE"));
+       if (!sgi_fragsize) sgi_fragsize=DEFAULT_SGI_FRAGSIZE;
+       if ((getenv("MM_SGI_BUFSIZE"))&&(sgi_bufsize!=DEFAULT_SGI_BUFSIZE))
+               sgi_bufsize=atol(getenv("MM_SGI_BUFSIZE"));
+       if (!sgi_bufsize) sgi_fragsize=DEFAULT_SGI_BUFSIZE;
+
+       ALsetqueuesize(sgi_config, sgi_bufsize);
+       if (!(sgi_port=ALopenport("libmikmod","w",sgi_config))) {
+               _mm_errno=MMERR_OPENING_AUDIO;
+               return 1;
+       }
+
+       if(!(audiobuffer=(SBYTE*)MikMod_malloc(sgi_fragsize))) return 1;
+
+       return VC_Init();
+}
+
+static void SGI_Exit(void)
+{
+       VC_Exit();
+       MikMod_free(audiobuffer);
+       audiobuffer=NULL;
+}
+
+static void SGI_Update(void)
+{
+       ALwritesamps(sgi_port,audiobuffer,
+                    VC_WriteBytes(audiobuffer,sgi_fragsize)>>sample_factor);
+}
+
+MIKMODAPI MDRIVER drv_sgi={
+       NULL,
+       "SGI Audio System",
+       "SGI Audio System driver v0.5",
+       0,255,
+       "sgi",
+       "fragsize:r:0,99999,20000:Sound buffer fragment size\n"
+        "bufsize:r:0,199999,40000:Sound buffer total size\n",
+       SGI_CommandLine,
+       SGI_IsThere,
+       VC_SampleLoad,
+       VC_SampleUnload,
+       VC_SampleSpace,
+       VC_SampleLength,
+       SGI_Init,
+       SGI_Exit,
+       NULL,
+       VC_SetNumVoices,
+       VC_PlayStart,
+       VC_PlayStop,
+       SGI_Update,
+       NULL,
+       VC_VoiceSetVolume,
+       VC_VoiceGetVolume,
+       VC_VoiceSetFrequency,
+       VC_VoiceGetFrequency,
+       VC_VoiceSetPanning,
+       VC_VoiceGetPanning,
+       VC_VoicePlay,
+       VC_VoiceStop,
+       VC_VoiceStopped,
+       VC_VoiceGetPosition,
+       VC_VoiceRealVolume
+};
+
+#else
+
+MISSING(drv_sgi);
+
+#endif
+
+/* ex:set ts=4: */
diff --git a/libs/mikmod/drivers/drv_ultra.c b/libs/mikmod/drivers/drv_ultra.c
deleted file mode 100644 (file)
index dbd0b7c..0000000
+++ /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 <andy@alsa-project.org>
-
-       Updated to work with later versions of both the ultrasound driver and
-       libmikmod by C. Ray C. <crayc@pyro.net>
-
-       Major fixes by Andrew Zabolotny <bit@eltech.ru>
-       + 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 <unistd.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#ifdef MIKMOD_DYNAMIC
-#include <dlfcn.h>
-#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libgus.h>
-
-#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 <time.h>
-#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: */
diff --git a/libs/mikmod/drivers/drv_wss.c b/libs/mikmod/drivers/drv_wss.c
deleted file mode 100644 (file)
index a89d5ec..0000000
+++ /dev/null
@@ -1,217 +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 Windows Sound System under DOS
-
-==============================================================================*/
-
-/*
-
-       Written by Andrew Zabolotny <bit@eltech.ru>
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef DRV_WSS
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "mikmod_internals.h"
-
-#include "doswss.h"
-
-static void WSS_CommandLine(const CHAR *cmdline)
-{
-       char *ptr, *end;
-
-       if ((ptr=MD_GetAtom("port",cmdline,0)) != NULL) {
-               wss.port = strtol(ptr, &end, 16);
-               MikMod_free(ptr);
-       }
-       if ((ptr=MD_GetAtom("irq",cmdline,0)) != NULL) {
-               wss.irq = strtol(ptr, &end, 10);
-               MikMod_free(ptr);
-       }
-       if ((ptr=MD_GetAtom("dma",cmdline,0)) != NULL) {
-               wss.dma = strtol(ptr, &end, 10);
-               MikMod_free(ptr);
-       }
-}
-
-static BOOL WSS_IsThere(void)
-{
-       return wss_detect();
-}
-
-static int WSS_Init(void)
-{
-       if (!wss_open()) {
-               _mm_errno = MMERR_INVALID_DEVICE;
-               return 1;
-       }
-
-       /* Adjust mixing frequency according to card capabilities */
-       md_mixfreq = wss_adjust_freq(md_mixfreq);
-
-       return VC_Init();
-}
-
-static void WSS_Exit(void)
-{
-       VC_Exit();
-       wss_close();
-}
-
-/* The last buffer byte filled with sound */
-static unsigned int buff_tail = 0;
-
-static void WSS_Callback(void)
-{
-       unsigned int dma_size, dma_pos;
-       ULONG (*mixer)(SBYTE *buf, ULONG todo);
-
-       wss_query_dma(&dma_size, &dma_pos);
-       /* There isn't much sense in filling less than 256 bytes */
-       dma_pos &= ~255;
-
-       /* If nothing to mix, quit */
-       if (buff_tail == dma_pos)
-               return;
-
-       if (Player_Paused_internal())
-               mixer = VC_SilenceBytes;
-       else
-               mixer = VC_WriteBytes;
-
-       /* If DMA pointer still didn't wrapped around ... */
-       if (dma_pos > buff_tail) {
-               buff_tail += mixer ((SBYTE *)(wss.dma_buff->linear + buff_tail), dma_pos - buff_tail);
-               /* If we arrived right to the DMA buffer end, jump to the beginning */
-               if (buff_tail >= dma_size)
-                       buff_tail = 0;
-       } else {
-               /* If wrapped around, fill first to the end of buffer */
-               mixer ((SBYTE *)(wss.dma_buff->linear + buff_tail), dma_size - buff_tail);
-               /* Now fill from buffer beginning to current DMA pointer */
-               buff_tail = mixer ((SBYTE *)wss.dma_buff->linear, dma_pos);
-       }
-}
-
-static void WSS_Update(void)
-{
-       /* Do nothing: the real update is done during SB interrupts */
-}
-
-static int WSS_PlayStart(void)
-{
-       if (VC_PlayStart())
-               return 1;
-
-       /* Set our routine to be called during WSS IRQs */
-       buff_tail = 0;
-       wss.timer_callback = WSS_Callback;
-
-       /* Start cyclic DMA transfer */
-       if (!wss_start_dma(((md_mode & DMODE_16BITS) ? WSSMODE_16BITS | WSSMODE_SIGNED : 0) |
-               ((md_mode & DMODE_STEREO) ? WSSMODE_STEREO : 0), md_mixfreq))
-       {
-               _mm_errno = MMERR_DOSWSS_STARTDMA;
-               return 1;
-       }
-
-       /* Enable speaker output */
-       wss_output(TRUE);
-
-       return 0;
-}
-
-static int WSS_Reset(void)
-{
-       wss_reset();
-       VC_Exit();
-       return VC_Init();
-}
-
-static void WSS_PlayStop(void)
-{
-       wss.timer_callback = NULL;
-       wss_output(FALSE);
-       wss_stop_dma();
-       VC_PlayStop();
-}
-
-MDRIVER drv_wss =
-{
-       NULL,
-       "Windows Sound System",
-       "Windows Sound System (CS423*,ESS*) v1.0",
-       0, 255,
-       "wss",
-       "port:c:32C,530,604,E80,F40,530:Windows Sound System base I/O port\n"
-       "irq:c:2,3,5,7,10,5:Windows Sound System IRQ\n"
-       "dma:c:0,1,3,0:Windows Sound System DMA channel\n",
-
-       WSS_CommandLine,
-       WSS_IsThere,
-       VC_SampleLoad,
-       VC_SampleUnload,
-       VC_SampleSpace,
-       VC_SampleLength,
-       WSS_Init,
-       WSS_Exit,
-       WSS_Reset,
-       VC_SetNumVoices,
-       WSS_PlayStart,
-       WSS_PlayStop,
-       WSS_Update,
-       NULL,
-       VC_VoiceSetVolume,
-       VC_VoiceGetVolume,
-       VC_VoiceSetFrequency,
-       VC_VoiceGetFrequency,
-       VC_VoiceSetPanning,
-       VC_VoiceGetPanning,
-       VC_VoicePlay,
-       VC_VoiceStop,
-       VC_VoiceStopped,
-       VC_VoiceGetPosition,
-       VC_VoiceRealVolume
-};
-
-#else /* ifdef DRV_WSS */
-
-#include "mikmod_internals.h"
-MISSING(drv_wss);
-
-#endif
-
-/* ex:set ts=4: */
diff --git a/libs/mikmod/posix/strcasecmp.c b/libs/mikmod/posix/strcasecmp.c
deleted file mode 100644 (file)
index 5b9935f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mikmod_internals.h"
-#include "mikmod_ctype.h"
-
-int _mm_strcasecmp(const char *__s1, const char *__s2)
-{
-       const char *p1 = __s1;
-       const char *p2 = __s2;
-       char c1, c2;
-
-       if (p1 == p2) return 0;
-
-       do {
-               c1 = mik_tolower(*p1++);
-               c2 = mik_tolower(*p2++);
-               if (c1 == '\0') break;
-       } while (c1 == c2);
-
-       return (int)(c1 - c2);
-}
diff --git a/libs/mikmod/posix/strccmp.c b/libs/mikmod/posix/strccmp.c
new file mode 100644 (file)
index 0000000..5b9935f
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mikmod_internals.h"
+#include "mikmod_ctype.h"
+
+int _mm_strcasecmp(const char *__s1, const char *__s2)
+{
+       const char *p1 = __s1;
+       const char *p2 = __s2;
+       char c1, c2;
+
+       if (p1 == p2) return 0;
+
+       do {
+               c1 = mik_tolower(*p1++);
+               c2 = mik_tolower(*p2++);
+               if (c1 == '\0') break;
+       } while (c1 == c2);
+
+       return (int)(c1 - c2);
+}
index 170e47f..2197858 100644 (file)
@@ -58,6 +58,10 @@ int parse_args(int argc, char **argv)
                                opt.fullscreen = 1;
                        } else if(strcmp(argv[i], "-win") == 0) {
                                opt.fullscreen = 0;
+                       } else if(strcmp(argv[i], "-scaler-nearest") == 0) {
+                               opt.scaler = SCALER_NEAREST;
+                       } else if(strcmp(argv[i], "-scaler-linear") == 0) {
+                               opt.scaler = SCALER_LINEAR;
 #endif
                        } else {
                                fprintf(stderr, "invalid option: %s\n", argv[i]);
@@ -152,6 +156,12 @@ int load_config(const char *fname)
 #ifndef MSDOS
                } else if(strcmp(line, "fullscreen") == 0) {
                        opt.fullscreen = bool_value(value);
+               } else if(strcmp(line, "scaler") == 0) {
+                       if(strcmp(value, "linear") == 0) {
+                               opt.scaler = SCALER_LINEAR;
+                       } else {
+                               opt.scaler = SCALER_NEAREST;
+                       }
 #endif
                } else {
                        fprintf(stderr, "%s:%d invalid option: %s\n", fname, nline, line);
index 9fc8c36..2bbaffb 100644 (file)
@@ -1,6 +1,15 @@
 #ifndef CFGOPT_H_
 #define CFGOPT_H_
 
+#ifndef MSDOS
+enum {
+       SCALER_NEAREST,
+       SCALER_LINEAR,
+
+       NUM_SCALERS
+};
+#endif
+
 struct options {
        const char *start_scr;
        int music;
@@ -9,6 +18,7 @@ struct options {
        int dbginfo;
 #ifndef MSDOS
        int fullscreen;
+       int scaler;
 #endif
 };
 
index 2060630..de0654b 100644 (file)
@@ -8,6 +8,7 @@
 /*extern int fb_width, fb_height, fb_bpp;*/
 #define FB_WIDTH       320
 #define FB_HEIGHT      240
+#define FB_ASPECT      ((float)FB_WIDTH / (float)FB_HEIGHT)
 #define FB_BPP         16
 extern uint16_t *fb_pixels;
 extern uint16_t *vmem;