FXJ - Updated the mikmod support to MikMod 3.1.8
authorSam Lantinga
Mon, 27 Dec 1999 19:24:50 +0000
changeset 2944b09d6e1170
parent 28 2279b6c0eced
child 30 d2e9f163f78f
FXJ - Updated the mikmod support to MikMod 3.1.8
FXJ - Added Mix_HookMusicFinished() API function
CHANGES
Makefile.am
Makefile.in
README
aclocal.m4
configure
configure.in
mikmod/Makefile.am
mikmod/Makefile.in
mikmod/README
mikmod/drv_nos.c
mikmod/drv_sdl.c
mikmod/load_it.c
mikmod/load_mod.c
mikmod/load_s3m.c
mikmod/load_xm.c
mikmod/mdreg.c
mikmod/mdriver.c
mikmod/mikmod.h
mikmod/mloader.c
mikmod/mlreg.c
mikmod/mmalloc.c
mikmod/mmerror.c
mikmod/mmio.c
mikmod/mplayer.c
mikmod/munitrk.c
mikmod/npertab.c
mikmod/sloader.c
mikmod/virtch.c
mixer.c
mixer.h
music.c
timidity/Makefile.in
wavestream.c
     1.1 --- a/CHANGES	Mon Dec 27 19:18:10 1999 +0000
     1.2 +++ b/CHANGES	Mon Dec 27 19:24:50 1999 +0000
     1.3 @@ -1,3 +1,7 @@
     1.4 +
     1.5 +1.0.2:
     1.6 +FXJ -	Updated the mikmod support to MikMod 3.1.8
     1.7 +FXJ -	Added Mix_HookMusicFinished() API function
     1.8  
     1.9  1.0.1:
    1.10  SOL -	Added a post-mixing callback
    1.11 @@ -14,4 +18,4 @@
    1.12  Initial Key:
    1.13  SOL - Sam Lantinga (hercules@lokigames.com)
    1.14  SP  - Stephane Peter (megastep@lokigames.com)
    1.15 -
    1.16 +FXJ - Markus Oberhumer (markus.oberhumer@jk.uni-linz.ac.at)
     2.1 --- a/Makefile.am	Mon Dec 27 19:18:10 1999 +0000
     2.2 +++ b/Makefile.am	Mon Dec 27 19:24:50 1999 +0000
     2.3 @@ -1,15 +1,15 @@
     2.4  # Makefile.am for the SDL sample mixer library and players
     2.5  
     2.6 -lib_LTLIBRARIES = libmixer.la
     2.7 +lib_LTLIBRARIES = libSDLmixer.la
     2.8  
     2.9  SUBDIRS = @MUSIC_SUBDIRS@
    2.10  DIST_SUBIDRS = mikmod timidity
    2.11  
    2.12 -libmixerincludedir = $(includedir)
    2.13 -libmixerinclude_HEADERS =	\
    2.14 +libSDLmixerincludedir = $(includedir)
    2.15 +libSDLmixerinclude_HEADERS =	\
    2.16  	mixer.h
    2.17  
    2.18 -libmixer_la_SOURCES =		\
    2.19 +libSDLmixer_la_SOURCES =	\
    2.20  	mixer.c			\
    2.21  	music.c			\
    2.22  	music_cmd.c		\
    2.23 @@ -29,12 +29,12 @@
    2.24  TIMIDITY_LIB =
    2.25  endif
    2.26  
    2.27 -libmixer_la_LDFLAGS = 		\
    2.28 +libSDLmixer_la_LDFLAGS = 		\
    2.29          -release $(LT_RELEASE)	\
    2.30  	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
    2.31 -libmixer_la_LIBADD = $(MIKMOD_LIB) $(TIMIDITY_LIB)
    2.32 +libSDLmixer_la_LIBADD = $(MIKMOD_LIB) $(TIMIDITY_LIB)
    2.33  
    2.34  bin_PROGRAMS = playwave playmus
    2.35  
    2.36 -playwave_LDADD = libmixer.la
    2.37 -playmus_LDADD = libmixer.la
    2.38 +playwave_LDADD = libSDLmixer.la
    2.39 +playmus_LDADD = libSDLmixer.la
     3.1 --- a/Makefile.in	Mon Dec 27 19:18:10 1999 +0000
     3.2 +++ b/Makefile.in	Mon Dec 27 19:24:50 1999 +0000
     3.3 @@ -1,4 +1,4 @@
     3.4 -# Makefile.in generated automatically by automake 1.4 from Makefile.am
     3.5 +# Makefile.in generated automatically by automake 1.4a from Makefile.am
     3.6  
     3.7  # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
     3.8  # This Makefile.in is free software; the Free Software Foundation
     3.9 @@ -48,9 +48,10 @@
    3.10  AUTOHEADER = @AUTOHEADER@
    3.11  
    3.12  INSTALL = @INSTALL@
    3.13 -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
    3.14 +INSTALL_PROGRAM = @INSTALL_PROGRAM@
    3.15  INSTALL_DATA = @INSTALL_DATA@
    3.16  INSTALL_SCRIPT = @INSTALL_SCRIPT@
    3.17 +INSTALL_STRIP_FLAG =
    3.18  transform = @program_transform_name@
    3.19  
    3.20  NORMAL_INSTALL = :
    3.21 @@ -87,30 +88,30 @@
    3.22  SDL_LIBS = @SDL_LIBS@
    3.23  VERSION = @VERSION@
    3.24  
    3.25 -lib_LTLIBRARIES = libmixer.la
    3.26 +lib_LTLIBRARIES = libSDLmixer.la
    3.27  
    3.28  SUBDIRS = @MUSIC_SUBDIRS@
    3.29  DIST_SUBIDRS = mikmod timidity
    3.30  
    3.31 -libmixerincludedir = $(includedir)
    3.32 -libmixerinclude_HEADERS =  	mixer.h
    3.33 +libSDLmixerincludedir = $(includedir)
    3.34 +libSDLmixerinclude_HEADERS =  	mixer.h
    3.35  
    3.36  
    3.37 -libmixer_la_SOURCES =  	mixer.c				music.c				music_cmd.c			music_cmd.h			wave.h				wavestream.c			wavestream.h
    3.38 +libSDLmixer_la_SOURCES =  	mixer.c				music.c				music_cmd.c			music_cmd.h			wave.h				wavestream.c			wavestream.h
    3.39  
    3.40  @USE_MIKMOD_TRUE@MIKMOD_LIB = mikmod/libmikmod.la
    3.41  @USE_MIKMOD_FALSE@MIKMOD_LIB = 
    3.42  @USE_TIMIDITY_TRUE@TIMIDITY_LIB = timidity/libtimidity.la
    3.43  @USE_TIMIDITY_FALSE@TIMIDITY_LIB = 
    3.44  
    3.45 -libmixer_la_LDFLAGS =          -release $(LT_RELEASE)		-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
    3.46 +libSDLmixer_la_LDFLAGS =          -release $(LT_RELEASE)		-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
    3.47  
    3.48 -libmixer_la_LIBADD = $(MIKMOD_LIB) $(TIMIDITY_LIB)
    3.49 +libSDLmixer_la_LIBADD = $(MIKMOD_LIB) $(TIMIDITY_LIB)
    3.50  
    3.51  bin_PROGRAMS = playwave playmus
    3.52  
    3.53 -playwave_LDADD = libmixer.la
    3.54 -playmus_LDADD = libmixer.la
    3.55 +playwave_LDADD = libSDLmixer.la
    3.56 +playmus_LDADD = libSDLmixer.la
    3.57  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    3.58  mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
    3.59  CONFIG_CLEAN_FILES = 
    3.60 @@ -121,31 +122,31 @@
    3.61  CPPFLAGS = @CPPFLAGS@
    3.62  LDFLAGS = @LDFLAGS@
    3.63  LIBS = @LIBS@
    3.64 -@USE_TIMIDITY_FALSE@@USE_MIKMOD_FALSE@libmixer_la_DEPENDENCIES = 
    3.65 -@USE_TIMIDITY_TRUE@@USE_MIKMOD_TRUE@libmixer_la_DEPENDENCIES =  \
    3.66 +@USE_TIMIDITY_FALSE@@USE_MIKMOD_FALSE@libSDLmixer_la_DEPENDENCIES = 
    3.67 +@USE_TIMIDITY_TRUE@@USE_MIKMOD_TRUE@libSDLmixer_la_DEPENDENCIES =  \
    3.68  @USE_TIMIDITY_TRUE@@USE_MIKMOD_TRUE@mikmod/libmikmod.la \
    3.69  @USE_TIMIDITY_TRUE@@USE_MIKMOD_TRUE@timidity/libtimidity.la
    3.70 -@USE_TIMIDITY_TRUE@@USE_MIKMOD_FALSE@libmixer_la_DEPENDENCIES =  \
    3.71 +@USE_TIMIDITY_TRUE@@USE_MIKMOD_FALSE@libSDLmixer_la_DEPENDENCIES =  \
    3.72  @USE_TIMIDITY_TRUE@@USE_MIKMOD_FALSE@timidity/libtimidity.la
    3.73 -@USE_TIMIDITY_FALSE@@USE_MIKMOD_TRUE@libmixer_la_DEPENDENCIES =  \
    3.74 +@USE_TIMIDITY_FALSE@@USE_MIKMOD_TRUE@libSDLmixer_la_DEPENDENCIES =  \
    3.75  @USE_TIMIDITY_FALSE@@USE_MIKMOD_TRUE@mikmod/libmikmod.la
    3.76 -libmixer_la_OBJECTS =  mixer.lo music.lo music_cmd.lo wavestream.lo
    3.77 +libSDLmixer_la_OBJECTS =  mixer.lo music.lo music_cmd.lo wavestream.lo
    3.78  PROGRAMS =  $(bin_PROGRAMS)
    3.79  
    3.80  playwave_SOURCES = playwave.c
    3.81  playwave_OBJECTS =  playwave.o
    3.82 -playwave_DEPENDENCIES =  libmixer.la
    3.83 +playwave_DEPENDENCIES =  libSDLmixer.la
    3.84  playwave_LDFLAGS = 
    3.85  playmus_SOURCES = playmus.c
    3.86  playmus_OBJECTS =  playmus.o
    3.87 -playmus_DEPENDENCIES =  libmixer.la
    3.88 +playmus_DEPENDENCIES =  libSDLmixer.la
    3.89  playmus_LDFLAGS = 
    3.90  CFLAGS = @CFLAGS@
    3.91  COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    3.92  LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    3.93  CCLD = $(CC)
    3.94  LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
    3.95 -HEADERS =  $(libmixerinclude_HEADERS)
    3.96 +HEADERS =  $(libSDLmixerinclude_HEADERS)
    3.97  
    3.98  DIST_COMMON =  README COPYING Makefile.am Makefile.in acinclude.m4 \
    3.99  aclocal.m4 config.guess config.sub configure configure.in install-sh \
   3.100 @@ -158,8 +159,8 @@
   3.101  GZIP_ENV = --best
   3.102  DEP_FILES =  .deps/mixer.P .deps/music.P .deps/music_cmd.P \
   3.103  .deps/playmus.P .deps/playwave.P .deps/wavestream.P
   3.104 -SOURCES = $(libmixer_la_SOURCES) playwave.c playmus.c
   3.105 -OBJECTS = $(libmixer_la_OBJECTS) playwave.o playmus.o
   3.106 +SOURCES = $(libSDLmixer_la_SOURCES) playwave.c playmus.c
   3.107 +OBJECTS = $(libSDLmixer_la_OBJECTS) playwave.o playmus.o
   3.108  
   3.109  all: all-redirect
   3.110  .SUFFIXES:
   3.111 @@ -236,8 +237,8 @@
   3.112  
   3.113  maintainer-clean-libtool:
   3.114  
   3.115 -libmixer.la: $(libmixer_la_OBJECTS) $(libmixer_la_DEPENDENCIES)
   3.116 -	$(LINK) -rpath $(libdir) $(libmixer_la_LDFLAGS) $(libmixer_la_OBJECTS) $(libmixer_la_LIBADD) $(LIBS)
   3.117 +libSDLmixer.la: $(libSDLmixer_la_OBJECTS) $(libSDLmixer_la_DEPENDENCIES)
   3.118 +	$(LINK) -rpath $(libdir) $(libSDLmixer_la_LDFLAGS) $(libSDLmixer_la_OBJECTS) $(libSDLmixer_la_LIBADD) $(LIBS)
   3.119  
   3.120  mostlyclean-binPROGRAMS:
   3.121  
   3.122 @@ -253,8 +254,8 @@
   3.123  	$(mkinstalldirs) $(DESTDIR)$(bindir)
   3.124  	@list='$(bin_PROGRAMS)'; for p in $$list; do \
   3.125  	  if test -f $$p; then \
   3.126 -	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
   3.127 -	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
   3.128 +	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
   3.129 +	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
   3.130  	  else :; fi; \
   3.131  	done
   3.132  
   3.133 @@ -272,19 +273,19 @@
   3.134  	@rm -f playmus
   3.135  	$(LINK) $(playmus_LDFLAGS) $(playmus_OBJECTS) $(playmus_LDADD) $(LIBS)
   3.136  
   3.137 -install-libmixerincludeHEADERS: $(libmixerinclude_HEADERS)
   3.138 +install-libSDLmixerincludeHEADERS: $(libSDLmixerinclude_HEADERS)
   3.139  	@$(NORMAL_INSTALL)
   3.140 -	$(mkinstalldirs) $(DESTDIR)$(libmixerincludedir)
   3.141 -	@list='$(libmixerinclude_HEADERS)'; for p in $$list; do \
   3.142 +	$(mkinstalldirs) $(DESTDIR)$(libSDLmixerincludedir)
   3.143 +	@list='$(libSDLmixerinclude_HEADERS)'; for p in $$list; do \
   3.144  	  if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
   3.145 -	  echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libmixerincludedir)/$$p"; \
   3.146 -	  $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libmixerincludedir)/$$p; \
   3.147 +	  echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libSDLmixerincludedir)/$$p"; \
   3.148 +	  $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libSDLmixerincludedir)/$$p; \
   3.149  	done
   3.150  
   3.151 -uninstall-libmixerincludeHEADERS:
   3.152 +uninstall-libSDLmixerincludeHEADERS:
   3.153  	@$(NORMAL_UNINSTALL)
   3.154 -	list='$(libmixerinclude_HEADERS)'; for p in $$list; do \
   3.155 -	  rm -f $(DESTDIR)$(libmixerincludedir)/$$p; \
   3.156 +	list='$(libSDLmixerinclude_HEADERS)'; for p in $$list; do \
   3.157 +	  rm -f $(DESTDIR)$(libSDLmixerincludedir)/$$p; \
   3.158  	done
   3.159  
   3.160  # This directory's subdirectories are mostly independent; you can cd
   3.161 @@ -422,7 +423,7 @@
   3.162  	@for file in $(DISTFILES); do \
   3.163  	  d=$(srcdir); \
   3.164  	  if test -d $$d/$$file; then \
   3.165 -	    cp -pr $$/$$file $(distdir)/$$file; \
   3.166 +	    cp -pr $$d/$$file $(distdir)/$$file; \
   3.167  	  else \
   3.168  	    test -f $(distdir)/$$file \
   3.169  	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
   3.170 @@ -482,23 +483,23 @@
   3.171  install-exec-am: install-libLTLIBRARIES install-binPROGRAMS
   3.172  install-exec: install-exec-recursive
   3.173  
   3.174 -install-data-am: install-libmixerincludeHEADERS
   3.175 +install-data-am: install-libSDLmixerincludeHEADERS
   3.176  install-data: install-data-recursive
   3.177  
   3.178  install-am: all-am
   3.179  	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
   3.180  install: install-recursive
   3.181  uninstall-am: uninstall-libLTLIBRARIES uninstall-binPROGRAMS \
   3.182 -		uninstall-libmixerincludeHEADERS
   3.183 +		uninstall-libSDLmixerincludeHEADERS
   3.184  uninstall: uninstall-recursive
   3.185  all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
   3.186  all-redirect: all-recursive
   3.187  install-strip:
   3.188 -	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
   3.189 +	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
   3.190  installdirs: installdirs-recursive
   3.191  installdirs-am:
   3.192  	$(mkinstalldirs)  $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) \
   3.193 -		$(DESTDIR)$(libmixerincludedir)
   3.194 +		$(DESTDIR)$(libSDLmixerincludedir)
   3.195  
   3.196  
   3.197  mostlyclean-generic:
   3.198 @@ -548,8 +549,8 @@
   3.199  mostlyclean-libtool distclean-libtool clean-libtool \
   3.200  maintainer-clean-libtool mostlyclean-binPROGRAMS distclean-binPROGRAMS \
   3.201  clean-binPROGRAMS maintainer-clean-binPROGRAMS uninstall-binPROGRAMS \
   3.202 -install-binPROGRAMS uninstall-libmixerincludeHEADERS \
   3.203 -install-libmixerincludeHEADERS install-data-recursive \
   3.204 +install-binPROGRAMS uninstall-libSDLmixerincludeHEADERS \
   3.205 +install-libSDLmixerincludeHEADERS install-data-recursive \
   3.206  uninstall-data-recursive install-exec-recursive \
   3.207  uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
   3.208  all-recursive check-recursive installcheck-recursive info-recursive \
     4.1 --- a/README	Mon Dec 27 19:18:10 1999 +0000
     4.2 +++ b/README	Mon Dec 27 19:24:50 1999 +0000
     4.3 @@ -6,7 +6,7 @@
     4.4  of music, mixed by the popular MikMod MOD, Timidity MIDI and SMPEG MP3
     4.5  libraries.
     4.6  
     4.7 -See the header file mixer.h and the examples playwave.c and playmus.c
     4.8 +See the header file SDL_mixer.h and the examples playwave.c and playmus.c
     4.9  for documentation on this mixer library.
    4.10  
    4.11  The mixer can currently load Microsoft WAVE files as audio samples
    4.12 @@ -19,7 +19,8 @@
    4.13  sound choppy, try using 8-bit audio, mono audio, or lower frequencies.
    4.14  
    4.15  To play MIDI files, you'll need to get a complete set of GUS patches
    4.16 -from:  http://www.devolution.com/~slouken/SDL/timidity/timidity.tar.gz
    4.17 +from:
    4.18 +http://www.devolution.com/~slouken/SDL/projectx/mixer/timidity/timidity.tar.gz
    4.19  and unpack them in /usr/local/lib under UNIX, and C:\ under Win32.
    4.20  
    4.21  You may add panning, reverb, echo, whatever, but if you do, please
     5.1 --- a/aclocal.m4	Mon Dec 27 19:18:10 1999 +0000
     5.2 +++ b/aclocal.m4	Mon Dec 27 19:24:50 1999 +0000
     5.3 @@ -1,4 +1,4 @@
     5.4 -dnl aclocal.m4 generated automatically by aclocal 1.4
     5.5 +dnl aclocal.m4 generated automatically by aclocal 1.4a
     5.6  
     5.7  dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
     5.8  dnl This file is free software; the Free Software Foundation
     5.9 @@ -627,6 +627,8 @@
    5.10  
    5.11  AC_DEFUN(AM_INIT_AUTOMAKE,
    5.12  [AC_REQUIRE([AC_PROG_INSTALL])
    5.13 +dnl We require 2.13 because we rely on SHELL being computed by configure.
    5.14 +AC_PREREQ([2.13])
    5.15  PACKAGE=[$1]
    5.16  AC_SUBST(PACKAGE)
    5.17  VERSION=[$2]
     6.1 --- a/configure	Mon Dec 27 19:18:10 1999 +0000
     6.2 +++ b/configure	Mon Dec 27 19:24:50 1999 +0000
     6.3 @@ -561,9 +561,9 @@
     6.4  
     6.5  MAJOR_VERSION=1
     6.6  MINOR_VERSION=0
     6.7 -MICRO_VERSION=1
     6.8 +MICRO_VERSION=2
     6.9  INTERFACE_AGE=0
    6.10 -BINARY_AGE=1
    6.11 +BINARY_AGE=2
    6.12  VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION
    6.13  
    6.14  
    6.15 @@ -752,6 +752,7 @@
    6.16  fi
    6.17  
    6.18  
    6.19 +
    6.20  PACKAGE=mixer
    6.21  
    6.22  VERSION=$VERSION
    6.23 @@ -771,7 +772,7 @@
    6.24  
    6.25  missing_dir=`cd $ac_aux_dir && pwd`
    6.26  echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
    6.27 -echo "configure:775: checking for working aclocal" >&5
    6.28 +echo "configure:776: checking for working aclocal" >&5
    6.29  # Run test in a subshell; some versions of sh will print an error if
    6.30  # an executable is not found, even if stderr is redirected.
    6.31  # Redirect stdin to placate older versions of autoconf.  Sigh.
    6.32 @@ -784,7 +785,7 @@
    6.33  fi
    6.34  
    6.35  echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
    6.36 -echo "configure:788: checking for working autoconf" >&5
    6.37 +echo "configure:789: checking for working autoconf" >&5
    6.38  # Run test in a subshell; some versions of sh will print an error if
    6.39  # an executable is not found, even if stderr is redirected.
    6.40  # Redirect stdin to placate older versions of autoconf.  Sigh.
    6.41 @@ -797,7 +798,7 @@
    6.42  fi
    6.43  
    6.44  echo $ac_n "checking for working automake""... $ac_c" 1>&6
    6.45 -echo "configure:801: checking for working automake" >&5
    6.46 +echo "configure:802: checking for working automake" >&5
    6.47  # Run test in a subshell; some versions of sh will print an error if
    6.48  # an executable is not found, even if stderr is redirected.
    6.49  # Redirect stdin to placate older versions of autoconf.  Sigh.
    6.50 @@ -810,7 +811,7 @@
    6.51  fi
    6.52  
    6.53  echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
    6.54 -echo "configure:814: checking for working autoheader" >&5
    6.55 +echo "configure:815: checking for working autoheader" >&5
    6.56  # Run test in a subshell; some versions of sh will print an error if
    6.57  # an executable is not found, even if stderr is redirected.
    6.58  # Redirect stdin to placate older versions of autoconf.  Sigh.
    6.59 @@ -823,7 +824,7 @@
    6.60  fi
    6.61  
    6.62  echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
    6.63 -echo "configure:827: checking for working makeinfo" >&5
    6.64 +echo "configure:828: checking for working makeinfo" >&5
    6.65  # Run test in a subshell; some versions of sh will print an error if
    6.66  # an executable is not found, even if stderr is redirected.
    6.67  # Redirect stdin to placate older versions of autoconf.  Sigh.
    6.68 @@ -839,7 +840,7 @@
    6.69  
    6.70  
    6.71  echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
    6.72 -echo "configure:843: checking whether ${MAKE-make} sets \${MAKE}" >&5
    6.73 +echo "configure:844: checking whether ${MAKE-make} sets \${MAKE}" >&5
    6.74  set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
    6.75  if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
    6.76    echo $ac_n "(cached) $ac_c" 1>&6
    6.77 @@ -868,7 +869,7 @@
    6.78  # Extract the first word of "gcc", so it can be a program name with args.
    6.79  set dummy gcc; ac_word=$2
    6.80  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
    6.81 -echo "configure:872: checking for $ac_word" >&5
    6.82 +echo "configure:873: checking for $ac_word" >&5
    6.83  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    6.84    echo $ac_n "(cached) $ac_c" 1>&6
    6.85  else
    6.86 @@ -898,7 +899,7 @@
    6.87    # Extract the first word of "cc", so it can be a program name with args.
    6.88  set dummy cc; ac_word=$2
    6.89  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
    6.90 -echo "configure:902: checking for $ac_word" >&5
    6.91 +echo "configure:903: checking for $ac_word" >&5
    6.92  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    6.93    echo $ac_n "(cached) $ac_c" 1>&6
    6.94  else
    6.95 @@ -949,7 +950,7 @@
    6.96        # Extract the first word of "cl", so it can be a program name with args.
    6.97  set dummy cl; ac_word=$2
    6.98  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
    6.99 -echo "configure:953: checking for $ac_word" >&5
   6.100 +echo "configure:954: checking for $ac_word" >&5
   6.101  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   6.102    echo $ac_n "(cached) $ac_c" 1>&6
   6.103  else
   6.104 @@ -981,7 +982,7 @@
   6.105  fi
   6.106  
   6.107  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
   6.108 -echo "configure:985: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
   6.109 +echo "configure:986: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
   6.110  
   6.111  ac_ext=c
   6.112  # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
   6.113 @@ -992,12 +993,12 @@
   6.114  
   6.115  cat > conftest.$ac_ext << EOF
   6.116  
   6.117 -#line 996 "configure"
   6.118 +#line 997 "configure"
   6.119  #include "confdefs.h"
   6.120  
   6.121  main(){return(0);}
   6.122  EOF
   6.123 -if { (eval echo configure:1001: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.124 +if { (eval echo configure:1002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.125    ac_cv_prog_cc_works=yes
   6.126    # If we can't run a trivial program, we are probably using a cross compiler.
   6.127    if (./conftest; exit) 2>/dev/null; then
   6.128 @@ -1023,12 +1024,12 @@
   6.129    { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
   6.130  fi
   6.131  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
   6.132 -echo "configure:1027: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
   6.133 +echo "configure:1028: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
   6.134  echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
   6.135  cross_compiling=$ac_cv_prog_cc_cross
   6.136  
   6.137  echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
   6.138 -echo "configure:1032: checking whether we are using GNU C" >&5
   6.139 +echo "configure:1033: checking whether we are using GNU C" >&5
   6.140  if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   6.141    echo $ac_n "(cached) $ac_c" 1>&6
   6.142  else
   6.143 @@ -1037,7 +1038,7 @@
   6.144    yes;
   6.145  #endif
   6.146  EOF
   6.147 -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1041: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   6.148 +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1042: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   6.149    ac_cv_prog_gcc=yes
   6.150  else
   6.151    ac_cv_prog_gcc=no
   6.152 @@ -1056,7 +1057,7 @@
   6.153  ac_save_CFLAGS="$CFLAGS"
   6.154  CFLAGS=
   6.155  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
   6.156 -echo "configure:1060: checking whether ${CC-cc} accepts -g" >&5
   6.157 +echo "configure:1061: checking whether ${CC-cc} accepts -g" >&5
   6.158  if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   6.159    echo $ac_n "(cached) $ac_c" 1>&6
   6.160  else
   6.161 @@ -1164,7 +1165,7 @@
   6.162  fi
   6.163  
   6.164  echo $ac_n "checking host system type""... $ac_c" 1>&6
   6.165 -echo "configure:1168: checking host system type" >&5
   6.166 +echo "configure:1169: checking host system type" >&5
   6.167  
   6.168  host_alias=$host
   6.169  case "$host_alias" in
   6.170 @@ -1185,7 +1186,7 @@
   6.171  echo "$ac_t""$host" 1>&6
   6.172  
   6.173  echo $ac_n "checking build system type""... $ac_c" 1>&6
   6.174 -echo "configure:1189: checking build system type" >&5
   6.175 +echo "configure:1190: checking build system type" >&5
   6.176  
   6.177  build_alias=$build
   6.178  case "$build_alias" in
   6.179 @@ -1214,7 +1215,7 @@
   6.180  if test "$ac_cv_prog_gcc" = yes; then
   6.181    # Check if gcc -print-prog-name=ld gives a path.
   6.182    echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
   6.183 -echo "configure:1218: checking for ld used by GCC" >&5
   6.184 +echo "configure:1219: checking for ld used by GCC" >&5
   6.185    case $host in
   6.186    *-*-mingw*)
   6.187      # gcc leaves a trailing carriage return which upsets mingw
   6.188 @@ -1244,10 +1245,10 @@
   6.189    esac
   6.190  elif test "$with_gnu_ld" = yes; then
   6.191    echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
   6.192 -echo "configure:1248: checking for GNU ld" >&5
   6.193 +echo "configure:1249: checking for GNU ld" >&5
   6.194  else
   6.195    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
   6.196 -echo "configure:1251: checking for non-GNU ld" >&5
   6.197 +echo "configure:1252: checking for non-GNU ld" >&5
   6.198  fi
   6.199  if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
   6.200    echo $ac_n "(cached) $ac_c" 1>&6
   6.201 @@ -1283,7 +1284,7 @@
   6.202  test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
   6.203  
   6.204  echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
   6.205 -echo "configure:1287: checking if the linker ($LD) is GNU ld" >&5
   6.206 +echo "configure:1288: checking if the linker ($LD) is GNU ld" >&5
   6.207  if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
   6.208    echo $ac_n "(cached) $ac_c" 1>&6
   6.209  else
   6.210 @@ -1299,7 +1300,7 @@
   6.211  
   6.212  
   6.213  echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
   6.214 -echo "configure:1303: checking for BSD-compatible nm" >&5
   6.215 +echo "configure:1304: checking for BSD-compatible nm" >&5
   6.216  if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
   6.217    echo $ac_n "(cached) $ac_c" 1>&6
   6.218  else
   6.219 @@ -1336,7 +1337,7 @@
   6.220  
   6.221  
   6.222  echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
   6.223 -echo "configure:1340: checking whether ln -s works" >&5
   6.224 +echo "configure:1341: checking whether ln -s works" >&5
   6.225  if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
   6.226    echo $ac_n "(cached) $ac_c" 1>&6
   6.227  else
   6.228 @@ -1366,7 +1367,7 @@
   6.229  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
   6.230  set dummy ${ac_tool_prefix}ranlib; ac_word=$2
   6.231  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.232 -echo "configure:1370: checking for $ac_word" >&5
   6.233 +echo "configure:1371: checking for $ac_word" >&5
   6.234  if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   6.235    echo $ac_n "(cached) $ac_c" 1>&6
   6.236  else
   6.237 @@ -1398,7 +1399,7 @@
   6.238    # Extract the first word of "ranlib", so it can be a program name with args.
   6.239  set dummy ranlib; ac_word=$2
   6.240  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.241 -echo "configure:1402: checking for $ac_word" >&5
   6.242 +echo "configure:1403: checking for $ac_word" >&5
   6.243  if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   6.244    echo $ac_n "(cached) $ac_c" 1>&6
   6.245  else
   6.246 @@ -1465,8 +1466,8 @@
   6.247  case "$host" in
   6.248  *-*-irix6*)
   6.249    # Find out which ABI we are using.
   6.250 -  echo '#line 1469 "configure"' > conftest.$ac_ext
   6.251 -  if { (eval echo configure:1470: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   6.252 +  echo '#line 1470 "configure"' > conftest.$ac_ext
   6.253 +  if { (eval echo configure:1471: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   6.254      case "`/usr/bin/file conftest.o`" in
   6.255      *32-bit*)
   6.256        LD="${LD-ld} -32"
   6.257 @@ -1487,19 +1488,19 @@
   6.258    SAVE_CFLAGS="$CFLAGS"
   6.259    CFLAGS="$CFLAGS -belf"
   6.260    echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
   6.261 -echo "configure:1491: checking whether the C compiler needs -belf" >&5
   6.262 +echo "configure:1492: checking whether the C compiler needs -belf" >&5
   6.263  if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
   6.264    echo $ac_n "(cached) $ac_c" 1>&6
   6.265  else
   6.266    cat > conftest.$ac_ext <<EOF
   6.267 -#line 1496 "configure"
   6.268 +#line 1497 "configure"
   6.269  #include "confdefs.h"
   6.270  
   6.271  int main() {
   6.272  
   6.273  ; return 0; }
   6.274  EOF
   6.275 -if { (eval echo configure:1503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.276 +if { (eval echo configure:1504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.277    rm -rf conftest*
   6.278    lt_cv_cc_needs_belf=yes
   6.279  else
   6.280 @@ -1522,7 +1523,7 @@
   6.281    # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
   6.282  set dummy ${ac_tool_prefix}dlltool; ac_word=$2
   6.283  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.284 -echo "configure:1526: checking for $ac_word" >&5
   6.285 +echo "configure:1527: checking for $ac_word" >&5
   6.286  if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
   6.287    echo $ac_n "(cached) $ac_c" 1>&6
   6.288  else
   6.289 @@ -1554,7 +1555,7 @@
   6.290    # Extract the first word of "dlltool", so it can be a program name with args.
   6.291  set dummy dlltool; ac_word=$2
   6.292  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.293 -echo "configure:1558: checking for $ac_word" >&5
   6.294 +echo "configure:1559: checking for $ac_word" >&5
   6.295  if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
   6.296    echo $ac_n "(cached) $ac_c" 1>&6
   6.297  else
   6.298 @@ -1589,7 +1590,7 @@
   6.299    # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
   6.300  set dummy ${ac_tool_prefix}as; ac_word=$2
   6.301  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.302 -echo "configure:1593: checking for $ac_word" >&5
   6.303 +echo "configure:1594: checking for $ac_word" >&5
   6.304  if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
   6.305    echo $ac_n "(cached) $ac_c" 1>&6
   6.306  else
   6.307 @@ -1621,7 +1622,7 @@
   6.308    # Extract the first word of "as", so it can be a program name with args.
   6.309  set dummy as; ac_word=$2
   6.310  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.311 -echo "configure:1625: checking for $ac_word" >&5
   6.312 +echo "configure:1626: checking for $ac_word" >&5
   6.313  if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
   6.314    echo $ac_n "(cached) $ac_c" 1>&6
   6.315  else
   6.316 @@ -1656,7 +1657,7 @@
   6.317    # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
   6.318  set dummy ${ac_tool_prefix}objdump; ac_word=$2
   6.319  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.320 -echo "configure:1660: checking for $ac_word" >&5
   6.321 +echo "configure:1661: checking for $ac_word" >&5
   6.322  if eval "test \"`echo '$''{'ac_cv_prog_OBJDUMP'+set}'`\" = set"; then
   6.323    echo $ac_n "(cached) $ac_c" 1>&6
   6.324  else
   6.325 @@ -1688,7 +1689,7 @@
   6.326    # Extract the first word of "objdump", so it can be a program name with args.
   6.327  set dummy objdump; ac_word=$2
   6.328  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.329 -echo "configure:1692: checking for $ac_word" >&5
   6.330 +echo "configure:1693: checking for $ac_word" >&5
   6.331  if eval "test \"`echo '$''{'ac_cv_prog_OBJDUMP'+set}'`\" = set"; then
   6.332    echo $ac_n "(cached) $ac_c" 1>&6
   6.333  else
   6.334 @@ -1724,19 +1725,19 @@
   6.335    # recent cygwin and mingw systems supply a stub DllMain which the user
   6.336    # can override, but on older systems we have to supply one
   6.337    echo $ac_n "checking if libtool should supply DllMain function""... $ac_c" 1>&6
   6.338 -echo "configure:1728: checking if libtool should supply DllMain function" >&5
   6.339 +echo "configure:1729: checking if libtool should supply DllMain function" >&5
   6.340  if eval "test \"`echo '$''{'lt_cv_need_dllmain'+set}'`\" = set"; then
   6.341    echo $ac_n "(cached) $ac_c" 1>&6
   6.342  else
   6.343    cat > conftest.$ac_ext <<EOF
   6.344 -#line 1733 "configure"
   6.345 +#line 1734 "configure"
   6.346  #include "confdefs.h"
   6.347  DllMain (0, 0, 0);
   6.348  int main() {
   6.349  extern int __attribute__((__stdcall__)) DllMain(void*, int, void*);
   6.350  ; return 0; }
   6.351  EOF
   6.352 -if { (eval echo configure:1740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.353 +if { (eval echo configure:1741: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.354    rm -rf conftest*
   6.355    lt_cv_need_dllmain=yes
   6.356  else
   6.357 @@ -1761,19 +1762,19 @@
   6.358      SAVE_CFLAGS="$CFLAGS"
   6.359      CFLAGS="$CFLAGS -mdll"
   6.360      echo $ac_n "checking how to link DLLs""... $ac_c" 1>&6
   6.361 -echo "configure:1765: checking how to link DLLs" >&5
   6.362 +echo "configure:1766: checking how to link DLLs" >&5
   6.363  if eval "test \"`echo '$''{'lt_cv_cc_dll_switch'+set}'`\" = set"; then
   6.364    echo $ac_n "(cached) $ac_c" 1>&6
   6.365  else
   6.366    cat > conftest.$ac_ext <<EOF
   6.367 -#line 1770 "configure"
   6.368 +#line 1771 "configure"
   6.369  #include "confdefs.h"
   6.370  
   6.371  int main() {
   6.372  
   6.373  ; return 0; }
   6.374  EOF
   6.375 -if { (eval echo configure:1777: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.376 +if { (eval echo configure:1778: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.377    rm -rf conftest*
   6.378    lt_cv_cc_dll_switch=-mdll
   6.379  else
   6.380 @@ -1883,7 +1884,7 @@
   6.381  # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
   6.382  # ./install, which can be erroneously created by make from ./install.sh.
   6.383  echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
   6.384 -echo "configure:1887: checking for a BSD compatible install" >&5
   6.385 +echo "configure:1888: checking for a BSD compatible install" >&5
   6.386  if test -z "$INSTALL"; then
   6.387  if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   6.388    echo $ac_n "(cached) $ac_c" 1>&6
   6.389 @@ -1937,7 +1938,7 @@
   6.390  
   6.391  
   6.392  echo $ac_n "checking target system type""... $ac_c" 1>&6
   6.393 -echo "configure:1941: checking target system type" >&5
   6.394 +echo "configure:1942: checking target system type" >&5
   6.395  
   6.396  target_alias=$target
   6.397  case "$target_alias" in
   6.398 @@ -2002,7 +2003,7 @@
   6.399    # Extract the first word of "sdl-config", so it can be a program name with args.
   6.400  set dummy sdl-config; ac_word=$2
   6.401  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
   6.402 -echo "configure:2006: checking for $ac_word" >&5
   6.403 +echo "configure:2007: checking for $ac_word" >&5
   6.404  if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
   6.405    echo $ac_n "(cached) $ac_c" 1>&6
   6.406  else
   6.407 @@ -2037,7 +2038,7 @@
   6.408  
   6.409    min_sdl_version=$SDL_VERSION
   6.410    echo $ac_n "checking for SDL - version >= $min_sdl_version""... $ac_c" 1>&6
   6.411 -echo "configure:2041: checking for SDL - version >= $min_sdl_version" >&5
   6.412 +echo "configure:2042: checking for SDL - version >= $min_sdl_version" >&5
   6.413    no_sdl=""
   6.414    if test "$SDL_CONFIG" = "no" ; then
   6.415      no_sdl=yes
   6.416 @@ -2061,7 +2062,7 @@
   6.417    echo $ac_n "cross compiling; assumed OK... $ac_c"
   6.418  else
   6.419    cat > conftest.$ac_ext <<EOF
   6.420 -#line 2065 "configure"
   6.421 +#line 2066 "configure"
   6.422  #include "confdefs.h"
   6.423  
   6.424  #include <stdio.h>
   6.425 @@ -2119,7 +2120,7 @@
   6.426  
   6.427  
   6.428  EOF
   6.429 -if { (eval echo configure:2123: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
   6.430 +if { (eval echo configure:2124: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
   6.431  then
   6.432    :
   6.433  else
   6.434 @@ -2153,7 +2154,7 @@
   6.435            CFLAGS="$CFLAGS $SDL_CFLAGS"
   6.436            LIBS="$LIBS $SDL_LIBS"
   6.437            cat > conftest.$ac_ext <<EOF
   6.438 -#line 2157 "configure"
   6.439 +#line 2158 "configure"
   6.440  #include "confdefs.h"
   6.441  
   6.442  #include <stdio.h>
   6.443 @@ -2163,7 +2164,7 @@
   6.444   return 0; 
   6.445  ; return 0; }
   6.446  EOF
   6.447 -if { (eval echo configure:2167: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.448 +if { (eval echo configure:2168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   6.449    rm -rf conftest*
   6.450     echo "*** The test program compiled, but did not run. This usually means"
   6.451            echo "*** that the run-time linker is not finding SDL or finding the wrong"
   6.452 @@ -2256,10 +2257,10 @@
   6.453  
   6.454  if test x$enable_music_mp3 = xyes; then
   6.455      echo $ac_n "checking for SMPEG headers and libraries""... $ac_c" 1>&6
   6.456 -echo "configure:2260: checking for SMPEG headers and libraries" >&5
   6.457 +echo "configure:2261: checking for SMPEG headers and libraries" >&5
   6.458      have_smpeg=no
   6.459      cat > conftest.$ac_ext <<EOF
   6.460 -#line 2263 "configure"
   6.461 +#line 2264 "configure"
   6.462  #include "confdefs.h"
   6.463  
   6.464       #include <smpeg/smpeg.h>
   6.465 @@ -2269,7 +2270,7 @@
   6.466      
   6.467  ; return 0; }
   6.468  EOF
   6.469 -if { (eval echo configure:2273: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   6.470 +if { (eval echo configure:2274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   6.471    rm -rf conftest*
   6.472    
   6.473      have_smpeg=yes
     7.1 --- a/configure.in	Mon Dec 27 19:18:10 1999 +0000
     7.2 +++ b/configure.in	Mon Dec 27 19:24:50 1999 +0000
     7.3 @@ -13,9 +13,9 @@
     7.4  
     7.5  MAJOR_VERSION=1
     7.6  MINOR_VERSION=0
     7.7 -MICRO_VERSION=1
     7.8 +MICRO_VERSION=2
     7.9  INTERFACE_AGE=0
    7.10 -BINARY_AGE=1
    7.11 +BINARY_AGE=2
    7.12  VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION
    7.13  
    7.14  AC_SUBST(MAJOR_VERSION)
     8.1 --- a/mikmod/Makefile.am	Mon Dec 27 19:18:10 1999 +0000
     8.2 +++ b/mikmod/Makefile.am	Mon Dec 27 19:24:50 1999 +0000
     8.3 @@ -10,20 +10,23 @@
     8.4  	load_xm.c		\
     8.5  	mdreg.c			\
     8.6  	mdriver.c		\
     8.7 +	mdulaw.c		\
     8.8  	mikmod.h		\
     8.9 +	mikmod_build.h		\
    8.10 +	mikmod_internals.h	\
    8.11  	mloader.c		\
    8.12  	mlreg.c			\
    8.13 +	mlutil.c		\
    8.14  	mmalloc.c		\
    8.15  	mmerror.c		\
    8.16  	mmio.c			\
    8.17 -	mmio.h			\
    8.18  	mplayer.c		\
    8.19  	munitrk.c		\
    8.20 +	mwav.c			\
    8.21  	npertab.c		\
    8.22 -	ptform.h		\
    8.23 -	s3m_it.c		\
    8.24  	sloader.c		\
    8.25 -	tdefs.h			\
    8.26 -	virtch.c
    8.27 +	virtch.c		\
    8.28 +	virtch2.c		\
    8.29 +	virtch_common.c
    8.30  
    8.31 -EXTRA_DIST = README license.txt
    8.32 +EXTRA_DIST = AUTHORS COPYING.LESSER README
     9.1 --- a/mikmod/Makefile.in	Mon Dec 27 19:18:10 1999 +0000
     9.2 +++ b/mikmod/Makefile.in	Mon Dec 27 19:24:50 1999 +0000
     9.3 @@ -1,4 +1,4 @@
     9.4 -# Makefile.in generated automatically by automake 1.4 from Makefile.am
     9.5 +# Makefile.in generated automatically by automake 1.4a from Makefile.am
     9.6  
     9.7  # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
     9.8  # This Makefile.in is free software; the Free Software Foundation
     9.9 @@ -46,9 +46,10 @@
    9.10  AUTOHEADER = @AUTOHEADER@
    9.11  
    9.12  INSTALL = @INSTALL@
    9.13 -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
    9.14 +INSTALL_PROGRAM = @INSTALL_PROGRAM@
    9.15  INSTALL_DATA = @INSTALL_DATA@
    9.16  INSTALL_SCRIPT = @INSTALL_SCRIPT@
    9.17 +INSTALL_STRIP_FLAG =
    9.18  transform = @program_transform_name@
    9.19  
    9.20  NORMAL_INSTALL = :
    9.21 @@ -87,10 +88,10 @@
    9.22  
    9.23  noinst_LTLIBRARIES = libmikmod.la
    9.24  
    9.25 -libmikmod_la_SOURCES =  	drv_nos.c			drv_sdl.c			load_it.c			load_mod.c			load_s3m.c			load_xm.c			mdreg.c				mdriver.c			mikmod.h			mloader.c			mlreg.c				mmalloc.c			mmerror.c			mmio.c				mmio.h				mplayer.c			munitrk.c			npertab.c			ptform.h			s3m_it.c			sloader.c			tdefs.h				virtch.c
    9.26 +libmikmod_la_SOURCES =  	drv_nos.c			drv_sdl.c			load_it.c			load_mod.c			load_s3m.c			load_xm.c			mdreg.c				mdriver.c			mdulaw.c			mikmod.h			mikmod_build.h			mikmod_internals.h		mloader.c			mlreg.c				mlutil.c			mmalloc.c			mmerror.c			mmio.c				mplayer.c			munitrk.c			mwav.c				npertab.c			sloader.c			virtch.c			virtch2.c			virtch_common.c
    9.27  
    9.28  
    9.29 -EXTRA_DIST = README license.txt
    9.30 +EXTRA_DIST = AUTHORS COPYING.LESSER README
    9.31  mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
    9.32  CONFIG_CLEAN_FILES = 
    9.33  LTLIBRARIES =  $(noinst_LTLIBRARIES)
    9.34 @@ -103,15 +104,15 @@
    9.35  libmikmod_la_LDFLAGS = 
    9.36  libmikmod_la_LIBADD = 
    9.37  libmikmod_la_OBJECTS =  drv_nos.lo drv_sdl.lo load_it.lo load_mod.lo \
    9.38 -load_s3m.lo load_xm.lo mdreg.lo mdriver.lo mloader.lo mlreg.lo \
    9.39 -mmalloc.lo mmerror.lo mmio.lo mplayer.lo munitrk.lo npertab.lo \
    9.40 -s3m_it.lo sloader.lo virtch.lo
    9.41 +load_s3m.lo load_xm.lo mdreg.lo mdriver.lo mdulaw.lo mloader.lo \
    9.42 +mlreg.lo mlutil.lo mmalloc.lo mmerror.lo mmio.lo mplayer.lo munitrk.lo \
    9.43 +mwav.lo npertab.lo sloader.lo virtch.lo virtch2.lo virtch_common.lo
    9.44  CFLAGS = @CFLAGS@
    9.45  COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    9.46  LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    9.47  CCLD = $(CC)
    9.48  LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
    9.49 -DIST_COMMON =  README Makefile.am Makefile.in
    9.50 +DIST_COMMON =  README AUTHORS Makefile.am Makefile.in
    9.51  
    9.52  
    9.53  DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
    9.54 @@ -120,9 +121,10 @@
    9.55  GZIP_ENV = --best
    9.56  DEP_FILES =  .deps/drv_nos.P .deps/drv_sdl.P .deps/load_it.P \
    9.57  .deps/load_mod.P .deps/load_s3m.P .deps/load_xm.P .deps/mdreg.P \
    9.58 -.deps/mdriver.P .deps/mloader.P .deps/mlreg.P .deps/mmalloc.P \
    9.59 -.deps/mmerror.P .deps/mmio.P .deps/mplayer.P .deps/munitrk.P \
    9.60 -.deps/npertab.P .deps/s3m_it.P .deps/sloader.P .deps/virtch.P
    9.61 +.deps/mdriver.P .deps/mdulaw.P .deps/mloader.P .deps/mlreg.P \
    9.62 +.deps/mlutil.P .deps/mmalloc.P .deps/mmerror.P .deps/mmio.P \
    9.63 +.deps/mplayer.P .deps/munitrk.P .deps/mwav.P .deps/npertab.P \
    9.64 +.deps/sloader.P .deps/virtch.P .deps/virtch2.P .deps/virtch_common.P
    9.65  SOURCES = $(libmikmod_la_SOURCES)
    9.66  OBJECTS = $(libmikmod_la_OBJECTS)
    9.67  
    9.68 @@ -223,7 +225,7 @@
    9.69  	@for file in $(DISTFILES); do \
    9.70  	  d=$(srcdir); \
    9.71  	  if test -d $$d/$$file; then \
    9.72 -	    cp -pr $$/$$file $(distdir)/$$file; \
    9.73 +	    cp -pr $$d/$$file $(distdir)/$$file; \
    9.74  	  else \
    9.75  	    test -f $(distdir)/$$file \
    9.76  	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
    9.77 @@ -284,7 +286,7 @@
    9.78  all-am: Makefile $(LTLIBRARIES)
    9.79  all-redirect: all-am
    9.80  install-strip:
    9.81 -	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
    9.82 +	$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
    9.83  installdirs:
    9.84  
    9.85  
    10.1 --- a/mikmod/README	Mon Dec 27 19:18:10 1999 +0000
    10.2 +++ b/mikmod/README	Mon Dec 27 19:24:50 1999 +0000
    10.3 @@ -1,14 +1,14 @@
    10.4  
    10.5 - --> MikMod Sound Libraries Version 3.0
    10.6 -  -> Release Notes - August 20th, 1997
    10.7 + --> MikMod Sound Libraries Version 3.1.8
    10.8 + --> libmikmod 3.1.8 was released on 10/25/1999.
    10.9  
   10.10 --- 
   10.11 -This version of the library is based on the official UNIX MikMod version 3.0,
   10.12 -found at:  http://freenet.tlh.fl.us/~amstpi/mikmod.html
   10.13 +--
   10.14 +This version of the library is based on the official UNIX MikMod
   10.15 +library version 3.1.8, found at:  http://mikmod.darkorb.net/
   10.16  
   10.17 -It has been stripped down for inclusion with Simple DirectMedia Layer, 
   10.18 +It has been stripped down for inclusion with Simple DirectMedia Layer,
   10.19  but the missing drivers and file loaders can be plugged right in from
   10.20 -the MikMod 3.03 archive.
   10.21 +the MikMod 3.1.8 archive.
   10.22  
   10.23 -See license.txt for copying information
   10.24 +See COPYING.LESSER for copying information
   10.25  --
    11.1 --- a/mikmod/drv_nos.c	Mon Dec 27 19:18:10 1999 +0000
    11.2 +++ b/mikmod/drv_nos.c	Mon Dec 27 19:24:50 1999 +0000
    11.3 @@ -1,161 +1,107 @@
    11.4 +/*	MikMod sound library
    11.5 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    11.6 +	complete list.
    11.7 +
    11.8 +	This library is free software; you can redistribute it and/or modify
    11.9 +	it under the terms of the GNU Library General Public License as
   11.10 +	published by the Free Software Foundation; either version 2 of
   11.11 +	the License, or (at your option) any later version.
   11.12 +
   11.13 +	This program is distributed in the hope that it will be useful,
   11.14 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.15 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.16 +	GNU Library General Public License for more details.
   11.17 +
   11.18 +	You should have received a copy of the GNU Library General Public
   11.19 +	License along with this library; if not, write to the Free Software
   11.20 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   11.21 +	02111-1307, USA.
   11.22 +*/
   11.23 +
   11.24 +/*==============================================================================
   11.25 +
   11.26 +  $Id$
   11.27 +
   11.28 +  Driver for no output
   11.29 +
   11.30 +==============================================================================*/
   11.31 +
   11.32  /*
   11.33  
   11.34 -Name:
   11.35 -DRV_NOS.C
   11.36 -
   11.37 -Description:
   11.38 -Mikmod driver for no output on any soundcard, monitor, keyboard, or whatever :)
   11.39 -
   11.40 -Portability:
   11.41 -All systems - All compilers
   11.42 +	Written by Jean-Paul Mikkers <mikmak@via.nl>
   11.43  
   11.44  */
   11.45  
   11.46 -#include "mikmod.h"
   11.47 +#ifdef HAVE_CONFIG_H
   11.48 +#include "config.h"
   11.49 +#endif
   11.50  
   11.51 +#ifdef HAVE_UNISTD_H
   11.52 +#include <unistd.h>
   11.53 +#endif
   11.54 +
   11.55 +#include "mikmod_internals.h"
   11.56 +
   11.57 +#define ZEROLEN 32768
   11.58 +
   11.59 +static	SBYTE *zerobuf=NULL;
   11.60  
   11.61  static BOOL NS_IsThere(void)
   11.62  {
   11.63 -    return 1;
   11.64 -}
   11.65 -
   11.66 -
   11.67 -static SWORD NS_SampleLoad(SAMPLOAD *s, int type)
   11.68 -{
   11.69 -    return 0;
   11.70 -}
   11.71 -
   11.72 -
   11.73 -static void NS_SampleUnload(SWORD h)
   11.74 -{
   11.75 +	return 1;
   11.76  }
   11.77  
   11.78 -
   11.79 -static ULONG NS_SampleSpace(int type)
   11.80 -{
   11.81 -    return 0;
   11.82 -}
   11.83 -
   11.84 -
   11.85 -static ULONG NS_SampleLength(int type, SAMPLE *s)
   11.86 -{
   11.87 -    return s->length;
   11.88 -}
   11.89 -
   11.90 -
   11.91  static BOOL NS_Init(void)
   11.92  {
   11.93 -    return 0;
   11.94 +	zerobuf=(SBYTE*)_mm_malloc(ZEROLEN);
   11.95 +	return VC_Init();
   11.96  }
   11.97  
   11.98 -
   11.99  static void NS_Exit(void)
  11.100  {
  11.101 -}
  11.102 -
  11.103 -
  11.104 -static BOOL NS_Reset(void)
  11.105 -{
  11.106 -    return 0;
  11.107 +	VC_Exit();
  11.108 +	_mm_free(zerobuf);
  11.109  }
  11.110  
  11.111 -
  11.112 -static BOOL NS_PlayStart(void)
  11.113 -{
  11.114 -    return 0;
  11.115 -}
  11.116 -
  11.117 -
  11.118 -static void NS_PlayStop(void)
  11.119 -{
  11.120 -}
  11.121 -
  11.122 -
  11.123  static void NS_Update(void)
  11.124  {
  11.125 -}
  11.126 -
  11.127 -
  11.128 -static BOOL NS_SetNumVoices(void)
  11.129 -{
  11.130 -    return 0;
  11.131 -}
  11.132 -
  11.133 -
  11.134 -static void NS_VoiceSetVolume(UBYTE voice,UWORD vol)
  11.135 -{
  11.136 -}
  11.137 -
  11.138 -
  11.139 -static void NS_VoiceSetFrequency(UBYTE voice,ULONG frq)
  11.140 -{
  11.141 +	if (zerobuf)
  11.142 +		VC_WriteBytes(zerobuf,ZEROLEN);
  11.143  }
  11.144  
  11.145 -
  11.146 -static void NS_VoiceSetPanning(UBYTE voice,ULONG pan)
  11.147 -{
  11.148 -}
  11.149 -
  11.150 -
  11.151 -static void NS_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
  11.152 -{
  11.153 -}
  11.154 +MDRIVER drv_nos={
  11.155 +	NULL,
  11.156 +	"No Sound",
  11.157 +	"Nosound Driver v3.0",
  11.158 +	255,255,
  11.159 +	"nosound",
  11.160  
  11.161 -
  11.162 -static void NS_VoiceStop(UBYTE voice)
  11.163 -{
  11.164 -}
  11.165 -
  11.166 -
  11.167 -static BOOL NS_VoiceStopped(UBYTE voice)
  11.168 -{
  11.169 -   return 0;
  11.170 -}
  11.171 +	NULL,
  11.172 +	NS_IsThere,
  11.173 +	VC_SampleLoad,
  11.174 +	VC_SampleUnload,
  11.175 +	VC_SampleSpace,
  11.176 +	VC_SampleLength,
  11.177 +	NS_Init,
  11.178 +	NS_Exit,
  11.179 +	NULL,
  11.180 +	VC_SetNumVoices,
  11.181 +	VC_PlayStart,
  11.182 +	VC_PlayStop,
  11.183 +	NS_Update,
  11.184 +	NULL,
  11.185 +	VC_VoiceSetVolume,
  11.186 +	VC_VoiceGetVolume,
  11.187 +	VC_VoiceSetFrequency,
  11.188 +	VC_VoiceGetFrequency,
  11.189 +	VC_VoiceSetPanning,
  11.190 +	VC_VoiceGetPanning,
  11.191 +	VC_VoicePlay,
  11.192 +	VC_VoiceStop,
  11.193 +	VC_VoiceStopped,
  11.194 +	VC_VoiceGetPosition,
  11.195 +	VC_VoiceRealVolume
  11.196 +};
  11.197  
  11.198  
  11.199 -static void NS_VoiceReleaseSustain(UBYTE voice)
  11.200 -{
  11.201 -}
  11.202 -
  11.203 -
  11.204 -static SLONG NS_VoiceGetPosition(UBYTE voice)
  11.205 -{
  11.206 -   return 0;
  11.207 -}
  11.208 -
  11.209 -
  11.210 -static ULONG NS_VoiceRealVolume(UBYTE voice)
  11.211 -{
  11.212 -   return 0;
  11.213 -}
  11.214 -
  11.215 -
  11.216 -
  11.217 -MDRIVER drv_nos =
  11.218 -{   NULL,
  11.219 -    "No Sound",
  11.220 -    "Nosound Driver v2.0 - (c) Creative Silence",
  11.221 -    255,255,
  11.222 -    NS_IsThere,
  11.223 -    NS_SampleLoad,
  11.224 -    NS_SampleUnload,
  11.225 -    NS_SampleSpace,
  11.226 -    NS_SampleLength,
  11.227 -    NS_Init,
  11.228 -    NS_Exit,
  11.229 -    NS_Reset,
  11.230 -    NS_SetNumVoices,
  11.231 -    NS_PlayStart,
  11.232 -    NS_PlayStop,
  11.233 -    NS_Update,
  11.234 -    NS_VoiceSetVolume,
  11.235 -    NS_VoiceSetFrequency,
  11.236 -    NS_VoiceSetPanning,
  11.237 -    NS_VoicePlay,
  11.238 -    NS_VoiceStop,
  11.239 -    NS_VoiceStopped,
  11.240 -    NS_VoiceReleaseSustain,
  11.241 -    NS_VoiceGetPosition,
  11.242 -    NS_VoiceRealVolume
  11.243 -};
  11.244 -
  11.245 +/* ex:set ts=4: */
    12.1 --- a/mikmod/drv_sdl.c	Mon Dec 27 19:18:10 1999 +0000
    12.2 +++ b/mikmod/drv_sdl.c	Mon Dec 27 19:24:50 1999 +0000
    12.3 @@ -8,7 +8,8 @@
    12.4  
    12.5  */
    12.6  
    12.7 -#include "mikmod.h"
    12.8 +
    12.9 +#include "mikmod_internals.h"
   12.10  
   12.11  
   12.12  static BOOL SDRV_IsThere(void)
   12.13 @@ -45,8 +46,11 @@
   12.14  MDRIVER drv_sdl =
   12.15  {   NULL,
   12.16      "SDL",
   12.17 -    "MikMod Simple DirectMedia Layer driver v1.0",
   12.18 +    "MikMod Simple DirectMedia Layer driver v1.1",
   12.19      0,255,
   12.20 +    "SDL",
   12.21 +
   12.22 +    NULL,
   12.23      SDRV_IsThere,
   12.24      VC_SampleLoad,
   12.25      VC_SampleUnload,
   12.26 @@ -59,13 +63,16 @@
   12.27      VC_PlayStart,
   12.28      VC_PlayStop,
   12.29      SDRV_Update,
   12.30 +    NULL,               /* FIXME: Pause */
   12.31      VC_VoiceSetVolume,
   12.32 +    VC_VoiceGetVolume,
   12.33      VC_VoiceSetFrequency,
   12.34 +    VC_VoiceGetFrequency,
   12.35      VC_VoiceSetPanning,
   12.36 +    VC_VoiceGetPanning,
   12.37      VC_VoicePlay,
   12.38      VC_VoiceStop,
   12.39      VC_VoiceStopped,
   12.40 -    VC_VoiceReleaseSustain,
   12.41      VC_VoiceGetPosition,
   12.42      VC_VoiceRealVolume
   12.43  };
    13.1 --- a/mikmod/load_it.c	Mon Dec 27 19:18:10 1999 +0000
    13.2 +++ b/mikmod/load_it.c	Mon Dec 27 19:24:50 1999 +0000
    13.3 @@ -1,857 +1,1011 @@
    13.4 -/*
    13.5 +/*	MikMod sound library
    13.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    13.7 +	complete list.
    13.8  
    13.9 - Name: LOAD_IT.C
   13.10 -
   13.11 - Description:
   13.12 - ImpulseTracker (IT) module loader
   13.13 +	This library is free software; you can redistribute it and/or modify
   13.14 +	it under the terms of the GNU Library General Public License as
   13.15 +	published by the Free Software Foundation; either version 2 of
   13.16 +	the License, or (at your option) any later version.
   13.17  
   13.18 - Portability:
   13.19 - All systems - all compilers (hopefully)
   13.20 +	This program is distributed in the hope that it will be useful,
   13.21 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.22 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.23 +	GNU Library General Public License for more details.
   13.24  
   13.25 - Copyright 1997 by Jake Stine and Divine Entertainment
   13.26 -
   13.27 - If this module is found to not be portable to any particular platform,
   13.28 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   13.29 - more information on contacting the author).
   13.30 +	You should have received a copy of the GNU Library General Public
   13.31 +	License along with this library; if not, write to the Free Software
   13.32 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   13.33 +	02111-1307, USA.
   13.34  */
   13.35  
   13.36 -#include <string.h>
   13.37 -#include "mikmod.h"
   13.38 +/*==============================================================================
   13.39 +
   13.40 +  $Id$
   13.41  
   13.42 -/**************************************************************************
   13.43 -**************************************************************************/
   13.44 +  Impulse tracker (IT) module loader
   13.45 +
   13.46 +==============================================================================*/
   13.47  
   13.48 -typedef struct ITNOTE
   13.49 -{   UBYTE note,ins,volpan,cmd,inf;
   13.50 -} ITNOTE;
   13.51 +#ifdef HAVE_CONFIG_H
   13.52 +#include "config.h"
   13.53 +#endif
   13.54  
   13.55 -UBYTE *IT_ConvertTrack(ITNOTE *tr,UWORD numrows);
   13.56 +#include <ctype.h>
   13.57 +#include <string.h>
   13.58  
   13.59 +#include "mikmod_internals.h"
   13.60  
   13.61 -/* Raw IT header struct: */
   13.62 +/*========== Module structure */
   13.63  
   13.64 -typedef struct ITHEADER
   13.65 -{   CHAR  songname[26];
   13.66 -    UBYTE blank01[2];
   13.67 -    UWORD ordnum;
   13.68 -    UWORD insnum;
   13.69 -    UWORD smpnum;
   13.70 -    UWORD patnum;
   13.71 -    UWORD cwt;          /* Created with tracker (y.xx = 0x0yxx) */
   13.72 -    UWORD cmwt;         /* Compatable with tracker ver > than val. */
   13.73 -    UWORD flags;
   13.74 -    UWORD special;      /* bit 0 set = song message attached */
   13.75 -    UBYTE globvol;
   13.76 -    UBYTE mixvol;       /* mixing volume [ignored] */
   13.77 -    UBYTE initspeed;
   13.78 -    UBYTE inittempo;
   13.79 -    UBYTE pansep;       /* panning separation between channels */
   13.80 -    UBYTE zerobyte;       
   13.81 -    UWORD msglength;
   13.82 -    ULONG msgoffset;
   13.83 -    UBYTE blank02[4];
   13.84 - 
   13.85 -    UBYTE pantable[64];
   13.86 -    UBYTE voltable[64];
   13.87 +/* header */
   13.88 +typedef struct ITHEADER {
   13.89 +	CHAR	songname[26];
   13.90 +	UBYTE	blank01[2];
   13.91 +	UWORD	ordnum;
   13.92 +	UWORD	insnum;
   13.93 +	UWORD	smpnum;
   13.94 +	UWORD	patnum;
   13.95 +	UWORD	cwt;		/* Created with tracker (y.xx = 0x0yxx) */
   13.96 +	UWORD	cmwt;		/* Compatible with tracker ver > than val. */
   13.97 +	UWORD	flags;
   13.98 +	UWORD	special;	/* bit 0 set = song message attached */
   13.99 +	UBYTE	globvol;
  13.100 +	UBYTE	mixvol;		/* mixing volume [ignored] */
  13.101 +	UBYTE	initspeed;
  13.102 +	UBYTE	inittempo;
  13.103 +	UBYTE	pansep;		/* panning separation between channels */
  13.104 +	UBYTE	zerobyte;
  13.105 +	UWORD	msglength;
  13.106 +	ULONG	msgoffset;
  13.107 +	UBYTE	blank02[4];
  13.108 +	UBYTE	pantable[64];
  13.109 +	UBYTE	voltable[64];
  13.110  } ITHEADER;
  13.111  
  13.112 -
  13.113 -/* Raw IT sampleinfo struct: */
  13.114 -
  13.115 -typedef struct ITSAMPLE
  13.116 -{   CHAR  filename[12];
  13.117 -    UBYTE zerobyte;
  13.118 -    UBYTE globvol;
  13.119 -    UBYTE flag;
  13.120 -    UBYTE volume;
  13.121 -    UBYTE panning;
  13.122 -    CHAR  sampname[28];
  13.123 -    UWORD convert;        /* sample conversion flag */
  13.124 -    ULONG length;
  13.125 -    ULONG loopbeg;
  13.126 -    ULONG loopend;
  13.127 -    ULONG c5spd;
  13.128 -    ULONG susbegin;
  13.129 -    ULONG susend;
  13.130 -    ULONG sampoffset;
  13.131 -    UBYTE vibspeed;
  13.132 -    UBYTE vibdepth;
  13.133 -    UBYTE vibrate;
  13.134 -    UBYTE vibwave;    /* 0 = sine; 1 = rampdown; 2 = square; 3 = random (speed ignored) */
  13.135 -
  13.136 -    UBYTE noteindex;  /* for converting c5spd to finetune */
  13.137 +/* sample information */
  13.138 +typedef struct ITSAMPLE {
  13.139 +	CHAR	filename[12];
  13.140 +	UBYTE	zerobyte;
  13.141 +	UBYTE	globvol;
  13.142 +	UBYTE	flag;
  13.143 +	UBYTE	volume;
  13.144 +	UBYTE	panning;
  13.145 +	CHAR	sampname[28];
  13.146 +	UWORD	convert;	/* sample conversion flag */
  13.147 +	ULONG	length;
  13.148 +	ULONG	loopbeg;
  13.149 +	ULONG	loopend;
  13.150 +	ULONG	c5spd;
  13.151 +	ULONG	susbegin;
  13.152 +	ULONG	susend;
  13.153 +	ULONG	sampoffset;
  13.154 +	UBYTE	vibspeed;
  13.155 +	UBYTE	vibdepth;
  13.156 +	UBYTE	vibrate;
  13.157 +	UBYTE	vibwave;	/* 0=sine, 1=rampdown, 2=square, 3=random (speed ignored) */
  13.158  } ITSAMPLE;
  13.159  
  13.160 +/* instrument information */
  13.161  
  13.162 -typedef struct ITINSTHEADER
  13.163 -{   ULONG size;             /* (dword) Instrument size */
  13.164 -    CHAR  filename[12];     /* (char) Instrument filename */
  13.165 -    UBYTE zerobyte;         /* (byte) Instrument type (always 0) */
  13.166 -    UBYTE volflg;
  13.167 -    UBYTE volpts;   
  13.168 -    UBYTE volbeg;           /* (byte) Volume loop start (node) */
  13.169 -    UBYTE volend;           /* (byte) Volume loop end (node) */
  13.170 -    UBYTE volsusbeg;        /* (byte) Volume sustain begin (node) */
  13.171 -    UBYTE volsusend;        /* (byte) Volume Sustain end (node) */
  13.172 -    UBYTE panflg;
  13.173 -    UBYTE panpts;  
  13.174 -    UBYTE panbeg;           /* (byte) channel loop start (node) */
  13.175 -    UBYTE panend;           /* (byte) channel loop end (node) */
  13.176 -    UBYTE pansusbeg;        /* (byte) cahnnel sustain begin (node) */
  13.177 -    UBYTE pansusend;        /* (byte) channel Sustain end (node) */
  13.178 -    UBYTE pitflg;
  13.179 -    UBYTE pitpts;   
  13.180 -    UBYTE pitbeg;           /* (byte) pitch loop start (node) */
  13.181 -    UBYTE pitend;           /* (byte) pitch loop end (node) */
  13.182 -    UBYTE pitsusbeg;        /* (byte) pitch sustain begin (node) */
  13.183 -    UBYTE pitsusend;        /* (byte) pitch Sustain end (node) */
  13.184 -    UWORD blank;
  13.185 -    UBYTE globvol;
  13.186 -    UBYTE chanpan;
  13.187 -    UWORD fadeout;          /* Envelope end / NNA volume fadeout */
  13.188 -    UBYTE dnc;              /* Duplicate note check */
  13.189 -    UBYTE dca;              /* Duplicate check action */
  13.190 -    UBYTE dct;              /* Duplicate check type */
  13.191 -    UBYTE nna;              /* New Note Action [0,1,2,3] */
  13.192 -    UWORD trkvers;          /* tracker version used to save [in files only] */
  13.193 -    UBYTE ppsep;            /* Pitch-pan Separation */
  13.194 -    UBYTE ppcenter;         /* Pitch-pan Center */
  13.195 -    UBYTE rvolvar;          /* random volume varations */
  13.196 -    UBYTE rpanvar;          /* random panning varations */
  13.197 -    UWORD numsmp;           /* Number of samples in instrument [in files only] */
  13.198 -    CHAR  name[26];         /* Instrument name */
  13.199 -    UBYTE blank01[6];
  13.200 -    UWORD samptable[120];   /* sample for each note [note / samp pairs] */
  13.201 +#define ITENVCNT 25
  13.202 +#define ITNOTECNT 120
  13.203 +typedef struct ITINSTHEADER {
  13.204 +	ULONG	size;			/* (dword) Instrument size */
  13.205 +	CHAR	filename[12];	/* (char) Instrument filename */
  13.206 +	UBYTE	zerobyte;		/* (byte) Instrument type (always 0) */
  13.207 +	UBYTE	volflg;
  13.208 +	UBYTE	volpts;
  13.209 +	UBYTE	volbeg;			/* (byte) Volume loop start (node) */
  13.210 +	UBYTE	volend;			/* (byte) Volume loop end (node) */
  13.211 +	UBYTE	volsusbeg;		/* (byte) Volume sustain begin (node) */
  13.212 +	UBYTE	volsusend;		/* (byte) Volume Sustain end (node) */
  13.213 +	UBYTE	panflg;
  13.214 +	UBYTE	panpts;
  13.215 +	UBYTE	panbeg;			/* (byte) channel loop start (node) */
  13.216 +	UBYTE	panend;			/* (byte) channel loop end (node) */
  13.217 +	UBYTE	pansusbeg;		/* (byte) channel sustain begin (node) */
  13.218 +	UBYTE	pansusend;		/* (byte) channel Sustain end (node) */
  13.219 +	UBYTE	pitflg;
  13.220 +	UBYTE	pitpts;
  13.221 +	UBYTE	pitbeg;			/* (byte) pitch loop start (node) */
  13.222 +	UBYTE	pitend;			/* (byte) pitch loop end (node) */
  13.223 +	UBYTE	pitsusbeg;		/* (byte) pitch sustain begin (node) */
  13.224 +	UBYTE	pitsusend;		/* (byte) pitch Sustain end (node) */
  13.225 +	UWORD	blank;
  13.226 +	UBYTE	globvol;
  13.227 +	UBYTE	chanpan;
  13.228 +	UWORD	fadeout;		/* Envelope end / NNA volume fadeout */
  13.229 +	UBYTE	dnc;			/* Duplicate note check */
  13.230 +	UBYTE	dca;			/* Duplicate check action */
  13.231 +	UBYTE	dct;			/* Duplicate check type */
  13.232 +	UBYTE	nna;			/* New Note Action [0,1,2,3] */
  13.233 +	UWORD	trkvers;		/* tracker version used to save [files only] */
  13.234 +	UBYTE	ppsep;			/* Pitch-pan Separation */
  13.235 +	UBYTE	ppcenter;		/* Pitch-pan Center */
  13.236 +	UBYTE	rvolvar;		/* random volume varations */
  13.237 +	UBYTE	rpanvar;		/* random panning varations */
  13.238 +	UWORD	numsmp;			/* Number of samples in instrument [files only] */
  13.239 +	CHAR	name[26];		/* Instrument name */
  13.240 +	UBYTE	blank01[6];
  13.241 +	UWORD	samptable[ITNOTECNT];/* sample for each note [note / samp pairs] */
  13.242 +	UBYTE	volenv[200];	     /* volume envelope (IT 1.x stuff) */
  13.243 +	UBYTE	oldvoltick[ITENVCNT];/* volume tick position (IT 1.x stuff) */
  13.244 +	UBYTE	volnode[ITENVCNT];   /* amplitude of volume nodes */
  13.245 +	UWORD	voltick[ITENVCNT];   /* tick value of volume nodes */
  13.246 +	SBYTE	pannode[ITENVCNT];   /* panenv - node points */
  13.247 +	UWORD	pantick[ITENVCNT];   /* tick value of panning nodes */
  13.248 +	SBYTE	pitnode[ITENVCNT];   /* pitchenv - node points */
  13.249 +	UWORD	pittick[ITENVCNT];   /* tick value of pitch nodes */
  13.250 +} ITINSTHEADER;
  13.251  
  13.252 -    UBYTE volenv[200];      /* volume envelope (IT 1.x stuff) */
  13.253 -    UBYTE oldvoltick[25];   /* volume tick position (IT 1.x stuff) */
  13.254 -    UBYTE volnode[25];      /* aplitude of volume nodes */
  13.255 -    UWORD voltick[25];      /* tick value of volume nodes */
  13.256 -    SBYTE pannode[25];      /* panenv - node points */
  13.257 -    UWORD pantick[25];      /* tick value of panning nodes */
  13.258 -    SBYTE pitnode[25];      /* pitchenv - node points */
  13.259 -    UWORD pittick[25];      /* tick value of pitch nodes */
  13.260 -} ITINSTHEADER;                       
  13.261 +/* unpacked note */
  13.262  
  13.263 +typedef struct ITNOTE {
  13.264 +	UBYTE note,ins,volpan,cmd,inf;
  13.265 +} ITNOTE;
  13.266  
  13.267 -/**************************************************************************
  13.268 -**************************************************************************/
  13.269 +/*========== Loader data */
  13.270  
  13.271 -extern SBYTE    remap[64];        /* for removing empty channels */
  13.272 -extern UBYTE    *poslookup;       /* S3M/IT fix - removing blank patterns needs a */
  13.273 -                                  /* lookup table to fix position-jump commands */
  13.274 -static ULONG    *paraptr = NULL;  /* parapointer array (see IT docs) */
  13.275 -static ITHEADER *mh = NULL;
  13.276 -static ITNOTE   *itpat = NULL;    /* allocate to space for one full pattern */
  13.277 -static UBYTE    *mask = NULL;     /* arrays allocated to 64 elements and used for */
  13.278 -static ITNOTE   *last = NULL;     /* uncompressing IT's pattern information */
  13.279 -static int       numtrk = 0;
  13.280 -static int       old_effect;      /* if set, use S3M old-effects stuffs */
  13.281 -static int       *noteindex;
  13.282 -   
  13.283 -CHAR IT_Version[] = "ImpulseTracker x.xx";
  13.284 +static ULONG *paraptr=NULL;	/* parapointer array (see IT docs) */
  13.285 +static ITHEADER *mh=NULL;
  13.286 +static ITNOTE *itpat=NULL;	/* allocate to space for one full pattern */
  13.287 +static UBYTE *mask=NULL;	/* arrays allocated to 64 elements and used for */
  13.288 +static ITNOTE *last=NULL;	/* uncompressing IT's pattern information */
  13.289 +static int numtrk=0;
  13.290 +static int old_effect;		/* if set, use S3M old-effects stuffs */
  13.291  
  13.292 +static CHAR* IT_Version[]={
  13.293 +	"ImpulseTracker  .  ",
  13.294 +	"Compressed ImpulseTracker  .  ",
  13.295 +	"ImpulseTracker 2.14p3",
  13.296 +	"Compressed ImpulseTracker 2.14p3",
  13.297 +	"ImpulseTracker 2.14p4",
  13.298 +	"Compressed ImpulseTracker 2.14p4",
  13.299 +};
  13.300 +
  13.301 +/* table for porta-to-note command within volume/panning column */
  13.302 +static UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255};
  13.303 +
  13.304 +/*========== Loader code */
  13.305  
  13.306  BOOL IT_Test(void)
  13.307  {
  13.308 -    UBYTE id[4];
  13.309 -    
  13.310 -    if(!_mm_read_UBYTES(id,4,modfp)) return 0;
  13.311 -    if(!memcmp(id,"IMPM",4)) return 1;
  13.312 -    return 0;
  13.313 +	UBYTE id[4];
  13.314 +
  13.315 +	if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  13.316 +	if(!memcmp(id,"IMPM",4)) return 1;
  13.317 +	return 0;
  13.318  }
  13.319  
  13.320  BOOL IT_Init(void)
  13.321  {
  13.322 -    if((mh=(ITHEADER *)_mm_calloc(1,sizeof(ITHEADER)))==NULL) return 0;
  13.323 -    if((poslookup=(UBYTE *)_mm_malloc(256*sizeof(UBYTE)))==NULL) return 0;
  13.324 -    if((itpat=(ITNOTE *)_mm_malloc(200*64*sizeof(ITNOTE)))==NULL) return 0;
  13.325 -    if((mask=(UBYTE *)_mm_malloc(64*sizeof(UBYTE)))==NULL) return 0;
  13.326 -    if((last=(ITNOTE *)_mm_malloc(64*sizeof(ITNOTE)))==NULL) return 0;
  13.327 -    
  13.328 -    return 1;
  13.329 +	if(!(mh=(ITHEADER*)_mm_malloc(sizeof(ITHEADER)))) return 0;
  13.330 +	if(!(poslookup=(UBYTE*)_mm_malloc(256*sizeof(UBYTE)))) return 0;
  13.331 +	if(!(itpat=(ITNOTE*)_mm_malloc(200*64*sizeof(ITNOTE)))) return 0;
  13.332 +	if(!(mask=(UBYTE*)_mm_malloc(64*sizeof(UBYTE)))) return 0;
  13.333 +	if(!(last=(ITNOTE*)_mm_malloc(64*sizeof(ITNOTE)))) return 0;
  13.334 +
  13.335 +	return 1;
  13.336  }
  13.337  
  13.338  void IT_Cleanup(void)
  13.339  {
  13.340 -    if(mh!=NULL) free(mh);
  13.341 -    if(poslookup!=NULL) free(poslookup);
  13.342 -    if(itpat!=NULL) free(itpat);
  13.343 -    if(mask!=NULL) free(mask);
  13.344 -    if(last!=NULL) free(last);
  13.345 -    if(paraptr!=NULL) free(paraptr);
  13.346 -    if(noteindex!=NULL) free(noteindex);
  13.347 +	FreeLinear();
  13.348 +
  13.349 +	_mm_free(mh);
  13.350 +	_mm_free(poslookup);
  13.351 +	_mm_free(itpat);
  13.352 +	_mm_free(mask);
  13.353 +	_mm_free(last);
  13.354 +	_mm_free(paraptr);
  13.355 +	_mm_free(origpositions);
  13.356 +}
  13.357 +
  13.358 +/* Because so many IT files have 64 channels as the set number used, but really
  13.359 +   only use far less (usually from 8 to 24 still), I had to make this function,
  13.360 +   which determines the number of channels that are actually USED by a pattern.
  13.361 +
  13.362 +   NOTE: You must first seek to the file location of the pattern before calling
  13.363 +         this procedure.
  13.364 +
  13.365 +   Returns 1 on error
  13.366 +*/
  13.367 +static BOOL IT_GetNumChannels(UWORD patrows)
  13.368 +{
  13.369 +	int row=0,flag,ch;
  13.370 +
  13.371 +	do {
  13.372 +		if((flag=_mm_read_UBYTE(modreader))==EOF) {
  13.373 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.374 +			return 1;
  13.375 +		}
  13.376 +		if(!flag)
  13.377 +			row++;
  13.378 +		else {
  13.379 +			ch=(flag-1)&63;
  13.380 +			remap[ch]=0;
  13.381 +			if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader);
  13.382 +			if(mask[ch]&1)   _mm_read_UBYTE(modreader);
  13.383 +			if(mask[ch]&2)   _mm_read_UBYTE(modreader);
  13.384 +			if(mask[ch]&4)   _mm_read_UBYTE(modreader);
  13.385 +			if(mask[ch]&8) { _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader); }
  13.386 +		}
  13.387 +	} while(row<patrows);
  13.388 +
  13.389 +	return 0;
  13.390 +}
  13.391 +
  13.392 +static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows)
  13.393 +{
  13.394 +	int t;
  13.395 +	UBYTE note,ins,volpan;
  13.396 +
  13.397 +	UniReset();
  13.398  
  13.399 -    mh        = NULL;
  13.400 -    poslookup = NULL;
  13.401 -    itpat     = NULL;
  13.402 -    mask      = NULL;
  13.403 -    last      = NULL;
  13.404 -    paraptr   = NULL;
  13.405 -    noteindex = NULL;
  13.406 +	for(t=0;t<numrows;t++) {
  13.407 +		note=tr[t*of.numchn].note;
  13.408 +		ins=tr[t*of.numchn].ins;
  13.409 +		volpan=tr[t*of.numchn].volpan;
  13.410 +
  13.411 +		if(note!=255) {
  13.412 +			if(note==253)
  13.413 +				UniWriteByte(UNI_KEYOFF);
  13.414 +			else if(note==254) {
  13.415 +				UniPTEffect(0xc,-1);	/* note cut command */
  13.416 +				volpan=255;
  13.417 +			} else
  13.418 +				UniNote(note);
  13.419 +		}
  13.420 +
  13.421 +		if((ins)&&(ins<100))
  13.422 +			UniInstrument(ins-1);
  13.423 +		else if(ins==253)
  13.424 +			UniWriteByte(UNI_KEYOFF);
  13.425 +		else if(ins!=255) { /* crap */
  13.426 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.427 +			return NULL;
  13.428 +		}
  13.429 +
  13.430 +		/* process volume / panning column
  13.431 +		   volume / panning effects do NOT all share the same memory address
  13.432 +		   yet. */
  13.433 +		if(volpan<=64)
  13.434 +			UniVolEffect(VOL_VOLUME,volpan);
  13.435 +		else if(volpan<=74)	/* fine volume slide up (65-74) */
  13.436 +			UniVolEffect(VOL_VOLSLIDE,0x0f+((volpan-65)<<4));
  13.437 +		else if(volpan<=84)	/* fine volume slide down (75-84) */
  13.438 +			UniVolEffect(VOL_VOLSLIDE,0xf0+(volpan-75));
  13.439 +		else if(volpan<=94)	/* volume slide up (85-94) */
  13.440 +			UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4));
  13.441 +		else if(volpan<=104)/* volume slide down (95-104) */
  13.442 +			UniVolEffect(VOL_VOLSLIDE,(volpan-95));
  13.443 +		else if(volpan<=114)/* pitch slide down (105-114) */
  13.444 +			UniVolEffect(VOL_PITCHSLIDEDN,(volpan-105));
  13.445 +		else if(volpan<=124)/* pitch slide up (115-124) */
  13.446 +			UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115));
  13.447 +		else if(volpan<=127) { /* crap */
  13.448 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.449 +			return NULL;
  13.450 +		} else if(volpan<=192)
  13.451 +			UniVolEffect(VOL_PANNING,((volpan-128)==64)?255:((volpan-128)<<2));
  13.452 +		else if(volpan<=202)/* portamento to note */
  13.453 +			UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]);
  13.454 +		else if(volpan<=212)/* vibrato */
  13.455 +			UniVolEffect(VOL_VIBRATO,(volpan-203));
  13.456 +		else if((volpan!=239)&&(volpan!=255)) { /* crap */
  13.457 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.458 +			return NULL;
  13.459 +		}
  13.460 +
  13.461 +		S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,old_effect|2);
  13.462 +
  13.463 +		UniNewline();
  13.464 +	}
  13.465 +	return UniDup();
  13.466  }
  13.467  
  13.468 +static BOOL IT_ReadPattern(UWORD patrows)
  13.469 +{
  13.470 +	int row=0,flag,ch,blah;
  13.471 +	ITNOTE *itt=itpat,dummy,*n,*l;
  13.472  
  13.473 -BOOL IT_GetNumChannels(UWORD patrows)
  13.474 +	memset(itt,255,200*64*sizeof(ITNOTE));
  13.475  
  13.476 -/* Because so many IT files have 64 channels as the set number used, but really */
  13.477 -/* only use far less (usually 8 to 12 still), I had to make this function, */
  13.478 -/* which determines the number of channels that are actually USED by a pattern. */
  13.479 -/* */
  13.480 -/* For every channel that's used, it sets the appropriate array entry of the */
  13.481 -/* global varialbe 'isused' */
  13.482 -/* */
  13.483 -/* NOTE: You must first seek to the file location of the pattern before calling */
  13.484 -/*       this procedure. */
  13.485 -/* Returns 1 on error */
  13.486 -{
  13.487 -    int  row=0,flag,ch;
  13.488 +	do {
  13.489 +		if((flag=_mm_read_UBYTE(modreader))==EOF) {
  13.490 +			_mm_errno = MMERR_LOADING_PATTERN;
  13.491 +			return 0;
  13.492 +		}
  13.493 +		if(!flag) {
  13.494 +			itt=&itt[of.numchn];
  13.495 +			row++;
  13.496 +		} else {
  13.497 +			ch=remap[(flag-1)&63];
  13.498 +			if(ch!=-1) {
  13.499 +				n=&itt[ch];
  13.500 +				l=&last[ch];
  13.501 +			} else
  13.502 +				n=l=&dummy;
  13.503  
  13.504 -    do
  13.505 -    {   flag = _mm_read_UBYTE(modfp);
  13.506 -        if(flag == EOF)
  13.507 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  13.508 -            return 1;
  13.509 -        }
  13.510 +			if(flag&128) mask[ch]=_mm_read_UBYTE(modreader);
  13.511 +			if(mask[ch]&1)
  13.512 +				/* convert IT note off to internal note off */
  13.513 +				if((l->note=n->note=_mm_read_UBYTE(modreader))==255)
  13.514 +					l->note=n->note=253;
  13.515 +			if(mask[ch]&2)
  13.516 +				l->ins=n->ins=_mm_read_UBYTE(modreader);
  13.517 +			if(mask[ch]&4)
  13.518 +				l->volpan=n->volpan=_mm_read_UBYTE(modreader);
  13.519 +			if(mask[ch]&8) {
  13.520 +				l->cmd=n->cmd=_mm_read_UBYTE(modreader);
  13.521 +				l->inf=n->inf=_mm_read_UBYTE(modreader);
  13.522 +			}
  13.523 +			if(mask[ch]&16)
  13.524 +				n->note=l->note;
  13.525 +			if(mask[ch]&32)
  13.526 +				n->ins=l->ins;
  13.527 +			if(mask[ch]&64)
  13.528 +				n->volpan=l->volpan;
  13.529 +			if(mask[ch]&128) {
  13.530 +				n->cmd=l->cmd;
  13.531 +				n->inf=l->inf;
  13.532 +			}
  13.533 +		}
  13.534 +	} while(row<patrows);
  13.535  
  13.536 -        if(flag == 0)
  13.537 -        {   row++;
  13.538 -        } else
  13.539 -        {   ch = (flag-1) & 63;
  13.540 -            remap[ch] = 0;
  13.541 -            if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp);
  13.542 -            if(mask[ch] &   1) _mm_read_UBYTE(modfp);
  13.543 -            if(mask[ch] &   2) _mm_read_UBYTE(modfp);
  13.544 -            if(mask[ch] &   4) _mm_read_UBYTE(modfp);
  13.545 -            if(mask[ch] &   8) { _mm_read_UBYTE(modfp); _mm_read_UBYTE(modfp); }
  13.546 -        }
  13.547 -    } while(row < patrows);
  13.548 +	for(blah=0;blah<of.numchn;blah++) {
  13.549 +		if(!(of.tracks[numtrk++]=IT_ConvertTrack(&itpat[blah],patrows)))
  13.550 +			return 0;
  13.551 +	}
  13.552  
  13.553 -    return 0;
  13.554 +	return 1;
  13.555  }
  13.556  
  13.557 -
  13.558 -BOOL IT_ReadPattern(UWORD patrows)
  13.559 +static void LoadMidiString(MREADER* modreader,CHAR* dest)
  13.560  {
  13.561 -   int    blah;
  13.562 -   int    row=0,flag,ch;
  13.563 -   ITNOTE *itt = itpat, dummy,*n,*l;
  13.564 +	CHAR *cur,*last;
  13.565 +
  13.566 +	_mm_read_UBYTES(dest,32,modreader);
  13.567 +	cur=last=dest;
  13.568 +	/* remove blanks and uppercase all */
  13.569 +	while(*last) {
  13.570 +		if(isalnum((int)*last)) *(cur++)=toupper((int)*last);
  13.571 +		last++;
  13.572 +	}
  13.573 +	*cur=0;
  13.574 +}
  13.575  
  13.576 -   memset(itt,255,patrows*of.numchn*sizeof(ITNOTE));
  13.577 +/* Load embedded midi information for resonant filters */
  13.578 +static void IT_LoadMidiConfiguration(MREADER* modreader)
  13.579 +{
  13.580 +	int i;
  13.581 +
  13.582 +	memset(filtermacros,0,sizeof(filtermacros));
  13.583 +	memset(filtersettings,0,sizeof(filtersettings));
  13.584 +
  13.585 +	if (modreader) { /* information is embedded in file */
  13.586 +		UWORD dat;
  13.587 +		CHAR midiline[33];
  13.588 +
  13.589 +		dat=_mm_read_I_UWORD(modreader);
  13.590 +		_mm_fseek(modreader,8*dat+0x120,SEEK_CUR);
  13.591  
  13.592 -   do 
  13.593 -   {   flag = _mm_read_UBYTE(modfp);
  13.594 -       if(feof(modfp))
  13.595 -       {   _mm_errno = MMERR_LOADING_PATTERN;
  13.596 -           return 0;
  13.597 -       }
  13.598 -       if(flag == 0)
  13.599 -       {   itt = &itt[of.numchn];
  13.600 -           row++;
  13.601 -       } else
  13.602 -       {   ch = remap[(flag-1) & 63];
  13.603 -           if(ch != -1)
  13.604 -           {   n = &itt[ch];
  13.605 -               l = &last[ch];
  13.606 -           } else
  13.607 -           {   n = l = &dummy;  }
  13.608 +		/* read midi macros */
  13.609 +		for(i=0;i<16;i++) {
  13.610 +			LoadMidiString(modreader,midiline);
  13.611 +			if((!strncmp(midiline,"F0F00",5))&&
  13.612 +			   ((midiline[5]=='0')||(midiline[5]=='1')))
  13.613 +					filtermacros[i]=(midiline[5]-'0')|0x80;
  13.614 +		}
  13.615  
  13.616 -           if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp);
  13.617 -           if(mask[ch] &   1) if((l->note = n->note   = _mm_read_UBYTE(modfp)) == 255)
  13.618 -                              {   l->note = n->note   = 253; }
  13.619 -           if(mask[ch] &   2) l->ins      = n->ins    = _mm_read_UBYTE(modfp);
  13.620 -           if(mask[ch] &   4) l->volpan   = n->volpan = _mm_read_UBYTE(modfp);
  13.621 -           if(mask[ch] &   8) { l->cmd    = n->cmd    = _mm_read_UBYTE(modfp);
  13.622 -                                l->inf    = n->inf    = _mm_read_UBYTE(modfp); }
  13.623 -           if(mask[ch] &  16) n->note     = l->note;
  13.624 -           if(mask[ch] &  32) n->ins      = l->ins;
  13.625 -           if(mask[ch] &  64) n->volpan   = l->volpan;
  13.626 -           if(mask[ch] & 128) { n->cmd    = l->cmd;
  13.627 -                                n->inf    = l->inf; }
  13.628 -        }
  13.629 -   } while(row < patrows);
  13.630 -
  13.631 -   for(blah=0; blah<of.numchn; blah++)
  13.632 -       of.tracks[numtrk++] = IT_ConvertTrack(&itpat[blah],patrows);
  13.633 -
  13.634 -   return 1;
  13.635 +		/* read standalone filters */
  13.636 +		for(i=0x80;i<0x100;i++) {
  13.637 +			LoadMidiString(modreader,midiline);
  13.638 +			if((!strncmp(midiline,"F0F00",5))&&
  13.639 +			   ((midiline[5]=='0')||(midiline[5]=='1'))) {
  13.640 +				filtersettings[i].filter=(midiline[5]-'0')|0x80;
  13.641 +				dat=(midiline[6])?(midiline[6]-'0'):0;
  13.642 +				if(midiline[7])dat=(dat<<4)|(midiline[7]-'0');
  13.643 +				filtersettings[i].inf=dat;
  13.644 +			}
  13.645 +		}
  13.646 +	} else { /* use default information */
  13.647 +		filtermacros[0]=FILT_CUT;
  13.648 +		for(i=0x80;i<0x90;i++) {
  13.649 +			filtersettings[i].filter=FILT_RESONANT;
  13.650 +			filtersettings[i].inf=(i&0x7f)<<3;
  13.651 +		}
  13.652 +	}
  13.653 +	activemacro=0;
  13.654 +	for(i=0;i<0x80;i++) {
  13.655 +		filtersettings[i].filter=filtermacros[0];
  13.656 +		filtersettings[i].inf=i;
  13.657 +	}
  13.658  }
  13.659  
  13.660 -
  13.661 -void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, BOOL oldeffect);
  13.662 -
  13.663 -/* table for porta-to-note command within volume/panning column */
  13.664 -static UBYTE portatable[] = "1, 4, 8, 16, 32, 64, 96, 128, 255";
  13.665 -
  13.666 -UBYTE *IT_ConvertTrack(ITNOTE *tr, UWORD numrows)
  13.667 -{
  13.668 -    int t;
  13.669 -
  13.670 -    UBYTE note,ins,volpan;
  13.671 -
  13.672 -    UniReset();
  13.673 -
  13.674 -    for(t=0; t<numrows; t++)
  13.675 -    {   note    = tr[t*of.numchn].note;
  13.676 -        ins     = tr[t*of.numchn].ins;
  13.677 -        volpan  = tr[t*of.numchn].volpan;
  13.678 -
  13.679 -        if(note!=255)
  13.680 -        {   if(note==253)
  13.681 -                UniWrite(UNI_KEYOFF);
  13.682 -            else if(note==254)
  13.683 -                UniPTEffect(0xc,0);   /* <- note cut command */
  13.684 -            else
  13.685 -                UniNote(note);
  13.686 -        }
  13.687 -
  13.688 -        if((ins != 0) && (ins < 100)) UniInstrument(ins-1);
  13.689 -
  13.690 -        /* process volume / panning column */
  13.691 -        /* volume / panning effects do NOT all share the same memory address */
  13.692 -        /* yet.  That requires more work than I care to apply at the moment ;) */
  13.693 -
  13.694 -        if(volpan<=64)
  13.695 -        {   UniVolEffect(VOL_VOLUME,volpan);
  13.696 -        } else if((volpan>=65) && (volpan<=74))        /* fine volume slide up (65-74) */
  13.697 -        {   UniVolEffect(VOL_VOLSLIDE,0x0f + ((volpan-65)<<4));
  13.698 -        } else if((volpan>=75) && (volpan<=84))        /* fine volume slide down   (75-84) */
  13.699 -        {   UniVolEffect(VOL_VOLSLIDE,0xf0 + (volpan-75));
  13.700 -        } else if((volpan>=85) && (volpan<=94))        /* volume slide up (85-94) */
  13.701 -        {   UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4));
  13.702 -        } else if((volpan>=95) && (volpan<=104))       /* volume slide down   (95-104) */
  13.703 -        {   UniVolEffect(VOL_VOLSLIDE,(volpan-95));
  13.704 -        } else if((volpan>=105) && (volpan<=114))      /* pitch slide up (105-114) */
  13.705 -        {   UniVolEffect(VOL_PITCHSLIDEDN,((volpan-105)<<4));
  13.706 -        } else if((volpan>=115) && (volpan<=124))      /* pitch slide down (115-124) */
  13.707 -        {   UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115));
  13.708 -        } else if((volpan>=128) && (volpan<=192))
  13.709 -        {   UniVolEffect(VOL_PANNING,((volpan-128) == 64) ? 255 : ((volpan-128) << 2));
  13.710 -        } else if((volpan>=193) && (volpan<=202))      /* portamento to note */
  13.711 -        {   UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]);
  13.712 -        } else if((volpan>=203) && (volpan<=212))      /* vibrato */
  13.713 -        {   UniVolEffect(VOL_VIBRATO,(volpan-203));
  13.714 -        }
  13.715 -
  13.716 -        S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,old_effect);
  13.717 -
  13.718 -        UniNewline();
  13.719 -    }
  13.720 -    return UniDup();
  13.721 -}
  13.722 -                                             
  13.723 -
  13.724 -int cvt_c5spd_to_finetune(ULONG c5spd, int sampnum)
  13.725 +BOOL IT_Load(BOOL curious)
  13.726  {
  13.727 -    int ctmp=0,tmp,note=1,finetune=0;
  13.728 -
  13.729 -    c5spd/=2;
  13.730 +	int t,u,lp;
  13.731 +	INSTRUMENT *d;
  13.732 +	SAMPLE *q;
  13.733 +	BOOL compressed=0;
  13.734  
  13.735 -    do
  13.736 -    {   tmp = getfrequency(of.flags,getlinearperiod(note,0));
  13.737 -        if(tmp >= c5spd) break;
  13.738 -        ctmp = tmp;
  13.739 -        note++;
  13.740 -    } while(1);
  13.741 +	numtrk=0;
  13.742 +	filters=0;
  13.743  
  13.744 -    if(tmp != c5spd)
  13.745 -    {   if((tmp-c5spd) < (c5spd-ctmp))
  13.746 -            while(tmp>c5spd) tmp = getfrequency(of.flags,getlinearperiod(note,--finetune));
  13.747 -        else
  13.748 -        {   note--;
  13.749 -            while(ctmp<c5spd) ctmp = getfrequency(of.flags,getlinearperiod(note,++finetune));
  13.750 -        }
  13.751 -    }
  13.752 +	/* try to read module header */
  13.753 +	_mm_read_I_ULONG(modreader);	/* kill the 4 byte header */
  13.754 +	_mm_read_string(mh->songname,26,modreader);
  13.755 +	_mm_read_UBYTES(mh->blank01,2,modreader);
  13.756 +	mh->ordnum      =_mm_read_I_UWORD(modreader);
  13.757 +	mh->insnum      =_mm_read_I_UWORD(modreader);
  13.758 +	mh->smpnum      =_mm_read_I_UWORD(modreader);
  13.759 +	mh->patnum      =_mm_read_I_UWORD(modreader);
  13.760 +	mh->cwt         =_mm_read_I_UWORD(modreader);
  13.761 +	mh->cmwt        =_mm_read_I_UWORD(modreader);
  13.762 +	mh->flags       =_mm_read_I_UWORD(modreader);
  13.763 +	mh->special     =_mm_read_I_UWORD(modreader);
  13.764 +	mh->globvol     =_mm_read_UBYTE(modreader);
  13.765 +	mh->mixvol      =_mm_read_UBYTE(modreader);
  13.766 +	mh->initspeed   =_mm_read_UBYTE(modreader);
  13.767 +	mh->inittempo   =_mm_read_UBYTE(modreader);
  13.768 +	mh->pansep      =_mm_read_UBYTE(modreader);
  13.769 +	mh->zerobyte    =_mm_read_UBYTE(modreader);
  13.770 +	mh->msglength   =_mm_read_I_UWORD(modreader);
  13.771 +	mh->msgoffset   =_mm_read_I_ULONG(modreader);
  13.772 +	_mm_read_UBYTES(mh->blank02,4,modreader);
  13.773 +	_mm_read_UBYTES(mh->pantable,64,modreader);
  13.774 +	_mm_read_UBYTES(mh->voltable,64,modreader);
  13.775  
  13.776 -    noteindex[sampnum] = note-48;
  13.777 -    return finetune;
  13.778 -}       
  13.779 -
  13.780 +	if(_mm_eof(modreader)) {
  13.781 +		_mm_errno=MMERR_LOADING_HEADER;
  13.782 +		return 0;
  13.783 +	}
  13.784  
  13.785 -BOOL IT_Load(void)
  13.786 -{
  13.787 -    int        t,u,lp;
  13.788 -    INSTRUMENT *d;
  13.789 -    SAMPLE     *q;
  13.790 +	/* set module variables */
  13.791 +	of.songname    = DupStr(mh->songname,26,0); /* make a cstr of songname  */
  13.792 +	of.reppos      = 0;
  13.793 +	of.numpat      = mh->patnum;
  13.794 +	of.numins      = mh->insnum;
  13.795 +	of.numsmp      = mh->smpnum;
  13.796 +	of.initspeed   = mh->initspeed;
  13.797 +	of.inittempo   = mh->inittempo;
  13.798 +	of.initvolume  = mh->globvol;
  13.799 +	of.flags      |= UF_BGSLIDES|UF_ARPMEM;
  13.800  
  13.801 -    numtrk = 0;
  13.802 +	if(mh->songname[25]) {
  13.803 +		of.numvoices=1+mh->songname[25];
  13.804 +#ifdef MIKMOD_DEBUG
  13.805 +		fprintf(stderr,"Embedded IT limitation to %d voices\n",of.numvoices);
  13.806 +#endif
  13.807 +	}
  13.808  
  13.809 -    /* try to read module header */
  13.810 +	/* set the module type */
  13.811 +	/* 2.17 : IT 2.14p4 */
  13.812 +	/* 2.16 : IT 2.14p3 with resonant filters */
  13.813 +	/* 2.15 : IT 2.14p3 (improved compression) */
  13.814 +	if((mh->cwt<=0x219)&&(mh->cwt>=0x217))
  13.815 +		of.modtype=strdup(IT_Version[mh->cmwt<0x214?4:5]);
  13.816 +	else if (mh->cwt>=0x215)
  13.817 +		of.modtype=strdup(IT_Version[mh->cmwt<0x214?2:3]);
  13.818 +	else {
  13.819 +		of.modtype     = strdup(IT_Version[mh->cmwt<0x214?0:1]);
  13.820 +		of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0';
  13.821 +		of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0';
  13.822 +		of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0';
  13.823 +	}
  13.824  
  13.825 -    _mm_read_I_ULONG(modfp);   /* kill the 4 byte header */
  13.826 -    _mm_read_string(mh->songname,26,modfp);
  13.827 -    _mm_read_UBYTES(mh->blank01,2,modfp);
  13.828 -    mh->ordnum      =_mm_read_I_UWORD(modfp);
  13.829 -    mh->insnum      =_mm_read_I_UWORD(modfp);
  13.830 -    mh->smpnum      =_mm_read_I_UWORD(modfp);
  13.831 -    mh->patnum      =_mm_read_I_UWORD(modfp);
  13.832 -    mh->cwt         =_mm_read_I_UWORD(modfp);
  13.833 -    mh->cmwt        =_mm_read_I_UWORD(modfp);
  13.834 -    mh->flags       =_mm_read_I_UWORD(modfp);
  13.835 -    mh->special     =_mm_read_I_UWORD(modfp);
  13.836 +	if(mh->flags&8)
  13.837 +		of.flags|=(UF_XMPERIODS | UF_LINEAR);
  13.838 +
  13.839 +	if((mh->cwt>=0x106)&&(mh->flags&16))
  13.840 +		old_effect=1;
  13.841 +	else
  13.842 +		old_effect=0;
  13.843  
  13.844 -    mh->globvol     =_mm_read_UBYTE(modfp);
  13.845 -    mh->mixvol      =_mm_read_UBYTE(modfp);
  13.846 -    mh->initspeed   =_mm_read_UBYTE(modfp);
  13.847 -    mh->inittempo   =_mm_read_UBYTE(modfp);
  13.848 -    mh->pansep      =_mm_read_UBYTE(modfp);
  13.849 -    mh->zerobyte    =_mm_read_UBYTE(modfp);
  13.850 -    mh->msglength   =_mm_read_I_UWORD(modfp);
  13.851 -    mh->msgoffset   =_mm_read_I_ULONG(modfp);
  13.852 -    _mm_read_UBYTES(mh->blank02,4,modfp);
  13.853 -    _mm_read_UBYTES(mh->pantable,64,modfp);
  13.854 -    _mm_read_UBYTES(mh->voltable,64,modfp);
  13.855 +	/* set panning positions */
  13.856 +	for(t=0;t<64;t++) {
  13.857 +		mh->pantable[t]&=0x7f;
  13.858 +		if(mh->pantable[t]<64)
  13.859 +			of.panning[t]=mh->pantable[t]<<2;
  13.860 +		else if(mh->pantable[t]==64)
  13.861 +			of.panning[t]=255;
  13.862 +		else if(mh->pantable[t]==100)
  13.863 +			of.panning[t]=PAN_SURROUND;
  13.864 +		else if(mh->pantable[t]==127)
  13.865 +			of.panning[t]=PAN_CENTER;
  13.866 +		else {
  13.867 +			_mm_errno=MMERR_LOADING_HEADER;
  13.868 +			return 0;
  13.869 +		}
  13.870 +	}
  13.871 +
  13.872 +	/* set channel volumes */
  13.873 +	memcpy(of.chanvol,mh->voltable,64);
  13.874 +
  13.875 +	/* read the order data */
  13.876 +	if(!AllocPositions(mh->ordnum)) return 0;
  13.877 +	if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
  13.878  
  13.879 -    if(feof(modfp))
  13.880 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.881 -        return 0;
  13.882 -    }
  13.883 +	for(t=0;t<mh->ordnum;t++) {
  13.884 +		origpositions[t]=_mm_read_UBYTE(modreader);
  13.885 +		if((origpositions[t]>mh->patnum)&&(origpositions[t]<254))
  13.886 +			origpositions[t]=255;
  13.887 +	}
  13.888 +
  13.889 +	if(_mm_eof(modreader)) {
  13.890 +		_mm_errno = MMERR_LOADING_HEADER;
  13.891 +		return 0;
  13.892 +	}
  13.893  
  13.894 -    /* set module variables */
  13.895 +	poslookupcnt=mh->ordnum;
  13.896 +	S3MIT_CreateOrders(curious);
  13.897 +
  13.898 +	if(!(paraptr=(ULONG*)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*
  13.899 +	                               sizeof(ULONG)))) return 0;
  13.900 +
  13.901 +	/* read the instrument, sample, and pattern parapointers */
  13.902 +	_mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modreader);
  13.903 +
  13.904 +	if(_mm_eof(modreader)) {
  13.905 +		_mm_errno = MMERR_LOADING_HEADER;
  13.906 +		return 0;
  13.907 +	}
  13.908  
  13.909 -    of.modtype     = strdup(IT_Version);
  13.910 -    of.modtype[15] = (mh->cwt >> 8) + 0x30;
  13.911 -    of.modtype[17] = ((mh->cwt >> 4) & 0xf) + 0x30;
  13.912 -    of.modtype[18] = ((mh->cwt) & 0xf) + 0x30;
  13.913 -    of.songname    = DupStr(mh->songname,26);    /* make a cstr of songname  */
  13.914 -    of.reppos      = 0;
  13.915 -    of.numpat      = mh->patnum;
  13.916 -    of.numins      = mh->insnum;
  13.917 -    of.numsmp      = mh->smpnum;
  13.918 -    of.initspeed   = mh->initspeed;
  13.919 -    of.inittempo   = mh->inittempo;
  13.920 -    of.initvolume  = mh->globvol;
  13.921 +	/* Check for and load midi information for resonant filters */
  13.922 +	if(mh->cmwt>=0x216) {
  13.923 +		if(mh->special&8) {
  13.924 +			IT_LoadMidiConfiguration(modreader);
  13.925 +			if(_mm_eof(modreader)) {
  13.926 +				_mm_errno = MMERR_LOADING_HEADER;
  13.927 +				return 0;
  13.928 +			}
  13.929 +		} else
  13.930 +			IT_LoadMidiConfiguration(NULL);
  13.931 +		filters=1;
  13.932 +	}
  13.933  
  13.934 -    old_effect = 0;
  13.935 -    if(mh->flags & 8) { of.flags |= (UF_XMPERIODS | UF_LINEAR); old_effect |= 2; }
  13.936 -    if((mh->cwt >= 0x106) && (mh->flags & 16))  old_effect |= 1;
  13.937 +	/* Check for and load song comment */
  13.938 +	if((mh->special&1)&&(mh->cwt>=0x104)&&(mh->msglength)) {
  13.939 +		_mm_fseek(modreader,(long)(mh->msgoffset),SEEK_SET);
  13.940 +		if(!ReadComment(mh->msglength)) return 0;
  13.941 +	}
  13.942  
  13.943 -    /* set panning positions */
  13.944 -    for(t=0; t<64; t++)
  13.945 -    {   if(mh->pantable[t] < 64) of.panning[t] = mh->pantable[t] << 2;
  13.946 -        else if(mh->pantable[t]==64) of.panning[t] = 255;
  13.947 -        else if(mh->pantable[t]==100) of.panning[t] = PAN_SURROUND;
  13.948 -    }
  13.949 +	if(!(mh->flags&4)) of.numins=of.numsmp;
  13.950 +	if(!AllocSamples()) return 0;
  13.951 +
  13.952 +	if(!AllocLinear()) return 0;
  13.953  
  13.954 -    /* set channel volumes */
  13.955 -    memcpy(of.chanvol,mh->voltable,64);
  13.956 -
  13.957 -    /* read the order data */
  13.958 -    if(!AllocPositions(mh->ordnum)) return 0;
  13.959 -
  13.960 -    for(t=0; t<mh->ordnum; t++)
  13.961 -        of.positions[t] = _mm_read_UBYTE(modfp);
  13.962 +	/* Load all samples */
  13.963 +	q = of.samples;
  13.964 +	for(t=0;t<mh->smpnum;t++) {
  13.965 +		ITSAMPLE s;
  13.966  
  13.967 -    if(feof(modfp))
  13.968 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.969 -        return 0;
  13.970 -    }
  13.971 -    
  13.972 -    of.numpos = 0;
  13.973 -    for(t=0; t<mh->ordnum; t++)
  13.974 -    {   of.positions[of.numpos] = of.positions[t];
  13.975 -        poslookup[t] = of.numpos;    /* bug fix for FREAKY S3Ms / ITs */
  13.976 -        if(of.positions[t]<254) of.numpos++;
  13.977 -    }
  13.978 -
  13.979 -    if((paraptr=(ULONG *)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*sizeof(ULONG))) == NULL) return 0;
  13.980 -
  13.981 -    /* read the instrument, sample, and pattern parapointers */
  13.982 -    _mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modfp);
  13.983 +		/* seek to sample position */
  13.984 +		_mm_fseek(modreader,(long)(paraptr[mh->insnum+t]+4),SEEK_SET);
  13.985  
  13.986 -    /* now is a good time to check if the header was too short :) */
  13.987 -    if(feof(modfp))
  13.988 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.989 -        return 0;
  13.990 -    }
  13.991 +		/* load sample info */
  13.992 +		_mm_read_string(s.filename,12,modreader);
  13.993 +		s.zerobyte    = _mm_read_UBYTE(modreader);
  13.994 +		s.globvol     = _mm_read_UBYTE(modreader);
  13.995 +		s.flag        = _mm_read_UBYTE(modreader);
  13.996 +		s.volume      = _mm_read_UBYTE(modreader);
  13.997 +		_mm_read_string(s.sampname,26,modreader);
  13.998 +		s.convert     = _mm_read_UBYTE(modreader);
  13.999 +		s.panning     = _mm_read_UBYTE(modreader);
 13.1000 +		s.length      = _mm_read_I_ULONG(modreader);
 13.1001 +		s.loopbeg     = _mm_read_I_ULONG(modreader);
 13.1002 +		s.loopend     = _mm_read_I_ULONG(modreader);
 13.1003 +		s.c5spd       = _mm_read_I_ULONG(modreader);
 13.1004 +		s.susbegin    = _mm_read_I_ULONG(modreader);
 13.1005 +		s.susend      = _mm_read_I_ULONG(modreader);
 13.1006 +		s.sampoffset  = _mm_read_I_ULONG(modreader);
 13.1007 +		s.vibspeed    = _mm_read_UBYTE(modreader);
 13.1008 +		s.vibdepth    = _mm_read_UBYTE(modreader);
 13.1009 +		s.vibrate     = _mm_read_UBYTE(modreader);
 13.1010 +		s.vibwave     = _mm_read_UBYTE(modreader);
 13.1011  
 13.1012 -    /* Check for and load song comment */
 13.1013 -    if(mh->special & 1)
 13.1014 -    {   _mm_fseek(modfp,(long)(mh->msgoffset),SEEK_SET);
 13.1015 -        if(!ReadComment(mh->msglength)) return 0;
 13.1016 -    }
 13.1017 +		/* Generate an error if c5spd is > 512k, or samplelength > 256 megs
 13.1018 +		   (nothing would EVER be that high) */
 13.1019  
 13.1020 -    if(!(mh->flags & 4)) of.numins = of.numsmp;
 13.1021 -    if(!AllocSamples()) return 0;
 13.1022 -
 13.1023 -    if((noteindex=(int *)_mm_malloc(mh->smpnum*sizeof(int)))==NULL) return 0;
 13.1024 -        
 13.1025 -    q = of.samples;
 13.1026 +		if(_mm_eof(modreader)||(s.c5spd>0x7ffffL)||(s.length>0xfffffffUL)||
 13.1027 +		   (s.loopbeg>0xfffffffUL)||(s.loopend>0xfffffffUL)) {
 13.1028 +			_mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1029 +			return 0;
 13.1030 +		}
 13.1031  
 13.1032 -    /* Load all samples (they're used either way) */
 13.1033 -    for(t=0; t<mh->smpnum; t++)
 13.1034 -    {   ITSAMPLE s;
 13.1035 +		q->samplename = DupStr(s.sampname,26,0);
 13.1036 +		q->speed      = s.c5spd / 2;
 13.1037 +		q->panning    = ((s.panning&127)==64)?255:(s.panning&127)<<2;
 13.1038 +		q->length     = s.length;
 13.1039 +		q->loopstart  = s.loopbeg;
 13.1040 +		q->loopend    = s.loopend;
 13.1041 +		q->volume     = s.volume;
 13.1042 +		q->globvol    = s.globvol;
 13.1043 +		q->seekpos    = s.sampoffset;
 13.1044  
 13.1045 -        /* seek to sample position */
 13.1046 -        _mm_fseek(modfp,(long)(paraptr[mh->insnum+t] + 4),SEEK_SET);
 13.1047 +		/* Convert speed to XM linear finetune */
 13.1048 +		if(of.flags&UF_LINEAR)
 13.1049 +			q->speed=speed_to_finetune(s.c5spd,t);
 13.1050 +
 13.1051 +		if(s.panning&128) q->flags|=SF_OWNPAN;
 13.1052  
 13.1053 -        /* and load sample info */
 13.1054 -        _mm_read_string(s.filename,12,modfp);
 13.1055 -        s.zerobyte    = _mm_read_UBYTE(modfp);
 13.1056 -        s.globvol     = _mm_read_UBYTE(modfp);
 13.1057 -        s.flag        = _mm_read_UBYTE(modfp);
 13.1058 -        s.volume      = _mm_read_UBYTE(modfp);
 13.1059 -        _mm_read_string(s.sampname,26,modfp);
 13.1060 -        s.convert     = _mm_read_UBYTE(modfp);
 13.1061 -        s.panning     = _mm_read_UBYTE(modfp);
 13.1062 -        s.length      = _mm_read_I_ULONG(modfp);
 13.1063 -        s.loopbeg     = _mm_read_I_ULONG(modfp);
 13.1064 -        s.loopend     = _mm_read_I_ULONG(modfp);
 13.1065 -        s.c5spd       = _mm_read_I_ULONG(modfp);
 13.1066 -        s.susbegin    = _mm_read_I_ULONG(modfp);
 13.1067 -        s.susend      = _mm_read_I_ULONG(modfp);
 13.1068 -        s.sampoffset  = _mm_read_I_ULONG(modfp);
 13.1069 -        s.vibspeed    = _mm_read_UBYTE(modfp);
 13.1070 -        s.vibdepth    = _mm_read_UBYTE(modfp);
 13.1071 -        s.vibrate     = _mm_read_UBYTE(modfp);
 13.1072 -        s.vibwave     = _mm_read_UBYTE(modfp);
 13.1073 +		if(s.vibrate) {
 13.1074 +			q->vibflags |= AV_IT;
 13.1075 +			q->vibtype   = s.vibwave;
 13.1076 +			q->vibsweep  = s.vibrate * 2;
 13.1077 +			q->vibdepth  = s.vibdepth;
 13.1078 +			q->vibrate   = s.vibspeed;
 13.1079 +		}
 13.1080  
 13.1081 - 
 13.1082 -        /* Generate an error if c5spd is > 512k, or samplelength > 256 megs */
 13.1083 -        /*  (nothing would EVER be that high) */
 13.1084 +		if(s.flag&2) q->flags|=SF_16BITS;
 13.1085 +		if((s.flag&8)&&(mh->cwt>=0x214)) {
 13.1086 +			q->flags|=SF_ITPACKED;
 13.1087 +			compressed=1;
 13.1088 +		}
 13.1089 +		if(s.flag&16) q->flags|=SF_LOOP;
 13.1090 +		if(s.flag&64) q->flags|=SF_BIDI;
 13.1091 +
 13.1092 +		if(mh->cwt>=0x200) {
 13.1093 +			if(s.convert&1) q->flags|=SF_SIGNED;
 13.1094 +			if(s.convert&4) q->flags|=SF_DELTA;
 13.1095 +		}
 13.1096 +
 13.1097 +		q++;
 13.1098 +	}
 13.1099  
 13.1100 -        if(feof(modfp) || (s.c5spd > 0x7ffffL) || (s.length > 0xfffffffUL) ||
 13.1101 -          (s.loopbeg > 0xfffffffUL) || (s.loopend > 0xfffffffUL))
 13.1102 -        {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1103 -            return 0;
 13.1104 -        }
 13.1105 -
 13.1106 -        q->samplename = DupStr(s.sampname,26);
 13.1107 +	/* Load instruments if instrument mode flag enabled */
 13.1108 +	if(mh->flags&4) {
 13.1109 +		if(!AllocInstruments()) return 0;
 13.1110 +		d=of.instruments;
 13.1111 +		of.flags|=UF_NNA|UF_INST;
 13.1112  
 13.1113 -        q->speed      = s.c5spd / 2;
 13.1114 -        q->panning    = ((s.panning & 127)==64) ? 255 : (s.panning & 127) << 2;
 13.1115 -        q->length     = s.length;
 13.1116 -        q->loopstart  = s.loopbeg;
 13.1117 -        q->loopend    = s.loopend;
 13.1118 -        q->volume     = s.volume;
 13.1119 -        q->globvol    = s.globvol;
 13.1120 -        q->seekpos    = s.sampoffset;
 13.1121 +		for(t=0;t<mh->insnum;t++) {
 13.1122 +			ITINSTHEADER ih;
 13.1123 +
 13.1124 +			/* seek to instrument position */
 13.1125 +			_mm_fseek(modreader,paraptr[t]+4,SEEK_SET);
 13.1126  
 13.1127 -        /* =================================== */
 13.1128 -        /* Convert speed to XM linear finetune */
 13.1129 -
 13.1130 -        if(of.flags & UF_LINEAR)
 13.1131 -            q->speed = cvt_c5spd_to_finetune(s.c5spd, t);
 13.1132 -
 13.1133 -        if(s.panning & 128) q->flags |= SF_OWNPAN;
 13.1134 -
 13.1135 -        if(s.vibrate)
 13.1136 -        {   q->vibflags |= AV_IT;
 13.1137 -            q->vibtype   = s.vibwave;
 13.1138 -            q->vibsweep  = s.vibrate * 2;
 13.1139 -            q->vibdepth  = s.vibdepth;
 13.1140 -            q->vibrate   = s.vibspeed;
 13.1141 -        }
 13.1142 -
 13.1143 -        if(s.flag & 2)  q->flags |= SF_16BITS;
 13.1144 -        if(s.flag & 16) q->flags |= SF_LOOP;
 13.1145 -        if(s.flag & 64) q->flags |= SF_BIDI;
 13.1146 +			/* load instrument info */
 13.1147 +			_mm_read_string(ih.filename,12,modreader);
 13.1148 +			ih.zerobyte  = _mm_read_UBYTE(modreader);
 13.1149 +			if(mh->cwt<0x200) {
 13.1150 +				/* load IT 1.xx inst header */
 13.1151 +				ih.volflg    = _mm_read_UBYTE(modreader);
 13.1152 +				ih.volbeg    = _mm_read_UBYTE(modreader);
 13.1153 +				ih.volend    = _mm_read_UBYTE(modreader);
 13.1154 +				ih.volsusbeg = _mm_read_UBYTE(modreader);
 13.1155 +				ih.volsusend = _mm_read_UBYTE(modreader);
 13.1156 +				_mm_read_I_UWORD(modreader);
 13.1157 +				ih.fadeout   = _mm_read_I_UWORD(modreader);
 13.1158 +				ih.nna       = _mm_read_UBYTE(modreader);
 13.1159 +				ih.dnc       = _mm_read_UBYTE(modreader);
 13.1160 +			} else {
 13.1161 +				/* Read IT200+ header */
 13.1162 +				ih.nna       = _mm_read_UBYTE(modreader);
 13.1163 +				ih.dct       = _mm_read_UBYTE(modreader);
 13.1164 +				ih.dca       = _mm_read_UBYTE(modreader);
 13.1165 +				ih.fadeout   = _mm_read_I_UWORD(modreader);
 13.1166 +				ih.ppsep     = _mm_read_UBYTE(modreader);
 13.1167 +				ih.ppcenter  = _mm_read_UBYTE(modreader);
 13.1168 +				ih.globvol   = _mm_read_UBYTE(modreader);
 13.1169 +				ih.chanpan   = _mm_read_UBYTE(modreader);
 13.1170 +				ih.rvolvar   = _mm_read_UBYTE(modreader);
 13.1171 +				ih.rpanvar   = _mm_read_UBYTE(modreader);
 13.1172 +			}
 13.1173  
 13.1174 -        if(mh->cwt >= 0x200)
 13.1175 -        {   if(s.convert & 1) q->flags |= SF_SIGNED;
 13.1176 -            if(s.convert & 4) q->flags |= SF_DELTA;   
 13.1177 -        }
 13.1178 -                              
 13.1179 -        q++;
 13.1180 -    }
 13.1181 -
 13.1182 -    /* Load instruments if instrument mode flag enabled */
 13.1183 -
 13.1184 -    if(mh->flags & 4)
 13.1185 -    {   if(!AllocInstruments()) return 0;
 13.1186 -        d = of.instruments;
 13.1187 -        of.flags |= UF_NNA | UF_INST;
 13.1188 -
 13.1189 -        for(t=0; t<mh->insnum; t++)
 13.1190 -        {   ITINSTHEADER ih;
 13.1191 -
 13.1192 -            /* seek to instrument position */
 13.1193 -            _mm_fseek(modfp,paraptr[t]+4,SEEK_SET);
 13.1194 +			ih.trkvers   = _mm_read_I_UWORD(modreader);
 13.1195 +			ih.numsmp    = _mm_read_UBYTE(modreader);
 13.1196 +			_mm_read_UBYTE(modreader);
 13.1197 +			_mm_read_string(ih.name,26,modreader);
 13.1198 +			_mm_read_UBYTES(ih.blank01,6,modreader);
 13.1199 +			_mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader);
 13.1200 +			if(mh->cwt<0x200) {
 13.1201 +				/* load IT 1xx volume envelope */
 13.1202 +				_mm_read_UBYTES(ih.volenv,200,modreader);
 13.1203 +				for(lp=0;lp<ITENVCNT;lp++) {
 13.1204 +					ih.oldvoltick[lp] = _mm_read_UBYTE(modreader);
 13.1205 +					ih.volnode[lp]    = _mm_read_UBYTE(modreader);
 13.1206 +				}
 13.1207 +			} else {
 13.1208 +				/* load IT 2xx volume, pan and pitch envelopes */
 13.1209 +#ifdef __STDC__
 13.1210 +#define IT_LoadEnvelope(name,type) 											\
 13.1211 +				ih.##name##flg   =_mm_read_UBYTE(modreader);				\
 13.1212 +				ih.##name##pts   =_mm_read_UBYTE(modreader);				\
 13.1213 +				ih.##name##beg   =_mm_read_UBYTE(modreader);				\
 13.1214 +				ih.##name##end   =_mm_read_UBYTE(modreader);				\
 13.1215 +				ih.##name##susbeg=_mm_read_UBYTE(modreader);				\
 13.1216 +				ih.##name##susend=_mm_read_UBYTE(modreader);				\
 13.1217 +				for(lp=0;lp<ITENVCNT;lp++) {								\
 13.1218 +					ih.##name##node[lp]=_mm_read_##type##(modreader);		\
 13.1219 +					ih.##name##tick[lp]=_mm_read_I_UWORD(modreader);		\
 13.1220 +				}															\
 13.1221 +				_mm_read_UBYTE(modreader);
 13.1222 +#else
 13.1223 +#define IT_LoadEnvelope(name,type) 											\
 13.1224 +				ih./**/name/**/flg   =_mm_read_UBYTE(modreader);			\
 13.1225 +				ih./**/name/**/pts   =_mm_read_UBYTE(modreader);			\
 13.1226 +				ih./**/name/**/beg   =_mm_read_UBYTE(modreader);			\
 13.1227 +				ih./**/name/**/end   =_mm_read_UBYTE(modreader);			\
 13.1228 +				ih./**/name/**/susbeg=_mm_read_UBYTE(modreader);			\
 13.1229 +				ih./**/name/**/susend=_mm_read_UBYTE(modreader);			\
 13.1230 +				for(lp=0;lp<ITENVCNT;lp++) {								\
 13.1231 +					ih./**/name/**/node[lp]=_mm_read_/**/type/**/(modreader);\
 13.1232 +					ih./**/name/**/tick[lp]=_mm_read_I_UWORD(modreader);	\
 13.1233 +				}															\
 13.1234 +				_mm_read_UBYTE(modreader);
 13.1235 +#endif
 13.1236  
 13.1237 -            /* and load instrument info */
 13.1238 -            _mm_read_string(ih.filename,12,modfp);
 13.1239 -            ih.zerobyte  = _mm_read_UBYTE(modfp);
 13.1240 -            if(mh->cwt < 0x200) /* load IT 1.xx inst header */
 13.1241 -            {   ih.volflg    = _mm_read_UBYTE(modfp);
 13.1242 -                ih.volbeg    = _mm_read_UBYTE(modfp);
 13.1243 -                ih.volend    = _mm_read_UBYTE(modfp);
 13.1244 -                ih.volsusbeg = _mm_read_UBYTE(modfp);
 13.1245 -                ih.volsusend = _mm_read_UBYTE(modfp);
 13.1246 -                _mm_read_I_UWORD(modfp);
 13.1247 -                ih.fadeout   = _mm_read_I_UWORD(modfp);
 13.1248 -                ih.nna       = _mm_read_UBYTE(modfp);
 13.1249 -                ih.dnc       = _mm_read_UBYTE(modfp);
 13.1250 -            } else   /* Read IT200+ header */
 13.1251 -            {   ih.nna       = _mm_read_UBYTE(modfp);
 13.1252 -                ih.dct       = _mm_read_UBYTE(modfp);
 13.1253 -                ih.dca       = _mm_read_UBYTE(modfp);
 13.1254 -                ih.fadeout   = _mm_read_I_UWORD(modfp);
 13.1255 -                ih.ppsep     = _mm_read_UBYTE(modfp);
 13.1256 -                ih.ppcenter  = _mm_read_UBYTE(modfp);
 13.1257 -                ih.globvol   = _mm_read_UBYTE(modfp);
 13.1258 -                ih.chanpan   = _mm_read_UBYTE(modfp);
 13.1259 -                ih.rvolvar   = _mm_read_UBYTE(modfp);
 13.1260 -                ih.rpanvar   = _mm_read_UBYTE(modfp);
 13.1261 -            }
 13.1262 +				IT_LoadEnvelope(vol,UBYTE);
 13.1263 +				IT_LoadEnvelope(pan,SBYTE);
 13.1264 +				IT_LoadEnvelope(pit,SBYTE);
 13.1265 +#undef IT_LoadEnvelope
 13.1266 +			}
 13.1267 +
 13.1268 +			if(_mm_eof(modreader)) {
 13.1269 +				_mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1270 +				return 0;
 13.1271 +			}
 13.1272 +
 13.1273 +			d->volflg|=EF_VOLENV;
 13.1274 +			d->insname = DupStr(ih.name,26,0);
 13.1275 +			d->nnatype = ih.nna;
 13.1276 +
 13.1277 +			if(mh->cwt<0x200) {
 13.1278 +				d->volfade=ih.fadeout<< 6;
 13.1279 +				if(ih.dnc) {
 13.1280 +					d->dct=DCT_NOTE;
 13.1281 +					d->dca=DCA_CUT;
 13.1282 +				}
 13.1283 +
 13.1284 +				if(ih.volflg&1) d->volflg|=EF_ON;
 13.1285 +				if(ih.volflg&2) d->volflg|=EF_LOOP;
 13.1286 +				if(ih.volflg&4) d->volflg|=EF_SUSTAIN;
 13.1287  
 13.1288 -            ih.trkvers   = _mm_read_I_UWORD(modfp);
 13.1289 -            ih.numsmp    = _mm_read_UBYTE(modfp);
 13.1290 -            _mm_read_UBYTE(modfp);
 13.1291 -            _mm_read_string(ih.name,26,modfp);
 13.1292 -            _mm_read_UBYTES(ih.blank01,6,modfp);
 13.1293 -            _mm_read_I_UWORDS(ih.samptable,120,modfp);
 13.1294 -            if(mh->cwt < 0x200)  /* load IT 1xx volume envelope */
 13.1295 -            {   _mm_read_UBYTES(ih.volenv,200,modfp);
 13.1296 -                for(lp=0; lp<25; lp++)
 13.1297 -                {   ih.oldvoltick[lp] = _mm_read_UBYTE(modfp);
 13.1298 -                    ih.volnode[lp]    = _mm_read_UBYTE(modfp);
 13.1299 -                }
 13.1300 -            } else /* load IT 2xx vol & chanpan & pitch envs */
 13.1301 -            {   ih.volflg    = _mm_read_UBYTE(modfp);
 13.1302 -                ih.volpts    = _mm_read_UBYTE(modfp);
 13.1303 -                ih.volbeg    = _mm_read_UBYTE(modfp);
 13.1304 -                ih.volend    = _mm_read_UBYTE(modfp);
 13.1305 -                ih.volsusbeg = _mm_read_UBYTE(modfp);
 13.1306 -                ih.volsusend = _mm_read_UBYTE(modfp);
 13.1307 -                for(lp=0; lp<25; lp++)
 13.1308 -                {   ih.volnode[lp] = _mm_read_UBYTE(modfp);
 13.1309 -                    ih.voltick[lp] = _mm_read_I_UWORD(modfp);
 13.1310 -                }
 13.1311 -                _mm_read_UBYTE(modfp);
 13.1312 +				/* XM conversion of IT envelope Array */
 13.1313 +				d->volbeg    = ih.volbeg;
 13.1314 +				d->volend    = ih.volend;
 13.1315 +				d->volsusbeg = ih.volsusbeg;
 13.1316 +				d->volsusend = ih.volsusend;
 13.1317  
 13.1318 -                ih.panflg    = _mm_read_UBYTE(modfp);
 13.1319 -                ih.panpts    = _mm_read_UBYTE(modfp);
 13.1320 -                ih.panbeg    = _mm_read_UBYTE(modfp);
 13.1321 -                ih.panend    = _mm_read_UBYTE(modfp);
 13.1322 -                ih.pansusbeg = _mm_read_UBYTE(modfp);
 13.1323 -                ih.pansusend = _mm_read_UBYTE(modfp);
 13.1324 -                for(lp=0; lp<25; lp++)
 13.1325 -                {   ih.pannode[lp] = _mm_read_SBYTE(modfp);
 13.1326 -                    ih.pantick[lp] = _mm_read_I_UWORD(modfp);
 13.1327 -                }
 13.1328 -                _mm_read_UBYTE(modfp);
 13.1329 +				if(ih.volflg&1) {
 13.1330 +					for(u=0;u<ITENVCNT;u++)
 13.1331 +						if(ih.oldvoltick[d->volpts]!=0xff) {
 13.1332 +							d->volenv[d->volpts].val=(ih.volnode[d->volpts]<<2);
 13.1333 +							d->volenv[d->volpts].pos=ih.oldvoltick[d->volpts];
 13.1334 +							d->volpts++;
 13.1335 +						} else
 13.1336 +							break;
 13.1337 +				}
 13.1338 +			} else {
 13.1339 +				d->panning=((ih.chanpan&127)==64)?255:(ih.chanpan&127)<<2;
 13.1340 +				if(!(ih.chanpan&128)) d->flags|=IF_OWNPAN;
 13.1341 +
 13.1342 +				if(!(ih.ppsep & 128)) {
 13.1343 +					d->pitpansep=ih.ppsep<<2;
 13.1344 +					d->pitpancenter=ih.ppcenter;
 13.1345 +					d->flags|=IF_PITCHPAN;
 13.1346 +				}
 13.1347 +				d->globvol=ih.globvol>>1;
 13.1348 +				d->volfade=ih.fadeout<<5;
 13.1349 +				d->dct    =ih.dct;
 13.1350 +				d->dca    =ih.dca;
 13.1351 +
 13.1352 +				if(mh->cwt>=0x204) {
 13.1353 +					d->rvolvar = ih.rvolvar;
 13.1354 +					d->rpanvar = ih.rpanvar;
 13.1355 +				}
 13.1356  
 13.1357 -                ih.pitflg    = _mm_read_UBYTE(modfp);
 13.1358 -                ih.pitpts    = _mm_read_UBYTE(modfp);
 13.1359 -                ih.pitbeg    = _mm_read_UBYTE(modfp);
 13.1360 -                ih.pitend    = _mm_read_UBYTE(modfp);
 13.1361 -                ih.pitsusbeg = _mm_read_UBYTE(modfp);
 13.1362 -                ih.pitsusend = _mm_read_UBYTE(modfp);
 13.1363 -                for(lp=0; lp<25; lp++)
 13.1364 -                {   ih.pitnode[lp] = _mm_read_SBYTE(modfp);
 13.1365 -                    ih.pittick[lp] = _mm_read_I_UWORD(modfp);
 13.1366 -                }
 13.1367 -                _mm_read_UBYTE(modfp);
 13.1368 -            }
 13.1369 - 
 13.1370 -            if(feof(modfp))
 13.1371 -            {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1372 -                return 0;
 13.1373 -            }
 13.1374 +#ifdef __STDC__
 13.1375 +#define IT_ProcessEnvelope(name) 											\
 13.1376 +				if(ih.##name##flg&1) d->##name##flg|=EF_ON;					\
 13.1377 +				if(ih.##name##flg&2) d->##name##flg|=EF_LOOP;				\
 13.1378 +				if(ih.##name##flg&4) d->##name##flg|=EF_SUSTAIN;			\
 13.1379 +				d->##name##pts=ih.##name##pts;								\
 13.1380 +				d->##name##beg=ih.##name##beg;								\
 13.1381 +				d->##name##end=ih.##name##end;								\
 13.1382 +				d->##name##susbeg=ih.##name##susbeg;						\
 13.1383 +				d->##name##susend=ih.##name##susend;						\
 13.1384 +																			\
 13.1385 +				for(u=0;u<ih.##name##pts;u++)								\
 13.1386 +					d->##name##env[u].pos=ih.##name##tick[u];				\
 13.1387 +																			\
 13.1388 +				if((d->##name##flg&EF_ON)&&(d->##name##pts<2))				\
 13.1389 +					d->##name##flg&=~EF_ON;
 13.1390 +#else
 13.1391 +#define IT_ProcessEnvelope(name) 											\
 13.1392 +				if(ih./**/name/**/flg&1) d->/**/name/**/flg|=EF_ON;			\
 13.1393 +				if(ih./**/name/**/flg&2) d->/**/name/**/flg|=EF_LOOP;		\
 13.1394 +				if(ih./**/name/**/flg&4) d->/**/name/**/flg|=EF_SUSTAIN;	\
 13.1395 +				d->/**/name/**/pts=ih./**/name/**/pts;						\
 13.1396 +				d->/**/name/**/beg=ih./**/name/**/beg;						\
 13.1397 +				d->/**/name/**/end=ih./**/name/**/end;						\
 13.1398 +				d->/**/name/**/susbeg=ih./**/name/**/susbeg;				\
 13.1399 +				d->/**/name/**/susend=ih./**/name/**/susend;				\
 13.1400 +																			\
 13.1401 +				for(u=0;u<ih./**/name/**/pts;u++)							\
 13.1402 +					d->/**/name/**/env[u].pos=ih./**/name/**/tick[u];		\
 13.1403 +																			\
 13.1404 +				if((d->/**/name/**/flg&EF_ON)&&(d->/**/name/**/pts<2))		\
 13.1405 +					d->/**/name/**/flg&=~EF_ON;
 13.1406 +#endif
 13.1407  
 13.1408 -            d->volflg |= EF_VOLENV;
 13.1409 -            d->insname = DupStr(ih.name,26);
 13.1410 -            d->nnatype = ih.nna;
 13.1411 -            
 13.1412 -            if(mh->cwt < 0x200)
 13.1413 -            {   d->volfade = ih.fadeout << 6;
 13.1414 -                if(ih.dnc)
 13.1415 -                {   d->dct = DCT_NOTE;
 13.1416 -                    d->dca = DCA_CUT;
 13.1417 -                }
 13.1418 -
 13.1419 -                if(ih.volflg & 1) d->volflg |= EF_ON;
 13.1420 -                if(ih.volflg & 2) d->volflg |= EF_LOOP;
 13.1421 -                if(ih.volflg & 4) d->volflg |= EF_SUSTAIN;      
 13.1422 -               
 13.1423 -                /* XM conversion of IT envelope Array */
 13.1424 -                
 13.1425 -                d->volbeg    = ih.volbeg;   
 13.1426 -                d->volend    = ih.volend;
 13.1427 -                d->volsusbeg = ih.volsusbeg;
 13.1428 -                d->volsusend = ih.volsusend;
 13.1429 -            
 13.1430 -                if(ih.volflg & 1)
 13.1431 -                {   for(u=0; u<25; u++)
 13.1432 -                        if(ih.oldvoltick[d->volpts] != 0xff)
 13.1433 -                        {   d->volenv[d->volpts].val = (ih.volnode[d->volpts] << 2);
 13.1434 -                            d->volenv[d->volpts].pos = ih.oldvoltick[d->volpts];
 13.1435 -                            d->volpts++;
 13.1436 -                        } else break;
 13.1437 -                }  
 13.1438 -            } else
 13.1439 -            {   d->panning = ((ih.chanpan&127) == 64) ? 255 : (ih.chanpan&127)<<2;
 13.1440 -                if(!(ih.chanpan & 128)) d->flags |= IF_OWNPAN;
 13.1441 +				IT_ProcessEnvelope(vol);
 13.1442 +				for(u=0;u<ih.volpts;u++)
 13.1443 +					d->volenv[u].val=(ih.volnode[u]<<2);
 13.1444  
 13.1445 -                if(!(ih.ppsep & 128))
 13.1446 -                {   d->pitpansep = ih.ppsep << 2;
 13.1447 -                    d->pitpancenter= ih.ppcenter;
 13.1448 -                    d->flags |= IF_PITCHPAN;
 13.1449 -                }
 13.1450 -                d->globvol = ih.globvol >> 1;
 13.1451 -                d->volfade = ih.fadeout << 5;
 13.1452 -                d->dct     = ih.dct;
 13.1453 -                d->dca     = ih.dca;
 13.1454 +				IT_ProcessEnvelope(pan);
 13.1455 +				for(u=0;u<ih.panpts;u++)
 13.1456 +					d->panenv[u].val=
 13.1457 +					  ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2;
 13.1458 +
 13.1459 +				IT_ProcessEnvelope(pit);
 13.1460 +				for(u=0;u<ih.pitpts;u++)
 13.1461 +					d->pitenv[u].val=ih.pitnode[u]+32;
 13.1462 +#undef IT_ProcessEnvelope
 13.1463  
 13.1464 -                if(mh->cwt >= 0x204)
 13.1465 -                {   d->rvolvar = ih.rvolvar;
 13.1466 -                    d->rpanvar = ih.rpanvar;
 13.1467 -                }
 13.1468 +				if(ih.pitflg&0x80) {
 13.1469 +					/* filter envelopes not supported yet */
 13.1470 +					d->pitflg&=~EF_ON;
 13.1471 +					ih.pitpts=ih.pitbeg=ih.pitend=0;
 13.1472 +#ifdef MIKMOD_DEBUG
 13.1473 +					{
 13.1474 +						static int warn=0;
 13.1475  
 13.1476 -                if(ih.volflg & 1) d->volflg |= EF_ON;
 13.1477 -                if(ih.volflg & 2) d->volflg |= EF_LOOP;
 13.1478 -                if(ih.volflg & 4) d->volflg |= EF_SUSTAIN;
 13.1479 +						if(!warn)
 13.1480 +							fputs("\rFilter envelopes not supported yet\n",stderr);
 13.1481 +						warn=1;
 13.1482 +					}
 13.1483 +#endif
 13.1484 +				}
 13.1485  
 13.1486 -                if(ih.panflg & 1) d->panflg |= EF_ON;
 13.1487 -                if(ih.panflg & 2) d->panflg |= EF_LOOP;
 13.1488 -                if(ih.panflg & 4) d->panflg |= EF_SUSTAIN;      
 13.1489 -
 13.1490 -                if(ih.pitflg & 1) d->pitflg |= EF_ON;
 13.1491 -                if(ih.pitflg & 2) d->pitflg |= EF_LOOP;
 13.1492 -                if(ih.pitflg & 4) d->pitflg |= EF_SUSTAIN;      
 13.1493 +				d->volpts    = ih.volpts;
 13.1494 +				d->volbeg    = ih.volbeg;
 13.1495 +				d->volend    = ih.volend;
 13.1496 +				d->volsusbeg = ih.volsusbeg;
 13.1497 +				d->volsusend = ih.volsusend;
 13.1498  
 13.1499 -                d->volpts    = ih.volpts;
 13.1500 -                d->volbeg    = ih.volbeg;   
 13.1501 -                d->volend    = ih.volend;
 13.1502 -                d->volsusbeg = ih.volsusbeg;
 13.1503 -                d->volsusend = ih.volsusend;
 13.1504 +				for(u=0;u<ih.volpts;u++) {
 13.1505 +					d->volenv[u].val=(ih.volnode[u]<<2);
 13.1506 +					d->volenv[u].pos=ih.voltick[u];
 13.1507 +				}
 13.1508  
 13.1509 -                for(u=0; u<ih.volpts; u++)
 13.1510 -                {   d->volenv[u].val = (ih.volnode[u] << 2);
 13.1511 -                    d->volenv[u].pos = ih.voltick[u];
 13.1512 -                }
 13.1513 +				d->panpts    = ih.panpts;
 13.1514 +				d->panbeg    = ih.panbeg;
 13.1515 +				d->panend    = ih.panend;
 13.1516 +				d->pansusbeg = ih.pansusbeg;
 13.1517 +				d->pansusend = ih.pansusend;
 13.1518 +
 13.1519 +				for(u=0;u<ih.panpts;u++) {
 13.1520 +					d->panenv[u].val=ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2;
 13.1521 +					d->panenv[u].pos=ih.pantick[u];
 13.1522 +				}
 13.1523  
 13.1524 -                d->panpts    = ih.panpts;
 13.1525 -                d->panbeg    = ih.panbeg;
 13.1526 -                d->panend    = ih.panend;
 13.1527 -                d->pansusbeg = ih.pansusbeg;
 13.1528 -                d->pansusend = ih.pansusend;
 13.1529 - 
 13.1530 -                for(u=0; u<ih.panpts; u++)                                               
 13.1531 -                {   d->panenv[u].val = (ih.pannode[u]+32) << 2;
 13.1532 -                    d->panenv[u].pos = ih.pantick[u];
 13.1533 -                }
 13.1534 +				d->pitpts   =ih.pitpts;
 13.1535 +				d->pitbeg   =ih.pitbeg;
 13.1536 +				d->pitend   =ih.pitend;
 13.1537 +				d->pitsusbeg=ih.pitsusbeg;
 13.1538 +				d->pitsusend=ih.pitsusend;
 13.1539 +
 13.1540 +				for(u=0;u<ih.pitpts;u++) {
 13.1541 +					d->pitenv[u].val=ih.pitnode[u]+32;
 13.1542 +					d->pitenv[u].pos=ih.pittick[u];
 13.1543 +				}
 13.1544 +			}
 13.1545  
 13.1546 -                d->pitpts    = ih.pitpts;
 13.1547 -                d->pitbeg    = ih.pitbeg;
 13.1548 -                d->pitend    = ih.pitend;
 13.1549 -                d->pitsusbeg = ih.pitsusbeg;
 13.1550 -                d->pitsusend = ih.pitsusend;
 13.1551 +			for(u=0;u<ITNOTECNT;u++) {
 13.1552 +				d->samplenote[u]=(ih.samptable[u]&255);
 13.1553 +				d->samplenumber[u]=
 13.1554 +				  (ih.samptable[u]>>8)?((ih.samptable[u]>>8)-1):0xffff;
 13.1555 +				if(d->samplenumber[u]>=of.numsmp)
 13.1556 +					d->samplenote[u]=255;
 13.1557 +				else if (of.flags&UF_LINEAR) {
 13.1558 +					int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];
 13.1559 +					d->samplenote[u]=(note<0)?0:(note>255?255:note);
 13.1560 +				}
 13.1561 +			}
 13.1562  
 13.1563 -                for(u=0; u<ih.pitpts; u++)
 13.1564 -                {   d->pitenv[u].val = (ih.pitnode[u]+32);
 13.1565 -                    d->pitenv[u].pos = ih.pittick[u];
 13.1566 -                }
 13.1567 -            }
 13.1568 -   
 13.1569 -            if(of.flags & UF_LINEAR)
 13.1570 -            {   for(u=0; u<120; u++)
 13.1571 -                {   d->samplenote[u]   = (ih.samptable[u] & 255);
 13.1572 -                    d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255;
 13.1573 -                    if(d->samplenumber[u]!=255)
 13.1574 -                        d->samplenote[u] += noteindex[d->samplenumber[u]];
 13.1575 -                }
 13.1576 -            } else
 13.1577 -            {   for(u=0; u<120; u++)
 13.1578 -                {   d->samplenote[u]   = (ih.samptable[u] & 255);
 13.1579 -                    d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255;
 13.1580 -                }
 13.1581 -            }
 13.1582 +			d++;
 13.1583 +		}
 13.1584 +	} else if(of.flags & UF_LINEAR) {
 13.1585 +		if(!AllocInstruments()) return 0;
 13.1586 +		d=of.instruments;
 13.1587 +		of.flags|=UF_INST;
 13.1588  
 13.1589 -            d++;                  
 13.1590 -        }
 13.1591 -    } else if(of.flags & UF_LINEAR)
 13.1592 -    {   if(!AllocInstruments()) return 0;
 13.1593 -        d = of.instruments;
 13.1594 -        of.flags |= UF_INST;
 13.1595 +		for(t=0;t<mh->smpnum;t++,d++)
 13.1596 +			for(u=0;u<ITNOTECNT;u++) {
 13.1597 +				if(d->samplenumber[u]>=of.numsmp)
 13.1598 +					d->samplenote[u]=255;
 13.1599 +				else {
 13.1600 +					int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];
 13.1601 +					d->samplenote[u]=(note<0)?0:(note>255?255:note);
 13.1602 +				}
 13.1603 +			}
 13.1604 +	}
 13.1605  
 13.1606 -        for(t=0; t<mh->smpnum; t++, d++)
 13.1607 -        {   for(u=0; u<120; u++)
 13.1608 -                d->samplenote[u] += noteindex[d->samplenumber[u]];
 13.1609 -        }
 13.1610 -    }
 13.1611 -
 13.1612 -
 13.1613 -    /* Figure out how many channels this blasted song actually uses (what */
 13.1614 -    /* ever happened to common courtesy of storing this simple value */
 13.1615 -    /* somewhere in the damn module, eh!?) */
 13.1616 -
 13.1617 -    of.numchn = 0;
 13.1618 -    memset(remap,-1,64*sizeof(UBYTE));
 13.1619 -    
 13.1620 -    for(t=0; t<of.numpat; t++)
 13.1621 -    {   UWORD packlen;
 13.1622 +	/* Figure out how many channels this song actually uses */
 13.1623 +	of.numchn=0;
 13.1624 +	memset(remap,-1,64*sizeof(UBYTE));
 13.1625 +	for(t=0;t<of.numpat;t++) {
 13.1626 +		UWORD packlen;
 13.1627  
 13.1628 -        /* seek to pattern position */
 13.1629 -        if(paraptr[mh->insnum+mh->smpnum+t] != 0)  /* No parapointer = pattern of 64 rows, EMPTY */
 13.1630 -        {   _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET);
 13.1631 -            packlen = _mm_read_I_UWORD(modfp);
 13.1632 -            packlen = _mm_read_I_UWORD(modfp);    /* read pattern length (# of rows) */
 13.1633 -            _mm_read_I_ULONG(modfp);
 13.1634 -            if(IT_GetNumChannels(packlen)) return 0;
 13.1635 -        }
 13.1636 -    }
 13.1637 +		/* seek to pattern position */
 13.1638 +		if(paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */
 13.1639 +			_mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);
 13.1640 +			_mm_read_I_UWORD(modreader);
 13.1641 +			/* read pattern length (# of rows)
 13.1642 +			   Impulse Tracker never creates patterns with less than 32 rows,
 13.1643 +			   but some other trackers do, so we only check for more than 256
 13.1644 +			   rows */
 13.1645 +			packlen=_mm_read_I_UWORD(modreader);
 13.1646 +			if(packlen>256) {
 13.1647 +				_mm_errno=MMERR_LOADING_PATTERN;
 13.1648 +				return 0;
 13.1649 +			}
 13.1650 +			_mm_read_I_ULONG(modreader);
 13.1651 +			if(IT_GetNumChannels(packlen)) return 0;
 13.1652 +		}
 13.1653 +	}
 13.1654  
 13.1655 -    /* give each of them a different number */
 13.1656 -    for(t=0; t<64; t++)
 13.1657 -    {   if(remap[t]==0)
 13.1658 -        {   remap[t] = of.numchn;
 13.1659 -            of.numchn++;
 13.1660 -        }
 13.1661 -    }
 13.1662 +	/* give each of them a different number */
 13.1663 +	for(t=0;t<64;t++)
 13.1664 +		if(!remap[t])
 13.1665 +			remap[t]=of.numchn++;
 13.1666  
 13.1667 -    of.numtrk = of.numpat*of.numchn;
 13.1668 -
 13.1669 -
 13.1670 -    if(!AllocPatterns()) return 0;
 13.1671 -    if(!AllocTracks()) return 0;
 13.1672 +	of.numtrk = of.numpat*of.numchn;
 13.1673 +	if(of.numvoices)
 13.1674 +		if (of.numvoices<of.numchn) of.numvoices=of.numchn;
 13.1675  
 13.1676 -    for(t=0; t<of.numpat; t++)
 13.1677 -    {   UWORD packlen;
 13.1678 +	if(!AllocPatterns()) return 0;
 13.1679 +	if(!AllocTracks()) return 0;
 13.1680 +
 13.1681 +	for(t=0;t<of.numpat;t++) {
 13.1682 +		UWORD packlen;
 13.1683 +
 13.1684 +		/* seek to pattern position */
 13.1685 +		if(!paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */
 13.1686 +			of.pattrows[t]=64;
 13.1687 +			for(u=0;u<of.numchn;u++) {
 13.1688 +				int k;
 13.1689  
 13.1690 -        /* seek to pattern position */
 13.1691 -        if(paraptr[mh->insnum+mh->smpnum+t] == 0)  /* No parapointer = pattern of 64 rows, EMPTY */
 13.1692 -        {  of.pattrows[t] = 64;
 13.1693 -           for(u=0; u<of.numchn; u++)
 13.1694 -           {  int k;
 13.1695 -              UniReset();
 13.1696 -              for(k=0; k<64; k++) UniNewline();
 13.1697 -              of.tracks[numtrk++] = UniDup();
 13.1698 -           }
 13.1699 -        } else
 13.1700 -        {  _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET);
 13.1701 -           packlen = _mm_read_I_UWORD(modfp);
 13.1702 -           of.pattrows[t] = _mm_read_I_UWORD(modfp);
 13.1703 -           _mm_read_I_ULONG(modfp);
 13.1704 +				UniReset();
 13.1705 +				for(k=0;k<64;k++) UniNewline();
 13.1706 +				of.tracks[numtrk++]=UniDup();
 13.1707 +			}
 13.1708 +		} else {
 13.1709 +			_mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);
 13.1710 +			packlen=_mm_read_I_UWORD(modreader);
 13.1711 +			of.pattrows[t]=_mm_read_I_UWORD(modreader);
 13.1712 +			_mm_read_I_ULONG(modreader);
 13.1713 +			if(!IT_ReadPattern(of.pattrows[t])) return 0;
 13.1714 +		}
 13.1715 +	}
 13.1716  
 13.1717 -           if(!IT_ReadPattern(of.pattrows[t])) return 0;
 13.1718 -        }
 13.1719 -    }
 13.1720 -
 13.1721 -    return 1;
 13.1722 +	return 1;
 13.1723  }
 13.1724  
 13.1725 -
 13.1726  CHAR *IT_LoadTitle(void)
 13.1727  {
 13.1728 -   CHAR s[26];
 13.1729 +	CHAR s[26];
 13.1730  
 13.1731 -   _mm_fseek(modfp,4,SEEK_SET);
 13.1732 -   if(!fread(s,26,1,modfp)) return NULL;
 13.1733 -   
 13.1734 -   return(DupStr(s,26));
 13.1735 +	_mm_fseek(modreader,4,SEEK_SET);
 13.1736 +	if(!_mm_read_UBYTES(s,26,modreader)) return NULL;
 13.1737 +
 13.1738 +	return(DupStr(s,26,0));
 13.1739  }
 13.1740  
 13.1741 +/*========== Loader information */
 13.1742  
 13.1743 -MLOADER load_it =
 13.1744 -{   NULL,
 13.1745 -    "IT",
 13.1746 -    "Portable IT loader v0.2",
 13.1747 -    IT_Init,
 13.1748 -    IT_Test,
 13.1749 -    IT_Load,
 13.1750 -    IT_Cleanup,
 13.1751 -
 13.1752 -    IT_LoadTitle
 13.1753 +MLOADER load_it={
 13.1754 +	NULL,
 13.1755 +	"IT",
 13.1756 +	"IT (Impulse Tracker)",
 13.1757 +	IT_Init,
 13.1758 +	IT_Test,
 13.1759 +	IT_Load,
 13.1760 +	IT_Cleanup,
 13.1761 +	IT_LoadTitle
 13.1762  };
 13.1763  
 13.1764 +/* ex:set ts=4: */
    14.1 --- a/mikmod/load_mod.c	Mon Dec 27 19:18:10 1999 +0000
    14.2 +++ b/mikmod/load_mod.c	Mon Dec 27 19:24:50 1999 +0000
    14.3 @@ -1,140 +1,146 @@
    14.4 -/*
    14.5 +/*	MikMod sound library
    14.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    14.7 +	complete list.
    14.8  
    14.9 - Name: LOAD_MOD.C
   14.10 +	This library is free software; you can redistribute it and/or modify
   14.11 +	it under the terms of the GNU Library General Public License as
   14.12 +	published by the Free Software Foundation; either version 2 of
   14.13 +	the License, or (at your option) any later version.
   14.14  
   14.15 - Description:
   14.16 - Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
   14.17 +	This program is distributed in the hope that it will be useful,
   14.18 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.19 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.20 +	GNU Library General Public License for more details.
   14.21  
   14.22 - Portability:
   14.23 - All systems - all compilers (hopefully)
   14.24 +	You should have received a copy of the GNU Library General Public
   14.25 +	License along with this library; if not, write to the Free Software
   14.26 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   14.27 +	02111-1307, USA.
   14.28 +*/
   14.29 +
   14.30 +/*==============================================================================
   14.31  
   14.32 - If this module is found to not be portable to any particular platform,
   14.33 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   14.34 - more information on contacting the author).
   14.35 +  $Id$
   14.36 +
   14.37 +  Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
   14.38  
   14.39 -*/
   14.40 +==============================================================================*/
   14.41 +
   14.42 +#ifdef HAVE_CONFIG_H
   14.43 +#include "config.h"
   14.44 +#endif
   14.45  
   14.46  #include <string.h>
   14.47 -#include "mikmod.h"
   14.48  
   14.49 -/*************************************************************************
   14.50 -*************************************************************************/
   14.51 +#include "mikmod_internals.h"
   14.52  
   14.53 +/*========== Module structure */
   14.54  
   14.55 -typedef struct MSAMPINFO                  /* sample header as it appears in a module */
   14.56 -{   CHAR  samplename[22];
   14.57 -    UWORD length;
   14.58 -    UBYTE finetune;
   14.59 -    UBYTE volume;
   14.60 -    UWORD reppos;
   14.61 -    UWORD replen;
   14.62 +typedef struct MSAMPINFO {
   14.63 +	CHAR  samplename[23];	/* 22 in module, 23 in memory */
   14.64 +	UWORD length;
   14.65 +	UBYTE finetune;
   14.66 +	UBYTE volume;
   14.67 +	UWORD reppos;
   14.68 +	UWORD replen;
   14.69  } MSAMPINFO;
   14.70  
   14.71 +typedef struct MODULEHEADER {
   14.72 +	CHAR      songname[21];		/* the songname.. 20 in module, 21 in memory */
   14.73 +	MSAMPINFO samples[31];		/* all sampleinfo */
   14.74 +	UBYTE     songlength;		/* number of patterns used */
   14.75 +	UBYTE     magic1;			/* should be 127 */
   14.76 +	UBYTE     positions[128];	/* which pattern to play at pos */
   14.77 +	UBYTE     magic2[4];		/* string "M.K." or "FLT4" or "FLT8" */
   14.78 +} MODULEHEADER;
   14.79  
   14.80 -typedef struct MODULEHEADER              /* verbatim module header */
   14.81 -{   CHAR       songname[20];             /* the songname.. */
   14.82 -    MSAMPINFO  samples[31];              /* all sampleinfo */
   14.83 -    UBYTE      songlength;               /* number of patterns used */
   14.84 -    UBYTE      magic1;                   /* should be 127 */
   14.85 -    UBYTE      positions[128];           /* which pattern to play at pos */
   14.86 -    UBYTE      magic2[4];                /* string "M.K." or "FLT4" or "FLT8" */
   14.87 -} MODULEHEADER;
   14.88 +typedef struct MODTYPE {
   14.89 +	CHAR  id[5];
   14.90 +	UBYTE channels;
   14.91 +	CHAR  *name;
   14.92 +} MODTYPE;
   14.93 +
   14.94 +typedef struct MODNOTE {
   14.95 +	UBYTE a,b,c,d;
   14.96 +} MODNOTE;
   14.97 +
   14.98 +/*========== Loader variables */
   14.99  
  14.100  #define MODULEHEADERSIZE 1084
  14.101  
  14.102 -
  14.103 -typedef struct MODTYPE              /* struct to identify type of module */
  14.104 -{   CHAR    id[5];
  14.105 -    UBYTE   channels;
  14.106 -    CHAR    *name;
  14.107 -} MODTYPE;
  14.108 -
  14.109 -
  14.110 -typedef struct MODNOTE
  14.111 -{   UBYTE a,b,c,d;
  14.112 -} MODNOTE;
  14.113 -
  14.114 -
  14.115 -/*************************************************************************
  14.116 -*************************************************************************/
  14.117 -
  14.118 -
  14.119 -CHAR protracker[]   = "Protracker";
  14.120 -CHAR startracker[]  = "Startracker";
  14.121 -CHAR fasttracker[]  = "Fasttracker";
  14.122 -CHAR ins15tracker[] = "15-instrument";
  14.123 -CHAR oktalyzer[]    = "Oktalyzer";
  14.124 -CHAR taketracker[]  = "TakeTracker";
  14.125 -
  14.126 +static CHAR protracker[]   = "Protracker";
  14.127 +static CHAR startracker[]  = "Startracker";
  14.128 +static CHAR fasttracker[]  = "Fasttracker";
  14.129 +static CHAR ins15tracker[] = "15-instrument";
  14.130 +static CHAR oktalyzer[]    = "Oktalyzer";
  14.131 +static CHAR taketracker[]  = "TakeTracker";
  14.132 +static CHAR orpheus[]      = "Imago Orpheus (MOD format)";
  14.133  
  14.134 -MODTYPE modtypes[] =
  14.135 -{   "M.K.",4,protracker,      /* protracker 4 channel */
  14.136 -    "M!K!",4,protracker,      /* protracker 4 channel */
  14.137 -    "FLT4",4,startracker,     /* startracker 4 channel */
  14.138 -    "2CHN",2,fasttracker,     /* fasttracker 2 channel */
  14.139 -    "4CHN",4,fasttracker,     /* fasttracker 4 channel */
  14.140 -    "6CHN",6,fasttracker,     /* fasttracker 6 channel */
  14.141 -    "8CHN",8,fasttracker,     /* fasttracker 8 channel */
  14.142 -    "10CH",10,fasttracker,    /* fasttracker 10 channel */
  14.143 -    "12CH",12,fasttracker,    /* fasttracker 12 channel */
  14.144 -    "14CH",14,fasttracker,    /* fasttracker 14 channel */
  14.145 -    "16CH",16,fasttracker,    /* fasttracker 16 channel */
  14.146 -    "18CH",18,fasttracker,    /* fasttracker 18 channel */
  14.147 -    "20CH",20,fasttracker,    /* fasttracker 20 channel */
  14.148 -    "22CH",22,fasttracker,    /* fasttracker 22 channel */
  14.149 -    "24CH",24,fasttracker,    /* fasttracker 24 channel */
  14.150 -    "26CH",26,fasttracker,    /* fasttracker 26 channel */
  14.151 -    "28CH",28,fasttracker,    /* fasttracker 28 channel */
  14.152 -    "30CH",30,fasttracker,    /* fasttracker 30 channel */
  14.153 -    "32CH",32,fasttracker,    /* fasttracker 32 channel */
  14.154 -    "CD81",8,oktalyzer,       /* atari oktalyzer 8 channel */
  14.155 -    "OKTA",8,oktalyzer,       /* atari oktalyzer 8 channel */
  14.156 -    "16CN",16,taketracker,    /* taketracker 16 channel */
  14.157 -    "32CN",32,taketracker,    /* taketracker 32 channel */
  14.158 -    "    ",4,ins15tracker     /* 15-instrument 4 channel     */
  14.159 +#define MODTYPE_COUNT 24
  14.160 +static MODTYPE modtypes[MODTYPE_COUNT+1]={
  14.161 +	{"M.K.", 4,  protracker},	/* protracker 4 channel */
  14.162 +	{"M!K!", 4,  protracker},	/* protracker 4 channel */
  14.163 +	{"FLT4", 4, startracker},	/* startracker 4 channel */
  14.164 +	{"2CHN", 2, fasttracker},	/* fasttracker 2 channel */
  14.165 +	{"4CHN", 4, fasttracker},	/* fasttracker 4 channel */
  14.166 +	{"6CHN", 6, fasttracker},	/* fasttracker 6 channel */
  14.167 +	{"8CHN", 8, fasttracker},	/* fasttracker 8 channel */
  14.168 +	{"10CH",10, fasttracker},	/* fasttracker 10 channel */
  14.169 +	{"12CH",12, fasttracker},	/* fasttracker 12 channel */
  14.170 +	{"14CH",14, fasttracker},	/* fasttracker 14 channel */
  14.171 +	{"15CH",15, fasttracker},	/* fasttracker 15 channel */
  14.172 +	{"16CH",16, fasttracker},	/* fasttracker 16 channel */
  14.173 +	{"18CH",18, fasttracker},	/* fasttracker 18 channel */
  14.174 +	{"20CH",20, fasttracker},	/* fasttracker 20 channel */
  14.175 +	{"22CH",22, fasttracker},	/* fasttracker 22 channel */
  14.176 +	{"24CH",24, fasttracker},	/* fasttracker 24 channel */
  14.177 +	{"26CH",26, fasttracker},	/* fasttracker 26 channel */
  14.178 +	{"28CH",28, fasttracker},	/* fasttracker 28 channel */
  14.179 +	{"30CH",30, fasttracker},	/* fasttracker 30 channel */
  14.180 +	{"32CH",32, fasttracker},	/* fasttracker 32 channel */
  14.181 +	{"CD81", 8,   oktalyzer},	/* atari oktalyzer 8 channel */
  14.182 +	{"OKTA", 8,   oktalyzer},	/* atari oktalyzer 8 channel */
  14.183 +	{"16CN",16, taketracker},	/* taketracker 16 channel */
  14.184 +	{"32CN",32, taketracker},	/* taketracker 32 channel */
  14.185 +	{"    ", 4,ins15tracker}	/* 15-instrument 4 channel */
  14.186  };
  14.187  
  14.188 -static MODULEHEADER *mh = NULL;        /* raw as-is module header */
  14.189 +static MODULEHEADER *mh = NULL;
  14.190  static MODNOTE *patbuf = NULL;
  14.191  static int modtype = 0;
  14.192  
  14.193 -BOOL MOD_Test(void)
  14.194 +/*========== Loader code */
  14.195 +
  14.196 +static BOOL MOD_Test(void)
  14.197  {
  14.198 -    UBYTE id[4];
  14.199 -
  14.200 -    _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
  14.201 -    if(!fread(id,4,1,modfp)) return 0;
  14.202 +	UBYTE id[4];
  14.203  
  14.204 -    /* find out which ID string */
  14.205 +	_mm_fseek(modreader,MODULEHEADERSIZE-4,SEEK_SET);
  14.206 +	if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  14.207  
  14.208 -    for(modtype=0; modtype<23; modtype++)
  14.209 -        if(!memcmp(id,modtypes[modtype].id,4)) return 1;
  14.210 +	/* find out which ID string */
  14.211 +	for(modtype=0;modtype<MODTYPE_COUNT;modtype++)
  14.212 +		if(!memcmp(id,modtypes[modtype].id,4)) return 1;
  14.213  
  14.214 -    return 0;
  14.215 +	return 0;
  14.216  }
  14.217  
  14.218 -
  14.219 -BOOL MOD_Init(void)
  14.220 +static BOOL MOD_Init(void)
  14.221  {
  14.222 -    if(!(mh=(MODULEHEADER *)_mm_calloc(1,sizeof(MODULEHEADER)))) return 0;
  14.223 -    return 1;
  14.224 +	if(	!(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
  14.225 +	return 1;
  14.226  }
  14.227  
  14.228 -
  14.229 -void MOD_Cleanup(void)
  14.230 +static void MOD_Cleanup(void)
  14.231  {
  14.232 -    if(mh!=NULL) free(mh);
  14.233 -    if(patbuf!=NULL) free(patbuf);
  14.234 -
  14.235 -    mh = NULL;
  14.236 -    patbuf = NULL;
  14.237 +	_mm_free(mh);
  14.238 +	_mm_free(patbuf);
  14.239  }
  14.240  
  14.241 -
  14.242  /*
  14.243  Old (amiga) noteinfo:
  14.244  
  14.245 - _____byte 1_____   byte2_    _____byte 3_____   byte4_
  14.246 +_____byte 1_____   byte2_    _____byte 3_____   byte4_
  14.247  /                \ /      \  /                \ /      \
  14.248  0000          0000-00000000  0000          0000-00000000
  14.249  
  14.250 @@ -144,198 +150,233 @@
  14.251  
  14.252  */
  14.253  
  14.254 -
  14.255 -void ConvertNote(MODNOTE *n)
  14.256 +static void ConvertNote(MODNOTE* n)
  14.257  {
  14.258 -    UBYTE instrument,effect,effdat,note;
  14.259 -    UWORD period;
  14.260 +	UBYTE instrument,effect,effdat,note;
  14.261 +	UWORD period;
  14.262 +	UBYTE lastnote=0;
  14.263  
  14.264 -    /* extract the various information from the 4 bytes that */
  14.265 -    /* make up a single note */
  14.266 +	/* extract the various information from the 4 bytes that make up a note */
  14.267 +	instrument = (n->a&0x10)|(n->c>>4);
  14.268 +	period     = (((UWORD)n->a&0xf)<<8)+n->b;
  14.269 +	effect     = n->c&0xf;
  14.270 +	effdat     = n->d;
  14.271  
  14.272 -    instrument = (n->a&0x10)|(n->c>>4);
  14.273 -    period     = (((UWORD)n->a&0xf)<<8)+n->b;
  14.274 -    effect     = n->c&0xf;
  14.275 -    effdat     = n->d;
  14.276 -
  14.277 -    /* Convert the period to a note number */
  14.278 +	/* Convert the period to a note number */
  14.279 +	note=0;
  14.280 +	if(period) {
  14.281 +		for(note=0;note<7*OCTAVE;note++)
  14.282 +			if(period>=npertab[note]) break;
  14.283 +		if(note==7*OCTAVE) note=0;
  14.284 +		else note++;
  14.285 +	}
  14.286  
  14.287 -    note=0;
  14.288 -    if(period!=0)
  14.289 -    {   for(note=0; note<60; note++)
  14.290 -            if(period >= npertab[note]) break;
  14.291 -        note++;
  14.292 -        if(note==61) note = 0;
  14.293 -    }
  14.294 +	if(instrument) {
  14.295 +		/* if instrument does not exist, note cut */
  14.296 +		if((instrument>31)||(!mh->samples[instrument-1].length)) {
  14.297 +			UniPTEffect(0xc,0);
  14.298 +			if(effect==0xc) effect=effdat=0;
  14.299 +		} else {
  14.300 +			/* Protracker handling */
  14.301 +			if(modtype<=2) {
  14.302 +				/* if we had a note, then change instrument... */
  14.303 +				if(note)
  14.304 +					UniInstrument(instrument-1);
  14.305 +				/* ...otherwise, only adjust volume... */
  14.306 +				else {
  14.307 +					/* ...unless an effect was specified, which forces a new
  14.308 +					   note to be played */
  14.309 +					if(effect||effdat) {
  14.310 +						UniInstrument(instrument-1);
  14.311 +						note=lastnote;
  14.312 +					} else
  14.313 +						UniPTEffect(0xc,mh->samples[instrument-1].volume&0x7f);
  14.314 +				}
  14.315 +			} else {
  14.316 +			/* Fasttracker handling */
  14.317 +				UniInstrument(instrument-1);
  14.318 +				if(!note) note=lastnote;
  14.319 +			}
  14.320 +		}
  14.321 +	}
  14.322 +	if(note) {
  14.323 +		UniNote(note+2*OCTAVE-1);
  14.324 +		lastnote=note;
  14.325 +	}
  14.326  
  14.327 -    if(instrument!=0) UniInstrument(instrument-1);
  14.328 -    if(note!=0) UniNote(note+23);
  14.329 +	/* Convert pattern jump from Dec to Hex */
  14.330 +	if(effect==0xd)
  14.331 +		effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
  14.332  
  14.333 -    /* Convert pattern jump from Dec to Hex */
  14.334 -    if(effect == 0xd)
  14.335 -        effdat = (((effdat&0xf0)>>4)*10)+(effdat&0xf);
  14.336 +	/* Volume slide, up has priority */
  14.337 +	if((effect==0xa)&&(effdat&0xf)&&(effdat&0xf0))
  14.338 +		effdat&=0xf0;
  14.339  
  14.340 -    UniPTEffect(effect,effdat);
  14.341 +	UniPTEffect(effect,effdat);
  14.342  }
  14.343  
  14.344 -
  14.345 -UBYTE *ConvertTrack(MODNOTE *n)
  14.346 +static UBYTE* ConvertTrack(MODNOTE* n)
  14.347  {
  14.348 -    int t;
  14.349 +	int t;
  14.350  
  14.351 -    UniReset();
  14.352 -    for(t=0;t<64;t++)
  14.353 -    {   ConvertNote(n);
  14.354 -        UniNewline();
  14.355 -        n+=of.numchn;
  14.356 -    }
  14.357 -    return UniDup();
  14.358 +	UniReset();
  14.359 +	for(t=0;t<64;t++) {
  14.360 +		ConvertNote(n);
  14.361 +		UniNewline();
  14.362 +		n+=of.numchn;
  14.363 +	}
  14.364 +	return UniDup();
  14.365  }
  14.366  
  14.367 -
  14.368 -BOOL ML_LoadPatterns(void)
  14.369 -/*  Loads all patterns of a modfile and converts them into the */
  14.370 -/*  3 byte format. */
  14.371 +/* Loads all patterns of a modfile and converts them into the 3 byte format. */
  14.372 +static BOOL ML_LoadPatterns(void)
  14.373  {
  14.374 -    int t,s,tracks = 0;
  14.375 +	int t,s,tracks = 0;
  14.376  
  14.377 -    if(!AllocPatterns()) return 0;
  14.378 -    if(!AllocTracks())   return 0;
  14.379 +	if(!AllocPatterns()) return 0;
  14.380 +	if(!AllocTracks())   return 0;
  14.381  
  14.382 -    /* Allocate temporary buffer for loading */
  14.383 -    /* and converting the patterns */
  14.384 -
  14.385 -    if(!(patbuf=(MODNOTE *)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  14.386 +	/* Allocate temporary buffer for loading and converting the patterns */
  14.387 +	if(!(patbuf=(MODNOTE*)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  14.388  
  14.389 -    for(t=0; t<of.numpat; t++)
  14.390 -    {   /* Load the pattern into the temp buffer */
  14.391 -        /* and convert it */
  14.392 -
  14.393 -        for(s=0; s<(64U*of.numchn); s++)
  14.394 -        {   patbuf[s].a = _mm_read_UBYTE(modfp);
  14.395 -            patbuf[s].b = _mm_read_UBYTE(modfp);
  14.396 -            patbuf[s].c = _mm_read_UBYTE(modfp);
  14.397 -            patbuf[s].d = _mm_read_UBYTE(modfp);
  14.398 -        }
  14.399 -
  14.400 -        for(s=0; s<of.numchn; s++)
  14.401 -            if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  14.402 -    }
  14.403 -
  14.404 -    return 1;
  14.405 +	for(t=0;t<of.numpat;t++) {
  14.406 +		/* Load the pattern into the temp buffer and convert it */
  14.407 +		for(s=0;s<(64U*of.numchn);s++) {
  14.408 +			patbuf[s].a=_mm_read_UBYTE(modreader);
  14.409 +			patbuf[s].b=_mm_read_UBYTE(modreader);
  14.410 +			patbuf[s].c=_mm_read_UBYTE(modreader);
  14.411 +			patbuf[s].d=_mm_read_UBYTE(modreader);
  14.412 +		}
  14.413 +		for(s=0;s<of.numchn;s++)
  14.414 +			if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  14.415 +	}
  14.416 +	return 1;
  14.417  }
  14.418  
  14.419 -
  14.420 -BOOL MOD_Load(void)
  14.421 +static BOOL MOD_Load(BOOL curious)
  14.422  {
  14.423 -    int       t;
  14.424 -    SAMPLE    *q;
  14.425 -    MSAMPINFO *s;           /* old module sampleinfo */
  14.426 -
  14.427 -    /* try to read module header */
  14.428 +	int t,scan;
  14.429 +	SAMPLE *q;
  14.430 +	MSAMPINFO *s;
  14.431 +	BOOL is_orpheus=0;
  14.432  
  14.433 -    _mm_read_string((CHAR *)mh->songname,20,modfp);
  14.434 -
  14.435 -    for(t=0; t<31; t++)
  14.436 -    {   s = &mh->samples[t];
  14.437 -        _mm_read_string(s->samplename,22,modfp);
  14.438 -        s->length   =_mm_read_M_UWORD(modfp);
  14.439 -        s->finetune =_mm_read_UBYTE(modfp);
  14.440 -        s->volume   =_mm_read_UBYTE(modfp);
  14.441 -        s->reppos   =_mm_read_M_UWORD(modfp);
  14.442 -        s->replen   =_mm_read_M_UWORD(modfp);
  14.443 -    }
  14.444 +	/* try to read module header */
  14.445 +	_mm_read_string((CHAR*)mh->songname,20,modreader);
  14.446 +	mh->songname[20]=0;	/* just in case */
  14.447  
  14.448 -    mh->songlength  =_mm_read_UBYTE(modfp);
  14.449 -    mh->magic1      =_mm_read_UBYTE(modfp);
  14.450 -
  14.451 -    _mm_read_UBYTES(mh->positions,128,modfp);
  14.452 -    _mm_read_UBYTES(mh->magic2,4,modfp);
  14.453 -
  14.454 -    if(feof(modfp))
  14.455 -    {   _mm_errno = MMERR_LOADING_HEADER;
  14.456 -        return 0;
  14.457 -    }
  14.458 +	for(t=0;t<31;t++) {
  14.459 +		s=&mh->samples[t];
  14.460 +		_mm_read_string(s->samplename,22,modreader);
  14.461 +		s->samplename[22]=0;	/* just in case */
  14.462 +		s->length   =_mm_read_M_UWORD(modreader);
  14.463 +		s->finetune =_mm_read_UBYTE(modreader);
  14.464 +		s->volume   =_mm_read_UBYTE(modreader);
  14.465 +		s->reppos   =_mm_read_M_UWORD(modreader);
  14.466 +		s->replen   =_mm_read_M_UWORD(modreader);
  14.467 +	}
  14.468  
  14.469 -    /* set module variables */
  14.470 +	mh->songlength  =_mm_read_UBYTE(modreader);
  14.471 +	mh->magic1      =_mm_read_UBYTE(modreader);
  14.472 +	_mm_read_UBYTES(mh->positions,128,modreader);
  14.473 +	_mm_read_UBYTES(mh->magic2,4,modreader);
  14.474  
  14.475 -    of.initspeed = 6;
  14.476 -    of.inittempo = 125;
  14.477 -    of.numchn    = modtypes[modtype].channels;      /* get number of channels */
  14.478 -    of.modtype   = strdup(modtypes[modtype].name);  /* get ascii type of mod */
  14.479 -    of.songname  = DupStr(mh->songname,20);         /* make a cstr of songname */
  14.480 -    of.numpos    = mh->songlength;                  /* copy the songlength */
  14.481 +	if(_mm_eof(modreader)) {
  14.482 +		_mm_errno = MMERR_LOADING_HEADER;
  14.483 +		return 0;
  14.484 +	}
  14.485  
  14.486 -    if(!AllocPositions(of.numpos)) return 0;
  14.487 -    for(t=0; t<of.numpos; t++)
  14.488 -        of.positions[t] = mh->positions[t];
  14.489 +	/* set module variables */
  14.490 +	of.initspeed = 6;
  14.491 +	of.inittempo = 125;
  14.492 +	of.numchn    = modtypes[modtype].channels;
  14.493 +	of.songname  = DupStr(mh->songname,21,1);
  14.494 +	of.numpos    = mh->songlength;
  14.495 +	of.reppos    = 0;
  14.496  
  14.497 -    /* Count the number of patterns */
  14.498 -
  14.499 -    of.numpat = 0;
  14.500 +	/* Count the number of patterns */
  14.501 +	of.numpat = 0;
  14.502 +	for(t=0;t<of.numpos;t++)
  14.503 +		if(mh->positions[t]>of.numpat)
  14.504 +			of.numpat=mh->positions[t];
  14.505 +	/* since some old modules embed extra patterns, we have to check the
  14.506 +	   whole list to get the samples' file offsets right - however we can find
  14.507 +	   garbage here, so check carefully */
  14.508 +	scan=1;
  14.509 +	for(t=of.numpos;t<128;t++)
  14.510 +		if(mh->positions[t]>=0x80) scan=0;
  14.511 +	if (scan)
  14.512 +		for(t=of.numpos;t<128;t++) {
  14.513 +			if(mh->positions[t]>of.numpat)
  14.514 +				of.numpat=mh->positions[t];
  14.515 +			if((curious)&&(mh->positions[t])) of.numpos=t+1;
  14.516 +		}
  14.517 +	of.numpat++;
  14.518 +	of.numtrk = of.numpat*of.numchn;
  14.519  
  14.520 -    for(t=0; t<of.numpos; t++)
  14.521 -    {   if(of.positions[t] > of.numpat)
  14.522 -            of.numpat = of.positions[t];
  14.523 -    }
  14.524 -    of.numpat++;
  14.525 -    of.numtrk = of.numpat*of.numchn;
  14.526 -    
  14.527 -    /* Finally, init the sampleinfo structures  */
  14.528 -    of.numins = of.numsmp = 31;
  14.529 +	if(!AllocPositions(of.numpos)) return 0;
  14.530 +	for(t=0;t<of.numpos;t++)
  14.531 +		of.positions[t]=mh->positions[t];
  14.532  
  14.533 -    if(!AllocSamples())     return 0;
  14.534 -    
  14.535 -    s = mh->samples;       /* init source pointer  */
  14.536 -    q = of.samples;
  14.537 -    
  14.538 -    for(t=0; t<of.numins; t++)
  14.539 -    {   /* convert the samplename */
  14.540 -        q->samplename = DupStr(s->samplename, 22);
  14.541 -
  14.542 -        /* init the sampleinfo variables and */
  14.543 -        /* convert the size pointers to longword format */
  14.544 +	/* Finally, init the sampleinfo structures  */
  14.545 +	of.numins=of.numsmp=31;
  14.546 +	if(!AllocSamples())     return 0;
  14.547 +	s = mh->samples;
  14.548 +	q = of.samples;
  14.549 +	for(t=0;t<of.numins;t++) {
  14.550 +		/* convert the samplename */
  14.551 +		q->samplename = DupStr(s->samplename,23,1);
  14.552 +		/* init the sampleinfo variables and convert the size pointers */
  14.553 +		q->speed     = finetune[s->finetune & 0xf];
  14.554 +		q->volume    = s->volume&0x7f;
  14.555 +		q->loopstart = (ULONG)s->reppos << 1;
  14.556 +		q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
  14.557 +		q->length    = (ULONG)s->length << 1;
  14.558 +		q->flags     = SF_SIGNED;
  14.559 +		/* Imago Orpheus creates MODs with 16 bit samples, check */
  14.560 +		if((modtypes[modtype].name==fasttracker)&&(s->volume&0x80)) {
  14.561 +			q->flags|=SF_16BITS;
  14.562 +			is_orpheus=1;
  14.563 +		}
  14.564  
  14.565 -        q->speed     = finetune[s->finetune & 0xf];
  14.566 -        q->volume    = s->volume;
  14.567 -        q->loopstart = (ULONG)s->reppos << 1;
  14.568 -        q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
  14.569 -        q->length    = (ULONG)s->length << 1;
  14.570 +		if(s->replen>1) q->flags |= SF_LOOP;
  14.571 +		/* fix replen if repend > length */
  14.572 +		if(q->loopend>q->length) q->loopend=q->length;
  14.573  
  14.574 -        q->flags     = SF_SIGNED;
  14.575 -        if(s->replen > 1) q->flags |= SF_LOOP;
  14.576 +		s++;
  14.577 +		q++;
  14.578 +	}
  14.579  
  14.580 -        /* fix replen if repend > length */
  14.581 -        if(q->loopend > q->length) q->loopend = q->length;
  14.582 +	if(is_orpheus)
  14.583 +		of.modtype=strdup(orpheus);
  14.584 +	else
  14.585 +		of.modtype=strdup(modtypes[modtype].name);
  14.586  
  14.587 -        s++;    /* point to next source sampleinfo */
  14.588 -        q++;
  14.589 -    }
  14.590 -
  14.591 -    if(!ML_LoadPatterns()) return 0;
  14.592 -    return 1;
  14.593 +	if(!ML_LoadPatterns()) return 0;
  14.594 +	return 1;
  14.595  }
  14.596  
  14.597 -
  14.598 -CHAR *MOD_LoadTitle(void)
  14.599 +static CHAR *MOD_LoadTitle(void)
  14.600  {
  14.601 -   CHAR s[20];
  14.602 +	CHAR s[21];
  14.603  
  14.604 -   _mm_fseek(modfp,0,SEEK_SET);
  14.605 -   if(!fread(s,20,1,modfp)) return NULL;
  14.606 -   
  14.607 -   return(DupStr(s,20));
  14.608 +	_mm_fseek(modreader,0,SEEK_SET);
  14.609 +	if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
  14.610 +	s[20]=0;	/* just in case */
  14.611 +
  14.612 +	return(DupStr(s,21,1));
  14.613  }
  14.614  
  14.615 +/*========== Loader information */
  14.616  
  14.617 -MLOADER load_mod =
  14.618 -{   NULL,
  14.619 -    "Standard module",
  14.620 -    "Portable MOD loader v0.11",
  14.621 -    MOD_Init,
  14.622 -    MOD_Test,
  14.623 -    MOD_Load,
  14.624 -    MOD_Cleanup,
  14.625 -    MOD_LoadTitle
  14.626 +MLOADER load_mod={
  14.627 +	NULL,
  14.628 +	"Standard module",
  14.629 +	"MOD (31 instrument)",
  14.630 +	MOD_Init,
  14.631 +	MOD_Test,
  14.632 +	MOD_Load,
  14.633 +	MOD_Cleanup,
  14.634 +	MOD_LoadTitle
  14.635  };
  14.636  
  14.637 +/* ex:set ts=4: */
    15.1 --- a/mikmod/load_s3m.c	Mon Dec 27 19:18:10 1999 +0000
    15.2 +++ b/mikmod/load_s3m.c	Mon Dec 27 19:24:50 1999 +0000
    15.3 @@ -1,466 +1,449 @@
    15.4 -/*
    15.5 +/*	MikMod sound library
    15.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    15.7 +	complete list.
    15.8  
    15.9 - Name: LOAD_S3M.C
   15.10 -
   15.11 - Description:
   15.12 - Screamtracker (S3M) module loader
   15.13 +	This library is free software; you can redistribute it and/or modify
   15.14 +	it under the terms of the GNU Library General Public License as
   15.15 +	published by the Free Software Foundation; either version 2 of
   15.16 +	the License, or (at your option) any later version.
   15.17  
   15.18 - Portability:
   15.19 - All systems - all compilers (hopefully)
   15.20 +	This program is distributed in the hope that it will be useful,
   15.21 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.22 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.23 +	GNU Library General Public License for more details.
   15.24  
   15.25 - If this module is found to not be portable to any particular platform,
   15.26 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   15.27 - more information on contacting the author).
   15.28 -
   15.29 +	You should have received a copy of the GNU Library General Public
   15.30 +	License along with this library; if not, write to the Free Software
   15.31 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   15.32 +	02111-1307, USA.
   15.33  */
   15.34  
   15.35 +/*==============================================================================
   15.36 +
   15.37 +  $Id$
   15.38 +
   15.39 +  Screamtracker (S3M) module loader
   15.40 +
   15.41 +==============================================================================*/
   15.42 +
   15.43 +#ifdef HAVE_CONFIG_H
   15.44 +#include "config.h"
   15.45 +#endif
   15.46 +
   15.47  #include <string.h>
   15.48 -#include "mikmod.h"
   15.49 +
   15.50 +#include "mikmod_internals.h"
   15.51 +
   15.52 +/*========== Module structure */
   15.53  
   15.54 -/**************************************************************************
   15.55 -**************************************************************************/
   15.56 +/* header */
   15.57 +typedef struct S3MHEADER {
   15.58 +	CHAR  songname[28];
   15.59 +	UBYTE t1a;
   15.60 +	UBYTE type;
   15.61 +	UBYTE unused1[2];
   15.62 +	UWORD ordnum;
   15.63 +	UWORD insnum;
   15.64 +	UWORD patnum;
   15.65 +	UWORD flags;
   15.66 +	UWORD tracker;
   15.67 +	UWORD fileformat;
   15.68 +	CHAR  scrm[4];
   15.69 +	UBYTE mastervol;
   15.70 +	UBYTE initspeed;
   15.71 +	UBYTE inittempo;
   15.72 +	UBYTE mastermult;
   15.73 +	UBYTE ultraclick;
   15.74 +	UBYTE pantable;
   15.75 +	UBYTE unused2[8];
   15.76 +	UWORD special;
   15.77 +	UBYTE channels[32];
   15.78 +} S3MHEADER;
   15.79  
   15.80 -typedef struct S3MNOTE
   15.81 -{   UBYTE note,ins,vol,cmd,inf;
   15.82 +/* sample information */
   15.83 +typedef struct S3MSAMPLE {
   15.84 +	UBYTE type;
   15.85 +	CHAR  filename[12];
   15.86 +	UBYTE memsegh;
   15.87 +	UWORD memsegl;
   15.88 +	ULONG length;
   15.89 +	ULONG loopbeg;
   15.90 +	ULONG loopend;
   15.91 +	UBYTE volume;
   15.92 +	UBYTE dsk;
   15.93 +	UBYTE pack;
   15.94 +	UBYTE flags;
   15.95 +	ULONG c2spd;
   15.96 +	UBYTE unused[12];
   15.97 +	CHAR  sampname[28];
   15.98 +	CHAR  scrs[4];
   15.99 +} S3MSAMPLE;
  15.100 +
  15.101 +typedef struct S3MNOTE {
  15.102 +	UBYTE note,ins,vol,cmd,inf;
  15.103  } S3MNOTE;
  15.104  
  15.105 -typedef S3MNOTE S3MTRACK[64];
  15.106 -
  15.107 -
  15.108 -/* Raw S3M header struct: */
  15.109 -
  15.110 -typedef struct S3MHEADER
  15.111 -{   CHAR  songname[28];
  15.112 -    UBYTE t1a;
  15.113 -    UBYTE type;
  15.114 -    UBYTE unused1[2];
  15.115 -    UWORD ordnum;
  15.116 -    UWORD insnum;
  15.117 -    UWORD patnum;
  15.118 -    UWORD flags;
  15.119 -    UWORD tracker;
  15.120 -    UWORD fileformat;
  15.121 -    CHAR  scrm[4];
  15.122 -    UBYTE mastervol;
  15.123 -    UBYTE initspeed;
  15.124 -    UBYTE inittempo;
  15.125 -    UBYTE mastermult;
  15.126 -    UBYTE ultraclick;
  15.127 -    UBYTE pantable;
  15.128 -    UBYTE unused2[8];
  15.129 -    UWORD special;
  15.130 -    UBYTE channels[32];
  15.131 -} S3MHEADER;
  15.132 -
  15.133 -
  15.134 -/* Raw S3M sampleinfo struct: */
  15.135 -
  15.136 -typedef struct S3MSAMPLE
  15.137 -{   UBYTE type;
  15.138 -    CHAR  filename[12];
  15.139 -    UBYTE memsegh;
  15.140 -    UWORD memsegl;
  15.141 -    ULONG length;
  15.142 -    ULONG loopbeg;
  15.143 -    ULONG loopend;
  15.144 -    UBYTE volume;
  15.145 -    UBYTE dsk;
  15.146 -    UBYTE pack;
  15.147 -    UBYTE flags;
  15.148 -    ULONG c2spd;
  15.149 -    UBYTE unused[12];
  15.150 -    CHAR  sampname[28];
  15.151 -    CHAR  scrs[4];
  15.152 -} S3MSAMPLE;
  15.153 -
  15.154 -/**************************************************************************
  15.155 -**************************************************************************/
  15.156 -
  15.157 -
  15.158 -extern UBYTE *poslookup;       /* S3M/IT fix - removing blank patterns needs a */
  15.159 -                               /* lookup table to fix position-jump commands */
  15.160 -extern SBYTE  remap[64];       /* for removing empty channels */
  15.161 +/*========== Loader variables */
  15.162  
  15.163  static S3MNOTE   *s3mbuf  = NULL; /* pointer to a complete S3M pattern */
  15.164  static S3MHEADER *mh      = NULL;
  15.165  static UWORD     *paraptr = NULL; /* parapointer array (see S3M docs) */
  15.166  
  15.167 -CHAR  S3M_Version[] = "Screamtracker 3.xx";
  15.168 +/* tracker identifiers */
  15.169 +#define NUMTRACKERS 4
  15.170 +static CHAR* S3M_Version[] = {
  15.171 +	"Screamtracker x.xx",
  15.172 +	"Imago Orpheus x.xx (S3M format)",
  15.173 +	"Impulse Tracker x.xx (S3M format)",
  15.174 +	"Unknown tracker x.xx (S3M format)",
  15.175 +	"Impulse Tracker 2.14p3 (S3M format)",
  15.176 +	"Impulse Tracker 2.14p4 (S3M format)"
  15.177 +};
  15.178 +/* version number position in above array */
  15.179 +static int numeric[NUMTRACKERS]={14,14,16,16};
  15.180 +
  15.181 +/*========== Loader code */
  15.182  
  15.183  BOOL S3M_Test(void)
  15.184  {
  15.185 -    UBYTE id[4];
  15.186 -    
  15.187 -    _mm_fseek(modfp,0x2c,SEEK_SET);
  15.188 -    if(!_mm_read_UBYTES(id,4,modfp)) return 0;
  15.189 -    if(!memcmp(id,"SCRM",4)) return 1;
  15.190 -    return 0;
  15.191 +	UBYTE id[4];
  15.192 +
  15.193 +	_mm_fseek(modreader,0x2c,SEEK_SET);
  15.194 +	if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  15.195 +	if(!memcmp(id,"SCRM",4)) return 1;
  15.196 +	return 0;
  15.197  }
  15.198  
  15.199  BOOL S3M_Init(void)
  15.200  {
  15.201 -    if(!(s3mbuf    = (S3MNOTE *)_mm_malloc(16*64*sizeof(S3MNOTE)))) return 0;
  15.202 -    if(!(mh        = (S3MHEADER *)_mm_calloc(1,sizeof(S3MHEADER)))) return 0;
  15.203 -    if(!(poslookup = (UBYTE *)_mm_malloc(sizeof(UBYTE)*128))) return 0;
  15.204 +	if(!(s3mbuf=(S3MNOTE*)_mm_malloc(32*64*sizeof(S3MNOTE)))) return 0;
  15.205 +	if(!(mh=(S3MHEADER*)_mm_malloc(sizeof(S3MHEADER)))) return 0;
  15.206 +	if(!(poslookup=(UBYTE*)_mm_malloc(sizeof(UBYTE)*256))) return 0;
  15.207 +	memset(poslookup,-1,256);
  15.208  
  15.209 -    return 1;
  15.210 +	return 1;
  15.211  }
  15.212  
  15.213  void S3M_Cleanup(void)
  15.214  {
  15.215 -    if(s3mbuf!=NULL) free(s3mbuf);
  15.216 -    if(paraptr!=NULL) free(paraptr);
  15.217 -    if(poslookup!=NULL) free(poslookup);
  15.218 -    if(mh!=NULL) free(mh);
  15.219 +	_mm_free(s3mbuf);
  15.220 +	_mm_free(paraptr);
  15.221 +	_mm_free(poslookup);
  15.222 +	_mm_free(mh);
  15.223 +	_mm_free(origpositions);
  15.224 +}
  15.225 +
  15.226 +/* Because so many s3m files have 16 channels as the set number used, but really
  15.227 +   only use far less (usually 8 to 12 still), I had to make this function, which
  15.228 +   determines the number of channels that are actually USED by a pattern.
  15.229 +
  15.230 +   For every channel that's used, it sets the appropriate array entry of the
  15.231 +   global variable 'remap'
  15.232 +
  15.233 +   NOTE: You must first seek to the file location of the pattern before calling
  15.234 +         this procedure.
  15.235  
  15.236 -    paraptr   = NULL;
  15.237 -    s3mbuf    = NULL;
  15.238 -    poslookup = NULL;
  15.239 -    mh        = NULL;
  15.240 +   Returns 1 on fail.                                                         */
  15.241 +static BOOL S3M_GetNumChannels(void)
  15.242 +{
  15.243 +	int row=0,flag,ch;
  15.244 +
  15.245 +	while(row<64) {
  15.246 +		flag=_mm_read_UBYTE(modreader);
  15.247 +
  15.248 +		if(_mm_eof(modreader)) {
  15.249 +			_mm_errno = MMERR_LOADING_PATTERN;
  15.250 +			return 1;
  15.251 +		}
  15.252 +
  15.253 +		if(flag) {
  15.254 +			ch=flag&31;
  15.255 +			if(mh->channels[ch]<32) remap[ch] = 0;
  15.256 +			if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  15.257 +			if(flag&64) _mm_read_UBYTE(modreader);
  15.258 +			if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  15.259 +		} else row++;
  15.260 +	}
  15.261 +	return 0;
  15.262  }
  15.263  
  15.264 -
  15.265 -BOOL S3M_GetNumChannels(void)
  15.266 +static BOOL S3M_ReadPattern(void)
  15.267 +{
  15.268 +	int row=0,flag,ch;
  15.269 +	S3MNOTE *n,dummy;
  15.270  
  15.271 -/* Because so many s3m files have 16 channels as the set number used, but really */
  15.272 -/* only use far less (usually 8 to 12 still), I had to make this function, */
  15.273 -/* which determines the number of channels that are actually USED by a pattern. */
  15.274 -/* */
  15.275 -/* For every channel that's used, it sets the appropriate array entry of the */
  15.276 -/* global varialbe 'isused' */
  15.277 -/* */
  15.278 -/* NOTE: You must first seek to the file location of the pattern before calling */
  15.279 -/*       this procedure. */
  15.280 -/* Returns 1 on fail. */
  15.281 -
  15.282 -{
  15.283 -    int row=0,flag,ch;
  15.284 -
  15.285 -    while(row<64)
  15.286 -    {   flag = _mm_read_UBYTE(modfp);
  15.287 +	/* clear pattern data */
  15.288 +	memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
  15.289  
  15.290 -        if(feof(modfp))
  15.291 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  15.292 -            return 1;
  15.293 -        }
  15.294 +	while(row<64) {
  15.295 +		flag=_mm_read_UBYTE(modreader);
  15.296  
  15.297 -        if(flag)
  15.298 -        {   ch = flag&31;
  15.299 -            if(mh->channels[ch] < 16) remap[ch] = 0;
  15.300 -            
  15.301 -            if(flag&32)
  15.302 -            {   _mm_read_UBYTE(modfp);
  15.303 -                _mm_read_UBYTE(modfp);
  15.304 -            }
  15.305 +		if(_mm_eof(modreader)) {
  15.306 +			_mm_errno = MMERR_LOADING_PATTERN;
  15.307 +			return 0;
  15.308 +		}
  15.309  
  15.310 -            if(flag&64)
  15.311 -                _mm_read_UBYTE(modfp);
  15.312 -
  15.313 -            if(flag&128)
  15.314 -            {   _mm_read_UBYTE(modfp);
  15.315 -                _mm_read_UBYTE(modfp);
  15.316 -            }
  15.317 -        } else row++;
  15.318 -    }
  15.319 +		if(flag) {
  15.320 +			ch=remap[flag&31];
  15.321  
  15.322 -    return 0;
  15.323 -}    
  15.324 -
  15.325 -
  15.326 -BOOL S3M_ReadPattern(void)
  15.327 -{
  15.328 -    int row=0,flag,ch;
  15.329 -    S3MNOTE *n;
  15.330 -    S3MNOTE dummy;
  15.331 -
  15.332 -    /* clear pattern data */
  15.333 -    memset(s3mbuf,255,16*64*sizeof(S3MNOTE));
  15.334 -
  15.335 -    while(row<64)
  15.336 -    {   flag = _mm_read_UBYTE(modfp);
  15.337 -
  15.338 -        if(flag==EOF)
  15.339 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  15.340 -            return 0;
  15.341 -        }
  15.342 +			if(ch!=-1)
  15.343 +				n=&s3mbuf[(64U*ch)+row];
  15.344 +			else
  15.345 +				n=&dummy;
  15.346  
  15.347 -        if(flag)
  15.348 -        {   ch = remap[flag&31];
  15.349 -
  15.350 -            if(ch != -1)
  15.351 -                n = &s3mbuf[(64U*ch)+row];
  15.352 -            else
  15.353 -                n = &dummy;
  15.354 -
  15.355 -            if(flag&32)
  15.356 -            {   n->note = _mm_read_UBYTE(modfp);
  15.357 -                n->ins  = _mm_read_UBYTE(modfp);
  15.358 -            }
  15.359 -
  15.360 -            if(flag&64)
  15.361 -                n->vol = _mm_read_UBYTE(modfp);
  15.362 -
  15.363 -            if(flag&128)
  15.364 -            {   n->cmd = _mm_read_UBYTE(modfp);
  15.365 -                n->inf = _mm_read_UBYTE(modfp);
  15.366 -            }
  15.367 -        } else row++;
  15.368 -    }
  15.369 -    return 1;
  15.370 +			if(flag&32) {
  15.371 +				n->note=_mm_read_UBYTE(modreader);
  15.372 +				n->ins=_mm_read_UBYTE(modreader);
  15.373 +			}
  15.374 +			if(flag&64)
  15.375 +				n->vol=_mm_read_UBYTE(modreader);
  15.376 +			if(flag&128) {
  15.377 +				n->cmd=_mm_read_UBYTE(modreader);
  15.378 +				n->inf=_mm_read_UBYTE(modreader);
  15.379 +			}
  15.380 +		} else row++;
  15.381 +	}
  15.382 +	return 1;
  15.383  }
  15.384  
  15.385 -
  15.386 -void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, BOOL oldeffect);
  15.387 -
  15.388 -UBYTE *S3M_ConvertTrack(S3MNOTE *tr)
  15.389 +static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
  15.390  {
  15.391 -    int t;
  15.392 +	int t;
  15.393  
  15.394 -    UBYTE note,ins,vol;
  15.395 +	UniReset();
  15.396 +	for(t=0;t<64;t++) {
  15.397 +		UBYTE note,ins,vol;
  15.398  
  15.399 -    UniReset();
  15.400 -    for(t=0; t<64; t++)
  15.401 -    {
  15.402 -        note = tr[t].note;
  15.403 -        ins  = tr[t].ins;
  15.404 -        vol  = tr[t].vol;
  15.405 +		note=tr[t].note;
  15.406 +		ins=tr[t].ins;
  15.407 +		vol=tr[t].vol;
  15.408  
  15.409 -
  15.410 -        if(ins!=0 && ins!=255) UniInstrument(ins-1);
  15.411 -        if(note!=255)
  15.412 -        {   if(note==254) UniPTEffect(0xc,0);             /* <- note off command */
  15.413 -            else UniNote(((note>>4)*12)+(note&0xf));      /* <- normal note */
  15.414 -        }
  15.415 +		if((ins)&&(ins!=255)) UniInstrument(ins-1);
  15.416 +		if(note!=255) {
  15.417 +			if(note==254) {
  15.418 +				UniPTEffect(0xc,0);	/* note cut command */
  15.419 +				vol=255;
  15.420 +			} else
  15.421 +				UniNote(((note>>4)*OCTAVE)+(note&0xf));	/* normal note */
  15.422 +		}
  15.423 +		if(vol<255) UniPTEffect(0xc,vol);
  15.424  
  15.425 -        if(vol<255)
  15.426 -            UniPTEffect(0xc,vol);
  15.427 -
  15.428 -        S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,1);
  15.429 -        UniNewline();
  15.430 -    }
  15.431 -
  15.432 -    return UniDup();
  15.433 +		S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,1);
  15.434 +		UniNewline();
  15.435 +	}
  15.436 +	return UniDup();
  15.437  }
  15.438  
  15.439 -
  15.440 -BOOL S3M_Load(void)
  15.441 +BOOL S3M_Load(BOOL curious)
  15.442  {
  15.443 -    int    t,u,track = 0;
  15.444 -    SAMPLE *q;
  15.445 -    UBYTE  pan[32];
  15.446 -
  15.447 -    /* try to read module header */
  15.448 +	int t,u,track = 0;
  15.449 +	SAMPLE *q;
  15.450 +	UBYTE pan[32];
  15.451  
  15.452 -    _mm_read_string(mh->songname,28,modfp);
  15.453 -    mh->t1a         =_mm_read_UBYTE(modfp);
  15.454 -    mh->type        =_mm_read_UBYTE(modfp);
  15.455 -    _mm_read_UBYTES(mh->unused1,2,modfp);
  15.456 -    mh->ordnum      =_mm_read_I_UWORD(modfp);
  15.457 -    mh->insnum      =_mm_read_I_UWORD(modfp);
  15.458 -    mh->patnum      =_mm_read_I_UWORD(modfp);
  15.459 -    mh->flags       =_mm_read_I_UWORD(modfp);
  15.460 -    mh->tracker     =_mm_read_I_UWORD(modfp);
  15.461 -    mh->fileformat  =_mm_read_I_UWORD(modfp);
  15.462 -    _mm_read_string(mh->scrm,4,modfp);
  15.463 +	/* try to read module header */
  15.464 +	_mm_read_string(mh->songname,28,modreader);
  15.465 +	mh->t1a         =_mm_read_UBYTE(modreader);
  15.466 +	mh->type        =_mm_read_UBYTE(modreader);
  15.467 +	_mm_read_UBYTES(mh->unused1,2,modreader);
  15.468 +	mh->ordnum      =_mm_read_I_UWORD(modreader);
  15.469 +	mh->insnum      =_mm_read_I_UWORD(modreader);
  15.470 +	mh->patnum      =_mm_read_I_UWORD(modreader);
  15.471 +	mh->flags       =_mm_read_I_UWORD(modreader);
  15.472 +	mh->tracker     =_mm_read_I_UWORD(modreader);
  15.473 +	mh->fileformat  =_mm_read_I_UWORD(modreader);
  15.474 +	_mm_read_string(mh->scrm,4,modreader);
  15.475 +	mh->mastervol   =_mm_read_UBYTE(modreader);
  15.476 +	mh->initspeed   =_mm_read_UBYTE(modreader);
  15.477 +	mh->inittempo   =_mm_read_UBYTE(modreader);
  15.478 +	mh->mastermult  =_mm_read_UBYTE(modreader);
  15.479 +	mh->ultraclick  =_mm_read_UBYTE(modreader);
  15.480 +	mh->pantable    =_mm_read_UBYTE(modreader);
  15.481 +	_mm_read_UBYTES(mh->unused2,8,modreader);
  15.482 +	mh->special     =_mm_read_I_UWORD(modreader);
  15.483 +	_mm_read_UBYTES(mh->channels,32,modreader);
  15.484  
  15.485 -    mh->mastervol   =_mm_read_UBYTE(modfp);
  15.486 -    mh->initspeed   =_mm_read_UBYTE(modfp);
  15.487 -    mh->inittempo   =_mm_read_UBYTE(modfp);
  15.488 -    mh->mastermult  =_mm_read_UBYTE(modfp);
  15.489 -    mh->ultraclick  =_mm_read_UBYTE(modfp);
  15.490 -    mh->pantable    =_mm_read_UBYTE(modfp);
  15.491 -    _mm_read_UBYTES(mh->unused2,8,modfp);
  15.492 -    mh->special     =_mm_read_I_UWORD(modfp);
  15.493 -    _mm_read_UBYTES(mh->channels,32,modfp);
  15.494 -
  15.495 -    if(feof(modfp))
  15.496 -    {   _mm_errno = MMERR_LOADING_HEADER;
  15.497 -        return 0;
  15.498 -    }
  15.499 -
  15.500 -    /* set module variables */
  15.501 +	if(_mm_eof(modreader)) {
  15.502 +		_mm_errno = MMERR_LOADING_HEADER;
  15.503 +		return 0;
  15.504 +	}
  15.505  
  15.506 -    of.modtype     = strdup(S3M_Version);
  15.507 -    of.modtype[14] = ((mh->tracker >> 8) &0xf) + 0x30;
  15.508 -    of.modtype[16] = ((mh->tracker >> 4)&0xf) + 0x30;
  15.509 -    of.modtype[17] = ((mh->tracker)&0xf) + 0x30;
  15.510 -    of.songname    = DupStr(mh->songname,28);
  15.511 -    of.numpat      = mh->patnum;
  15.512 -    of.reppos      = 0;
  15.513 -    of.numins      = of.numsmp = mh->insnum;
  15.514 -    of.initspeed   = mh->initspeed;
  15.515 -    of.inittempo   = mh->inittempo;
  15.516 -    of.initvolume  = mh->mastervol<<1;
  15.517 +	/* set module variables */
  15.518 +	of.songname    = DupStr(mh->songname,28,0);
  15.519 +	of.numpat      = mh->patnum;
  15.520 +	of.reppos      = 0;
  15.521 +	of.numins      = of.numsmp = mh->insnum;
  15.522 +	of.initspeed   = mh->initspeed;
  15.523 +	of.inittempo   = mh->inittempo;
  15.524 +	of.initvolume  = mh->mastervol<<1;
  15.525 +	of.flags      |= UF_ARPMEM;
  15.526 +	if((mh->tracker==0x1300)||(mh->flags&64))
  15.527 +		of.flags|=UF_S3MSLIDES;
  15.528  
  15.529 -    /* read the order data */
  15.530 -    if(!AllocPositions(mh->ordnum)) return 0;
  15.531 -    for(t=0; t<mh->ordnum; t++)
  15.532 -        of.positions[t] = _mm_read_UBYTE(modfp);
  15.533 +	/* read the order data */
  15.534 +	if(!AllocPositions(mh->ordnum)) return 0;
  15.535 +	if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
  15.536  
  15.537 -    of.numpos = 0;
  15.538 -    for(t=0; t<mh->ordnum; t++)
  15.539 -    {   of.positions[of.numpos] = of.positions[t];
  15.540 -        poslookup[t]            = of.numpos;   /* bug fix for FREAKY S3Ms */
  15.541 -        if(of.positions[t]<254) of.numpos++;        
  15.542 -    }
  15.543 -
  15.544 -    if((paraptr=(UWORD *)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD)))==NULL) return 0;
  15.545 -
  15.546 -    /* read the instrument+pattern parapointers */
  15.547 -    _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modfp);
  15.548 +	for(t=0;t<mh->ordnum;t++) {
  15.549 +		origpositions[t]=_mm_read_UBYTE(modreader);
  15.550 +		if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
  15.551 +			origpositions[t]=255/*mh->patnum-1*/;
  15.552 +	}
  15.553  
  15.554 -
  15.555 -    if(mh->pantable==252)
  15.556 -    {   /* read the panning table (ST 3.2 addition.  See below for further */
  15.557 -        /* portions of channel panning [past reampper]). */
  15.558 -        _mm_read_UBYTES(pan,32,modfp);
  15.559 -    }
  15.560 +	if(_mm_eof(modreader)) {
  15.561 +		_mm_errno = MMERR_LOADING_HEADER;
  15.562 +		return 0;
  15.563 +	}
  15.564  
  15.565 -
  15.566 -    /* now is a good time to check if the header was too short :) */
  15.567 +	poslookupcnt=mh->ordnum;
  15.568 +	S3MIT_CreateOrders(curious);
  15.569  
  15.570 -    if(feof(modfp))
  15.571 -    {   _mm_errno = MMERR_LOADING_HEADER;
  15.572 -        return 0;
  15.573 -    }
  15.574 +	if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
  15.575 +		return 0;
  15.576 +
  15.577 +	/* read the instrument+pattern parapointers */
  15.578 +	_mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
  15.579  
  15.580 -
  15.581 -    /* ============================================== */
  15.582 -    /* Load those darned Samples!  (no insts in ST3) */
  15.583 -
  15.584 -    if(!AllocSamples()) return 0;
  15.585 +	if(mh->pantable==252) {
  15.586 +		/* read the panning table (ST 3.2 addition.  See below for further
  15.587 +		   portions of channel panning [past reampper]). */
  15.588 +		_mm_read_UBYTES(pan,32,modreader);
  15.589 +	}
  15.590  
  15.591 -    q = of.samples;
  15.592 +	if(_mm_eof(modreader)) {
  15.593 +		_mm_errno = MMERR_LOADING_HEADER;
  15.594 +		return 0;
  15.595 +	}
  15.596  
  15.597 -    for(t=0; t<of.numins; t++)
  15.598 -    {   S3MSAMPLE s;
  15.599 -
  15.600 -        /* seek to instrument position */
  15.601 -
  15.602 -        _mm_fseek(modfp,((long)paraptr[t])<<4,SEEK_SET);
  15.603 +	/* load samples */
  15.604 +	if(!AllocSamples()) return 0;
  15.605 +	q = of.samples;
  15.606 +	for(t=0;t<of.numins;t++) {
  15.607 +		S3MSAMPLE s;
  15.608  
  15.609 -        /* and load sample info */
  15.610 -
  15.611 -        s.type      =_mm_read_UBYTE(modfp);
  15.612 -        _mm_read_string(s.filename,12,modfp);
  15.613 -        s.memsegh   =_mm_read_UBYTE(modfp);
  15.614 -        s.memsegl   =_mm_read_I_UWORD(modfp);
  15.615 -        s.length    =_mm_read_I_ULONG(modfp);
  15.616 -        s.loopbeg   =_mm_read_I_ULONG(modfp);
  15.617 -        s.loopend   =_mm_read_I_ULONG(modfp);
  15.618 -        s.volume    =_mm_read_UBYTE(modfp);
  15.619 -        s.dsk       =_mm_read_UBYTE(modfp);
  15.620 -        s.pack      =_mm_read_UBYTE(modfp);
  15.621 -        s.flags     =_mm_read_UBYTE(modfp);
  15.622 -        s.c2spd     =_mm_read_I_ULONG(modfp);
  15.623 -        _mm_read_UBYTES(s.unused,12,modfp);
  15.624 -        _mm_read_string(s.sampname,28,modfp);
  15.625 -        _mm_read_string(s.scrs,4,modfp);
  15.626 -
  15.627 -        if(feof(modfp))
  15.628 -        {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  15.629 -            return 0;
  15.630 -        }
  15.631 +		/* seek to instrument position */
  15.632 +		_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
  15.633 +		/* and load sample info */
  15.634 +		s.type      =_mm_read_UBYTE(modreader);
  15.635 +		_mm_read_string(s.filename,12,modreader);
  15.636 +		s.memsegh   =_mm_read_UBYTE(modreader);
  15.637 +		s.memsegl   =_mm_read_I_UWORD(modreader);
  15.638 +		s.length    =_mm_read_I_ULONG(modreader);
  15.639 +		s.loopbeg   =_mm_read_I_ULONG(modreader);
  15.640 +		s.loopend   =_mm_read_I_ULONG(modreader);
  15.641 +		s.volume    =_mm_read_UBYTE(modreader);
  15.642 +		s.dsk       =_mm_read_UBYTE(modreader);
  15.643 +		s.pack      =_mm_read_UBYTE(modreader);
  15.644 +		s.flags     =_mm_read_UBYTE(modreader);
  15.645 +		s.c2spd     =_mm_read_I_ULONG(modreader);
  15.646 +		_mm_read_UBYTES(s.unused,12,modreader);
  15.647 +		_mm_read_string(s.sampname,28,modreader);
  15.648 +		_mm_read_string(s.scrs,4,modreader);
  15.649  
  15.650 -        q->samplename = DupStr(s.sampname,28);
  15.651 -        q->speed      = s.c2spd;
  15.652 -        q->length     = s.length;
  15.653 -        q->loopstart  = s.loopbeg;
  15.654 -        q->loopend    = s.loopend;
  15.655 -        q->volume     = s.volume;
  15.656 -        q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  15.657 -
  15.658 -        if(s.flags&1) q->flags |= SF_LOOP;
  15.659 -        if(s.flags&4) q->flags |= SF_16BITS;
  15.660 -        if(mh->fileformat==1) q->flags |= SF_SIGNED;
  15.661 +		if(_mm_eof(modreader)) {
  15.662 +			_mm_errno = MMERR_LOADING_SAMPLEINFO;
  15.663 +			return 0;
  15.664 +		}
  15.665  
  15.666 -        /* DON'T load sample if it doesn't have the SCRS tag */
  15.667 -        if(memcmp(s.scrs,"SCRS",4)!=0) q->length = 0;
  15.668 -
  15.669 -        q++;
  15.670 -    }
  15.671 +		q->samplename = DupStr(s.sampname,28,0);
  15.672 +		q->speed      = s.c2spd;
  15.673 +		q->length     = s.length;
  15.674 +		q->loopstart  = s.loopbeg>s.length?s.length:s.loopbeg;
  15.675 +		q->loopend    = s.loopend>s.length?s.length:s.loopend;
  15.676 +		q->volume     = s.volume;
  15.677 +		q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  15.678  
  15.679 -    /* ==================================== */
  15.680 -    /* Determine the number of channels actually used.  (what ever happened */
  15.681 -    /* to the concept of a single "numchn" variable, eh?! */
  15.682 +		if(s.flags&1) q->flags |= SF_LOOP;
  15.683 +		if(s.flags&4) q->flags |= SF_16BITS;
  15.684 +		if(mh->fileformat==1) q->flags |= SF_SIGNED;
  15.685  
  15.686 -    of.numchn = 0;
  15.687 -    memset(remap,-1,32*sizeof(UBYTE));
  15.688 +		/* don't load sample if it doesn't have the SCRS tag */
  15.689 +		if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
  15.690 +
  15.691 +		q++;
  15.692 +	}
  15.693  
  15.694 -    for(t=0; t<of.numpat; t++)
  15.695 -    {   /* seek to pattern position ( + 2 skip pattern length ) */
  15.696 -        _mm_fseek(modfp,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.697 -        if(S3M_GetNumChannels()) return 0;
  15.698 -    }
  15.699 -    
  15.700 -    /* build the remap array  */
  15.701 -    for(t=0; t<32; t++)
  15.702 -    {   if(remap[t]==0)
  15.703 -        {   remap[t] = of.numchn;
  15.704 -            of.numchn++;
  15.705 -        }
  15.706 -    }
  15.707 -
  15.708 -    /* ============================================================ */
  15.709 -    /* set panning positions AFTER building remap chart! */
  15.710 -
  15.711 -    for(t=0; t<32; t++)
  15.712 -    {   if((mh->channels[t]<16) && (remap[t]!=-1))
  15.713 -        {   if(mh->channels[t]<8)
  15.714 -                of.panning[remap[t]] = 0x20;     /* 0x30 = std s3m val */
  15.715 -            else
  15.716 -                of.panning[remap[t]] = 0xd0;     /* 0xc0 = std s3m val */
  15.717 -        }
  15.718 -    }
  15.719 +	/* determine the number of channels actually used. */
  15.720 +	of.numchn = 0;
  15.721 +	memset(remap,-1,32*sizeof(UBYTE));
  15.722 +	for(t=0;t<of.numpat;t++) {
  15.723 +		/* seek to pattern position (+2 skip pattern length) */
  15.724 +		_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.725 +		if(S3M_GetNumChannels()) return 0;
  15.726 +	}
  15.727 +	/* then we can decide the module type */
  15.728 +	t=mh->tracker>>12;
  15.729 +	if((!t)||(t>3))
  15.730 +		t=NUMTRACKERS-1; /* unknown tracker */
  15.731 +	else {
  15.732 +		if(mh->tracker>=0x3217)
  15.733 +			t=NUMTRACKERS+1; /* IT 2.14p4 */
  15.734 +		else if(mh->tracker>=0x3216)
  15.735 +			t=NUMTRACKERS; /* IT 2.14p3 */
  15.736 +		else t--;
  15.737 +	}
  15.738 +	of.modtype = strdup(S3M_Version[t]);
  15.739 +	if(t<NUMTRACKERS) {
  15.740 +		of.modtype[numeric[t]] = ((mh->tracker>>8) &0xf)+'0';
  15.741 +		of.modtype[numeric[t]+2] = ((mh->tracker>>4)&0xf)+'0';
  15.742 +		of.modtype[numeric[t]+3] = ((mh->tracker)&0xf)+'0';
  15.743 +	}
  15.744  
  15.745 -    if(mh->pantable==252)
  15.746 -    {   /* set panning positions according to panning table (new for st3.2) */
  15.747 -        for(t=0; t<32; t++)
  15.748 -        {   if((pan[t]&0x20) && (mh->channels[t]<16) && (remap[t]!=-1))
  15.749 -                of.panning[remap[t]] = (pan[t]&0xf)<<4;
  15.750 -        }
  15.751 -    }
  15.752 -
  15.753 +	/* build the remap array  */
  15.754 +	for(t=0;t<32;t++)
  15.755 +		if(!remap[t])
  15.756 +			remap[t]=of.numchn++;
  15.757  
  15.758 -    /* ============================== */
  15.759 -    /* Load the pattern info now! */
  15.760 -    
  15.761 -    of.numtrk = of.numpat*of.numchn;
  15.762 -    if(!AllocTracks()) return 0;
  15.763 -    if(!AllocPatterns()) return 0;
  15.764 +	/* set panning positions after building remap chart! */
  15.765 +	for(t=0;t<32;t++)
  15.766 +		if((mh->channels[t]<32)&&(remap[t]!=-1)) {
  15.767 +			if(mh->channels[t]<8)
  15.768 +				of.panning[remap[t]]=0x20;	/* 0x30 = std s3m val */
  15.769 +			else
  15.770 +				of.panning[remap[t]]=0xd0;	/* 0xc0 = std s3m val */
  15.771 +		}
  15.772 +	if(mh->pantable==252)
  15.773 +		/* set panning positions according to panning table (new for st3.2) */
  15.774 +		for(t=0;t<32;t++)
  15.775 +			if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
  15.776 +				of.panning[remap[t]]=(pan[t]&0xf)<<4;
  15.777  
  15.778 -    for(t=0; t<of.numpat; t++)
  15.779 -    {   /* seek to pattern position ( + 2 skip pattern length ) */
  15.780 -        _mm_fseek(modfp,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.781 -        if(!S3M_ReadPattern()) return 0;
  15.782 -        for(u=0; u<of.numchn; u++)
  15.783 -            if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  15.784 -    }
  15.785 +	/* load pattern info */
  15.786 +	of.numtrk=of.numpat*of.numchn;
  15.787 +	if(!AllocTracks()) return 0;
  15.788 +	if(!AllocPatterns()) return 0;
  15.789  
  15.790 -    return 1;
  15.791 +	for(t=0;t<of.numpat;t++) {
  15.792 +		/* seek to pattern position (+2 skip pattern length) */
  15.793 +		_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.794 +		if(!S3M_ReadPattern()) return 0;
  15.795 +		for(u=0;u<of.numchn;u++)
  15.796 +			if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  15.797 +	}
  15.798 +
  15.799 +	return 1;
  15.800  }
  15.801  
  15.802 -         
  15.803  CHAR *S3M_LoadTitle(void)
  15.804  {
  15.805 -   CHAR s[28];
  15.806 +	CHAR s[28];
  15.807  
  15.808 -   _mm_fseek(modfp,0,SEEK_SET);
  15.809 -   if(!fread(s,28,1,modfp)) return NULL;
  15.810 -   
  15.811 -   return(DupStr(s,28));
  15.812 +	_mm_fseek(modreader,0,SEEK_SET);
  15.813 +	if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
  15.814 +
  15.815 +	return(DupStr(s,28,0));
  15.816  }
  15.817  
  15.818 +/*========== Loader information */
  15.819  
  15.820 -MLOADER load_s3m =
  15.821 -{   NULL,
  15.822 -    "S3M",
  15.823 -    "S3M loader v0.3",
  15.824 -    S3M_Init,
  15.825 -    S3M_Test,
  15.826 -    S3M_Load,
  15.827 -    S3M_Cleanup,
  15.828 -
  15.829 -    S3M_LoadTitle
  15.830 +MLOADER load_s3m={
  15.831 +	NULL,
  15.832 +	"S3M",
  15.833 +	"S3M (Scream Tracker 3)",
  15.834 +	S3M_Init,
  15.835 +	S3M_Test,
  15.836 +	S3M_Load,
  15.837 +	S3M_Cleanup,
  15.838 +	S3M_LoadTitle
  15.839  };
  15.840  
  15.841 +/* ex:set ts=4: */
    16.1 --- a/mikmod/load_xm.c	Mon Dec 27 19:18:10 1999 +0000
    16.2 +++ b/mikmod/load_xm.c	Mon Dec 27 19:24:50 1999 +0000
    16.3 @@ -1,679 +1,747 @@
    16.4 -/*
    16.5 +/*	MikMod sound library
    16.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    16.7 +	complete list.
    16.8  
    16.9 - Name: LOAD_XM.C
   16.10 +	This library is free software; you can redistribute it and/or modify
   16.11 +	it under the terms of the GNU Library General Public License as
   16.12 +	published by the Free Software Foundation; either version 2 of
   16.13 +	the License, or (at your option) any later version.
   16.14  
   16.15 - Description:
   16.16 - Fasttracker (XM) module loader
   16.17 +	This program is distributed in the hope that it will be useful,
   16.18 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.19 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.20 +	GNU Library General Public License for more details.
   16.21  
   16.22 - Portability:
   16.23 - All systems - all compilers (hopefully)
   16.24 +	You should have received a copy of the GNU Library General Public
   16.25 +	License along with this library; if not, write to the Free Software
   16.26 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   16.27 +	02111-1307, USA.
   16.28 +*/
   16.29 +
   16.30 +/*==============================================================================
   16.31  
   16.32 - If this module is found to not be portable to any particular platform,
   16.33 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   16.34 - more information on contacting the author).
   16.35 +  $Id$
   16.36 +
   16.37 +  Fasttracker (XM) module loader
   16.38  
   16.39 -*/
   16.40 +==============================================================================*/
   16.41 +
   16.42 +#ifdef HAVE_CONFIG_H
   16.43 +#include "config.h"
   16.44 +#endif
   16.45  
   16.46  #include <string.h>
   16.47 -#include "mikmod.h"
   16.48  
   16.49 -/**************************************************************************
   16.50 -**************************************************************************/
   16.51 +#include "mikmod_internals.h"
   16.52  
   16.53 +/*========== Module structure */
   16.54  
   16.55 -typedef struct XMHEADER
   16.56 -{   CHAR  id[17];                   /* ID text: 'Extended module: ' */
   16.57 -    CHAR  songname[21];             /* Module name, padded with zeroes and 0x1a at the end */
   16.58 -    CHAR  trackername[20];          /* Tracker name */
   16.59 -    UWORD version;                  /* (word) Version number, hi-byte major and low-byte minor */
   16.60 -    ULONG headersize;               /* Header size */
   16.61 -    UWORD songlength;               /* (word) Song length (in patten order table) */
   16.62 -    UWORD restart;                  /* (word) Restart position */
   16.63 -    UWORD numchn;                   /* (word) Number of channels (2,4,6,8,10,...,32) */
   16.64 -    UWORD numpat;                   /* (word) Number of patterns (max 256) */
   16.65 -    UWORD numins;                   /* (word) Number of instruments (max 128) */
   16.66 -    UWORD flags;                    /* (word) Flags: bit 0: 0 = Amiga frequency table (see below) 1 = Linear frequency table */
   16.67 -    UWORD tempo;                    /* (word) Default tempo */
   16.68 -    UWORD bpm;                      /* (word) Default BPM */
   16.69 -    UBYTE orders[256];              /* (byte) Pattern order table  */
   16.70 +typedef struct XMHEADER {
   16.71 +	CHAR  id[17];          /* ID text: 'Extended module: ' */
   16.72 +	CHAR  songname[21];    /* Module name */
   16.73 +	CHAR  trackername[20]; /* Tracker name */
   16.74 +	UWORD version;         /* Version number */
   16.75 +	ULONG headersize;      /* Header size */
   16.76 +	UWORD songlength;      /* Song length (in patten order table) */
   16.77 +	UWORD restart;         /* Restart position */
   16.78 +	UWORD numchn;          /* Number of channels (2,4,6,8,10,...,32) */
   16.79 +	UWORD numpat;          /* Number of patterns (max 256) */
   16.80 +	UWORD numins;          /* Number of instruments (max 128) */
   16.81 +	UWORD flags;
   16.82 +	UWORD tempo;           /* Default tempo */
   16.83 +	UWORD bpm;             /* Default BPM */
   16.84 +	UBYTE orders[256];     /* Pattern order table  */
   16.85  } XMHEADER;
   16.86  
   16.87 -
   16.88 -typedef struct XMINSTHEADER
   16.89 -{   ULONG size;                     /* (dword) Instrument size */
   16.90 -    CHAR  name[22];                 /* (char) Instrument name */
   16.91 -    UBYTE type;                     /* (byte) Instrument type (always 0) */
   16.92 -    UWORD numsmp;                   /* (word) Number of samples in instrument */
   16.93 -    ULONG ssize;                    /* */
   16.94 +typedef struct XMINSTHEADER {
   16.95 +	ULONG size;     /* Instrument size */
   16.96 +	CHAR  name[22]; /* Instrument name */
   16.97 +	UBYTE type;     /* Instrument type (always 0) */
   16.98 +	UWORD numsmp;   /* Number of samples in instrument */
   16.99 +	ULONG ssize;
  16.100  } XMINSTHEADER;
  16.101  
  16.102 -
  16.103 -typedef struct XMPATCHHEADER
  16.104 -{   UBYTE what[96];         /* (byte) Sample number for all notes */
  16.105 -    UWORD volenv[24];       /* (byte) Points for volume envelope */
  16.106 -    UWORD panenv[24];       /* (byte) Points for panning envelope */
  16.107 -    UBYTE volpts;           /* (byte) Number of volume points */
  16.108 -    UBYTE panpts;           /* (byte) Number of panning points */
  16.109 -    UBYTE volsus;           /* (byte) Volume sustain point */
  16.110 -    UBYTE volbeg;           /* (byte) Volume loop start point */
  16.111 -    UBYTE volend;           /* (byte) Volume loop end point */
  16.112 -    UBYTE pansus;           /* (byte) Panning sustain point */
  16.113 -    UBYTE panbeg;           /* (byte) Panning loop start point */
  16.114 -    UBYTE panend;           /* (byte) Panning loop end point */
  16.115 -    UBYTE volflg;           /* (byte) Volume type: bit 0: On; 1: Sustain; 2: Loop */
  16.116 -    UBYTE panflg;           /* (byte) Panning type: bit 0: On; 1: Sustain; 2: Loop */
  16.117 -    UBYTE vibflg;           /* (byte) Vibrato type */
  16.118 -    UBYTE vibsweep;         /* (byte) Vibrato sweep */
  16.119 -    UBYTE vibdepth;         /* (byte) Vibrato depth */
  16.120 -    UBYTE vibrate;          /* (byte) Vibrato rate */
  16.121 -    UWORD volfade;          /* (word) Volume fadeout */
  16.122 -    UWORD reserved[11];     /* (word) Reserved */
  16.123 +#define XMENVCNT (12*2)
  16.124 +#define XMNOTECNT (8*OCTAVE)
  16.125 +typedef struct XMPATCHHEADER {
  16.126 +	UBYTE what[XMNOTECNT];  /*  Sample number for all notes */
  16.127 +	UWORD volenv[XMENVCNT]; /*  Points for volume envelope */
  16.128 +	UWORD panenv[XMENVCNT]; /*  Points for panning envelope */
  16.129 +	UBYTE volpts;      /*  Number of volume points */
  16.130 +	UBYTE panpts;      /*  Number of panning points */
  16.131 +	UBYTE volsus;      /*  Volume sustain point */
  16.132 +	UBYTE volbeg;      /*  Volume loop start point */
  16.133 +	UBYTE volend;      /*  Volume loop end point */
  16.134 +	UBYTE pansus;      /*  Panning sustain point */
  16.135 +	UBYTE panbeg;      /*  Panning loop start point */
  16.136 +	UBYTE panend;      /*  Panning loop end point */
  16.137 +	UBYTE volflg;      /*  Volume type: bit 0: On; 1: Sustain; 2: Loop */
  16.138 +	UBYTE panflg;      /*  Panning type: bit 0: On; 1: Sustain; 2: Loop */
  16.139 +	UBYTE vibflg;      /*  Vibrato type */
  16.140 +	UBYTE vibsweep;    /*  Vibrato sweep */
  16.141 +	UBYTE vibdepth;    /*  Vibrato depth */
  16.142 +	UBYTE vibrate;     /*  Vibrato rate */
  16.143 +	UWORD volfade;     /*  Volume fadeout */
  16.144  } XMPATCHHEADER;
  16.145  
  16.146 -
  16.147 -typedef struct XMWAVHEADER
  16.148 -{   ULONG length;           /* (dword) Sample length */
  16.149 -    ULONG loopstart;        /* (dword) Sample loop start */
  16.150 -    ULONG looplength;       /* (dword) Sample loop length */
  16.151 -    UBYTE volume;           /* (byte) Volume  */
  16.152 -    SBYTE finetune;         /* (byte) Finetune (signed byte -128..+127) */
  16.153 -    UBYTE type;             /* (byte) Type: Bit 0-1: 0 = No loop, 1 = Forward loop, */
  16.154 -                            /*                       2 = Ping-pong loop; */
  16.155 -                            /*                    4: 16-bit sampledata */
  16.156 -    UBYTE panning;          /* (byte) Panning (0-255) */
  16.157 -    SBYTE relnote;          /* (byte) Relative note number (signed byte) */
  16.158 -    UBYTE reserved;         /* (byte) Reserved */
  16.159 -    CHAR  samplename[22];   /* (char) Sample name */
  16.160 -
  16.161 -    UBYTE vibtype;          /* (byte) Vibrato type */
  16.162 -    UBYTE vibsweep;         /* (byte) Vibrato sweep */
  16.163 -    UBYTE vibdepth;         /* (byte) Vibrato depth */
  16.164 -    UBYTE vibrate;          /* (byte) Vibrato rate */
  16.165 +typedef struct XMWAVHEADER {
  16.166 +	ULONG length;         /* Sample length */
  16.167 +	ULONG loopstart;      /* Sample loop start */
  16.168 +	ULONG looplength;     /* Sample loop length */
  16.169 +	UBYTE volume;         /* Volume  */
  16.170 +	SBYTE finetune;       /* Finetune (signed byte -128..+127) */
  16.171 +	UBYTE type;           /* Loop type */
  16.172 +	UBYTE panning;        /* Panning (0-255) */
  16.173 +	SBYTE relnote;        /* Relative note number (signed byte) */
  16.174 +	UBYTE reserved;
  16.175 +	CHAR  samplename[22]; /* Sample name */
  16.176 +	UBYTE vibtype;        /* Vibrato type */
  16.177 +	UBYTE vibsweep;       /* Vibrato sweep */
  16.178 +	UBYTE vibdepth;       /* Vibrato depth */
  16.179 +	UBYTE vibrate;        /* Vibrato rate */
  16.180  } XMWAVHEADER;
  16.181  
  16.182 -
  16.183 -typedef struct XMPATHEADE
  16.184 -{   ULONG size;                     /* (dword) Pattern header length  */
  16.185 -    UBYTE packing;                  /* (byte) Packing type (always 0) */
  16.186 -    UWORD numrows;                  /* (word) Number of rows in pattern (1..256) */
  16.187 -    UWORD packsize;                 /* (word) Packed patterndata size */
  16.188 +typedef struct XMPATHEADER {
  16.189 +	ULONG size;     /* Pattern header length  */
  16.190 +	UBYTE packing;  /* Packing type (always 0) */
  16.191 +	UWORD numrows;  /* Number of rows in pattern (1..256) */
  16.192 +	SWORD packsize; /* Packed patterndata size */
  16.193  } XMPATHEADER;
  16.194  
  16.195 -typedef struct MTMNOTE
  16.196 -{    UBYTE a,b,c;
  16.197 -} MTMNOTE;
  16.198 +typedef struct XMNOTE {
  16.199 +	UBYTE note,ins,vol,eff,dat;
  16.200 +} XMNOTE;
  16.201  
  16.202 +/*========== Loader variables */
  16.203  
  16.204 -typedef struct XMNOTE
  16.205 -{    UBYTE note,ins,vol,eff,dat;
  16.206 -}XMNOTE;
  16.207 +static	XMNOTE *xmpat=NULL;
  16.208 +static	XMHEADER *mh=NULL;
  16.209  
  16.210 -/**************************************************************************
  16.211 -**************************************************************************/
  16.212 +/* increment unit for sample array reallocation */
  16.213 +#define XM_SMPINCR 64
  16.214 +static	ULONG *nextwav=NULL;
  16.215 +static	XMWAVHEADER *wh=NULL,*s=NULL;
  16.216  
  16.217 -static XMNOTE *xmpat = NULL;
  16.218 -static XMHEADER *mh = NULL;
  16.219 +/*========== Loader code */
  16.220  
  16.221  BOOL XM_Test(void)
  16.222  {
  16.223 -    UBYTE id[17];
  16.224 -    
  16.225 -    if(!_mm_read_UBYTES(id,17,modfp)) return 0;
  16.226 -    if(!memcmp(id,"Extended Module: ",17)) return 1;
  16.227 -    return 0;
  16.228 +	UBYTE id[38];
  16.229 +
  16.230 +	if(!_mm_read_UBYTES(id,38,modreader)) return 0;
  16.231 +	if(memcmp(id,"Extended Module: ",17)) return 0;
  16.232 +	if(id[37]==0x1a) return 1;
  16.233 +	return 0;
  16.234  }
  16.235  
  16.236 -
  16.237  BOOL XM_Init(void)
  16.238  {
  16.239 -    if(!(mh=(XMHEADER *)_mm_calloc(1,sizeof(XMHEADER)))) return 0;
  16.240 -    return 1;
  16.241 +	if(!(mh=(XMHEADER *)_mm_malloc(sizeof(XMHEADER)))) return 0;
  16.242 +	return 1;
  16.243  }
  16.244  
  16.245 -
  16.246  void XM_Cleanup(void)
  16.247  {
  16.248 -    if(mh!=NULL) free(mh);
  16.249 -    mh = NULL;
  16.250 +	_mm_free(mh);
  16.251  }
  16.252  
  16.253 -
  16.254 -void XM_ReadNote(XMNOTE *n)
  16.255 +static int XM_ReadNote(XMNOTE* n)
  16.256  {
  16.257 -    UBYTE cmp;
  16.258 +	UBYTE cmp,result=1;
  16.259  
  16.260 -    memset(n,0,sizeof(XMNOTE));
  16.261 -
  16.262 -    cmp = _mm_read_UBYTE(modfp);
  16.263 +	memset(n,0,sizeof(XMNOTE));
  16.264 +	cmp=_mm_read_UBYTE(modreader);
  16.265  
  16.266 -    if(cmp&0x80)
  16.267 -    {   if(cmp&1)  n->note = _mm_read_UBYTE(modfp);
  16.268 -        if(cmp&2)  n->ins  = _mm_read_UBYTE(modfp);
  16.269 -        if(cmp&4)  n->vol  = _mm_read_UBYTE(modfp);
  16.270 -        if(cmp&8)  n->eff  = _mm_read_UBYTE(modfp);
  16.271 -        if(cmp&16) n->dat  = _mm_read_UBYTE(modfp);
  16.272 -    }
  16.273 -    else
  16.274 -    {   n->note = cmp;
  16.275 -        n->ins  = _mm_read_UBYTE(modfp);
  16.276 -        n->vol  = _mm_read_UBYTE(modfp);
  16.277 -        n->eff  = _mm_read_UBYTE(modfp);
  16.278 -        n->dat  = _mm_read_UBYTE(modfp);
  16.279 -    }
  16.280 +	if(cmp&0x80) {
  16.281 +		if(cmp&1)  { result++;n->note = _mm_read_UBYTE(modreader); }
  16.282 +		if(cmp&2)  { result++;n->ins  = _mm_read_UBYTE(modreader); }
  16.283 +		if(cmp&4)  { result++;n->vol  = _mm_read_UBYTE(modreader); }
  16.284 +		if(cmp&8)  { result++;n->eff  = _mm_read_UBYTE(modreader); }
  16.285 +		if(cmp&16) { result++;n->dat  = _mm_read_UBYTE(modreader); }
  16.286 +	} else {
  16.287 +		n->note = cmp;
  16.288 +		n->ins  = _mm_read_UBYTE(modreader);
  16.289 +		n->vol  = _mm_read_UBYTE(modreader);
  16.290 +		n->eff  = _mm_read_UBYTE(modreader);
  16.291 +		n->dat  = _mm_read_UBYTE(modreader);
  16.292 +		result += 4;
  16.293 +	}
  16.294 +	return result;
  16.295  }
  16.296  
  16.297 -
  16.298 -UBYTE *XM_Convert(XMNOTE *xmtrack,UWORD rows)
  16.299 +static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
  16.300  {
  16.301 -    int t;
  16.302 -    UBYTE note,ins,vol,eff,dat;
  16.303 +	int t;
  16.304 +	UBYTE note,ins,vol,eff,dat;
  16.305  
  16.306 -    UniReset();
  16.307 -
  16.308 -    for(t=0; t<rows; t++)
  16.309 -    {   note = xmtrack->note;
  16.310 -        ins  = xmtrack->ins;
  16.311 -        vol  = xmtrack->vol;
  16.312 -        eff  = xmtrack->eff;
  16.313 -        dat  = xmtrack->dat;
  16.314 +	UniReset();
  16.315 +	for(t=0;t<rows;t++) {
  16.316 +		note = xmtrack->note;
  16.317 +		ins  = xmtrack->ins;
  16.318 +		vol  = xmtrack->vol;
  16.319 +		eff  = xmtrack->eff;
  16.320 +		dat  = xmtrack->dat;
  16.321  
  16.322 -        if(note!=0)
  16.323 -        {  if(note==97) 
  16.324 -           {   UniWrite(UNI_KEYFADE);
  16.325 -               UniWrite(0);
  16.326 -           } else
  16.327 -               UniNote(note-1);
  16.328 -        }
  16.329 -
  16.330 -        if(ins!=0) UniInstrument(ins-1);
  16.331 +		if(note) {
  16.332 +			if(note>XMNOTECNT)
  16.333 +				UniEffect(UNI_KEYFADE,0);
  16.334 +			else
  16.335 +				UniNote(note-1);
  16.336 +		}
  16.337 +		if(ins) UniInstrument(ins-1);
  16.338  
  16.339 -        switch(vol>>4)
  16.340 -        {
  16.341 -            case 0x6:                   /* volslide down */
  16.342 -                if(vol&0xf)
  16.343 -                {   UniWrite(UNI_XMEFFECTA);
  16.344 -                    UniWrite(vol&0xf);
  16.345 -                }
  16.346 -                break;
  16.347 -
  16.348 -            case 0x7:                   /* volslide up */
  16.349 -                if(vol&0xf)
  16.350 -                {   UniWrite(UNI_XMEFFECTA);
  16.351 -                    UniWrite(vol<<4);
  16.352 -                }
  16.353 -                break;
  16.354 -
  16.355 -            /* volume-row fine volume slide is compatible with protracker */
  16.356 -            /* EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as */
  16.357 -            /* opposed to 'take the last sliding value'. */
  16.358 +		switch(vol>>4) {
  16.359 +			case 0x6: /* volslide down */
  16.360 +				if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
  16.361 +				break;
  16.362 +			case 0x7: /* volslide up */
  16.363 +				if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
  16.364 +				break;
  16.365  
  16.366 -            case 0x8:                       /* finevol down */
  16.367 -                UniPTEffect(0xe,0xb0 | (vol&0xf));
  16.368 -                break;
  16.369 -
  16.370 -            case 0x9:                       /* finevol up */
  16.371 -                UniPTEffect(0xe,0xa0 | (vol&0xf));
  16.372 -                break;
  16.373 -
  16.374 -            case 0xa:                       /* set vibrato speed */
  16.375 -                UniPTEffect(0x4,vol<<4);
  16.376 -                break;
  16.377 -
  16.378 -            case 0xb:                       /* vibrato */
  16.379 -                UniPTEffect(0x4,vol&0xf);
  16.380 -                break;
  16.381 -
  16.382 -            case 0xc:                       /* set panning */
  16.383 -                UniPTEffect(0x8,vol<<4);
  16.384 -                break;
  16.385 -
  16.386 -            case 0xd:                       /* panning slide left */
  16.387 -                /* only slide when data nibble not zero: */
  16.388 -
  16.389 -                if(vol&0xf)
  16.390 -                {   UniWrite(UNI_XMEFFECTP);
  16.391 -                    UniWrite(vol&0xf);
  16.392 -                }
  16.393 -                break;
  16.394 -
  16.395 -            case 0xe:                       /* panning slide right */
  16.396 -                /* only slide when data nibble not zero: */
  16.397 -
  16.398 -                if(vol&0xf)
  16.399 -                {   UniWrite(UNI_XMEFFECTP);
  16.400 -                    UniWrite(vol<<4);
  16.401 -                }
  16.402 -             break;
  16.403 -
  16.404 -            case 0xf:                       /* tone porta */
  16.405 -                UniPTEffect(0x3,vol<<4);
  16.406 -            break;
  16.407 -
  16.408 -            default:
  16.409 -                if(vol>=0x10 && vol<=0x50)
  16.410 -                    UniPTEffect(0xc,vol-0x10);
  16.411 -        }
  16.412 +				/* volume-row fine volume slide is compatible with protracker
  16.413 +				   EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
  16.414 +				   opposed to 'take the last sliding value'. */
  16.415 +			case 0x8: /* finevol down */
  16.416 +				UniPTEffect(0xe,0xb0|(vol&0xf));
  16.417 +				break;
  16.418 +			case 0x9: /* finevol up */
  16.419 +				UniPTEffect(0xe,0xa0|(vol&0xf));
  16.420 +				break;
  16.421 +			case 0xa: /* set vibrato speed */
  16.422 +				UniPTEffect(0x4,vol<<4);
  16.423 +				break;
  16.424 +			case 0xb: /* vibrato */
  16.425 +				UniPTEffect(0x4,vol&0xf);
  16.426 +				break;
  16.427 +			case 0xc: /* set panning */
  16.428 +				UniPTEffect(0x8,vol<<4);
  16.429 +				break;
  16.430 +			case 0xd: /* panning slide left (only slide when data not zero) */
  16.431 +				if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
  16.432 +				break;
  16.433 +			case 0xe: /* panning slide right (only slide when data not zero) */
  16.434 +				if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
  16.435 +				break;
  16.436 +			case 0xf: /* tone porta */
  16.437 +				UniPTEffect(0x3,vol<<4);
  16.438 +				break;
  16.439 +			default:
  16.440 +				if((vol>=0x10)&&(vol<=0x50))
  16.441 +					UniPTEffect(0xc,vol-0x10);
  16.442 +		}
  16.443  
  16.444 -        switch(eff)
  16.445 -        {
  16.446 -            case 0x4:                       /* Effect 4: Vibrato */
  16.447 -                UniWrite(UNI_XMEFFECT4);
  16.448 -                UniWrite(dat);
  16.449 -            break;
  16.450 -
  16.451 -            case 0xa:
  16.452 -                UniWrite(UNI_XMEFFECTA);
  16.453 -                UniWrite(dat);
  16.454 -            break;
  16.455 -
  16.456 -            case 0xe:
  16.457 -                switch(dat>>4)
  16.458 -                {  case 0x1:      /* XM fine porta up */
  16.459 -                      UniWrite(UNI_XMEFFECTE1);
  16.460 -                      UniWrite(dat&0xf);
  16.461 -                   break;
  16.462 -
  16.463 -                   case 0x2:      /* XM fine porta down */
  16.464 -                      UniWrite(UNI_XMEFFECTE2);
  16.465 -                      UniWrite(dat&0xf);
  16.466 -                   break;
  16.467 -
  16.468 -                   case 0xa:      /* XM fine volume up */
  16.469 -                      UniWrite(UNI_XMEFFECTEA);
  16.470 -                      UniWrite(dat&0xf);
  16.471 -                   break;
  16.472 -
  16.473 -                   case 0xb:      /* XM fine volume down */
  16.474 -                      UniWrite(UNI_XMEFFECTEB);
  16.475 -                      UniWrite(dat&0xf);
  16.476 -                   break;
  16.477 -
  16.478 -                   default:
  16.479 -                      UniPTEffect(0x0e,dat);
  16.480 -                }
  16.481 -            break;
  16.482 -
  16.483 -            case 'G'-55:                    /* G - set global volume */
  16.484 -                if(dat>64) dat = 64;
  16.485 -                UniWrite(UNI_XMEFFECTG);
  16.486 -                UniWrite(dat);
  16.487 -                break;
  16.488 -
  16.489 -            case 'H'-55:                    /* H - global volume slide */
  16.490 -                UniWrite(UNI_XMEFFECTH);
  16.491 -                UniWrite(dat);
  16.492 -                break;
  16.493 +		switch(eff) {
  16.494 +			case 0x4:
  16.495 +				UniEffect(UNI_XMEFFECT4,dat);
  16.496 +				break;
  16.497 +			case 0xa:
  16.498 +				UniEffect(UNI_XMEFFECTA,dat);
  16.499 +				break;
  16.500 +			case 0xe: /* Extended effects */
  16.501 +				switch(dat>>4) {
  16.502 +					case 0x1: /* XM fine porta up */
  16.503 +						UniEffect(UNI_XMEFFECTE1,dat&0xf);
  16.504 +						break;
  16.505 +					case 0x2: /* XM fine porta down */
  16.506 +						UniEffect(UNI_XMEFFECTE2,dat&0xf);
  16.507 +						break;
  16.508 +					case 0xa: /* XM fine volume up */
  16.509 +						UniEffect(UNI_XMEFFECTEA,dat&0xf);
  16.510 +						break;
  16.511 +					case 0xb: /* XM fine volume down */
  16.512 +						UniEffect(UNI_XMEFFECTEB,dat&0xf);
  16.513 +						break;
  16.514 +					default:
  16.515 +						UniPTEffect(eff,dat);
  16.516 +				}
  16.517 +				break;
  16.518 +			case 'G'-55: /* G - set global volume */
  16.519 +				UniEffect(UNI_XMEFFECTG,dat>64?64:dat);
  16.520 +				break;
  16.521 +			case 'H'-55: /* H - global volume slide */
  16.522 +				UniEffect(UNI_XMEFFECTH,dat);
  16.523 +				break;
  16.524 +			case 'K'-55: /* K - keyOff and KeyFade */
  16.525 +				UniEffect(UNI_KEYFADE,dat);
  16.526 +				break;
  16.527 +			case 'L'-55: /* L - set envelope position */
  16.528 +				UniEffect(UNI_XMEFFECTL,dat);
  16.529 +				break;
  16.530 +			case 'P'-55: /* P - panning slide */
  16.531 +				UniEffect(UNI_XMEFFECTP,dat);
  16.532 +				break;
  16.533 +			case 'R'-55: /* R - multi retrig note */
  16.534 +				UniEffect(UNI_S3MEFFECTQ,dat);
  16.535 +				break;
  16.536 +			case 'T'-55: /* T - Tremor */
  16.537 +				UniEffect(UNI_S3MEFFECTI,dat);
  16.538 +				break;
  16.539 +			case 'X'-55:
  16.540 +				switch(dat>>4) {
  16.541 +					case 1: /* X1 - Extra Fine Porta up */
  16.542 +						UniEffect(UNI_XMEFFECTX1,dat&0xf);
  16.543 +						break;
  16.544 +					case 2: /* X2 - Extra Fine Porta down */
  16.545 +						UniEffect(UNI_XMEFFECTX2,dat&0xf);
  16.546 +						break;
  16.547 +				}
  16.548 +				break;
  16.549 +			default:
  16.550 +				if(eff<=0xf) {
  16.551 +					/* the pattern jump destination is written in decimal,
  16.552 +					   but it seems some poor tracker software writes them
  16.553 +					   in hexadecimal... (sigh) */
  16.554 +					if (eff==0xd)
  16.555 +						/* don't change anything if we're sure it's in hexa */
  16.556 +						if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
  16.557 +							/* otherwise, convert from dec to hex */
  16.558 +							dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
  16.559 +					UniPTEffect(eff,dat);
  16.560 +				}
  16.561 +				break;
  16.562 +		}
  16.563 +		UniNewline();
  16.564 +		xmtrack++;
  16.565 +	}
  16.566 +	return UniDup();
  16.567 +}
  16.568  
  16.569 -            case 'K'-55:                    /* K - keyOff and KeyFade */
  16.570 -                UniWrite(UNI_KEYFADE);
  16.571 -                UniWrite(dat);
  16.572 -                break;
  16.573 +static BOOL LoadPatterns(BOOL dummypat)
  16.574 +{
  16.575 +	int t,u,v,numtrk;
  16.576  
  16.577 -            case 'L'-55:                    /* L - set envelope position */
  16.578 -                UniWrite(UNI_XMEFFECTL);
  16.579 -                UniWrite(dat);
  16.580 -                break;
  16.581 +	if(!AllocTracks()) return 0;
  16.582 +	if(!AllocPatterns()) return 0;
  16.583 +
  16.584 +	numtrk=0;
  16.585 +	for(t=0;t<mh->numpat;t++) {
  16.586 +		XMPATHEADER ph;
  16.587  
  16.588 -            case 'P'-55:                    /* P - panning slide */
  16.589 -                UniWrite(UNI_XMEFFECTP);
  16.590 -                UniWrite(dat);
  16.591 -                break;
  16.592 +		ph.size     =_mm_read_I_ULONG(modreader);
  16.593 +		if (ph.size<(mh->version==0x0102?8:9)) {
  16.594 +			_mm_errno=MMERR_LOADING_PATTERN;
  16.595 +			return 0;
  16.596 +		}
  16.597 +		ph.packing  =_mm_read_UBYTE(modreader);
  16.598 +		if(ph.packing) {
  16.599 +			_mm_errno=MMERR_LOADING_PATTERN;
  16.600 +			return 0;
  16.601 +		}
  16.602 +		if(mh->version==0x0102)
  16.603 +			ph.numrows  =_mm_read_UBYTE(modreader)+1;
  16.604 +		else
  16.605 +			ph.numrows  =_mm_read_I_UWORD(modreader);
  16.606 +		ph.packsize =_mm_read_I_UWORD(modreader);
  16.607  
  16.608 -            case 'R'-55:                    /* R - multi retrig note */
  16.609 -                UniWrite(UNI_S3MEFFECTQ);
  16.610 -                UniWrite(dat);
  16.611 -                break;
  16.612 +		ph.size-=(mh->version==0x0102?8:9);
  16.613 +		if(ph.size)
  16.614 +			_mm_fseek(modreader,ph.size,SEEK_CUR);
  16.615  
  16.616 -            case 'T'-55:                    /* T - Tremor !! (== S3M effect I) */
  16.617 -                UniWrite(UNI_S3MEFFECTI);
  16.618 -                UniWrite(dat);
  16.619 -                break;
  16.620 +		of.pattrows[t]=ph.numrows;
  16.621 +
  16.622 +		if(ph.numrows) {
  16.623 +			if(!(xmpat=(XMNOTE*)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
  16.624 +				return 0;
  16.625  
  16.626 -            case 'X'-55:
  16.627 -                if((dat>>4) == 1)           /* X1 - Extra Fine Porta up */
  16.628 -                {  UniWrite(UNI_XMEFFECTX1);
  16.629 -                   UniWrite(dat & 0xf);
  16.630 -                } else if((dat>>4) == 2)    /* X2 - Extra Fine Porta down */
  16.631 -                {  UniWrite(UNI_XMEFFECTX2);
  16.632 -                   UniWrite(dat & 0xf);
  16.633 -                }
  16.634 -            break;
  16.635 +			/* when packsize is 0, don't try to load a pattern.. it's empty. */
  16.636 +			if(ph.packsize)
  16.637 +				for(u=0;u<ph.numrows;u++)
  16.638 +					for(v=0;v<of.numchn;v++) {
  16.639 +						if(!ph.packsize) break;
  16.640 +
  16.641 +						ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  16.642 +						if(ph.packsize<0) {
  16.643 +							free(xmpat);xmpat=NULL;
  16.644 +							_mm_errno=MMERR_LOADING_PATTERN;
  16.645 +							return 0;
  16.646 +						}
  16.647 +					}
  16.648 +
  16.649 +			if(ph.packsize) {
  16.650 +				_mm_fseek(modreader,ph.packsize,SEEK_CUR);
  16.651 +			}
  16.652  
  16.653 -            default:
  16.654 -                if(eff <= 0xf)
  16.655 -                {   /* Convert pattern jump from Dec to Hex */
  16.656 -                    if(eff == 0xd)
  16.657 -                        dat = (((dat&0xf0)>>4)*10)+(dat&0xf);
  16.658 -                    UniPTEffect(eff,dat);
  16.659 -                }
  16.660 -            break;
  16.661 -        }
  16.662 +			if(_mm_eof(modreader)) {
  16.663 +				free(xmpat);xmpat=NULL;
  16.664 +				_mm_errno=MMERR_LOADING_PATTERN;
  16.665 +				return 0;
  16.666 +			}
  16.667 +
  16.668 +			for(v=0;v<of.numchn;v++)
  16.669 +				of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  16.670  
  16.671 -        UniNewline();
  16.672 -        xmtrack++;
  16.673 -    }
  16.674 -    return UniDup();
  16.675 +			free(xmpat);xmpat=NULL;
  16.676 +		} else {
  16.677 +			for(v=0;v<of.numchn;v++)
  16.678 +				of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
  16.679 +		}
  16.680 +	}
  16.681 +
  16.682 +	if(dummypat) {
  16.683 +		of.pattrows[t]=64;
  16.684 +		if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
  16.685 +		for(v=0;v<of.numchn;v++)
  16.686 +			of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
  16.687 +		free(xmpat);xmpat=NULL;
  16.688 +	}
  16.689 +
  16.690 +	return 1;
  16.691  }
  16.692  
  16.693 -
  16.694 -
  16.695 -BOOL XM_Load(void)
  16.696 +static BOOL LoadInstruments(void)
  16.697  {
  16.698 -    INSTRUMENT *d;
  16.699 -    SAMPLE     *q;
  16.700 -    XMWAVHEADER *wh,*s;
  16.701 -    int   t,u,v,p,numtrk;
  16.702 -    long  next;
  16.703 -    ULONG nextwav[256];
  16.704 -    BOOL  dummypat=0;
  16.705 - 
  16.706 -    /* try to read module header */
  16.707 +	int t,u;
  16.708 +	INSTRUMENT *d;
  16.709 +	long next=0;
  16.710 +	UWORD wavcnt=0;
  16.711  
  16.712 -    _mm_read_string(mh->id,17,modfp);
  16.713 -    _mm_read_string(mh->songname,21,modfp);
  16.714 -    _mm_read_string(mh->trackername,20,modfp);
  16.715 -    mh->version     =_mm_read_I_UWORD(modfp);
  16.716 -    mh->headersize  =_mm_read_I_ULONG(modfp);
  16.717 -    mh->songlength  =_mm_read_I_UWORD(modfp);
  16.718 -    mh->restart     =_mm_read_I_UWORD(modfp);
  16.719 -    mh->numchn      =_mm_read_I_UWORD(modfp);
  16.720 -    mh->numpat      =_mm_read_I_UWORD(modfp);
  16.721 -    mh->numins      =_mm_read_I_UWORD(modfp);
  16.722 -    mh->flags       =_mm_read_I_UWORD(modfp);
  16.723 -    mh->tempo       =_mm_read_I_UWORD(modfp);
  16.724 -    mh->bpm         =_mm_read_I_UWORD(modfp);
  16.725 -    _mm_read_UBYTES(mh->orders,256,modfp);
  16.726 +	if(!AllocInstruments()) return 0;
  16.727 +	d=of.instruments;
  16.728 +	for(t=0;t<of.numins;t++,d++) {
  16.729 +		XMINSTHEADER ih;
  16.730 +		long headend;
  16.731 +
  16.732 +		memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
  16.733  
  16.734 -    if(feof(modfp))
  16.735 -    {   _mm_errno = MMERR_LOADING_HEADER;
  16.736 -        return 0;
  16.737 -    }
  16.738 +		/* read instrument header */
  16.739 +		headend     = _mm_ftell(modreader);
  16.740 +		ih.size     = _mm_read_I_ULONG(modreader);
  16.741 +		headend    += ih.size;
  16.742 +		_mm_read_string(ih.name, 22, modreader);
  16.743 +		ih.type     = _mm_read_UBYTE(modreader);
  16.744 +		ih.numsmp   = _mm_read_I_UWORD(modreader);
  16.745  
  16.746 -    /* set module variables */
  16.747 -    of.initspeed = mh->tempo;         
  16.748 -    of.inittempo = mh->bpm;
  16.749 -    of.modtype   = DupStr(mh->trackername,20);
  16.750 -    of.numchn    = mh->numchn;
  16.751 -    of.numpat    = mh->numpat;
  16.752 -    of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
  16.753 -    of.songname  = DupStr(mh->songname,20);      /* make a cstr of songname */
  16.754 -    of.numpos    = mh->songlength;               /* copy the songlength */
  16.755 -    of.reppos    = mh->restart;
  16.756 -    of.numins    = mh->numins;
  16.757 -    of.flags |= UF_XMPERIODS | UF_INST;
  16.758 -    if(mh->flags&1) of.flags |= UF_LINEAR;
  16.759 +		d->insname  = DupStr(ih.name,22,1);
  16.760  
  16.761 -    memset(of.chanvol,64,of.numchn);             /* store channel volumes */
  16.762 -
  16.763 -    if(!AllocPositions(of.numpos+3)) return 0;
  16.764 -    for(t=0; t<of.numpos; t++)
  16.765 -        of.positions[t] = mh->orders[t];
  16.766 -
  16.767 -/*
  16.768 -   WHY THIS CODE HERE?? I CAN'T REMEMBER!
  16.769 -   
  16.770 -   Well, I do know why, mikmak!  Seems that FT2 doesn't always count blank 
  16.771 -   patterns AT ALL if they are at the END of the song.  So, we have to check
  16.772 -   for any patter numbers in the order list greater than the number of pat-
  16.773 -   terns total.  If one or more is found, we set it equal to the pattern total
  16.774 -   and make a dummy pattern to accomidate for the discrepency!
  16.775 -*/
  16.776 +		if((SWORD)ih.size>29) {
  16.777 +			ih.ssize    = _mm_read_I_ULONG(modreader);
  16.778 +			if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
  16.779 +				XMPATCHHEADER pth;
  16.780 +				int p;
  16.781  
  16.782 -    for(t=0; t<of.numpos; t++)
  16.783 -    {   if(of.positions[t] > of.numpat)
  16.784 -        {  of.positions[t] = of.numpat;
  16.785 -           dummypat = 1;
  16.786 -        }
  16.787 -    }      
  16.788 -
  16.789 -    if(dummypat) { of.numpat++; of.numtrk+=of.numchn; }
  16.790 -
  16.791 -    if(!AllocTracks()) return 0;
  16.792 -    if(!AllocPatterns()) return 0;
  16.793 -
  16.794 -    numtrk = 0;
  16.795 -    for(t=0; t<mh->numpat; t++)
  16.796 -    {   XMPATHEADER ph;
  16.797 -
  16.798 -        ph.size     =_mm_read_I_ULONG(modfp);
  16.799 -        ph.packing  =_mm_read_UBYTE(modfp);
  16.800 -        ph.numrows  =_mm_read_I_UWORD(modfp);
  16.801 -        ph.packsize =_mm_read_I_UWORD(modfp);
  16.802 -
  16.803 -        of.pattrows[t] = ph.numrows;
  16.804 -
  16.805 -        /*  Gr8.. when packsize is 0, don't try to load a pattern.. it's empty. */
  16.806 -        /*  This bug was discovered thanks to Khyron's module.. */
  16.807 -
  16.808 -        if(!(xmpat=(XMNOTE *)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0;
  16.809 -
  16.810 -        if(ph.packsize>0)
  16.811 -        {   for(u=0; u<ph.numrows; u++)
  16.812 -            {   for(v=0; v<of.numchn; v++)
  16.813 -                    XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  16.814 -            }
  16.815 -        }
  16.816 +				_mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
  16.817 +				_mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
  16.818 +				_mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
  16.819 +				pth.volpts      =  _mm_read_UBYTE(modreader);
  16.820 +				pth.panpts      =  _mm_read_UBYTE(modreader);
  16.821 +				pth.volsus      =  _mm_read_UBYTE(modreader);
  16.822 +				pth.volbeg      =  _mm_read_UBYTE(modreader);
  16.823 +				pth.volend      =  _mm_read_UBYTE(modreader);
  16.824 +				pth.pansus      =  _mm_read_UBYTE(modreader);
  16.825 +				pth.panbeg      =  _mm_read_UBYTE(modreader);
  16.826 +				pth.panend      =  _mm_read_UBYTE(modreader);
  16.827 +				pth.volflg      =  _mm_read_UBYTE(modreader);
  16.828 +				pth.panflg      =  _mm_read_UBYTE(modreader);
  16.829 +				pth.vibflg      =  _mm_read_UBYTE(modreader);
  16.830 +				pth.vibsweep    =  _mm_read_UBYTE(modreader);
  16.831 +				pth.vibdepth    =  _mm_read_UBYTE(modreader);
  16.832 +				pth.vibrate     =  _mm_read_UBYTE(modreader);
  16.833 +				pth.volfade     =  _mm_read_I_UWORD(modreader);
  16.834  
  16.835 -        if(feof(modfp))
  16.836 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  16.837 -            return 0;
  16.838 -        }
  16.839 -
  16.840 -        for(v=0; v<of.numchn; v++)                                           
  16.841 -           of.tracks[numtrk++] = XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  16.842 +				/* read the remainder of the header
  16.843 +				   (2 bytes for 1.03, 22 for 1.04) */
  16.844 +				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
  16.845  
  16.846 -        free(xmpat);
  16.847 -    }
  16.848 -                                                          
  16.849 -    if(dummypat)
  16.850 -    {  of.pattrows[t] = 64;
  16.851 -       if(!(xmpat=(XMNOTE *)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
  16.852 -       for(v=0; v<of.numchn; v++)
  16.853 -           of.tracks[numtrk++] = XM_Convert(&xmpat[v*64],64);
  16.854 -       free(xmpat);
  16.855 -    }
  16.856 +				/* #@!$&% fix for K_OSPACE.XM */
  16.857 +				if(pth.volpts==32) pth.volpts=XMENVCNT/2;
  16.858  
  16.859 -    if(!AllocInstruments()) return 0;
  16.860 -    if((wh = (XMWAVHEADER *)_mm_calloc(256,sizeof(XMWAVHEADER))) == NULL) return 0;
  16.861 -    d = of.instruments;
  16.862 -    s = wh;
  16.863 -
  16.864 -
  16.865 -    for(t=0; t<of.numins; t++)
  16.866 -    {   XMINSTHEADER ih;
  16.867 -        int          headend;
  16.868 +				if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
  16.869 +					if(nextwav) { free(nextwav);nextwav=NULL; }
  16.870 +					if(wh) { free(wh);wh=NULL; }
  16.871 +					_mm_errno = MMERR_LOADING_SAMPLEINFO;
  16.872 +					return 0;
  16.873 +				}
  16.874  
  16.875 -        memset(d->samplenumber,255,120);
  16.876 -
  16.877 -        /* read instrument header */
  16.878 -
  16.879 -        headend     = _mm_ftell(modfp);
  16.880 -        ih.size     = _mm_read_I_ULONG(modfp);
  16.881 -        headend    += ih.size;
  16.882 -        _mm_read_string(ih.name, 22, modfp);
  16.883 -        ih.type     = _mm_read_UBYTE(modfp);
  16.884 -        ih.numsmp   = _mm_read_I_UWORD(modfp);
  16.885 -        d->insname  = DupStr(ih.name,22);
  16.886 +				for(u=0;u<XMNOTECNT;u++)
  16.887 +					d->samplenumber[u]=pth.what[u]+of.numsmp;
  16.888 +				d->volfade = pth.volfade;
  16.889  
  16.890 -        if(ih.size > 29)
  16.891 -        {   ih.ssize    = _mm_read_I_ULONG(modfp);
  16.892 -            if(ih.numsmp > 0)
  16.893 -            {   XMPATCHHEADER pth;
  16.894 -    
  16.895 -                _mm_read_UBYTES (pth.what, 96, modfp);
  16.896 -                _mm_read_I_UWORDS (pth.volenv, 24, modfp);
  16.897 -                _mm_read_I_UWORDS (pth.panenv, 24, modfp);
  16.898 -                pth.volpts      =  _mm_read_UBYTE(modfp);
  16.899 -                pth.panpts      =  _mm_read_UBYTE(modfp);
  16.900 -                pth.volsus      =  _mm_read_UBYTE(modfp);
  16.901 -                pth.volbeg      =  _mm_read_UBYTE(modfp);
  16.902 -                pth.volend      =  _mm_read_UBYTE(modfp);
  16.903 -                pth.pansus      =  _mm_read_UBYTE(modfp);
  16.904 -                pth.panbeg      =  _mm_read_UBYTE(modfp);
  16.905 -                pth.panend      =  _mm_read_UBYTE(modfp);
  16.906 -                pth.volflg      =  _mm_read_UBYTE(modfp);
  16.907 -                pth.panflg      =  _mm_read_UBYTE(modfp);
  16.908 -                pth.vibflg      =  _mm_read_UBYTE(modfp);
  16.909 -                pth.vibsweep    =  _mm_read_UBYTE(modfp);
  16.910 -                pth.vibdepth    =  _mm_read_UBYTE(modfp);
  16.911 -                pth.vibrate     =  _mm_read_UBYTE(modfp);
  16.912 -                pth.volfade     =  _mm_read_I_UWORD(modfp);
  16.913 -    
  16.914 -                /* read the remainder of the header */
  16.915 -                for(u=headend-_mm_ftell(modfp); u; u--)  _mm_read_UBYTE(modfp);
  16.916 -    
  16.917 -                if(feof(modfp))
  16.918 -                {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  16.919 -                    return 0;
  16.920 -                }
  16.921 -    
  16.922 -                for(u=0; u<96; u++)         
  16.923 -                   d->samplenumber[u] = pth.what[u] + of.numsmp;
  16.924 -    
  16.925 -                d->volfade = pth.volfade;
  16.926 -    
  16.927 -                memcpy(d->volenv,pth.volenv,24);
  16.928 -                if(pth.volflg & 1)  d->volflg |= EF_ON;
  16.929 -                if(pth.volflg & 2)  d->volflg |= EF_SUSTAIN;
  16.930 -                if(pth.volflg & 4)  d->volflg |= EF_LOOP;
  16.931 -                d->volsusbeg = d->volsusend = pth.volsus;
  16.932 -                d->volbeg    = pth.volbeg;
  16.933 -                d->volend    = pth.volend;
  16.934 -                d->volpts    = pth.volpts;
  16.935 -    
  16.936 -                /* scale volume envelope: */
  16.937 -    
  16.938 -                for(p=0; p<12; p++)
  16.939 -                    d->volenv[p].val <<= 2;
  16.940 -    
  16.941 -                if((d->volflg & EF_ON) && (d->volpts < 2))
  16.942 -                    d->volflg &= ~EF_ON;
  16.943 -    
  16.944 -                memcpy(d->panenv,pth.panenv,24);
  16.945 -                d->panflg    = pth.panflg;
  16.946 -                d->pansusbeg = d->pansusend = pth.pansus;
  16.947 -                d->panbeg    = pth.panbeg;
  16.948 -                d->panend    = pth.panend;
  16.949 -                d->panpts    = pth.panpts;
  16.950 -    
  16.951 -                /* scale panning envelope: */
  16.952 -    
  16.953 -                for(p=0; p<12; p++)
  16.954 -                    d->panenv[p].val <<= 2;
  16.955 -                if((d->panflg & EF_ON) && (d->panpts < 2))
  16.956 -                    d->panflg &= ~EF_ON;
  16.957 -    
  16.958 -                next = 0;
  16.959 -    
  16.960 -                /*  Samples are stored outside the instrument struct now, so we have */
  16.961 -                /*  to load them all into a temp area, count the of.numsmp along the */
  16.962 -                /*  way and then do an AllocSamples() and move everything over  */
  16.963 -    
  16.964 -                for(u=0; u<ih.numsmp; u++,s++)
  16.965 -                {   s->length       =_mm_read_I_ULONG (modfp);
  16.966 -                    s->loopstart    =_mm_read_I_ULONG (modfp);
  16.967 -                    s->looplength   =_mm_read_I_ULONG (modfp);
  16.968 -                    s->volume       =_mm_read_UBYTE (modfp);
  16.969 -                    s->finetune     =_mm_read_SBYTE (modfp);
  16.970 -                    s->type         =_mm_read_UBYTE (modfp);
  16.971 -                    s->panning      =_mm_read_UBYTE (modfp);
  16.972 -                    s->relnote      =_mm_read_SBYTE (modfp);
  16.973 -                    s->vibtype      = pth.vibflg;
  16.974 -                    s->vibsweep     = pth.vibsweep;
  16.975 -                    s->vibdepth     = pth.vibdepth*4;
  16.976 -                    s->vibrate      = pth.vibrate;
  16.977 -    
  16.978 -                    s->reserved =_mm_read_UBYTE (modfp);
  16.979 -                    _mm_read_string(s->samplename, 22, modfp);
  16.980 -    
  16.981 -                    nextwav[of.numsmp+u] = next;
  16.982 -                    next += s->length;
  16.983 -    
  16.984 -                    if(feof(modfp))
  16.985 -                    {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  16.986 -                        return 0;
  16.987 -                    }
  16.988 -                }
  16.989 -    
  16.990 -                for(u=0; u<ih.numsmp; u++) nextwav[of.numsmp++] += _mm_ftell(modfp);
  16.991 -                _mm_fseek(modfp,next,SEEK_CUR);
  16.992 -            }
  16.993 -        }
  16.994 +#ifdef __STDC__
  16.995 +#define XM_ProcessEnvelope(name) 											\
  16.996 +				memcpy(d->##name##env,pth.##name##env,XMENVCNT);			\
  16.997 +				if (pth.##name##flg&1) d->##name##flg|=EF_ON;				\
  16.998 +				if (pth.##name##flg&2) d->##name##flg|=EF_SUSTAIN;			\
  16.999 +				if (pth.##name##flg&4) d->##name##flg|=EF_LOOP;				\
 16.1000 +				d->##name##susbeg=d->##name##susend=pth.##name##sus;		\
 16.1001 +				d->##name##beg=pth.##name##beg;								\
 16.1002 +				d->##name##end=pth.##name##end;								\
 16.1003 +				d->##name##pts=pth.##name##pts;								\
 16.1004 +																			\
 16.1005 +				/* scale envelope */										\
 16.1006 +				for (p=0;p<XMENVCNT/2;p++)									\
 16.1007 +					d->##name##env[p].val<<=2;								\
 16.1008 +																			\
 16.1009 +				if ((d->##name##flg&EF_ON)&&(d->##name##pts<2))				\
 16.1010 +					d->##name##flg&=~EF_ON;
 16.1011 +#else
 16.1012 +#define XM_ProcessEnvelope(name) 											\
 16.1013 +				memcpy(d->/**/name/**/env,pth./**/name/**/env,XMENVCNT);	\
 16.1014 +				if (pth./**/name/**/flg&1) d->/**/name/**/flg|=EF_ON;		\
 16.1015 +				if (pth./**/name/**/flg&2) d->/**/name/**/flg|=EF_SUSTAIN;	\
 16.1016 +				if (pth./**/name/**/flg&4) d->/**/name/**/flg|=EF_LOOP;		\
 16.1017 +				d->/**/name/**/susbeg=d->/**/name/**/susend=				\
 16.1018 +				                      pth./**/name/**/sus;					\
 16.1019 +				d->/**/name/**/beg=pth./**/name/**/beg;						\
 16.1020 +				d->/**/name/**/end=pth./**/name/**/end;						\
 16.1021 +				d->/**/name/**/pts=pth./**/name/**/pts;						\
 16.1022 +																			\
 16.1023 +				/* scale envelope */										\
 16.1024 +				for (p=0;p<XMENVCNT/2;p++)									\
 16.1025 +					d->/**/name/**/env[p].val<<=2;							\
 16.1026 +																			\
 16.1027 +				if ((d->/**/name/**/flg&EF_ON)&&(d->/**/name/**/pts<2))		\
 16.1028 +					d->/**/name/**/flg&=~EF_ON;
 16.1029 +#endif
 16.1030 +
 16.1031 +				XM_ProcessEnvelope(vol);
 16.1032 +				XM_ProcessEnvelope(pan);
 16.1033 +#undef XM_ProcessEnvelope
 16.1034  
 16.1035 -        d++;
 16.1036 -    }
 16.1037 -
 16.1038 -    if(!AllocSamples()) return 0;
 16.1039 -    q = of.samples;
 16.1040 -    s = wh;
 16.1041 +				/* Samples are stored outside the instrument struct now, so we
 16.1042 +				   have to load them all into a temp area, count the of.numsmp
 16.1043 +				   along the way and then do an AllocSamples() and move
 16.1044 +				   everything over */
 16.1045 +				if(mh->version>0x0103) next = 0;
 16.1046 +				for(u=0;u<ih.numsmp;u++,s++) {
 16.1047 +					/* Allocate more room for sample information if necessary */
 16.1048 +					if(of.numsmp+u==wavcnt) {
 16.1049 +						wavcnt+=XM_SMPINCR;
 16.1050 +						if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
 16.1051 +							if(wh) { free(wh);wh=NULL; }
 16.1052 +							_mm_errno = MMERR_OUT_OF_MEMORY;
 16.1053 +							return 0;
 16.1054 +						}
 16.1055 +						if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
 16.1056 +							free(nextwav);nextwav=NULL;
 16.1057 +							_mm_errno = MMERR_OUT_OF_MEMORY;
 16.1058 +							return 0;
 16.1059 +						}
 16.1060 +						s=wh+(wavcnt-XM_SMPINCR);
 16.1061 +					}
 16.1062  
 16.1063 -    for(u=0; u<of.numsmp; u++,q++,s++)
 16.1064 -    {   q->samplename   = DupStr(s->samplename,22);
 16.1065 -        q->length       = s->length;
 16.1066 -        q->loopstart    = s->loopstart;
 16.1067 -        q->loopend      = s->loopstart+s->looplength;
 16.1068 -        q->volume       = s->volume;
 16.1069 -        q->speed        = s->finetune+128;
 16.1070 -        q->panning      = s->panning;
 16.1071 -        q->seekpos      = nextwav[u];
 16.1072 -        q->vibtype      = s->vibtype;
 16.1073 -        q->vibsweep     = s->vibsweep;
 16.1074 -        q->vibdepth     = s->vibdepth;
 16.1075 -        q->vibrate      = s->vibrate;
 16.1076 +					s->length       =_mm_read_I_ULONG (modreader);
 16.1077 +					s->loopstart    =_mm_read_I_ULONG (modreader);
 16.1078 +					s->looplength   =_mm_read_I_ULONG (modreader);
 16.1079 +					s->volume       =_mm_read_UBYTE (modreader);
 16.1080 +					s->finetune     =_mm_read_SBYTE (modreader);
 16.1081 +					s->type         =_mm_read_UBYTE (modreader);
 16.1082 +					s->panning      =_mm_read_UBYTE (modreader);
 16.1083 +					s->relnote      =_mm_read_SBYTE (modreader);
 16.1084 +					s->vibtype      = pth.vibflg;
 16.1085 +					s->vibsweep     = pth.vibsweep;
 16.1086 +					s->vibdepth     = pth.vibdepth*4;
 16.1087 +					s->vibrate      = pth.vibrate;
 16.1088 +					s->reserved     =_mm_read_UBYTE (modreader);
 16.1089 +					_mm_read_string(s->samplename, 22, modreader);
 16.1090  
 16.1091 -        if(s->type & 0x10)
 16.1092 -        {   q->length    >>= 1;
 16.1093 -            q->loopstart >>= 1;
 16.1094 -            q->loopend   >>= 1;
 16.1095 -        }
 16.1096 +					nextwav[of.numsmp+u]=next;
 16.1097 +					next+=s->length;
 16.1098  
 16.1099 -        q->flags|=SF_OWNPAN;
 16.1100 -        if(s->type&0x3) q->flags|=SF_LOOP;
 16.1101 -        if(s->type&0x2) q->flags|=SF_BIDI;
 16.1102 -
 16.1103 -        if(s->type&0x10) q->flags|=SF_16BITS;
 16.1104 -        q->flags|=SF_DELTA;
 16.1105 -        q->flags|=SF_SIGNED;
 16.1106 -    }
 16.1107 +					if(_mm_eof(modreader)) {
 16.1108 +						free(nextwav);free(wh);
 16.1109 +						nextwav=NULL;wh=NULL;
 16.1110 +						_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1111 +						return 0;
 16.1112 +					}
 16.1113 +				}
 16.1114  
 16.1115 -    d = of.instruments;
 16.1116 -    s = wh;
 16.1117 -    for(u=0; u<of.numins; u++, d++)
 16.1118 -    {  /*for(t=0; t<3; t++)
 16.1119 -          if((s[d->samplenumber[t]].relnote / 12) > )
 16.1120 -          {  s[d->samplenumber[t]].relnote -= 12;
 16.1121 -             of.samples[d->samplenumber[t]].speed <<= 1;
 16.1122 -          }
 16.1123 -       */
 16.1124 -       for(t=0; t<96; t++)
 16.1125 -          d->samplenote[t] = (d->samplenumber[t]==of.numsmp) ? 255 : (t+s[d->samplenumber[t]].relnote);
 16.1126 -    }
 16.1127 +				if(mh->version>0x0103) {
 16.1128 +					for(u=0;u<ih.numsmp;u++)
 16.1129 +						nextwav[of.numsmp++]+=_mm_ftell(modreader);
 16.1130 +					_mm_fseek(modreader,next,SEEK_CUR);
 16.1131 +				} else
 16.1132 +					of.numsmp+=ih.numsmp;
 16.1133 +			} else {
 16.1134 +				/* read the remainder of the header */
 16.1135 +				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
 16.1136  
 16.1137 -    free(wh);
 16.1138 -    return 1;
 16.1139 +				if(_mm_eof(modreader)) {
 16.1140 +					free(nextwav);free(wh);
 16.1141 +					nextwav=NULL;wh=NULL;
 16.1142 +					_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1143 +					return 0;
 16.1144 +				}
 16.1145 +			}
 16.1146 +		}
 16.1147 +	}
 16.1148 +
 16.1149 +	/* sanity check */
 16.1150 +	if(!of.numsmp) {
 16.1151 +		if(nextwav) { free(nextwav);nextwav=NULL; }
 16.1152 +		if(wh) { free(wh);wh=NULL; }
 16.1153 +		_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1154 +		return 0;
 16.1155 +	}
 16.1156 +
 16.1157 +	return 1;
 16.1158  }
 16.1159  
 16.1160 +BOOL XM_Load(BOOL curious)
 16.1161 +{
 16.1162 +	INSTRUMENT *d;
 16.1163 +	SAMPLE *q;
 16.1164 +	int t,u;
 16.1165 +	BOOL dummypat=0;
 16.1166 +	char tracker[21],modtype[60];
 16.1167  
 16.1168 +	/* try to read module header */
 16.1169 +	_mm_read_string(mh->id,17,modreader);
 16.1170 +	_mm_read_string(mh->songname,21,modreader);
 16.1171 +	_mm_read_string(mh->trackername,20,modreader);
 16.1172 +	mh->version     =_mm_read_I_UWORD(modreader);
 16.1173 +	if((mh->version<0x102)||(mh->version>0x104)) {
 16.1174 +		_mm_errno=MMERR_NOT_A_MODULE;
 16.1175 +		return 0;
 16.1176 +	}
 16.1177 +	mh->headersize  =_mm_read_I_ULONG(modreader);
 16.1178 +	mh->songlength  =_mm_read_I_UWORD(modreader);
 16.1179 +	mh->restart     =_mm_read_I_UWORD(modreader);
 16.1180 +	mh->numchn      =_mm_read_I_UWORD(modreader);
 16.1181 +	mh->numpat      =_mm_read_I_UWORD(modreader);
 16.1182 +	mh->numins      =_mm_read_I_UWORD(modreader);
 16.1183 +	mh->flags       =_mm_read_I_UWORD(modreader);
 16.1184 +	mh->tempo       =_mm_read_I_UWORD(modreader);
 16.1185 +	mh->bpm         =_mm_read_I_UWORD(modreader);
 16.1186 +	if(!mh->bpm) {
 16.1187 +		_mm_errno=MMERR_NOT_A_MODULE;
 16.1188 +		return 0;
 16.1189 +	}
 16.1190 +	_mm_read_UBYTES(mh->orders,256,modreader);
 16.1191 +
 16.1192 +	if(_mm_eof(modreader)) {
 16.1193 +		_mm_errno = MMERR_LOADING_HEADER;
 16.1194 +		return 0;
 16.1195 +	}
 16.1196 +
 16.1197 +	/* set module variables */
 16.1198 +	of.initspeed = mh->tempo;
 16.1199 +	of.inittempo = mh->bpm;
 16.1200 +	strncpy(tracker,mh->trackername,20);tracker[20]=0;
 16.1201 +	for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
 16.1202 +
 16.1203 +	/* some modules have the tracker name empty */
 16.1204 +	if (!tracker[0])
 16.1205 +		strcpy(tracker,"Unknown tracker");
 16.1206 +
 16.1207 +#ifdef HAVE_SNPRINTF
 16.1208 +	snprintf(modtype,60,"%s (XM format %d.%02d)",
 16.1209 +	                    tracker,mh->version>>8,mh->version&0xff);
 16.1210 +#else
 16.1211 +	sprintf(modtype,"%s (XM format %d.%02d)",
 16.1212 +	                tracker,mh->version>>8,mh->version&0xff);
 16.1213 +#endif
 16.1214 +	of.modtype   = strdup(modtype);
 16.1215 +	of.numchn    = mh->numchn;
 16.1216 +	of.numpat    = mh->numpat;
 16.1217 +	of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
 16.1218 +	of.songname  = DupStr(mh->songname,20,1);
 16.1219 +	of.numpos    = mh->songlength;               /* copy the songlength */
 16.1220 +	of.reppos    = mh->restart<mh->songlength?mh->restart:0;
 16.1221 +	of.numins    = mh->numins;
 16.1222 +	of.flags    |= UF_XMPERIODS|UF_INST|UF_BGSLIDES|UF_NOWRAP|UF_FT2QUIRKS;
 16.1223 +	if(mh->flags&1) of.flags |= UF_LINEAR;
 16.1224 +
 16.1225 +	memset(of.chanvol,64,of.numchn);             /* store channel volumes */
 16.1226 +
 16.1227 +	if(!AllocPositions(of.numpos+1)) return 0;
 16.1228 +	for(t=0;t<of.numpos;t++)
 16.1229 +		of.positions[t]=mh->orders[t];
 16.1230 +
 16.1231 +	/* We have to check for any pattern numbers in the order list greater than
 16.1232 +	   the number of patterns total. If one or more is found, we set it equal to
 16.1233 +	   the pattern total and make a dummy pattern to workaround the problem */
 16.1234 +	for(t=0;t<of.numpos;t++) {
 16.1235 +		if(of.positions[t]>=of.numpat) {
 16.1236 +			of.positions[t]=of.numpat;
 16.1237 +			dummypat=1;
 16.1238 +		}
 16.1239 +	}
 16.1240 +	if(dummypat) {
 16.1241 +		of.numpat++;of.numtrk+=of.numchn;
 16.1242 +	}
 16.1243 +
 16.1244 +	if(mh->version<0x0104) {
 16.1245 +		if(!LoadInstruments()) return 0;
 16.1246 +		if(!LoadPatterns(dummypat)) return 0;
 16.1247 +		for(t=0;t<of.numsmp;t++)
 16.1248 +			nextwav[t]+=_mm_ftell(modreader);
 16.1249 +	} else {
 16.1250 +		if(!LoadPatterns(dummypat)) return 0;
 16.1251 +		if(!LoadInstruments()) return 0;
 16.1252 +	}
 16.1253 +
 16.1254 +	if(!AllocSamples()) {
 16.1255 +		free(nextwav);free(wh);
 16.1256 +		nextwav=NULL;wh=NULL;
 16.1257 +		return 0;
 16.1258 +	}
 16.1259 +	q = of.samples;
 16.1260 +	s = wh;
 16.1261 +	for(u=0;u<of.numsmp;u++,q++,s++) {
 16.1262 +		q->samplename   = DupStr(s->samplename,22,1);
 16.1263 +		q->length       = s->length;
 16.1264 +		q->loopstart    = s->loopstart;
 16.1265 +		q->loopend      = s->loopstart+s->looplength;
 16.1266 +		q->volume       = s->volume;
 16.1267 +		q->speed        = s->finetune+128;
 16.1268 +		q->panning      = s->panning;
 16.1269 +		q->seekpos      = nextwav[u];
 16.1270 +		q->vibtype      = s->vibtype;
 16.1271 +		q->vibsweep     = s->vibsweep;
 16.1272 +		q->vibdepth     = s->vibdepth;
 16.1273 +		q->vibrate      = s->vibrate;
 16.1274 +
 16.1275 +		if(s->type & 0x10) {
 16.1276 +			q->length    >>= 1;
 16.1277 +			q->loopstart >>= 1;
 16.1278 +			q->loopend   >>= 1;
 16.1279 +		}
 16.1280 +
 16.1281 +		q->flags|=SF_OWNPAN;
 16.1282 +		if(s->type&0x3) q->flags|=SF_LOOP;
 16.1283 +		if(s->type&0x2) q->flags|=SF_BIDI;
 16.1284 +		if(s->type&0x10) q->flags|=SF_16BITS;
 16.1285 +		q->flags|=SF_DELTA|SF_SIGNED;
 16.1286 +	}
 16.1287 +
 16.1288 +	d=of.instruments;
 16.1289 +	s=wh;
 16.1290 +	for(u=0;u<of.numins;u++,d++)
 16.1291 +		for(t=0;t<XMNOTECNT;t++) {
 16.1292 +			if (d->samplenumber[t]>=of.numsmp)
 16.1293 +				d->samplenote[t]=255;
 16.1294 +			else {
 16.1295 +				int note=t+s[d->samplenumber[t]].relnote;
 16.1296 +				d->samplenote[t]=(note<0)?0:note;
 16.1297 +			}
 16.1298 +		}
 16.1299 +
 16.1300 +	free(wh);free(nextwav);
 16.1301 +	wh=NULL;nextwav=NULL;
 16.1302 +	return 1;
 16.1303 +}
 16.1304  
 16.1305  CHAR *XM_LoadTitle(void)
 16.1306  {
 16.1307 -    CHAR s[21];
 16.1308 +	CHAR s[21];
 16.1309  
 16.1310 -    _mm_fseek(modfp,17,SEEK_SET);
 16.1311 -    if(!fread(s,21,1,modfp)) return NULL;
 16.1312 -  
 16.1313 -    return(DupStr(s,21));
 16.1314 +	_mm_fseek(modreader,17,SEEK_SET);
 16.1315 +	if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
 16.1316 +
 16.1317 +	return(DupStr(s,21,1));
 16.1318  }
 16.1319  
 16.1320 -
 16.1321 +/*========== Loader information */
 16.1322  
 16.1323 -MLOADER load_xm =
 16.1324 -{   NULL,
 16.1325 -    "XM",
 16.1326 -    "Portable XM loader v0.5",
 16.1327 -    XM_Init,
 16.1328 -    XM_Test,
 16.1329 -    XM_Load,
 16.1330 -    XM_Cleanup,
 16.1331 -    XM_LoadTitle
 16.1332 +MLOADER load_xm={
 16.1333 +	NULL,
 16.1334 +	"XM",
 16.1335 +	"XM (FastTracker 2)",
 16.1336 +	XM_Init,
 16.1337 +	XM_Test,
 16.1338 +	XM_Load,
 16.1339 +	XM_Cleanup,
 16.1340 +	XM_LoadTitle
 16.1341  };
 16.1342 +
 16.1343 +/* ex:set ts=4: */
    17.1 --- a/mikmod/mdreg.c	Mon Dec 27 19:18:10 1999 +0000
    17.2 +++ b/mikmod/mdreg.c	Mon Dec 27 19:24:50 1999 +0000
    17.3 @@ -1,31 +1,50 @@
    17.4 -/*
    17.5 -
    17.6 - Name:  MDREG.C
    17.7 +/*	MikMod sound library
    17.8 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    17.9 +	complete list.
   17.10  
   17.11 - Description:
   17.12 - A single routine for registering all drivers in MikMod for the current
   17.13 - platform.
   17.14 +	This library is free software; you can redistribute it and/or modify
   17.15 +	it under the terms of the GNU Library General Public License as
   17.16 +	published by the Free Software Foundation; either version 2 of
   17.17 +	the License, or (at your option) any later version.
   17.18  
   17.19 - Portability:
   17.20 - DOS, WIN95, OS2, SunOS, Solaris,
   17.21 - Linux, HPUX, AIX, SGI, Alpha
   17.22 +	This program is distributed in the hope that it will be useful,
   17.23 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.24 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.25 +	GNU Library General Public License for more details.
   17.26  
   17.27 - Anything not listed above is assumed to not be supported by this procedure!
   17.28 -
   17.29 - All Others: n
   17.30 -
   17.31 - - all compilers!
   17.32 -
   17.33 +	You should have received a copy of the GNU Library General Public
   17.34 +	License along with this library; if not, write to the Free Software
   17.35 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   17.36 +	02111-1307, USA.
   17.37  */
   17.38  
   17.39 -#include "mikmod.h"
   17.40 +/*==============================================================================
   17.41 +
   17.42 +  $Id$
   17.43 +
   17.44 +  Routine for registering all drivers in libmikmod for the current platform.
   17.45 +
   17.46 +==============================================================================*/
   17.47 +
   17.48 +#ifdef HAVE_CONFIG_H
   17.49 +#include "config.h"
   17.50 +#endif
   17.51 +
   17.52 +#include "mikmod_internals.h"
   17.53 +
   17.54 +MIKMODAPI extern struct MDRIVER drv_sdl;    /* Simple Direct Media */
   17.55 +
   17.56 +void _mm_registeralldrivers(void)
   17.57 +{
   17.58 +	_mm_registerdriver(&drv_sdl);
   17.59 +	_mm_registerdriver(&drv_nos);
   17.60 +}
   17.61  
   17.62  void MikMod_RegisterAllDrivers(void)
   17.63  {
   17.64 -
   17.65 -    MikMod_RegisterDriver(drv_sdl);
   17.66 -    MikMod_RegisterDriver(drv_nos);
   17.67 -
   17.68 +	MUTEX_LOCK(lists);
   17.69 +	_mm_registeralldrivers();
   17.70 +	MUTEX_UNLOCK(lists);
   17.71  }
   17.72  
   17.73 -
   17.74 +/* ex:set ts=4: */
    18.1 --- a/mikmod/mdriver.c	Mon Dec 27 19:18:10 1999 +0000
    18.2 +++ b/mikmod/mdriver.c	Mon Dec 27 19:24:50 1999 +0000
    18.3 @@ -1,557 +1,907 @@
    18.4 -/*
    18.5 +/*	MikMod sound library
    18.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    18.7 +	complete list.
    18.8  
    18.9 -Name:  MDRIVER.C
   18.10 +	This library is free software; you can redistribute it and/or modify
   18.11 +	it under the terms of the GNU Library General Public License as
   18.12 +	published by the Free Software Foundation; either version 2 of
   18.13 +	the License, or (at your option) any later version.
   18.14  
   18.15 -Description:
   18.16 -These routines are used to access the available soundcard drivers.
   18.17 +	This program is distributed in the hope that it will be useful,
   18.18 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.19 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.20 +	GNU Library General Public License for more details.
   18.21  
   18.22 -Portability:
   18.23 -All systems - all compilers
   18.24 -
   18.25 +	You should have received a copy of the GNU Library General Public
   18.26 +	License along with this library; if not, write to the Free Software
   18.27 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   18.28 +	02111-1307, USA.
   18.29  */
   18.30  
   18.31 -#include "mikmod.h"
   18.32 +/*==============================================================================
   18.33 +
   18.34 +  $Id$
   18.35 +
   18.36 +  These routines are used to access the available soundcard drivers.
   18.37 +
   18.38 +==============================================================================*/
   18.39  
   18.40 -MDRIVER *firstdriver = NULL, *md_driver = &drv_nos;
   18.41 -extern UNIMOD     *pf;           /* <- this modfile is being played */
   18.42 +#ifdef HAVE_CONFIG_H
   18.43 +#include "config.h"
   18.44 +#endif
   18.45 +
   18.46 +#ifdef HAVE_UNISTD_H
   18.47 +#include <unistd.h>
   18.48 +#endif
   18.49 +
   18.50 +#ifdef unix
   18.51 +#include <pwd.h>
   18.52 +#include <sys/stat.h>
   18.53 +#endif
   18.54  
   18.55 -UWORD md_device         = 0;
   18.56 -UWORD md_mixfreq        = 44100;
   18.57 -UWORD md_mode           = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND;
   18.58 -UWORD md_dmabufsize     = 50;
   18.59 -UBYTE md_pansep         = 128;      /* 128 == 100% (full left/right) */
   18.60 +#include "mikmod_internals.h"
   18.61 +
   18.62 +#include <string.h>
   18.63 +#ifdef HAVE_STRINGS_H
   18.64 +#include <strings.h>
   18.65 +#endif
   18.66 +
   18.67 +static	MDRIVER *firstdriver=NULL;
   18.68 +		MDRIVER *md_driver=NULL;
   18.69 +extern	MODULE *pf; /* modfile being played */
   18.70  
   18.71 -UBYTE md_reverb         = 6;       /* Reverb */
   18.72 -
   18.73 -UBYTE md_volume         = 96;       /* Global sound volume (0-128) */
   18.74 -UBYTE md_musicvolume    = 128;      /* volume of song */
   18.75 -UBYTE md_sndfxvolume    = 128;      /* volume of sound effects */
   18.76 -
   18.77 -UBYTE md_bpm            = 125;
   18.78 -
   18.79 +		UWORD md_device         = 0;
   18.80 +		UWORD md_mixfreq        = 44100;
   18.81 +		UWORD md_mode           = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND
   18.82 +		                         |DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
   18.83 +		UBYTE md_pansep         = 128; /* 128 == 100% (full left/right) */
   18.84 +		UBYTE md_reverb         = 6; /* Reverb */
   18.85 +		UBYTE md_volume         = 128;  /* Global sound volume (0-128) */
   18.86 +		UBYTE md_musicvolume    = 128; /* volume of song */
   18.87 +		UBYTE md_sndfxvolume    = 128; /* volume of sound effects */
   18.88 +		UWORD md_bpm            = 125;
   18.89  
   18.90  /* Do not modify the numchn variables yourself!  use MD_SetVoices() */
   18.91 -
   18.92 -UBYTE md_numchn = 0,  md_sngchn = 0,  md_sfxchn = 0;
   18.93 -UBYTE md_hardchn = 0, md_softchn = 0;
   18.94 -
   18.95 +		UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0;
   18.96 +		UBYTE md_hardchn=0,md_softchn=0;
   18.97  
   18.98 -void (*md_player)(void) = Player_HandleTick;
   18.99 -static BOOL  isplaying = 0, initialized = 0;
  18.100 -static UBYTE *sfxinfo;
  18.101 -static int   sfxpool;
  18.102 +		void (*md_player)(void) = Player_HandleTick;
  18.103 +static	BOOL  isplaying=0, initialized = 0;
  18.104 +static	UBYTE *sfxinfo;
  18.105 +static	int sfxpool;
  18.106  
  18.107 -static SAMPLE **md_sample = NULL;
  18.108 +static	SAMPLE **md_sample = NULL;
  18.109  
  18.110 -/* Backup variables.  This way, the end programmer can fiddle with the */
  18.111 -/* main globals without mikmod blowing up. */
  18.112 -
  18.113 -static UWORD idevice, imixfreq, imode, idmabufsize;
  18.114 -
  18.115 +/* Previous driver in use */
  18.116 +static	UWORD idevice;
  18.117  
  18.118 -static void LimitHardVoices(int limit)
  18.119 +/* Limits the number of hardware voices to the specified amount.
  18.120 +   This function should only be used by the low-level drivers. */
  18.121 +static	void LimitHardVoices(int limit)
  18.122 +{
  18.123 +	int t=0;
  18.124  
  18.125 -/* Limits the number of hardware voices to the specified amount. */
  18.126 -/* This function should only be used by the low-level drivers. */
  18.127 -
  18.128 -{
  18.129 -    int t = 0;
  18.130 +	if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
  18.131 +	if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
  18.132  
  18.133 -    if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit;
  18.134 -    if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit;
  18.135 +	if (!(md_mode & DMODE_SOFT_SNDFX))
  18.136 +		md_hardchn=md_sfxchn;
  18.137 +	else
  18.138 +		md_hardchn=0;
  18.139  
  18.140 -    if(!(md_mode & DMODE_SOFT_SNDFX))
  18.141 -       md_hardchn = md_sfxchn;
  18.142 -    else
  18.143 -       md_hardchn = 0;
  18.144 +	if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn += md_sngchn;
  18.145  
  18.146 -    if(!(md_mode & DMODE_SOFT_MUSIC))
  18.147 -       md_hardchn += md_sngchn;
  18.148 -    
  18.149 -    while(md_hardchn > limit)
  18.150 -    {
  18.151 -        if(++t & 1)
  18.152 -            if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--;
  18.153 -        else
  18.154 -            if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--;
  18.155 +	while (md_hardchn>limit) {
  18.156 +		if (++t & 1) {
  18.157 +			if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
  18.158 +		} else {
  18.159 +			if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
  18.160 +		}
  18.161  
  18.162 -        if(!(md_mode & DMODE_SOFT_SNDFX))
  18.163 -           md_hardchn = md_sfxchn;
  18.164 -        else
  18.165 -           md_hardchn = 0;
  18.166 +		if (!(md_mode & DMODE_SOFT_SNDFX))
  18.167 +			md_hardchn=md_sfxchn;
  18.168 +		else
  18.169 +			md_hardchn=0;
  18.170  
  18.171 -        if(!(md_mode & DMODE_SOFT_MUSIC))
  18.172 -           md_hardchn += md_sngchn;
  18.173 -    }
  18.174 -
  18.175 -    md_numchn = md_hardchn + md_softchn;
  18.176 +		if (!(md_mode & DMODE_SOFT_MUSIC))
  18.177 +			md_hardchn+=md_sngchn;
  18.178 +	}
  18.179 +	md_numchn=md_hardchn+md_softchn;
  18.180  }
  18.181  
  18.182 -
  18.183 -static void LimitSoftVoices(int limit)
  18.184 -
  18.185 -/* Limits the number of hardware voices to the specified amount. */
  18.186 -/* This function should only be used by the low-level drivers. */
  18.187 -
  18.188 +/* Limits the number of hardware voices to the specified amount.
  18.189 +   This function should only be used by the low-level drivers. */
  18.190 +static	void LimitSoftVoices(int limit)
  18.191  {
  18.192 -    int t = 0;
  18.193 +	int t=0;
  18.194  
  18.195 -    if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit;
  18.196 -    if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit;
  18.197 +	if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
  18.198 +	if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
  18.199  
  18.200 -    if(md_mode & DMODE_SOFT_SNDFX)
  18.201 -       md_softchn = md_sfxchn;
  18.202 -    else
  18.203 -       md_softchn = 0;
  18.204 +	if (md_mode & DMODE_SOFT_SNDFX)
  18.205 +		md_softchn=md_sfxchn;
  18.206 +	else
  18.207 +		md_softchn=0;
  18.208 +
  18.209 +	if (md_mode & DMODE_SOFT_MUSIC) md_softchn+=md_sngchn;
  18.210  
  18.211 -    if(md_mode & DMODE_SOFT_MUSIC)
  18.212 -       md_softchn += md_sngchn;
  18.213 -    
  18.214 -    while(md_softchn > limit)
  18.215 -    {
  18.216 -        if(++t & 1)
  18.217 -            if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--;
  18.218 -        else
  18.219 -            if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--;
  18.220 +	while (md_softchn>limit) {
  18.221 +		if (++t & 1) {
  18.222 +			if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
  18.223 +		} else {
  18.224 +			if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
  18.225 +		}
  18.226  
  18.227 -        if(!(md_mode & DMODE_SOFT_SNDFX))
  18.228 -           md_softchn = md_sfxchn;
  18.229 -        else
  18.230 -           md_softchn = 0;
  18.231 +		if (!(md_mode & DMODE_SOFT_SNDFX))
  18.232 +			md_softchn=md_sfxchn;
  18.233 +		else
  18.234 +			md_softchn=0;
  18.235  
  18.236 -        if(!(md_mode & DMODE_SOFT_MUSIC))
  18.237 -           md_softchn += md_sngchn;
  18.238 -    }
  18.239 -
  18.240 -    md_numchn = md_hardchn + md_softchn;
  18.241 +		if (!(md_mode & DMODE_SOFT_MUSIC))
  18.242 +			md_softchn+=md_sngchn;
  18.243 +	}
  18.244 +	md_numchn=md_hardchn+md_softchn;
  18.245  }
  18.246  
  18.247 -
  18.248 -/* Note: 'type' indicates whether the returned value should be for music */
  18.249 -/*       or for sound effects. */
  18.250 -
  18.251 +/* Note: 'type' indicates whether the returned value should be for music or for
  18.252 +   sound effects. */
  18.253  ULONG MD_SampleSpace(int type)
  18.254  {
  18.255 -    if(type==MD_MUSIC)
  18.256 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.257 -    else if(type==MD_SNDFX)
  18.258 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.259 +	if(type==MD_MUSIC)
  18.260 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.261 +	else if(type==MD_SNDFX)
  18.262 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.263  
  18.264 -    return md_driver->FreeSampleSpace(type);
  18.265 +	return md_driver->FreeSampleSpace(type);
  18.266  }
  18.267  
  18.268 -
  18.269 -ULONG MD_SampleLength(int type, SAMPLE *s)
  18.270 +ULONG MD_SampleLength(int type,SAMPLE* s)
  18.271  {
  18.272 -    if(type==MD_MUSIC)
  18.273 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.274 -    else if(type==MD_SNDFX)
  18.275 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.276 +	if(type==MD_MUSIC)
  18.277 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.278 +	else
  18.279 +	  if(type==MD_SNDFX)
  18.280 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.281  
  18.282 -    return md_driver->RealSampleLength(type, s);
  18.283 +	return md_driver->RealSampleLength(type,s);
  18.284  }
  18.285  
  18.286 -
  18.287 -UWORD MD_SetDMA(int secs)
  18.288 -
  18.289 -/* Converts the given number of 1/10th seconds into the number of bytes of */
  18.290 -/* audio that a sample # 1/10th seconds long would require at the current md_* */
  18.291 -/* settings. */
  18.292 -
  18.293 +CHAR* MikMod_InfoDriver(void)
  18.294  {
  18.295 -    ULONG result;
  18.296 +	int t,len=0;
  18.297 +	MDRIVER *l;
  18.298 +	CHAR *list=NULL;
  18.299 +
  18.300 +	MUTEX_LOCK(lists);
  18.301 +	/* compute size of buffer */
  18.302 +	for(l=firstdriver;l;l=l->next) len+=4+(l->next?1:0)+strlen(l->Version);
  18.303  
  18.304 -    result = (md_mixfreq * ((md_mode & DMODE_STEREO) ? 2 : 1) *
  18.305 -             ((md_mode & DMODE_16BITS) ? 2 : 1) * secs) * 10;
  18.306 -
  18.307 -    if(result > 32000) result = 32000;
  18.308 -    return(md_dmabufsize = (result & ~3));  /* round it off to an 8 byte boundry */
  18.309 +	if(len)
  18.310 +		if((list=_mm_malloc(len*sizeof(CHAR)))) {
  18.311 +			list[0]=0;
  18.312 +			/* list all registered device drivers : */
  18.313 +			for(t=1,l=firstdriver;l;l=l->next,t++)
  18.314 +				sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s",list,t,l->Version);
  18.315 +		}
  18.316 +	MUTEX_UNLOCK(lists);
  18.317 +	return list;
  18.318  }
  18.319  
  18.320 -
  18.321 -void MD_InfoDriver(void)
  18.322 +void _mm_registerdriver(struct MDRIVER* drv)
  18.323  {
  18.324 -    int t;
  18.325 -    MDRIVER *l;
  18.326 +	MDRIVER *cruise = firstdriver;
  18.327 +
  18.328 +	if(cruise) {
  18.329 +		while(cruise->next) cruise=cruise->next;
  18.330 +		cruise->next=drv;
  18.331 +	} else
  18.332 +		firstdriver = drv;
  18.333 +}
  18.334  
  18.335 -    /* list all registered devicedrivers: */
  18.336 -    for(t=1,l=firstdriver; l!=NULL; l=l->next, t++)
  18.337 -        printf("%d. %s\n",t,l->Version);
  18.338 +void MikMod_RegisterDriver(struct MDRIVER* drv)
  18.339 +{
  18.340 +	/* if we try to register an invalid driver, or an already registered driver,
  18.341 +	   ignore this attempt */
  18.342 +	if ((!drv)||(drv->next))
  18.343 +		return;
  18.344 +
  18.345 +	MUTEX_LOCK(lists);
  18.346 +	_mm_registerdriver(drv);
  18.347 +	MUTEX_UNLOCK(lists);
  18.348  }
  18.349  
  18.350 -
  18.351 -void MD_RegisterDriver(MDRIVER *drv)
  18.352 +int MikMod_DriverFromAlias(CHAR *alias)
  18.353  {
  18.354 -    MDRIVER *cruise = firstdriver;
  18.355 +	int rank=1;
  18.356 +	MDRIVER *cruise;
  18.357  
  18.358 -    if(cruise!=NULL)
  18.359 -    {   while(cruise->next!=NULL)  cruise = cruise->next;
  18.360 -        cruise->next = drv;
  18.361 -    } else
  18.362 -        firstdriver = drv; 
  18.363 +	MUTEX_LOCK(lists);
  18.364 +	cruise=firstdriver;
  18.365 +	while(cruise) {
  18.366 +		if (!(strcasecmp(alias,cruise->Alias))) break;
  18.367 +		cruise=cruise->next;rank++;
  18.368 +	}
  18.369 +	if(!cruise) rank=0;
  18.370 +	MUTEX_UNLOCK(lists);
  18.371 +
  18.372 +	return rank;
  18.373  }
  18.374  
  18.375 -
  18.376 -SWORD MD_SampleLoad(SAMPLOAD *s, int type, FILE *fp)
  18.377 -/*  type - sample type .. MD_MUSIC or MD_SNDFX */
  18.378 +SWORD MD_SampleLoad(SAMPLOAD* s, int type)
  18.379  {
  18.380 -    SWORD result;
  18.381 +	SWORD result;
  18.382  
  18.383 -    if(type==MD_MUSIC)
  18.384 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.385 -    else if(type==MD_SNDFX)
  18.386 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.387 +	if(type==MD_MUSIC)
  18.388 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.389 +	else if(type==MD_SNDFX)
  18.390 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.391  
  18.392 -    SL_Init(s);
  18.393 -    result = md_driver->SampleLoad(s, type);
  18.394 -    SL_Exit(s);
  18.395 +	SL_Init(s);
  18.396 +	result=md_driver->SampleLoad(s,type);
  18.397 +	SL_Exit(s);
  18.398  
  18.399 -    return result;
  18.400 +	return result;
  18.401  }
  18.402  
  18.403 -
  18.404 -void MD_SampleUnLoad(SWORD handle)
  18.405 +void MD_SampleUnload(SWORD handle)
  18.406  {
  18.407 -    md_driver->SampleUnLoad(handle);
  18.408 +	md_driver->SampleUnload(handle);
  18.409  }
  18.410  
  18.411 -
  18.412 -void MD_SetBPM(UBYTE bpm)
  18.413 +MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player)
  18.414  {
  18.415 -    md_bpm = bpm;
  18.416 -}
  18.417 +	MikMod_player_t result;
  18.418  
  18.419 +	MUTEX_LOCK(vars);
  18.420 +	result=md_player;
  18.421 +	md_player=player;
  18.422 +	MUTEX_UNLOCK(vars);
  18.423  
  18.424 -void MikMod_RegisterPlayer(void (*player)(void))
  18.425 -{
  18.426 -    md_player = player;
  18.427 +	return result;
  18.428  }
  18.429  
  18.430 -
  18.431  void MikMod_Update(void)
  18.432  {
  18.433 -    if(isplaying && !(pf->forbid)) md_driver->Update();
  18.434 +	MUTEX_LOCK(vars);
  18.435 +	if(isplaying) {
  18.436 +		if((!pf)||(!pf->forbid))
  18.437 +			md_driver->Update();
  18.438 +		else {
  18.439 +			if (md_driver->Pause)
  18.440 +				md_driver->Pause();
  18.441 +		}
  18.442 +	}
  18.443 +	MUTEX_UNLOCK(vars);
  18.444  }
  18.445  
  18.446 -
  18.447 -void Voice_SetVolume(int voice, UWORD vol)
  18.448 +void Voice_SetVolume_internal(SBYTE voice,UWORD vol)
  18.449  {
  18.450 -    ULONG  tmp;
  18.451 +	ULONG  tmp;
  18.452 +
  18.453 +	if((voice<0)||(voice>=md_numchn)) return;
  18.454  
  18.455 -    if((voice<0) || (voice>=md_numchn)) return;
  18.456 -    tmp = (ULONG)vol * (ULONG)md_volume * ((voice < md_sngchn) ? (ULONG)md_musicvolume : (ULONG)md_sndfxvolume);
  18.457 -    md_driver->VoiceSetVolume(voice,tmp/16384UL);
  18.458 +	/* range checks */
  18.459 +	if(md_musicvolume>128) md_musicvolume=128;
  18.460 +	if(md_sndfxvolume>128) md_sndfxvolume=128;
  18.461 +	if(md_volume>128) md_volume=128;
  18.462 +
  18.463 +	tmp=(ULONG)vol*(ULONG)md_volume*
  18.464 +	     ((voice<md_sngchn)?(ULONG)md_musicvolume:(ULONG)md_sndfxvolume);
  18.465 +	md_driver->VoiceSetVolume(voice,tmp/16384UL);
  18.466  }
  18.467  
  18.468 -
  18.469 -void Voice_SetFrequency(int voice, ULONG frq)
  18.470 +void Voice_SetVolume(SBYTE voice,UWORD vol)
  18.471  {
  18.472 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.473 -    if(md_sample[voice]!=NULL && md_sample[voice]->divfactor!=0) frq/=md_sample[voice]->divfactor;
  18.474 -    md_driver->VoiceSetFrequency(voice, frq);
  18.475 +	MUTEX_LOCK(vars);
  18.476 +	Voice_SetVolume_internal(voice,vol);
  18.477 +	MUTEX_UNLOCK(vars);
  18.478  }
  18.479  
  18.480 -
  18.481 -void Voice_SetPanning(int voice, ULONG pan)
  18.482 +UWORD Voice_GetVolume(SBYTE voice)
  18.483  {
  18.484 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.485 -    if(pan!=PAN_SURROUND)
  18.486 -    {   if(md_mode & DMODE_REVERSE) pan = 255-pan;
  18.487 -        pan = (((SWORD)(pan-128)*md_pansep) / 128)+128;
  18.488 -    }
  18.489 -    md_driver->VoiceSetPanning(voice, pan);
  18.490 +	UWORD result=0;
  18.491 +
  18.492 +	MUTEX_LOCK(vars);
  18.493 +	if((voice>=0)&&(voice<md_numchn))
  18.494 +		result=md_driver->VoiceGetVolume(voice);
  18.495 +	MUTEX_UNLOCK(vars);
  18.496 +
  18.497 +	return result;
  18.498 +}
  18.499 +
  18.500 +void Voice_SetFrequency_internal(SBYTE voice,ULONG frq)
  18.501 +{
  18.502 +	if((voice<0)||(voice>=md_numchn)) return;
  18.503 +	if((md_sample[voice])&&(md_sample[voice]->divfactor))
  18.504 +		frq/=md_sample[voice]->divfactor;
  18.505 +	md_driver->VoiceSetFrequency(voice,frq);
  18.506 +}
  18.507 +
  18.508 +void Voice_SetFrequency(SBYTE voice,ULONG frq)
  18.509 +{
  18.510 +	MUTEX_LOCK(vars);
  18.511 +	Voice_SetFrequency_internal(voice,frq);
  18.512 +	MUTEX_UNLOCK(vars);
  18.513  }
  18.514  
  18.515 -
  18.516 -void Voice_Play(int voice, SAMPLE *s, ULONG start)
  18.517 +ULONG Voice_GetFrequency(SBYTE voice)
  18.518  {
  18.519 -    ULONG  repend;
  18.520 -    
  18.521 -    if((voice < 0) || (voice >= md_numchn) || (start >= s->length)) return;
  18.522 +	ULONG result=0;
  18.523 +
  18.524 +	MUTEX_LOCK(vars);
  18.525 +	if((voice>=0)&&(voice<md_numchn))
  18.526 +		result=md_driver->VoiceGetFrequency(voice);
  18.527 +	MUTEX_UNLOCK(vars);
  18.528 +
  18.529 +	return result;
  18.530 +}
  18.531  
  18.532 -    md_sample[voice] = s;
  18.533 -    repend = s->loopend;
  18.534 +void Voice_SetPanning_internal(SBYTE voice,ULONG pan)
  18.535 +{
  18.536 +	if((voice<0)||(voice>=md_numchn)) return;
  18.537 +	if(pan!=PAN_SURROUND) {
  18.538 +		if(md_pansep>128) md_pansep=128;
  18.539 +		if(md_mode & DMODE_REVERSE) pan=255-pan;
  18.540 +		pan = (((SWORD)(pan-128)*md_pansep)/128)+128;
  18.541 +	}
  18.542 +	md_driver->VoiceSetPanning(voice, pan);
  18.543 +}
  18.544  
  18.545 -    if(s->flags&SF_LOOP)
  18.546 -       if(repend > s->length) repend = s->length;    /* repend can't be bigger than size */
  18.547 +void Voice_SetPanning(SBYTE voice,ULONG pan)
  18.548 +{
  18.549 +#ifdef MIKMOD_DEBUG
  18.550 +	if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255)))
  18.551 +		fprintf(stderr,"\rVoice_SetPanning called with pan=%ld\n",(long)pan);
  18.552 +#endif
  18.553  
  18.554 -    md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
  18.555 +	MUTEX_LOCK(vars);
  18.556 +	Voice_SetPanning_internal(voice,pan);
  18.557 +	MUTEX_UNLOCK(vars);
  18.558  }
  18.559  
  18.560 -
  18.561 -void Voice_Stop(int voice)
  18.562 +ULONG Voice_GetPanning(SBYTE voice)
  18.563  {
  18.564 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.565 -    if(voice >= md_sngchn)
  18.566 -    {   /* It is a sound effects channel, so flag the voice as non-critical! */
  18.567 -        sfxinfo[voice-md_sngchn] = 0;
  18.568 -    }
  18.569 +	ULONG result=PAN_CENTER;
  18.570  
  18.571 -    md_driver->VoiceStop(voice);
  18.572 +	MUTEX_LOCK(vars);
  18.573 +	if((voice>=0)&&(voice<md_numchn))
  18.574 +		result=md_driver->VoiceGetPanning(voice);
  18.575 +	MUTEX_UNLOCK(vars);
  18.576 +
  18.577 +	return result;
  18.578  }
  18.579  
  18.580 - 
  18.581 -BOOL Voice_Stopped(int voice)
  18.582 +void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start)
  18.583  {
  18.584 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.585 -    return(md_driver->VoiceStopped(voice));
  18.586 +	ULONG  repend;
  18.587 +
  18.588 +	if((voice<0)||(voice>=md_numchn)) return;
  18.589 +
  18.590 +	md_sample[voice]=s;
  18.591 +	repend=s->loopend;
  18.592 +
  18.593 +	if(s->flags&SF_LOOP)
  18.594 +		/* repend can't be bigger than size */
  18.595 +		if(repend>s->length) repend=s->length;
  18.596 +
  18.597 +	md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
  18.598 +}
  18.599 +
  18.600 +void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start)
  18.601 +{
  18.602 +	if(start>s->length) return;
  18.603 +
  18.604 +	MUTEX_LOCK(vars);
  18.605 +	Voice_Play_internal(voice,s,start);
  18.606 +	MUTEX_UNLOCK(vars);
  18.607  }
  18.608  
  18.609 -
  18.610 -SLONG Voice_GetPosition(int voice)
  18.611 +void Voice_Stop_internal(SBYTE voice)
  18.612  {
  18.613 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.614 -    return(md_driver->VoiceGetPosition(voice));
  18.615 +	if((voice<0)||(voice>=md_numchn)) return;
  18.616 +	if(voice>=md_sngchn)
  18.617 +		/* It is a sound effects channel, so flag the voice as non-critical! */
  18.618 +		sfxinfo[voice-md_sngchn]=0;
  18.619 +	md_driver->VoiceStop(voice);
  18.620 +}
  18.621 +
  18.622 +void Voice_Stop(SBYTE voice)
  18.623 +{
  18.624 +	MUTEX_LOCK(vars);
  18.625 +	Voice_Stop_internal(voice);
  18.626 +	MUTEX_UNLOCK(vars);
  18.627 +}
  18.628 +
  18.629 +BOOL Voice_Stopped_internal(SBYTE voice)
  18.630 +{
  18.631 +	if((voice<0)||(voice>=md_numchn)) return 0;
  18.632 +	return(md_driver->VoiceStopped(voice));
  18.633  }
  18.634  
  18.635 +BOOL Voice_Stopped(SBYTE voice)
  18.636 +{
  18.637 +	BOOL result;
  18.638  
  18.639 -ULONG Voice_RealVolume(int voice)
  18.640 +	MUTEX_LOCK(vars);
  18.641 +	result=Voice_Stopped_internal(voice);
  18.642 +	MUTEX_UNLOCK(vars);
  18.643 +
  18.644 +	return result;
  18.645 +}
  18.646 +
  18.647 +SLONG Voice_GetPosition(SBYTE voice)
  18.648  {
  18.649 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.650 -    return(md_driver->VoiceRealVolume(voice));
  18.651 +	SLONG result=0;
  18.652 +
  18.653 +	MUTEX_LOCK(vars);
  18.654 +	if((voice>=0)&&(voice<md_numchn))
  18.655 +		result=(md_driver->VoiceGetPosition(voice));
  18.656 +	MUTEX_UNLOCK(vars);
  18.657 +
  18.658 +	return result;
  18.659 +}
  18.660 +
  18.661 +ULONG Voice_RealVolume(SBYTE voice)
  18.662 +{
  18.663 +	ULONG result=0;
  18.664 +
  18.665 +	MUTEX_LOCK(vars);
  18.666 +	if((voice>=0)&&(voice<md_numchn))
  18.667 +		result=(md_driver->VoiceRealVolume(voice));
  18.668 +	MUTEX_UNLOCK(vars);
  18.669 +
  18.670 +	return result;
  18.671  }
  18.672  
  18.673 -
  18.674 -/* ================================ */
  18.675 -/*  Functions prefixed with MikMod */
  18.676 -/* ================================ */
  18.677 +static BOOL _mm_init(CHAR *cmdline)
  18.678 +{
  18.679 +	UWORD t;
  18.680  
  18.681 -BOOL MikMod_Init(void)
  18.682 -{
  18.683 -    UWORD t;
  18.684 +	_mm_critical = 1;
  18.685  
  18.686 -    _mm_critical = 1;
  18.687 +	/* if md_device==0, try to find a device number */
  18.688 +	if(!md_device) {
  18.689 +		cmdline=NULL;
  18.690  
  18.691 -    /* if md_device==0, try to find a device number */
  18.692 -
  18.693 -    if(md_device==0)
  18.694 -    {   for(t=1,md_driver=firstdriver; md_driver!=NULL; md_driver=md_driver->next, t++)
  18.695 -        {   if(md_driver->IsPresent()) break;
  18.696 -        }
  18.697 +		for(t=1,md_driver=firstdriver;md_driver;md_driver=md_driver->next,t++)
  18.698 +			if(md_driver->IsPresent()) break;
  18.699  
  18.700 -        if(md_driver==NULL)
  18.701 -        {   _mm_errno = MMERR_DETECTING_DEVICE;
  18.702 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.703 -            md_driver = &drv_nos;
  18.704 -            return 1;
  18.705 -        }
  18.706 +		if(!md_driver) {
  18.707 +			_mm_errno = MMERR_DETECTING_DEVICE;
  18.708 +			if(_mm_errorhandler) _mm_errorhandler();
  18.709 +			md_driver = &drv_nos;
  18.710 +			return 1;
  18.711 +		}
  18.712 +
  18.713 +		md_device = t;
  18.714 +	} else {
  18.715 +		/* if n>0, use that driver */
  18.716 +		for(t=1,md_driver=firstdriver;(md_driver)&&(t!=md_device);md_driver=md_driver->next,t++);
  18.717  
  18.718 -        md_device = t;
  18.719 -    } else
  18.720 -    {   /* if n>0 use that driver */
  18.721 -        for(t=1,md_driver=firstdriver; (md_driver!=NULL) && (t!=md_device); md_driver=md_driver->next, t++);
  18.722 +		if(!md_driver) {
  18.723 +			_mm_errno = MMERR_INVALID_DEVICE;
  18.724 +			if(_mm_errorhandler) _mm_errorhandler();
  18.725 +			md_driver = &drv_nos;
  18.726 +			return 1;
  18.727 +		}
  18.728 +
  18.729 +		/* arguments here might be necessary for the presence check to succeed */
  18.730 +		if(cmdline&&(md_driver->CommandLine))
  18.731 +			md_driver->CommandLine(cmdline);
  18.732  
  18.733 -        if(md_driver==NULL)
  18.734 -        {   _mm_errno = MMERR_INVALID_DEVICE;
  18.735 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.736 -            md_driver = &drv_nos;
  18.737 -            return 1;
  18.738 -        }
  18.739 -    
  18.740 -        if(!md_driver->IsPresent())
  18.741 -        {   _mm_errno = MMERR_DETECTING_DEVICE;
  18.742 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.743 -            md_driver = &drv_nos;
  18.744 -            return 1;
  18.745 -        }
  18.746 -    }
  18.747 +		if(!md_driver->IsPresent()) {
  18.748 +			_mm_errno = MMERR_DETECTING_DEVICE;
  18.749 +			if(_mm_errorhandler) _mm_errorhandler();
  18.750 +			md_driver = &drv_nos;
  18.751 +			return 1;
  18.752 +		}
  18.753 +	}
  18.754  
  18.755 -    if(md_driver->Init())
  18.756 -    {   MikMod_Exit();
  18.757 -        if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.758 -        return 1;
  18.759 -    }
  18.760 +	if(md_driver->Init()) {
  18.761 +		md_driver->Exit();
  18.762 +		MikMod_Exit_internal();
  18.763 +		if(_mm_errorhandler) _mm_errorhandler();
  18.764 +		return 1;
  18.765 +	}
  18.766  
  18.767 -    idevice  = md_device;   imode       = md_mode;
  18.768 -    imixfreq = md_mixfreq;  idmabufsize = md_dmabufsize;
  18.769 -    initialized = 1;
  18.770 -    _mm_critical = 0;
  18.771 +	initialized=1;
  18.772 +	_mm_critical=0;
  18.773  
  18.774 -    return 0;
  18.775 +	return 0;
  18.776  }
  18.777  
  18.778 +BOOL MikMod_Init(CHAR *cmdline)
  18.779 +{
  18.780 +	BOOL result;
  18.781 +
  18.782 +	MUTEX_LOCK(vars);
  18.783 +	MUTEX_LOCK(lists);
  18.784 +	result=_mm_init(cmdline);
  18.785 +	MUTEX_UNLOCK(lists);
  18.786 +	MUTEX_UNLOCK(vars);
  18.787 +
  18.788 +	return result;
  18.789 +}
  18.790 +
  18.791 +void MikMod_Exit_internal(void)
  18.792 +{
  18.793 +	MikMod_DisableOutput_internal();
  18.794 +	md_driver->Exit();
  18.795 +	md_numchn = md_sfxchn = md_sngchn = 0;
  18.796 +	md_driver = &drv_nos;
  18.797 +
  18.798 +	if(sfxinfo) free(sfxinfo);
  18.799 +	if(md_sample) free(md_sample);
  18.800 +	md_sample  = NULL;
  18.801 +	sfxinfo    = NULL;
  18.802 +
  18.803 +	initialized = 0;
  18.804 +}
  18.805  
  18.806  void MikMod_Exit(void)
  18.807  {
  18.808 -    MikMod_DisableOutput();
  18.809 -    md_driver->Exit();
  18.810 -    md_numchn = md_sfxchn = md_sngchn = 0;
  18.811 -    md_driver = &drv_nos;
  18.812 -    initialized = 0;
  18.813 +	MUTEX_LOCK(vars);
  18.814 +	MUTEX_LOCK(lists);
  18.815 +	MikMod_Exit_internal();
  18.816 +	MUTEX_UNLOCK(lists);
  18.817 +	MUTEX_UNLOCK(vars);
  18.818  }
  18.819  
  18.820 -
  18.821 -BOOL MikMod_Reset(void)
  18.822 -
  18.823 -/* Reset the driver using the new global variable settings. */
  18.824 -/* If the driver has not been initialized, it will be now. */
  18.825 -
  18.826 +/* Reset the driver using the new global variable settings.
  18.827 +   If the driver has not been initialized, it will be now. */
  18.828 +static BOOL _mm_reset(CHAR *cmdline)
  18.829  {
  18.830 -    if(!initialized) return MikMod_Init();
  18.831 -    if((md_driver->Reset == NULL) || (md_device != idevice))
  18.832 -    {   /* md_driver->Reset was NULL, or md_device was changed, */
  18.833 -        /* so do a full reset of the driver. */
  18.834 +	if(!initialized) return _mm_init(cmdline);
  18.835  
  18.836 -        if(isplaying) md_driver->PlayStop();
  18.837 -        md_driver->Exit();
  18.838 -        if(MikMod_Init())
  18.839 -        {   MikMod_Exit();
  18.840 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.841 -            return 1;
  18.842 -        }
  18.843 -        if(isplaying) md_driver->PlayStart();
  18.844 -    } else
  18.845 -    {   if(md_driver->Reset())
  18.846 -        {   MikMod_Exit();
  18.847 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.848 -            return 1;
  18.849 -        }
  18.850 -    }
  18.851 -    
  18.852 -    return 0;
  18.853 +	if((!md_driver->Reset)||(md_device != idevice)) {
  18.854 +		/* md_driver->Reset was NULL, or md_device was changed, so do a full
  18.855 +		   reset of the driver. */
  18.856 +		if(isplaying) md_driver->PlayStop();
  18.857 +		md_driver->Exit();
  18.858 +		if(_mm_init(cmdline)) {
  18.859 +			MikMod_Exit_internal();
  18.860 +			if(_mm_errno)
  18.861 +				if(_mm_errorhandler) _mm_errorhandler();
  18.862 +			return 1;
  18.863 +		}
  18.864 +		if(isplaying) md_driver->PlayStart();
  18.865 +	} else {
  18.866 +		if(md_driver->Reset()) {
  18.867 +			MikMod_Exit_internal();
  18.868 +			if(_mm_errno)
  18.869 +				if(_mm_errorhandler) _mm_errorhandler();
  18.870 +			return 1;
  18.871 +		}
  18.872 +	}
  18.873 +	return 0;
  18.874  }
  18.875  
  18.876 +BOOL MikMod_Reset(CHAR *cmdline)
  18.877 +{
  18.878 +	BOOL result;
  18.879  
  18.880 -BOOL MikMod_SetNumVoices(int music, int sfx)
  18.881 +	MUTEX_LOCK(vars);
  18.882 +	MUTEX_LOCK(lists);
  18.883 +	result=_mm_reset(cmdline);
  18.884 +	MUTEX_UNLOCK(lists);
  18.885 +	MUTEX_UNLOCK(vars);
  18.886 +
  18.887 +	return result;
  18.888 +}
  18.889  
  18.890  /* If either parameter is -1, the current set value will be retained. */
  18.891 -
  18.892 +BOOL MikMod_SetNumVoices_internal(int music, int sfx)
  18.893  {
  18.894 -    BOOL resume = 0;
  18.895 -    int  t, oldchn = 0;
  18.896 -
  18.897 -    if((music==0) && (sfx==0)) return 0;
  18.898 -
  18.899 -    _mm_critical = 1;
  18.900 +	BOOL resume = 0;
  18.901 +	int t, oldchn = 0;
  18.902  
  18.903 -    if(isplaying)
  18.904 -    {   MikMod_DisableOutput();
  18.905 -        oldchn = md_numchn;
  18.906 -        resume = 1;
  18.907 -    }
  18.908 +	if((!music)&&(!sfx)) return 1;
  18.909 +	_mm_critical = 1;
  18.910 +	if(isplaying) {
  18.911 +		MikMod_DisableOutput_internal();
  18.912 +		oldchn = md_numchn;
  18.913 +		resume = 1;
  18.914 +	}
  18.915  
  18.916 -    if(sfxinfo!=NULL)   free(sfxinfo);
  18.917 -    if(md_sample!=NULL) free(md_sample);
  18.918 -    md_sample  = NULL;
  18.919 -    sfxinfo    = NULL;
  18.920 -
  18.921 -    /*md_softchn = md_hardchn = 0;
  18.922 +	if(sfxinfo) free(sfxinfo);
  18.923 +	if(md_sample) free(md_sample);
  18.924 +	md_sample  = NULL;
  18.925 +	sfxinfo    = NULL;
  18.926  
  18.927 -    if(md_mode & DMODE_SOFT_SNDFX)
  18.928 -       md_softchn = sfx; else md_hardchn = sfx;
  18.929 -
  18.930 -    if(md_mode & DMODE_SOFT_MUSIC)
  18.931 -       md_softchn += music; else md_hardchn += music;
  18.932 -    */
  18.933 +	if(music!=-1) md_sngchn = music;
  18.934 +	if(sfx!=-1)   md_sfxchn = sfx;
  18.935 +	md_numchn = md_sngchn + md_sfxchn;
  18.936  
  18.937 -    if(music != -1) md_sngchn = music;
  18.938 -    if(sfx != -1)   md_sfxchn = sfx;
  18.939 -
  18.940 -    md_numchn = md_sngchn + md_sfxchn;
  18.941 +	LimitHardVoices(md_driver->HardVoiceLimit);
  18.942 +	LimitSoftVoices(md_driver->SoftVoiceLimit);
  18.943  
  18.944 -    LimitHardVoices(md_driver->HardVoiceLimit);
  18.945 -    LimitSoftVoices(md_driver->SoftVoiceLimit);
  18.946 -
  18.947 -    if(md_driver->SetNumVoices())
  18.948 -    {   MikMod_Exit();
  18.949 -        md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
  18.950 -        if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.951 -        return 1;
  18.952 -    }
  18.953 +	if(md_driver->SetNumVoices()) {
  18.954 +		MikMod_Exit_internal();
  18.955 +		if(_mm_errno)
  18.956 +			if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.957 +		md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
  18.958 +		return 1;
  18.959 +	}
  18.960  
  18.961 -    if(md_sngchn || md_sfxchn)
  18.962 -        md_sample = (SAMPLE **)_mm_calloc(md_sngchn+md_sfxchn, sizeof(SAMPLE *));
  18.963 -    if(md_sfxchn)
  18.964 -        sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn, sizeof(UBYTE));
  18.965 +	if(md_sngchn+md_sfxchn)
  18.966 +		md_sample=(SAMPLE**)_mm_calloc(md_sngchn+md_sfxchn,sizeof(SAMPLE*));
  18.967 +	if(md_sfxchn)
  18.968 +		sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn,sizeof(UBYTE));
  18.969  
  18.970 -    /* make sure the player doesn't start with garbage */
  18.971 -    for(t=oldchn; t<md_numchn; t++)  Voice_Stop(t);
  18.972 -
  18.973 -    sfxpool = 0;
  18.974 +	/* make sure the player doesn't start with garbage */
  18.975 +	for(t=oldchn;t<md_numchn;t++)  Voice_Stop_internal(t);
  18.976  
  18.977 -    if(resume) MikMod_EnableOutput();
  18.978 -    _mm_critical = 0;
  18.979 +	sfxpool = 0;
  18.980 +	if(resume) MikMod_EnableOutput_internal();
  18.981 +	_mm_critical = 0;
  18.982  
  18.983 -    return 0;
  18.984 +	return 0;
  18.985  }
  18.986  
  18.987 +BOOL MikMod_SetNumVoices(int music, int sfx)
  18.988 +{
  18.989 +	BOOL result;
  18.990 +
  18.991 +	MUTEX_LOCK(vars);
  18.992 +	result=MikMod_SetNumVoices_internal(music,sfx);
  18.993 +	MUTEX_UNLOCK(vars);
  18.994 +
  18.995 +	return result;
  18.996 +}
  18.997 +
  18.998 +BOOL MikMod_EnableOutput_internal(void)
  18.999 +{
 18.1000 +	_mm_critical = 1;
 18.1001 +	if(!isplaying) {
 18.1002 +		if(md_driver->PlayStart()) return 1;
 18.1003 +		isplaying = 1;
 18.1004 +	}
 18.1005 +	_mm_critical = 0;
 18.1006 +	return 0;
 18.1007 +}
 18.1008  
 18.1009  BOOL MikMod_EnableOutput(void)
 18.1010  {
 18.1011 -    /* safety valve, prevents entering */
 18.1012 -    /* playstart twice: */
 18.1013 +	BOOL result;
 18.1014  
 18.1015 -    _mm_critical = 1;
 18.1016 -    if(!isplaying)
 18.1017 -    {   if(md_driver->PlayStart()) return 1;
 18.1018 -        isplaying = 1;
 18.1019 -    }
 18.1020 -    _mm_critical = 0;
 18.1021 -    return 0;
 18.1022 +	MUTEX_LOCK(vars);
 18.1023 +	result=MikMod_EnableOutput_internal();
 18.1024 +	MUTEX_UNLOCK(vars);
 18.1025 +
 18.1026 +	return result;
 18.1027  }
 18.1028  
 18.1029 +void MikMod_DisableOutput_internal(void)
 18.1030 +{
 18.1031 +	if(isplaying && md_driver) {
 18.1032 +		isplaying = 0;
 18.1033 +		md_driver->PlayStop();
 18.1034 +	}
 18.1035 +}
 18.1036  
 18.1037  void MikMod_DisableOutput(void)
 18.1038  {
 18.1039 -    /* safety valve, prevents calling playStop when playstart */
 18.1040 -    /* hasn't been called: */
 18.1041 -
 18.1042 -    if(isplaying && md_driver!=NULL)
 18.1043 -    {   isplaying = 0;
 18.1044 -        md_driver->PlayStop();
 18.1045 -    }
 18.1046 +	MUTEX_LOCK(vars);
 18.1047 +	MikMod_DisableOutput_internal();
 18.1048 +	MUTEX_UNLOCK(vars);
 18.1049  }
 18.1050  
 18.1051 +BOOL MikMod_Active_internal(void)
 18.1052 +{
 18.1053 +	return isplaying;
 18.1054 +}
 18.1055  
 18.1056  BOOL MikMod_Active(void)
 18.1057  {
 18.1058 -    return isplaying;
 18.1059 +	BOOL result;
 18.1060 +
 18.1061 +	MUTEX_LOCK(vars);
 18.1062 +	result=MikMod_Active_internal();
 18.1063 +	MUTEX_UNLOCK(vars);
 18.1064 +
 18.1065 +	return result;
 18.1066 +}
 18.1067 +
 18.1068 +/* Plays a sound effects sample.  Picks a voice from the number of voices
 18.1069 +   allocated for use as sound effects (loops through voices, skipping all active
 18.1070 +   criticals).
 18.1071 +
 18.1072 +   Returns the voice that the sound is being played on.                       */
 18.1073 +SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags)
 18.1074 +{
 18.1075 +	int orig=sfxpool;/* for cases where all channels are critical */
 18.1076 +	int c;
 18.1077 +
 18.1078 +	if(!md_sfxchn) return -1;
 18.1079 +	if(s->volume>64) s->volume = 64;
 18.1080 +
 18.1081 +	/* check the first location after sfxpool */
 18.1082 +	do {
 18.1083 +		if(sfxinfo[sfxpool]&SFX_CRITICAL) {
 18.1084 +			if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) {
 18.1085 +				sfxinfo[sfxpool]=flags;
 18.1086 +				Voice_Play_internal(c,s,start);
 18.1087 +				md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1088 +				Voice_SetPanning_internal(c,s->panning);
 18.1089 +				md_driver->VoiceSetFrequency(c,s->speed);
 18.1090 +				sfxpool++;
 18.1091 +				if(sfxpool>=md_sfxchn) sfxpool=0;
 18.1092 +				return c;
 18.1093 +			}
 18.1094 +		} else {
 18.1095 +			sfxinfo[sfxpool]=flags;
 18.1096 +			Voice_Play_internal(c=sfxpool+md_sngchn,s,start);
 18.1097 +			md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1098 +			Voice_SetPanning_internal(c,s->panning);
 18.1099 +			md_driver->VoiceSetFrequency(c,s->speed);
 18.1100 +			sfxpool++;
 18.1101 +			if(sfxpool>=md_sfxchn) sfxpool=0;
 18.1102 +			return c;
 18.1103 +		}
 18.1104 +
 18.1105 +		sfxpool++;
 18.1106 +		if(sfxpool>=md_sfxchn) sfxpool = 0;
 18.1107 +	} while(sfxpool!=orig);
 18.1108 +
 18.1109 +	return -1;
 18.1110 +}
 18.1111 +
 18.1112 +SBYTE Sample_Play(SAMPLE *s,ULONG start,UBYTE flags)
 18.1113 +{
 18.1114 +	SBYTE result;
 18.1115 +
 18.1116 +	MUTEX_LOCK(vars);
 18.1117 +	result=Sample_Play_internal(s,start,flags);
 18.1118 +	MUTEX_UNLOCK(vars);
 18.1119 +
 18.1120 +	return result;
 18.1121 +}
 18.1122 +
 18.1123 +long MikMod_GetVersion(void)
 18.1124 +{
 18.1125 +	return LIBMIKMOD_VERSION;
 18.1126  }
 18.1127  
 18.1128 -
 18.1129 -int MikMod_PlaySample(SAMPLE *s, ULONG start, UBYTE flags)
 18.1130 +/*========== MT-safe stuff */
 18.1131  
 18.1132 -/* Plays a sound effects sample.  Picks a voice from the number of voices */
 18.1133 -/* allocated for use as sound effects (loops through voices, skipping all */
 18.1134 -/* active criticals). */
 18.1135 -/* */
 18.1136 -/* Returns the voice that the sound is being played on. */
 18.1137 +#ifdef HAVE_PTHREAD
 18.1138 +#define INIT_MUTEX(name) \
 18.1139 +	pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER
 18.1140 +#elif defined(__OS2__)||defined(__EMX__)
 18.1141 +#define INIT_MUTEX(name) \
 18.1142 +	HMTX _mm_mutex_##name
 18.1143 +#elif defined(WIN32)
 18.1144 +#define INIT_MUTEX(name) \
 18.1145 +	HANDLE _mm_mutex_##name
 18.1146 +#else
 18.1147 +#define INIT_MUTEX(name)
 18.1148 +#endif
 18.1149  
 18.1150 +INIT_MUTEX(vars);
 18.1151 +INIT_MUTEX(lists);
 18.1152 +
 18.1153 +BOOL MikMod_InitThreads(void)
 18.1154  {
 18.1155 -    int orig = sfxpool;    /* for cases where all channels are critical */
 18.1156 -    int c;
 18.1157 +	static int firstcall=1;
 18.1158 +	static int result=0;
 18.1159  
 18.1160 -    if(md_sfxchn==0) return -1;
 18.1161 -    if(s->volume > 64) s->volume = 64;
 18.1162 -    
 18.1163 -    /* check the first location after sfxpool */
 18.1164 -    do
 18.1165 -    {   if(sfxinfo[sfxpool] & SFX_CRITICAL)
 18.1166 -        {   if(md_driver->VoiceStopped(c=sfxpool+md_sngchn))
 18.1167 -            {   sfxinfo[sfxpool] = flags;
 18.1168 -                Voice_Play(c, s, start);
 18.1169 -                md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1170 -                md_driver->VoiceSetPanning(c,s->panning);
 18.1171 -                md_driver->VoiceSetFrequency(c,s->speed);
 18.1172 -                sfxpool++;
 18.1173 -                if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1174 -                return c;
 18.1175 -            }
 18.1176 -        } else
 18.1177 -        {   sfxinfo[sfxpool] = flags;
 18.1178 -            Voice_Play(c=sfxpool+md_sngchn, s, start);
 18.1179 -            md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1180 -            md_driver->VoiceSetPanning(c,s->panning);
 18.1181 -            md_driver->VoiceSetFrequency(c,s->speed);
 18.1182 -            sfxpool++;
 18.1183 -            if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1184 -            return c;
 18.1185 -        }
 18.1186 +	if (firstcall) {
 18.1187 +		firstcall=0;
 18.1188 +#ifdef HAVE_PTHREAD
 18.1189 +		result=1;
 18.1190 +#elif defined(__OS2__)||defined(__EMX__)
 18.1191 +		if(DosCreateMutexSem((PSZ)NULL,&_mm_mutex_lists,0,0) ||
 18.1192 +		   DosCreateMutexSem((PSZ)NULL,&_mm_mutex_vars,0,0)) {
 18.1193 +			_mm_mutex_lists=_mm_mutex_vars=(HMTX)NULL;
 18.1194 +			result=0;
 18.1195 +		} else
 18.1196 +			result=1;
 18.1197 +#elif defined(WIN32)
 18.1198 +		if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))||
 18.1199 +		   (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)"))))
 18.1200 +			result=0;
 18.1201 +		else
 18.1202 +			result=1;
 18.1203 +#endif
 18.1204 +	}
 18.1205 +	return result;
 18.1206 +}
 18.1207  
 18.1208 -        sfxpool++;
 18.1209 -        if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1210 -    } while(sfxpool!=orig);
 18.1211 +void MikMod_Unlock(void)
 18.1212 +{
 18.1213 +	MUTEX_UNLOCK(lists);
 18.1214 +	MUTEX_UNLOCK(vars);
 18.1215 +}
 18.1216  
 18.1217 -    return -1;
 18.1218 +void MikMod_Lock(void)
 18.1219 +{
 18.1220 +	MUTEX_LOCK(vars);
 18.1221 +	MUTEX_LOCK(lists);
 18.1222  }
 18.1223  
 18.1224 +/*========== Parameter extraction helper */
 18.1225 +
 18.1226 +CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,BOOL implicit)
 18.1227 +{
 18.1228 +	CHAR *ret=NULL;
 18.1229 +
 18.1230 +	if(cmdline) {
 18.1231 +		CHAR *buf=strstr(cmdline,atomname);
 18.1232 +
 18.1233 +		if((buf)&&((buf==cmdline)||(*(buf-1)==','))) {
 18.1234 +			CHAR *ptr=buf+strlen(atomname);
 18.1235 +
 18.1236 +			if(*ptr=='=') {
 18.1237 +				for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++);
 18.1238 +				ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
 18.1239 +				if(ret)
 18.1240 +					strncpy(ret,buf,ptr-buf);
 18.1241 +			} else if((*ptr==',')||(!*ptr)) {
 18.1242 +				if(implicit) {
 18.1243 +					ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
 18.1244 +					if(ret)
 18.1245 +						strncpy(ret,buf,ptr-buf);
 18.1246 +				}
 18.1247 +			}
 18.1248 +		}
 18.1249 +	}
 18.1250 +	return ret;
 18.1251 +}
 18.1252 +
 18.1253 +#ifdef unix
 18.1254 +
 18.1255 +#include <unistd.h>
 18.1256 +
 18.1257 +/*========== Posix helper functions */
 18.1258 +
 18.1259 +/* Check if the file is a regular or nonexistant file (or a link to a such a
 18.1260 +   file), and that, should the calling program be setuid, the access rights are
 18.1261 +   reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise.
 18.1262 +   The goal is to prevent a setuid root libmikmod application from overriding
 18.1263 +   files like /etc/passwd with digital sound... */
 18.1264 +BOOL MD_Access(CHAR *filename)
 18.1265 +{
 18.1266 +	struct stat buf;
 18.1267 +
 18.1268 +	if(!stat(filename,&buf)) {
 18.1269 +		/* not a regular file ? */
 18.1270 +		if(!S_ISREG(buf.st_mode)) return 0;
 18.1271 +		/* more than one hard link to the file ? */
 18.1272 +		if(buf.st_nlink>1) return 0;
 18.1273 +		/* check access rights with the real user and group id */
 18.1274 +		if(getuid()==buf.st_uid) {
 18.1275 +			if(!(buf.st_mode&S_IWUSR)) return 0;
 18.1276 +		} else if(getgid()==buf.st_gid) {
 18.1277 +			if(!(buf.st_mode&S_IWGRP)) return 0;
 18.1278 +		} else
 18.1279 +			if(!(buf.st_mode&S_IWOTH)) return 0;
 18.1280 +	}
 18.1281 +
 18.1282 +	return 1;
 18.1283 +}
 18.1284 +
 18.1285 +/* Drop all root privileges we might have */
 18.1286 +BOOL MD_DropPrivileges(void)
 18.1287 +{
 18.1288 +	if(!geteuid()) {
 18.1289 +		if(getuid()) {
 18.1290 +			/* we are setuid root -> drop setuid to become the real user */
 18.1291 +			if(setuid(getuid())) return 1;
 18.1292 +		} else {
 18.1293 +			/* we are run as root -> drop all and become user 'nobody' */
 18.1294 +			struct passwd *nobody;
 18.1295 +			int uid;
 18.1296 +
 18.1297 +			if(!(nobody=getpwnam("nobody"))) return 1; /* no such user ? */
 18.1298 +			uid=nobody->pw_uid;
 18.1299 +			if (!uid) /* user 'nobody' has root privileges ? weird... */
 18.1300 +				return 1;
 18.1301 +			if (setuid(uid)) return 1;
 18.1302 +		}
 18.1303 +	}
 18.1304 +	return 0;
 18.1305 +}
 18.1306 +
 18.1307 +#endif
 18.1308 +
 18.1309 +/* ex:set ts=4: */
    19.1 --- a/mikmod/mikmod.h	Mon Dec 27 19:18:10 1999 +0000
    19.2 +++ b/mikmod/mikmod.h	Mon Dec 27 19:24:50 1999 +0000
    19.3 @@ -1,394 +1,699 @@
    19.4 -#ifndef _MIKMOD_H
    19.5 -#define _MIKMOD_H
    19.6 +/*	MikMod sound library
    19.7 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    19.8 +	complete list.
    19.9 +
   19.10 +	This library is free software; you can redistribute it and/or modify
   19.11 +	it under the terms of the GNU Library General Public License as
   19.12 +	published by the Free Software Foundation; either version 2 of
   19.13 +	the License, or (at your option) any later version.
   19.14 +
   19.15 +	This program is distributed in the hope that it will be useful,
   19.16 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.17 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.18 +	GNU Library General Public License for more details.
   19.19  
   19.20 -#include "mmio.h"
   19.21 +	You should have received a copy of the GNU Library General Public
   19.22 +	License along with this library; if not, write to the Free Software
   19.23 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19.24 +	02111-1307, USA.
   19.25 +*/
   19.26 +
   19.27 +/*==============================================================================
   19.28 +
   19.29 +  $Id$
   19.30 +
   19.31 +  MikMod sound library include file
   19.32 +
   19.33 +==============================================================================*/
   19.34 +
   19.35 +#ifndef _MIKMOD_H_
   19.36 +#define _MIKMOD_H_
   19.37 +
   19.38 +#include <stdio.h>
   19.39 +#include <stdlib.h>
   19.40  
   19.41  #ifdef __cplusplus
   19.42  extern "C" {
   19.43  #endif
   19.44  
   19.45 +/*
   19.46 + * ========== Compiler magic for shared libraries
   19.47 + */
   19.48 +
   19.49 +#ifdef WIN32
   19.50 +#ifdef DLL_EXPORTS
   19.51 +#define MIKMODAPI __declspec(dllexport)
   19.52 +#else
   19.53 +#define MIKMODAPI __declspec(dllimport)
   19.54 +#endif
   19.55 +#else
   19.56 +#define MIKMODAPI
   19.57 +#endif
   19.58 +
   19.59 +/*
   19.60 + *	========== Library version
   19.61 + */
   19.62 +
   19.63 +#define LIBMIKMOD_VERSION_MAJOR 3
   19.64 +#define LIBMIKMOD_VERSION_MINOR 1
   19.65 +#define LIBMIKMOD_REVISION      8
   19.66 +
   19.67 +#define LIBMIKMOD_VERSION \
   19.68 +	((LIBMIKMOD_VERSION_MAJOR<<16)| \
   19.69 +	 (LIBMIKMOD_VERSION_MINOR<< 8)| \
   19.70 +	 (LIBMIKMOD_REVISION))
   19.71 +
   19.72 +MIKMODAPI extern long MikMod_GetVersion(void);
   19.73 +
   19.74 +/*
   19.75 + *	========== Platform independent-type definitions
   19.76 + */
   19.77 +
   19.78 +#ifdef WIN32
   19.79 +#define WIN32_LEAN_AND_MEAN
   19.80 +#include <windows.h>
   19.81 +#include <io.h>
   19.82 +#endif
   19.83 +
   19.84 +#if defined(__OS2__)||defined(__EMX__)
   19.85 +#define INCL_DOSSEMAPHORES
   19.86 +#include <os2.h>
   19.87 +#else
   19.88 +typedef char CHAR;
   19.89 +#endif
   19.90 +
   19.91 +/*@DOES_NOT_HAVE_SIGNED@*/
   19.92 +
   19.93 +#if defined(__alpha)
   19.94 +/* 64 bit architectures */
   19.95 +
   19.96 +typedef signed char     SBYTE;      /* 1 byte, signed */
   19.97 +typedef unsigned char   UBYTE;      /* 1 byte, unsigned */
   19.98 +typedef signed short    SWORD;      /* 2 bytes, signed */
   19.99 +typedef unsigned short  UWORD;      /* 2 bytes, unsigned */
  19.100 +typedef signed int      SLONG;      /* 4 bytes, signed */
  19.101 +typedef unsigned int    ULONG;      /* 4 bytes, unsigned */
  19.102 +typedef int             BOOL;       /* 0=false, <>0 true */
  19.103 +
  19.104 +#else
  19.105 +/* 32 bit architectures */
  19.106 +
  19.107 +typedef signed char     SBYTE;      /* 1 byte, signed */
  19.108 +typedef unsigned char   UBYTE;      /* 1 byte, unsigned */
  19.109 +typedef signed short    SWORD;      /* 2 bytes, signed */
  19.110 +typedef unsigned short  UWORD;      /* 2 bytes, unsigned */
  19.111 +typedef signed long     SLONG;      /* 4 bytes, signed */
  19.112 +#if !defined(__OS2__)&&!defined(__EMX__)&&!defined(WIN32)
  19.113 +typedef unsigned long   ULONG;      /* 4 bytes, unsigned */
  19.114 +typedef int             BOOL;       /* 0=false, <>0 true */
  19.115 +#endif
  19.116 +#endif
  19.117 +
  19.118 +/*
  19.119 + *	========== Error codes
  19.120 + */
  19.121 +
  19.122 +enum {
  19.123 +	MMERR_OPENING_FILE = 1,
  19.124 +	MMERR_OUT_OF_MEMORY,
  19.125 +	MMERR_DYNAMIC_LINKING,
  19.126 +
  19.127 +	MMERR_SAMPLE_TOO_BIG,
  19.128 +	MMERR_OUT_OF_HANDLES,
  19.129 +	MMERR_UNKNOWN_WAVE_TYPE,
  19.130 +
  19.131 +	MMERR_LOADING_PATTERN,
  19.132 +	MMERR_LOADING_TRACK,
  19.133 +	MMERR_LOADING_HEADER,
  19.134 +	MMERR_LOADING_SAMPLEINFO,
  19.135 +	MMERR_NOT_A_MODULE,
  19.136 +	MMERR_NOT_A_STREAM,
  19.137 +	MMERR_MED_SYNTHSAMPLES,
  19.138 +	MMERR_ITPACK_INVALID_DATA,
  19.139 +
  19.140 +	MMERR_DETECTING_DEVICE,
  19.141 +	MMERR_INVALID_DEVICE,
  19.142 +	MMERR_INITIALIZING_MIXER,
  19.143 +	MMERR_OPENING_AUDIO,
  19.144 +	MMERR_8BIT_ONLY,
  19.145 +	MMERR_16BIT_ONLY,
  19.146 +	MMERR_STEREO_ONLY,
  19.147 +	MMERR_ULAW,
  19.148 +	MMERR_NON_BLOCK,
  19.149 +
  19.150 +	MMERR_AF_AUDIO_PORT,
  19.151 +
  19.152 +	MMERR_AIX_CONFIG_INIT,
  19.153 +	MMERR_AIX_CONFIG_CONTROL,
  19.154 +	MMERR_AIX_CONFIG_START,
  19.155 +
  19.156 +	MMERR_GUS_SETTINGS,
  19.157 +	MMERR_GUS_RESET,
  19.158 +	MMERR_GUS_TIMER,
  19.159 +
  19.160 +	MMERR_HP_SETSAMPLESIZE,
  19.161 +	MMERR_HP_SETSPEED,
  19.162 +	MMERR_HP_CHANNELS,
  19.163 +	MMERR_HP_AUDIO_OUTPUT,
  19.164 +	MMERR_HP_AUDIO_DESC,
  19.165 +	MMERR_HP_BUFFERSIZE,
  19.166 +
  19.167 +	MMERR_OSS_SETFRAGMENT,
  19.168 +	MMERR_OSS_SETSAMPLESIZE,
  19.169 +	MMERR_OSS_SETSTEREO,
  19.170 +	MMERR_OSS_SETSPEED,
  19.171 +
  19.172 +	MMERR_SGI_SPEED,
  19.173 +	MMERR_SGI_16BIT,
  19.174 +	MMERR_SGI_8BIT,
  19.175 +	MMERR_SGI_STEREO,
  19.176 +	MMERR_SGI_MONO,
  19.177 +
  19.178 +	MMERR_SUN_INIT,
  19.179 +
  19.180 +	MMERR_OS2_MIXSETUP,
  19.181 +	MMERR_OS2_SEMAPHORE,
  19.182 +	MMERR_OS2_TIMER,
  19.183 +	MMERR_OS2_THREAD,
  19.184 +
  19.185 +	MMERR_DS_PRIORITY,
  19.186 +	MMERR_DS_BUFFER,
  19.187 +	MMERR_DS_FORMAT,
  19.188 +	MMERR_DS_NOTIFY,
  19.189 +	MMERR_DS_EVENT,
  19.190 +	MMERR_DS_THREAD,
  19.191 +	MMERR_DS_UPDATE,
  19.192 +
  19.193 +	MMERR_WINMM_HANDLE,
  19.194 +	MMERR_WINMM_ALLOCATED,
  19.195 +	MMERR_WINMM_DEVICEID,
  19.196 +	MMERR_WINMM_FORMAT,
  19.197 +	MMERR_WINMM_UNKNOWN,
  19.198 +
  19.199 +	MMERR_MAC_SPEED,
  19.200 +	MMERR_MAC_START,
  19.201 +
  19.202 +	MMERR_MAX
  19.203 +};
  19.204 +
  19.205 +/*
  19.206 + *	========== Error handling
  19.207 + */
  19.208 +
  19.209 +typedef void (MikMod_handler)(void);
  19.210 +typedef MikMod_handler *MikMod_handler_t;
  19.211 +
  19.212 +MIKMODAPI extern int  MikMod_errno;
  19.213 +MIKMODAPI extern BOOL MikMod_critical;
  19.214 +MIKMODAPI extern char *MikMod_strerror(int);
  19.215 +
  19.216 +MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t);
  19.217 +
  19.218 +/*
  19.219 + *	========== Library initialization and core functions
  19.220 + */
  19.221 +
  19.222 +struct MDRIVER;
  19.223 +
  19.224 +MIKMODAPI extern void   MikMod_RegisterAllDrivers(void);
  19.225 +
  19.226 +MIKMODAPI extern CHAR*  MikMod_InfoDriver(void);
  19.227 +MIKMODAPI extern void   MikMod_RegisterDriver(struct MDRIVER*);
  19.228 +MIKMODAPI extern int    MikMod_DriverFromAlias(CHAR*);
  19.229 +
  19.230 +MIKMODAPI extern BOOL   MikMod_Init(CHAR*);
  19.231 +MIKMODAPI extern void   MikMod_Exit(void);
  19.232 +MIKMODAPI extern BOOL   MikMod_Reset(CHAR*);
  19.233 +MIKMODAPI extern BOOL   MikMod_SetNumVoices(int,int);
  19.234 +MIKMODAPI extern BOOL   MikMod_Active(void);
  19.235 +MIKMODAPI extern BOOL   MikMod_EnableOutput(void);
  19.236 +MIKMODAPI extern void   MikMod_DisableOutput(void);
  19.237 +MIKMODAPI extern void   MikMod_Update(void);
  19.238 +
  19.239 +MIKMODAPI extern BOOL   MikMod_InitThreads(void);
  19.240 +MIKMODAPI extern void   MikMod_Lock(void);
  19.241 +MIKMODAPI extern void   MikMod_Unlock(void);
  19.242 +
  19.243 +/*
  19.244 + *	========== Reader, Writer
  19.245 + */
  19.246 +
  19.247 +typedef struct MREADER {
  19.248 +	BOOL (*Seek)(struct MREADER*,long,int);
  19.249 +	long (*Tell)(struct MREADER*);
  19.250 +	BOOL (*Read)(struct MREADER*,void*,size_t);
  19.251 +	int  (*Get)(struct MREADER*);
  19.252 +	BOOL (*Eof)(struct MREADER*);
  19.253 +} MREADER;
  19.254 +
  19.255 +typedef struct MWRITER {
  19.256 +	BOOL (*Seek)(struct MWRITER*,long,int);
  19.257 +	long (*Tell)(struct MWRITER*);
  19.258 +	BOOL (*Write)(struct MWRITER*,void*,size_t);
  19.259 +	BOOL (*Put)(struct MWRITER*,int);
  19.260 +} MWRITER;
  19.261 +
  19.262 +/*
  19.263 + *	========== Samples
  19.264 + */
  19.265 +
  19.266 +/* Sample playback should not be interrupted */
  19.267 +#define SFX_CRITICAL 1
  19.268 +
  19.269 +/* Sample format [loading and in-memory] flags: */
  19.270 +#define SF_16BITS       0x0001
  19.271 +#define SF_STEREO       0x0002
  19.272 +#define SF_SIGNED       0x0004
  19.273 +#define SF_BIG_ENDIAN   0x0008
  19.274 +#define SF_DELTA        0x0010
  19.275 +#define SF_ITPACKED		0x0020
  19.276 +
  19.277 +#define	SF_FORMATMASK	0x003F
  19.278 +
  19.279 +/* General Playback flags */
  19.280 +
  19.281 +#define SF_LOOP         0x0100
  19.282 +#define SF_BIDI         0x0200
  19.283 +#define SF_REVERSE      0x0400
  19.284 +#define SF_SUSTAIN      0x0800
  19.285 +
  19.286 +#define SF_PLAYBACKMASK	0x0C00
  19.287 +
  19.288 +/* Module-only Playback Flags */
  19.289 +
  19.290 +#define SF_OWNPAN		0x1000
  19.291 +#define SF_UST_LOOP     0x2000
  19.292 +
  19.293 +#define SF_EXTRAPLAYBACKMASK	0x3000
  19.294 +
  19.295 +/* Panning constants */
  19.296 +#define PAN_LEFT       0
  19.297 +#define PAN_CENTER   128
  19.298 +#define PAN_RIGHT    255
  19.299 +#define PAN_SURROUND 512 /* panning value for Dolby Surround */
  19.300 +
  19.301 +typedef struct SAMPLE {
  19.302 +	SWORD  panning;     /* panning (0-255 or PAN_SURROUND) */
  19.303 +	ULONG  speed;       /* Base playing speed/frequency of note */
  19.304 +	UBYTE  volume;      /* volume 0-64 */
  19.305 +	UWORD  inflags;		/* sample format on disk */
  19.306 +	UWORD  flags;       /* sample format in memory */
  19.307 +	ULONG  length;      /* length of sample (in samples!) */
  19.308 +	ULONG  loopstart;   /* repeat position (relative to start, in samples) */
  19.309 +	ULONG  loopend;     /* repeat end */
  19.310 +	ULONG  susbegin;    /* sustain loop begin (in samples) \  Not Supported */
  19.311 +	ULONG  susend;      /* sustain loop end                /      Yet! */
  19.312 +
  19.313 +	/* Variables used by the module player only! (ignored for sound effects) */
  19.314 +	UBYTE  globvol;     /* global volume */
  19.315 +	UBYTE  vibflags;    /* autovibrato flag stuffs */
  19.316 +	UBYTE  vibtype;     /* Vibratos moved from INSTRUMENT to SAMPLE */
  19.317 +	UBYTE  vibsweep;
  19.318 +	UBYTE  vibdepth;
  19.319 +	UBYTE  vibrate;
  19.320 +	CHAR*  samplename;  /* name of the sample */
  19.321 +
  19.322 +	/* Values used internally only */
  19.323 +	UWORD  avibpos;     /* autovibrato pos [player use] */
  19.324 +	UBYTE  divfactor;   /* for sample scaling, maintains proper period slides */
  19.325 +	ULONG  seekpos;     /* seek position in file */
  19.326 +	SWORD  handle;      /* sample handle used by individual drivers */
  19.327 +} SAMPLE;
  19.328 +
  19.329 +/* Sample functions */
  19.330 +
  19.331 +MIKMODAPI extern SAMPLE *Sample_Load(CHAR*);
  19.332 +MIKMODAPI extern SAMPLE *Sample_LoadFP(FILE*);
  19.333 +MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*);
  19.334 +MIKMODAPI extern void   Sample_Free(SAMPLE*);
  19.335 +MIKMODAPI extern SBYTE  Sample_Play(SAMPLE*,ULONG,UBYTE);
  19.336 +
  19.337 +MIKMODAPI extern void   Voice_SetVolume(SBYTE,UWORD);
  19.338 +MIKMODAPI extern UWORD  Voice_GetVolume(SBYTE);
  19.339 +MIKMODAPI extern void   Voice_SetFrequency(SBYTE,ULONG);
  19.340 +MIKMODAPI extern ULONG  Voice_GetFrequency(SBYTE);
  19.341 +MIKMODAPI extern void   Voice_SetPanning(SBYTE,ULONG);
  19.342 +MIKMODAPI extern ULONG  Voice_GetPanning(SBYTE);
  19.343 +MIKMODAPI extern void   Voice_Play(SBYTE,SAMPLE*,ULONG);
  19.344 +MIKMODAPI extern void   Voice_Stop(SBYTE);
  19.345 +MIKMODAPI extern BOOL   Voice_Stopped(SBYTE);
  19.346 +MIKMODAPI extern SLONG  Voice_GetPosition(SBYTE);
  19.347 +MIKMODAPI extern ULONG  Voice_RealVolume(SBYTE);
  19.348 +
  19.349 +/*
  19.350 + *	========== Internal module representation (UniMod)
  19.351 + */
  19.352 +
  19.353 +/*
  19.354 +	Instrument definition - for information only, the only field which may be
  19.355 +	of use in user programs is the name field
  19.356 +*/
  19.357 +
  19.358 +/* Instrument note count */
  19.359 +#define INSTNOTES 120
  19.360 +
  19.361 +/* Envelope point */
  19.362 +typedef struct ENVPT {
  19.363 +	SWORD pos;
  19.364 +	SWORD val;
  19.365 +} ENVPT;
  19.366 +
  19.367 +/* Envelope point count */
  19.368 +#define ENVPOINTS 32
  19.369 +
  19.370 +/* Instrument structure */
  19.371 +typedef struct INSTRUMENT {
  19.372 +	CHAR* insname;
  19.373 +
  19.374 +	UBYTE flags;
  19.375 +	UWORD samplenumber[INSTNOTES];
  19.376 +	UBYTE samplenote[INSTNOTES];
  19.377 +
  19.378 +	UBYTE nnatype;
  19.379 +	UBYTE dca;              /* duplicate check action */
  19.380 +	UBYTE dct;              /* duplicate check type */
  19.381 +	UBYTE globvol;
  19.382 +	UWORD volfade;
  19.383 +	SWORD panning;          /* instrument-based panning var */
  19.384 +
  19.385 +	UBYTE pitpansep;        /* pitch pan separation (0 to 255) */
  19.386 +	UBYTE pitpancenter;     /* pitch pan center (0 to 119) */
  19.387 +	UBYTE rvolvar;          /* random volume varations (0 - 100%) */
  19.388 +	UBYTE rpanvar;          /* random panning varations (0 - 100%) */
  19.389 +
  19.390 +	/* volume envelope */
  19.391 +	UBYTE volflg;           /* bit 0: on 1: sustain 2: loop */
  19.392 +	UBYTE volpts;
  19.393 +	UBYTE volsusbeg;
  19.394 +	UBYTE volsusend;
  19.395 +	UBYTE volbeg;
  19.396 +	UBYTE volend;
  19.397 +	ENVPT volenv[ENVPOINTS];
  19.398 +	/* panning envelope */
  19.399 +	UBYTE panflg;           /* bit 0: on 1: sustain 2: loop */
  19.400 +	UBYTE panpts;
  19.401 +	UBYTE pansusbeg;
  19.402 +	UBYTE pansusend;
  19.403 +	UBYTE panbeg;
  19.404 +	UBYTE panend;
  19.405 +	ENVPT panenv[ENVPOINTS];
  19.406 +	/* pitch envelope */
  19.407 +	UBYTE pitflg;           /* bit 0: on 1: sustain 2: loop */
  19.408 +	UBYTE pitpts;
  19.409 +	UBYTE pitsusbeg;
  19.410 +	UBYTE pitsusend;
  19.411 +	UBYTE pitbeg;
  19.412 +	UBYTE pitend;
  19.413 +	ENVPT pitenv[ENVPOINTS];
  19.414 +} INSTRUMENT;
  19.415 +
  19.416 +struct MP_CONTROL;
  19.417 +struct MP_VOICE;
  19.418 +
  19.419 +/* Module flags */
  19.420 +#define UF_XMPERIODS 0x0001 /* XM periods / finetuning */
  19.421 +#define UF_LINEAR    0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */
  19.422 +#define UF_INST      0x0004 /* Instruments are used */
  19.423 +#define UF_NNA       0x0008 /* IT: NNA used, set numvoices rather than numchn */
  19.424 +#define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */
  19.425 +#define UF_BGSLIDES  0x0020 /* continue volume slides in the background */
  19.426 +#define UF_HIGHBPM   0x0040 /* MED: can use >255 bpm */
  19.427 +#define UF_NOWRAP    0x0080 /* XM-type (i.e. illogical) pattern brk semantics */
  19.428 +#define UF_ARPMEM    0x0100 /* IT: need arpeggio memory */
  19.429 +#define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */
  19.430 +
  19.431 +typedef struct MODULE {
  19.432 +	/* general module information */
  19.433 +		CHAR*       songname;    /* name of the song */
  19.434 +		CHAR*       modtype;     /* string type of module loaded */
  19.435 +		CHAR*       comment;     /* module comments */
  19.436 +
  19.437 +		UWORD       flags;       /* See module flags above */
  19.438 +		UBYTE       numchn;      /* number of module channels */
  19.439 +		UBYTE       numvoices;   /* max # voices used for full NNA playback */
  19.440 +		UWORD       numpos;      /* number of positions in this song */
  19.441 +		UWORD       numpat;      /* number of patterns in this song */
  19.442 +		UWORD       numins;      /* number of instruments */
  19.443 +		UWORD       numsmp;      /* number of samples */
  19.444 +struct  INSTRUMENT* instruments; /* all instruments */
  19.445 +struct  SAMPLE*     samples;     /* all samples */
  19.446 +		UBYTE       realchn;     /* real number of channels used */
  19.447 +		UBYTE       totalchn;    /* total number of channels used (incl NNAs) */
  19.448 +
  19.449 +	/* playback settings */
  19.450 +		UWORD       reppos;      /* restart position */
  19.451 +		UBYTE       initspeed;   /* initial song speed */
  19.452 +		UWORD       inittempo;   /* initial song tempo */
  19.453 +		UBYTE       initvolume;  /* initial global volume (0 - 128) */
  19.454 +		UWORD       panning[64]; /* 64 panning positions */
  19.455 +		UBYTE       chanvol[64]; /* 64 channel positions */
  19.456 +		UWORD       bpm;         /* current beats-per-minute speed */
  19.457 +		UWORD       sngspd;      /* current song speed */
  19.458 +		SWORD       volume;      /* song volume (0-128) (or user volume) */
  19.459 +
  19.460 +		BOOL        extspd;      /* extended speed flag (default enabled) */
  19.461 +		BOOL        panflag;     /* panning flag (default enabled) */
  19.462 +		BOOL        wrap;        /* wrap module ? (default disabled) */
  19.463 +		BOOL        loop;		 /* allow module to loop ? (default enabled) */
  19.464 +		BOOL        fadeout;	 /* volume fade out during last pattern */
  19.465 +
  19.466 +		UWORD       patpos;      /* current row number */
  19.467 +		SWORD       sngpos;      /* current song position */
  19.468 +		ULONG       sngtime;     /* current song time in 2^-10 seconds */
  19.469 +
  19.470 +		SWORD       relspd;      /* relative speed factor */
  19.471 +
  19.472 +	/* internal module representation */
  19.473 +		UWORD       numtrk;      /* number of tracks */
  19.474 +		UBYTE**     tracks;      /* array of numtrk pointers to tracks */
  19.475 +		UWORD*      patterns;    /* array of Patterns */
  19.476 +		UWORD*      pattrows;    /* array of number of rows for each pattern */
  19.477 +		UWORD*      positions;   /* all positions */
  19.478 +
  19.479 +		BOOL        forbid;      /* if true, no player update! */
  19.480 +		UWORD       numrow;      /* number of rows on current pattern */
  19.481 +		UWORD       vbtick;      /* tick counter (counts from 0 to sngspd) */
  19.482 +		UWORD       sngremainder;/* used for song time computation */
  19.483 +
  19.484 +struct MP_CONTROL*  control;     /* Effects Channel info (size pf->numchn) */
  19.485 +struct MP_VOICE*    voice;       /* Audio Voice information (size md_numchn) */
  19.486 +
  19.487 +		UBYTE       globalslide; /* global volume slide rate */
  19.488 +		UBYTE       pat_repcrazy;/* module has just looped to position -1 */
  19.489 +		UWORD       patbrk;      /* position where to start a new pattern */
  19.490 +		UBYTE       patdly;      /* patterndelay counter (command memory) */
  19.491 +		UBYTE       patdly2;     /* patterndelay counter (real one) */
  19.492 +		SWORD       posjmp;      /* flag to indicate a jump is needed... */
  19.493 +} MODULE;
  19.494 +
  19.495 +/*
  19.496 + *	========== Module loaders
  19.497 + */
  19.498 +
  19.499 +struct MLOADER;
  19.500 +
  19.501 +MIKMODAPI extern CHAR*   MikMod_InfoLoader(void);
  19.502 +MIKMODAPI extern void    MikMod_RegisterAllLoaders(void);
  19.503 +MIKMODAPI extern void    MikMod_RegisterLoader(struct MLOADER*);
  19.504 +
  19.505 +MIKMODAPI extern struct MLOADER load_669; /* 669 and Extended-669 (by Tran/Renaissance) */
  19.506 +MIKMODAPI extern struct MLOADER load_amf; /* DMP Advanced Module Format (by Otto Chrons) */
  19.507 +MIKMODAPI extern struct MLOADER load_dsm; /* DSIK internal module format */
  19.508 +MIKMODAPI extern struct MLOADER load_far; /* Farandole Composer (by Daniel Potter) */
  19.509 +MIKMODAPI extern struct MLOADER load_gdm; /* General DigiMusic (by Edward Schlunder) */
  19.510 +MIKMODAPI extern struct MLOADER load_it;  /* Impulse Tracker (by Jeffrey Lim) */
  19.511 +MIKMODAPI extern struct MLOADER load_imf; /* Imago Orpheus (by Lutz Roeder) */
  19.512 +MIKMODAPI extern struct MLOADER load_med; /* Amiga MED modules (by Teijo Kinnunen) */
  19.513 +MIKMODAPI extern struct MLOADER load_m15; /* Soundtracker 15-instrument */
  19.514 +MIKMODAPI extern struct MLOADER load_mod; /* Standard 31-instrument Module loader */
  19.515 +MIKMODAPI extern struct MLOADER load_mtm; /* Multi-Tracker Module (by Renaissance) */
  19.516 +MIKMODAPI extern struct MLOADER load_stm; /* ScreamTracker 2 (by Future Crew) */
  19.517 +MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */
  19.518 +MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */
  19.519 +MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker  (by MAS) */
  19.520 +MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */
  19.521 +MIKMODAPI extern struct MLOADER load_xm;  /* FastTracker 2 (by Triton) */
  19.522 +
  19.523 +/*
  19.524 + *	========== Module player
  19.525 + */
  19.526 +
  19.527 +MIKMODAPI extern MODULE* Player_Load(CHAR*,int,BOOL);
  19.528 +MIKMODAPI extern MODULE* Player_LoadFP(FILE*,int,BOOL);
  19.529 +MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,BOOL);
  19.530 +MIKMODAPI extern CHAR*   Player_LoadTitle(CHAR*);
  19.531 +MIKMODAPI extern void    Player_Free(MODULE*);
  19.532 +MIKMODAPI extern void    Player_Start(MODULE*);
  19.533 +MIKMODAPI extern BOOL    Player_Active(void);
  19.534 +MIKMODAPI extern void    Player_Stop(void);
  19.535 +MIKMODAPI extern void    Player_TogglePause(void);
  19.536 +MIKMODAPI extern BOOL    Player_Paused(void);
  19.537 +MIKMODAPI extern void    Player_NextPosition(void);
  19.538 +MIKMODAPI extern void    Player_PrevPosition(void);
  19.539 +MIKMODAPI extern void    Player_SetPosition(UWORD);
  19.540 +MIKMODAPI extern BOOL    Player_Muted(UBYTE);
  19.541 +MIKMODAPI extern void    Player_SetVolume(SWORD);
  19.542 +MIKMODAPI extern MODULE* Player_GetModule(void);
  19.543 +MIKMODAPI extern void    Player_SetSpeed(UWORD);
  19.544 +MIKMODAPI extern void    Player_SetTempo(UWORD);
  19.545 +MIKMODAPI extern void    Player_Unmute(SLONG,...);
  19.546 +MIKMODAPI extern void    Player_Mute(SLONG,...);
  19.547 +MIKMODAPI extern void    Player_ToggleMute(SLONG,...);
  19.548 +MIKMODAPI extern int     Player_GetChannelVoice(UBYTE);
  19.549 +MIKMODAPI extern UWORD   Player_GetChannelPeriod(UBYTE);
  19.550 +
  19.551 +typedef void (MikMod_player)(void);
  19.552 +typedef MikMod_player *MikMod_player_t;
  19.553 +
  19.554 +MIKMODAPI extern MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t);
  19.555  
  19.556  #define MUTE_EXCLUSIVE  32000
  19.557  #define MUTE_INCLUSIVE  32001
  19.558  
  19.559 -#define PAN_LEFT           0
  19.560 -#define PAN_CENTER       128
  19.561 -#define PAN_RIGHT        255
  19.562 -#define PAN_SURROUND     512         /* panning value for Dolby Surround */
  19.563 -
  19.564 -
  19.565 -#define MikMod_RegisterDriver(x) MD_RegisterDriver(&x)
  19.566 -#define MikMod_RegisterLoader(x) ML_RegisterLoader(&x)
  19.567 -#define MikMod_RegisterErrorHandler(x) _mm_RegisterErrorHandler(x)
  19.568 -
  19.569 -
  19.570 -/* The following #define macros are for retaining API compatiability */
  19.571 -/* with the beta version of MikMod 3.0, and are TEMPORARY!  They WILL */
  19.572 -/* be removed in the future! */
  19.573 -
  19.574 -#define MD_RegisterPlayer(x)      MikMod_RegisterPlayer(x)
  19.575 -#define MD_Init                   MikMod_Init
  19.576 -#define MD_Exit                   MikMod_Exit
  19.577 -#define MD_Update                 MikMod_Update
  19.578 -#define ML_Free(x)                MikMod_FreeSong(x)
  19.579 -#define MD_SetNumChannels(x,y)    MikMod_SetNumVoices(x,y)
  19.580 -#define MD_SetNumVoices(x,y)      MikMod_SetNumVoices(x,y)
  19.581 -#define MD_PlayStart              MikMod_EnableOutput
  19.582 -#define MD_PlayStop               MikMod_DisableOutput
  19.583 -
  19.584 -#define MD_VoiceSetVolume(x,y)    Voice_SetVolume(x,y)
  19.585 -#define MD_VoiceSetFrequency(x,y) Voice_SetFrequency(x,y)
  19.586 -#define MD_VoiceSetPanning(x,y)   Voice_SetPanning(x,y)
  19.587 -#define MD_VoicePlay(x,y,z)       Voice_Play(x,y,z)
  19.588 -#define MD_VoiceStop(x)           Voice_Stop(x)
  19.589 -#define MD_VoiceReleaseSustain(x) Voice_ReleaseSustain(x)
  19.590 -#define MD_VoiceStopped(x)        Voice_Stopped(x)
  19.591 -#define MD_VoiceGetPosition(x)    Voice_GetPosition(x)
  19.592 -#define MD_VoiceRealVolume(x)     Voice_RealVolume(x)
  19.593 -
  19.594 -
  19.595 -#define SFX_CRITICAL  1
  19.596 -
  19.597 -
  19.598 -/**************************************************************************
  19.599 -****** mikmod types: ******************************************************
  19.600 -**************************************************************************/
  19.601 -
  19.602 -/* Sample format [loading and in-memory] flags: */
  19.603 -#define SF_16BITS       1
  19.604 -#define SF_SIGNED       2
  19.605 -#define SF_STEREO       4
  19.606 -#define SF_DELTA        8
  19.607 -#define SF_BIG_ENDIAN   16
  19.608 -
  19.609 -/* General Playback flags */
  19.610 -
  19.611 -#define SF_LOOP         32
  19.612 -#define SF_BIDI         64
  19.613 -#define SF_SUSTAIN      128
  19.614 -#define SF_REVERSE      256
  19.615 -
  19.616 -/* Module-only Playback Flags */
  19.617 -
  19.618 -#define SF_OWNPAN       512
  19.619 -#define SF_UST_LOOP     1024
  19.620 -
  19.621 -
  19.622 -typedef struct SAMPLE
  19.623 -{   ULONG  speed;            /* Base playing speed/frequency of note (Middle C in player) */
  19.624 -    UBYTE  volume;           /* volume 0-64 */
  19.625 -    UWORD  panning;          /* panning (0-255 or PAN_SURROUND) */
  19.626 -    ULONG  length;           /* length of sample (in samples!) */
  19.627 -    ULONG  loopstart;        /* repeat position (relative to start, in samples) */
  19.628 -    ULONG  loopend;          /* repeat end */
  19.629 -    ULONG  susbegin;         /* sustain loop begin (in samples) \  Not Supported */
  19.630 -    ULONG  susend;           /* sustain loop end                /      Yet! */
  19.631 -
  19.632 -    UWORD  flags;            /* sample format in memory */
  19.633 +/*
  19.634 + *	========== Drivers
  19.635 + */
  19.636  
  19.637 -/* Variables used by the module player only! (ignored for sound effects) */
  19.638 -
  19.639 -    UBYTE  globvol;          /* global volume */
  19.640 -    UBYTE  vibflags;         /* autovibrato flag stuffs */
  19.641 -    UBYTE  vibtype;          /* Vibratos moved from INSTRUMENT to SAMPLE */
  19.642 -    UBYTE  vibsweep;
  19.643 -    UBYTE  vibdepth;
  19.644 -    UBYTE  vibrate;
  19.645 -
  19.646 -    CHAR   *samplename;      /* name of the sample */
  19.647 -
  19.648 -/* Values used internally only (not saved in disk formats) */
  19.649 -
  19.650 -    UWORD  avibpos;          /* autovibrato pos [player use] */
  19.651 -    UBYTE  divfactor;        /* for sample scaling (maintains proper period slides) */
  19.652 -    ULONG  seekpos;          /* seek position in file */
  19.653 -    SWORD  handle;           /* sample handle used by individual drivers */
  19.654 -} SAMPLE;
  19.655 -
  19.656 -
  19.657 -
  19.658 -/* --> Struct : SAMPLOAD */
  19.659 -/* This is a handle of sorts attached to any sample registered with */
  19.660 -/* SL_RegisterSample.  Generally, this only need be used or changed by the */
  19.661 -/* loaders and drivers of mikmod. */
  19.662 -
  19.663 -typedef struct SAMPLOAD
  19.664 -{   struct SAMPLOAD *next;
  19.665 -
  19.666 -    ULONG  length;           /* length of sample (in samples!) */
  19.667 -    ULONG  loopstart;        /* repeat position (relative to start, in samples) */
  19.668 -    ULONG  loopend;          /* repeat end */
  19.669 -
  19.670 -    UWORD   infmt, outfmt;
  19.671 -    int     scalefactor;
  19.672 -    SAMPLE  *sample;
  19.673 -    FILE    *fp;
  19.674 -} SAMPLOAD;
  19.675 -
  19.676 -extern void SL_HalveSample(SAMPLOAD *s);
  19.677 -extern void SL_Sample8to16(SAMPLOAD *s);
  19.678 -extern void SL_Sample16to8(SAMPLOAD *s);
  19.679 -extern void SL_SampleSigned(SAMPLOAD *s);
  19.680 -extern void SL_SampleUnsigned(SAMPLOAD *s);
  19.681 -extern BOOL SL_LoadSamples(void);                      /* Returns 1 on error! */
  19.682 -extern SAMPLOAD *SL_RegisterSample(SAMPLE *s, int type, FILE *fp);    /* Returns 1 on error! */
  19.683 -extern void SL_Load(void *buffer, SAMPLOAD *smp, int length);
  19.684 -extern BOOL SL_Init(SAMPLOAD *s);
  19.685 -extern void SL_Exit(SAMPLOAD *s);
  19.686 -
  19.687 -
  19.688 -/**************************************************************************
  19.689 -****** Wavload stuff: *****************************************************
  19.690 -**************************************************************************/
  19.691 -
  19.692 -SAMPLE *WAV_LoadFP(FILE *fp);
  19.693 -SAMPLE *WAV_LoadFN(CHAR *filename);
  19.694 -void WAV_Free(SAMPLE *si);
  19.695 -
  19.696 -
  19.697 -#include "ptform.h"
  19.698 -
  19.699 -
  19.700 -/**************************************************************************
  19.701 -****** Driver stuff: ******************************************************
  19.702 -**************************************************************************/
  19.703 -
  19.704 -/* max. number of handles a driver has to provide. (not strict) */
  19.705 -
  19.706 -#define MAXSAMPLEHANDLES 384
  19.707 -
  19.708 -
  19.709 -enum
  19.710 -{   MD_MUSIC = 0,
  19.711 -    MD_SNDFX
  19.712 +enum {
  19.713 +	MD_MUSIC = 0,
  19.714 +	MD_SNDFX
  19.715  };
  19.716  
  19.717 -enum
  19.718 -{   MD_HARDWARE = 0,
  19.719 -    MD_SOFTWARE
  19.720 +enum {
  19.721 +	MD_HARDWARE = 0,
  19.722 +	MD_SOFTWARE
  19.723  };
  19.724  
  19.725 -
  19.726 -/* possible mixing mode bits: */
  19.727 -/* -------------------------- */
  19.728 -/* These take effect only after MikMod_Init or MikMod_Reset. */
  19.729 -
  19.730 -#define DMODE_16BITS       1         /* enable 16 bit output */
  19.731 -#define DMODE_SURROUND     2         /* enable Dolby surround sound (not yet supported) */
  19.732 -#define DMODE_SOFT_SNDFX   4         /* Process sound effects via software mixer (not yet supported) */
  19.733 -#define DMODE_SOFT_MUSIC   8         /* Process music via software mixer (not yet supported) */
  19.734 -
  19.735 -/* These take effect immidiately. */
  19.736 +/* Mixing flags */
  19.737  
  19.738 -#define DMODE_STEREO      16         /* enable stereo output */
  19.739 -#define DMODE_REVERSE     32         /* reverse stereo */
  19.740 -#define DMODE_INTERP      64         /* enable interpolation (not yet supported) */
  19.741 -
  19.742 -
  19.743 -/* driver structure: */
  19.744 +/* These ones take effect only after MikMod_Init or MikMod_Reset */
  19.745 +#define DMODE_16BITS     0x0001 /* enable 16 bit output */
  19.746 +#define DMODE_STEREO     0x0002 /* enable stereo output */
  19.747 +#define DMODE_SOFT_SNDFX 0x0004 /* Process sound effects via software mixer */
  19.748 +#define DMODE_SOFT_MUSIC 0x0008 /* Process music via software mixer */
  19.749 +#define DMODE_HQMIXER    0x0010 /* Use high-quality (slower) software mixer */
  19.750 +/* These take effect immediately. */
  19.751 +#define DMODE_SURROUND   0x0100 /* enable surround sound */
  19.752 +#define DMODE_INTERP     0x0200 /* enable interpolation */
  19.753 +#define DMODE_REVERSE    0x0400 /* reverse stereo */
  19.754  
  19.755 -typedef struct MDRIVER
  19.756 -{   struct MDRIVER *next;
  19.757 -    CHAR    *Name;
  19.758 -    CHAR    *Version;
  19.759 -    UBYTE   HardVoiceLimit,       /* Limit of hardware mixer voices for this driver */
  19.760 -            SoftVoiceLimit;       /* Limit of software mixer voices for this driver */
  19.761 +struct SAMPLOAD;
  19.762 +typedef struct MDRIVER {
  19.763 +struct MDRIVER* next;
  19.764 +	CHAR*       Name;
  19.765 +	CHAR*       Version;
  19.766 +
  19.767 +	UBYTE       HardVoiceLimit; /* Limit of hardware mixer voices */
  19.768 +	UBYTE       SoftVoiceLimit; /* Limit of software mixer voices */
  19.769 +
  19.770 +	CHAR*       Alias;
  19.771  
  19.772 -    BOOL    (*IsPresent)          (void);
  19.773 -    SWORD   (*SampleLoad)         (SAMPLOAD *s, int type);
  19.774 -    void    (*SampleUnLoad)       (SWORD handle);
  19.775 -    ULONG   (*FreeSampleSpace)    (int type);
  19.776 -    ULONG   (*RealSampleLength)   (int type, SAMPLE *s);
  19.777 -    BOOL    (*Init)               (void);
  19.778 -    void    (*Exit)               (void);
  19.779 -    BOOL    (*Reset)              (void);
  19.780 -    BOOL    (*SetNumVoices)       (void);
  19.781 -    BOOL    (*PlayStart)          (void);
  19.782 -    void    (*PlayStop)           (void);
  19.783 -    void    (*Update)             (void);
  19.784 -    void    (*VoiceSetVolume)     (UBYTE voice, UWORD vol);
  19.785 -    void    (*VoiceSetFrequency)  (UBYTE voice, ULONG frq);
  19.786 -    void    (*VoiceSetPanning)    (UBYTE voice, ULONG pan);
  19.787 -    void    (*VoicePlay)          (UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags);
  19.788 -    void    (*VoiceStop)          (UBYTE voice);
  19.789 -    BOOL    (*VoiceStopped)       (UBYTE voice);
  19.790 -    void    (*VoiceReleaseSustain)(UBYTE voice);
  19.791 -    SLONG   (*VoiceGetPosition)   (UBYTE voice);
  19.792 -    ULONG   (*VoiceRealVolume)    (UBYTE voice);
  19.793 -
  19.794 -    BOOL    (*StreamInit)         (ULONG speed, UWORD flags);
  19.795 -    void    (*StreamExit)         (void);
  19.796 -    void    (*StreamSetSpeed)     (ULONG speed);
  19.797 -    SLONG   (*StreamGetPosition)  (void);
  19.798 -    void    (*StreamLoadFP)       (FILE *fp);
  19.799 +	void        (*CommandLine)      (CHAR*);
  19.800 +	BOOL        (*IsPresent)        (void);
  19.801 +	SWORD       (*SampleLoad)       (struct SAMPLOAD*,int);
  19.802 +	void        (*SampleUnload)     (SWORD);
  19.803 +	ULONG       (*FreeSampleSpace)  (int);
  19.804 +	ULONG       (*RealSampleLength) (int,struct SAMPLE*);
  19.805 +	BOOL        (*Init)             (void);
  19.806 +	void        (*Exit)             (void);
  19.807 +	BOOL        (*Reset)            (void);
  19.808 +	BOOL        (*SetNumVoices)     (void);
  19.809 +	BOOL        (*PlayStart)        (void);
  19.810 +	void        (*PlayStop)         (void);
  19.811 +	void        (*Update)           (void);
  19.812 +	void		(*Pause)			(void);
  19.813 +	void        (*VoiceSetVolume)   (UBYTE,UWORD);
  19.814 +	UWORD       (*VoiceGetVolume)   (UBYTE);
  19.815 +	void        (*VoiceSetFrequency)(UBYTE,ULONG);
  19.816 +	ULONG       (*VoiceGetFrequency)(UBYTE);
  19.817 +	void        (*VoiceSetPanning)  (UBYTE,ULONG);
  19.818 +	ULONG       (*VoiceGetPanning)  (UBYTE);
  19.819 +	void        (*VoicePlay)        (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
  19.820 +	void        (*VoiceStop)        (UBYTE);
  19.821 +	BOOL        (*VoiceStopped)     (UBYTE);
  19.822 +	SLONG       (*VoiceGetPosition) (UBYTE);
  19.823 +	ULONG       (*VoiceRealVolume)  (UBYTE);
  19.824  } MDRIVER;
  19.825  
  19.826 -
  19.827 -/* These variables can be changed at ANY time and results */
  19.828 -/* will be immidiate: */
  19.829 -
  19.830 -extern UBYTE md_bpm;            /* current song / hardware BPM rate */
  19.831 -extern UBYTE md_volume;         /* Global sound volume (0-128) */
  19.832 -extern UBYTE md_musicvolume;    /* volume of song */
  19.833 -extern UBYTE md_sndfxvolume;    /* volume of sound effects */
  19.834 -extern UBYTE md_reverb;         /* 0 = none;  15 = chaos */
  19.835 -extern UBYTE md_pansep;         /* 0 = mono;  128 == 100% (full left/right) */
  19.836 -
  19.837 -
  19.838 -/* The variables below can be changed at any time, but changes will */
  19.839 -/* not be implimented until MikMod_Reset is called.  A call to */
  19.840 -/* MikMod_Reset may result in a skip or pop in audio (depending on */
  19.841 -/* the soundcard driver and the settings changed). */
  19.842 +/* These variables can be changed at ANY time and results will be immediate */
  19.843 +MIKMODAPI extern UBYTE md_volume;      /* global sound volume (0-128) */
  19.844 +MIKMODAPI extern UBYTE md_musicvolume; /* volume of song */
  19.845 +MIKMODAPI extern UBYTE md_sndfxvolume; /* volume of sound effects */
  19.846 +MIKMODAPI extern UBYTE md_reverb;      /* 0 = none;  15 = chaos */
  19.847 +MIKMODAPI extern UBYTE md_pansep;      /* 0 = mono;  128 == 100% (full left/right) */
  19.848  
  19.849 -extern UWORD md_device;         /* Device.  0 = autodetect, other # depend on driver register order. */
  19.850 -extern UWORD md_mixfreq;        /* mixing frequency.  Valid 5000 -> 44100 */
  19.851 -extern UWORD md_dmabufsize;     /* DMA buffer size.  Valid 512 -> 32000 */
  19.852 -extern UWORD md_mode;           /* Mode.  See DMODE_? flags above */
  19.853 -
  19.854 -
  19.855 -/* Variables below can be changed via MD_SetNumVoices at any time. */
  19.856 -/*  However, a call to MD_SetNumVoicess while the driver */
  19.857 -/* is active will cause the sound to skip slightly. */
  19.858 +/* The variables below can be changed at any time, but changes will not be
  19.859 +   implemented until MikMod_Reset is called. A call to MikMod_Reset may result
  19.860 +   in a skip or pop in audio (depending on the soundcard driver and the settings
  19.861 +   changed). */
  19.862 +MIKMODAPI extern UWORD md_device;      /* device */
  19.863 +MIKMODAPI extern UWORD md_mixfreq;     /* mixing frequency */
  19.864 +MIKMODAPI extern UWORD md_mode;        /* mode. See DMODE_? flags above */
  19.865  
  19.866 -extern UBYTE md_numchn,         /* number of song + sound effects voices */
  19.867 -             md_sngchn,         /* number of song voices */
  19.868 -             md_sfxchn,         /* number of sound effects voices */
  19.869 -             md_hardchn,        /* number of hardware mixed voices */
  19.870 -             md_softchn;        /* number of software mixed voices */
  19.871 -
  19.872 -
  19.873 -/* Following variables should not be changed! */
  19.874 -extern MDRIVER *md_driver;      /* Current driver in use.  See MDRIVER struct */
  19.875 -                                /* above for structure info contents. */
  19.876 +/* The following variable should not be changed! */
  19.877 +MIKMODAPI extern MDRIVER* md_driver;   /* Current driver in use. */
  19.878  
  19.879 -/* This is for use by the hardware drivers only.  It points to the */
  19.880 -/* registered tickhandler function. */
  19.881 -extern void (*md_player)(void);
  19.882 -
  19.883 -
  19.884 -/* main driver prototypes: */
  19.885 -
  19.886 -extern void   MikMod_RegisterAllDrivers(void);
  19.887 -extern void   MikMod_RegisterAllLoaders(void);
  19.888 +/* Known drivers list */
  19.889  
  19.890 -extern BOOL   MikMod_Init(void);
  19.891 -extern void   MikMod_Exit(void);
  19.892 -extern BOOL   MikMod_Reset(void);
  19.893 -extern int    MikMod_PlaySample(SAMPLE *s, ULONG start, UBYTE flags);
  19.894 -extern BOOL   MikMod_SetNumVoices(int music, int sndfx);
  19.895 -extern BOOL   MikMod_Active(void);
  19.896 -extern BOOL   MikMod_EnableOutput(void);
  19.897 -extern void   MikMod_DisableOutput(void);
  19.898 -extern void   MikMod_RegisterPlayer(void (*plr)(void));
  19.899 -extern void   MikMod_Update(void);
  19.900 +MIKMODAPI extern struct MDRIVER drv_nos;    /* no sound */
  19.901 +MIKMODAPI extern struct MDRIVER drv_pipe;   /* piped output */
  19.902 +MIKMODAPI extern struct MDRIVER drv_raw;    /* raw file disk writer [music.raw] */
  19.903 +MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */
  19.904 +MIKMODAPI extern struct MDRIVER drv_wav;    /* RIFF WAVE file disk writer [music.wav] */
  19.905  
  19.906 -extern void   Voice_SetVolume(int voice, UWORD ivol);
  19.907 -extern void   Voice_SetFrequency(int voice, ULONG frq);
  19.908 -extern void   Voice_SetPanning(int voice, ULONG pan);
  19.909 -extern void   Voice_Play(int voice,SAMPLE *s, ULONG start);
  19.910 -extern void   Voice_Stop(int voice);
  19.911 -extern void   Voice_ReleaseSustain(int voice);
  19.912 -extern BOOL   Voice_Stopped(int voice);
  19.913 -extern SLONG  Voice_GetPosition(int voice);
  19.914 -extern ULONG  Voice_RealVolume(int voice);
  19.915 +MIKMODAPI extern struct MDRIVER drv_ultra;  /* Linux Ultrasound driver */
  19.916  
  19.917 -extern void   MD_InfoDriver(void);
  19.918 -extern void   MD_RegisterDriver(MDRIVER *drv);
  19.919 -extern SWORD  MD_SampleLoad(SAMPLOAD *s, int type, FILE *fp);
  19.920 -extern void   MD_SampleUnLoad(SWORD handle);
  19.921 -extern void   MD_SetBPM(UBYTE bpm);
  19.922 -extern ULONG  MD_SampleSpace(int type);
  19.923 -extern ULONG  MD_SampleLength(int type, SAMPLE *s);
  19.924 -
  19.925 -/* Declare external drivers: */
  19.926 -
  19.927 -extern MDRIVER drv_sdl;      /* Simple DirectMedia Layer driver */
  19.928 -extern MDRIVER drv_nos;      /* nosound driver */
  19.929 +MIKMODAPI extern struct MDRIVER drv_AF;     /* Dec Alpha AudioFile */
  19.930 +MIKMODAPI extern struct MDRIVER drv_aix;    /* AIX audio device */
  19.931 +MIKMODAPI extern struct MDRIVER drv_alsa;   /* Advanced Linux Sound Architecture (ALSA) */
  19.932 +MIKMODAPI extern struct MDRIVER drv_esd;    /* Enlightened sound daemon (EsounD) */
  19.933 +MIKMODAPI extern struct MDRIVER drv_hp;     /* HP-UX audio device */
  19.934 +MIKMODAPI extern struct MDRIVER drv_oss;    /* OpenSound System (Linux,FreeBSD...) */
  19.935 +MIKMODAPI extern struct MDRIVER drv_sgi;    /* SGI audio library */
  19.936 +MIKMODAPI extern struct MDRIVER drv_sun;    /* Sun/NetBSD/OpenBSD audio device */
  19.937  
  19.938 -
  19.939 -/**************************************************************************
  19.940 -****** Streaming Audio stuff: *********************************************
  19.941 -**************************************************************************/
  19.942 -
  19.943 +MIKMODAPI extern struct MDRIVER drv_dart;   /* OS/2 Direct Audio RealTime */
  19.944 +MIKMODAPI extern struct MDRIVER drv_os2;    /* OS/2 MMPM/2 */
  19.945  
  19.946 -typedef struct MSTREAM
  19.947 -{   struct MSTREAM *next;
  19.948 -    CHAR    *type;
  19.949 -    CHAR    *version;
  19.950 -    BOOL    (*Init)(void);
  19.951 -    BOOL    (*Test)(void);
  19.952 -    BOOL    (*Load)(void);
  19.953 -    void    (*Cleanup)(void);
  19.954 -} MSTREAM;
  19.955 +MIKMODAPI extern struct MDRIVER drv_ds;     /* Win32 DirectSound driver */
  19.956 +MIKMODAPI extern struct MDRIVER drv_win;    /* Win32 multimedia API driver */
  19.957  
  19.958 +MIKMODAPI extern struct MDRIVER drv_mac;    /* Macintosh Sound Manager driver */
  19.959  
  19.960 -extern int   stream_bufsize;
  19.961 -extern FILE  *stream_fp;
  19.962 -extern SLONG stream_seekpos;
  19.963 -extern SLONG stream_reppos;
  19.964 -
  19.965 -
  19.966 -/**************************************************************************
  19.967 -****** Virtual channel stuff: *********************************************
  19.968 -**************************************************************************/
  19.969 +/*========== Virtual channel mixer interface (for user-supplied drivers only) */
  19.970  
  19.971 -extern BOOL    VC_Init(void);