FXJ - Updated the mikmod support to MikMod 3.1.8
authorSam Lantinga <slouken@lokigames.com>
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 +	return 1;
   11.65  }
   11.66  
   11.67 -
   11.68 -static SWORD NS_SampleLoad(SAMPLOAD *s, int type)
   11.69 -{
   11.70 -    return 0;
   11.71 -}
   11.72 -
   11.73 -
   11.74 -static void NS_SampleUnload(SWORD h)
   11.75 -{
   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 +	VC_Exit();
  11.102 +	_mm_free(zerobuf);
  11.103  }
  11.104  
  11.105 -
  11.106 -static BOOL NS_Reset(void)
  11.107 -{
  11.108 -    return 0;
  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 +	if (zerobuf)
  11.126 +		VC_WriteBytes(zerobuf,ZEROLEN);
  11.127  }
  11.128  
  11.129 +MDRIVER drv_nos={
  11.130 +	NULL,
  11.131 +	"No Sound",
  11.132 +	"Nosound Driver v3.0",
  11.133 +	255,255,
  11.134 +	"nosound",
  11.135  
  11.136 -static BOOL NS_SetNumVoices(void)
  11.137 -{
  11.138 -    return 0;
  11.139 -}
  11.140 -
  11.141 -
  11.142 -static void NS_VoiceSetVolume(UBYTE voice,UWORD vol)
  11.143 -{
  11.144 -}
  11.145 -
  11.146 -
  11.147 -static void NS_VoiceSetFrequency(UBYTE voice,ULONG frq)
  11.148 -{
  11.149 -}
  11.150 -
  11.151 -
  11.152 -static void NS_VoiceSetPanning(UBYTE voice,ULONG pan)
  11.153 -{
  11.154 -}
  11.155 -
  11.156 -
  11.157 -static void NS_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
  11.158 -{
  11.159 -}
  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 -
  11.172 -
  11.173 -static void NS_VoiceReleaseSustain(UBYTE voice)
  11.174 -{
  11.175 -}
  11.176 -
  11.177 -
  11.178 -static SLONG NS_VoiceGetPosition(UBYTE voice)
  11.179 -{
  11.180 -   return 0;
  11.181 -}
  11.182 -
  11.183 -
  11.184 -static ULONG NS_VoiceRealVolume(UBYTE voice)
  11.185 -{
  11.186 -   return 0;
  11.187 -}
  11.188 -
  11.189 -
  11.190 -
  11.191 -MDRIVER drv_nos =
  11.192 -{   NULL,
  11.193 -    "No Sound",
  11.194 -    "Nosound Driver v2.0 - (c) Creative Silence",
  11.195 -    255,255,
  11.196 -    NS_IsThere,
  11.197 -    NS_SampleLoad,
  11.198 -    NS_SampleUnload,
  11.199 -    NS_SampleSpace,
  11.200 -    NS_SampleLength,
  11.201 -    NS_Init,
  11.202 -    NS_Exit,
  11.203 -    NS_Reset,
  11.204 -    NS_SetNumVoices,
  11.205 -    NS_PlayStart,
  11.206 -    NS_PlayStop,
  11.207 -    NS_Update,
  11.208 -    NS_VoiceSetVolume,
  11.209 -    NS_VoiceSetFrequency,
  11.210 -    NS_VoiceSetPanning,
  11.211 -    NS_VoicePlay,
  11.212 -    NS_VoiceStop,
  11.213 -    NS_VoiceStopped,
  11.214 -    NS_VoiceReleaseSustain,
  11.215 -    NS_VoiceGetPosition,
  11.216 -    NS_VoiceRealVolume
  11.217 +	NULL,
  11.218 +	NS_IsThere,
  11.219 +	VC_SampleLoad,
  11.220 +	VC_SampleUnload,
  11.221 +	VC_SampleSpace,
  11.222 +	VC_SampleLength,
  11.223 +	NS_Init,
  11.224 +	NS_Exit,
  11.225 +	NULL,
  11.226 +	VC_SetNumVoices,
  11.227 +	VC_PlayStart,
  11.228 +	VC_PlayStop,
  11.229 +	NS_Update,
  11.230 +	NULL,
  11.231 +	VC_VoiceSetVolume,
  11.232 +	VC_VoiceGetVolume,
  11.233 +	VC_VoiceSetFrequency,
  11.234 +	VC_VoiceGetFrequency,
  11.235 +	VC_VoiceSetPanning,
  11.236 +	VC_VoiceGetPanning,
  11.237 +	VC_VoicePlay,
  11.238 +	VC_VoiceStop,
  11.239 +	VC_VoiceStopped,
  11.240 +	VC_VoiceGetPosition,
  11.241 +	VC_VoiceRealVolume
  11.242  };
  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 +	This library is free software; you can redistribute it and/or modify
   13.11 +	it under the terms of the GNU Library General Public License as
   13.12 +	published by the Free Software Foundation; either version 2 of
   13.13 +	the License, or (at your option) any later version.
   13.14  
   13.15 - Description:
   13.16 - ImpulseTracker (IT) module loader
   13.17 +	This program is distributed in the hope that it will be useful,
   13.18 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.19 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.20 +	GNU Library General Public License for more details.
   13.21  
   13.22 - Portability:
   13.23 - All systems - all compilers (hopefully)
   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 +/*==============================================================================
   13.37 +
   13.38 +  $Id$
   13.39 +
   13.40 +  Impulse tracker (IT) module loader
   13.41 +
   13.42 +==============================================================================*/
   13.43 +
   13.44 +#ifdef HAVE_CONFIG_H
   13.45 +#include "config.h"
   13.46 +#endif
   13.47 +
   13.48 +#include <ctype.h>
   13.49  #include <string.h>
   13.50 -#include "mikmod.h"
   13.51  
   13.52 -/**************************************************************************
   13.53 -**************************************************************************/
   13.54 +#include "mikmod_internals.h"
   13.55  
   13.56 -typedef struct ITNOTE
   13.57 -{   UBYTE note,ins,volpan,cmd,inf;
   13.58 +/*========== Module structure */
   13.59 +
   13.60 +/* header */
   13.61 +typedef struct ITHEADER {
   13.62 +	CHAR	songname[26];
   13.63 +	UBYTE	blank01[2];
   13.64 +	UWORD	ordnum;
   13.65 +	UWORD	insnum;
   13.66 +	UWORD	smpnum;
   13.67 +	UWORD	patnum;
   13.68 +	UWORD	cwt;		/* Created with tracker (y.xx = 0x0yxx) */
   13.69 +	UWORD	cmwt;		/* Compatible with tracker ver > than val. */
   13.70 +	UWORD	flags;
   13.71 +	UWORD	special;	/* bit 0 set = song message attached */
   13.72 +	UBYTE	globvol;
   13.73 +	UBYTE	mixvol;		/* mixing volume [ignored] */
   13.74 +	UBYTE	initspeed;
   13.75 +	UBYTE	inittempo;
   13.76 +	UBYTE	pansep;		/* panning separation between channels */
   13.77 +	UBYTE	zerobyte;
   13.78 +	UWORD	msglength;
   13.79 +	ULONG	msgoffset;
   13.80 +	UBYTE	blank02[4];
   13.81 +	UBYTE	pantable[64];
   13.82 +	UBYTE	voltable[64];
   13.83 +} ITHEADER;
   13.84 +
   13.85 +/* sample information */
   13.86 +typedef struct ITSAMPLE {
   13.87 +	CHAR	filename[12];
   13.88 +	UBYTE	zerobyte;
   13.89 +	UBYTE	globvol;
   13.90 +	UBYTE	flag;
   13.91 +	UBYTE	volume;
   13.92 +	UBYTE	panning;
   13.93 +	CHAR	sampname[28];
   13.94 +	UWORD	convert;	/* sample conversion flag */
   13.95 +	ULONG	length;
   13.96 +	ULONG	loopbeg;
   13.97 +	ULONG	loopend;
   13.98 +	ULONG	c5spd;
   13.99 +	ULONG	susbegin;
  13.100 +	ULONG	susend;
  13.101 +	ULONG	sampoffset;
  13.102 +	UBYTE	vibspeed;
  13.103 +	UBYTE	vibdepth;
  13.104 +	UBYTE	vibrate;
  13.105 +	UBYTE	vibwave;	/* 0=sine, 1=rampdown, 2=square, 3=random (speed ignored) */
  13.106 +} ITSAMPLE;
  13.107 +
  13.108 +/* instrument information */
  13.109 +
  13.110 +#define ITENVCNT 25
  13.111 +#define ITNOTECNT 120
  13.112 +typedef struct ITINSTHEADER {
  13.113 +	ULONG	size;			/* (dword) Instrument size */
  13.114 +	CHAR	filename[12];	/* (char) Instrument filename */
  13.115 +	UBYTE	zerobyte;		/* (byte) Instrument type (always 0) */
  13.116 +	UBYTE	volflg;
  13.117 +	UBYTE	volpts;
  13.118 +	UBYTE	volbeg;			/* (byte) Volume loop start (node) */
  13.119 +	UBYTE	volend;			/* (byte) Volume loop end (node) */
  13.120 +	UBYTE	volsusbeg;		/* (byte) Volume sustain begin (node) */
  13.121 +	UBYTE	volsusend;		/* (byte) Volume Sustain end (node) */
  13.122 +	UBYTE	panflg;
  13.123 +	UBYTE	panpts;
  13.124 +	UBYTE	panbeg;			/* (byte) channel loop start (node) */
  13.125 +	UBYTE	panend;			/* (byte) channel loop end (node) */
  13.126 +	UBYTE	pansusbeg;		/* (byte) channel sustain begin (node) */
  13.127 +	UBYTE	pansusend;		/* (byte) channel Sustain end (node) */
  13.128 +	UBYTE	pitflg;
  13.129 +	UBYTE	pitpts;
  13.130 +	UBYTE	pitbeg;			/* (byte) pitch loop start (node) */
  13.131 +	UBYTE	pitend;			/* (byte) pitch loop end (node) */
  13.132 +	UBYTE	pitsusbeg;		/* (byte) pitch sustain begin (node) */
  13.133 +	UBYTE	pitsusend;		/* (byte) pitch Sustain end (node) */
  13.134 +	UWORD	blank;
  13.135 +	UBYTE	globvol;
  13.136 +	UBYTE	chanpan;
  13.137 +	UWORD	fadeout;		/* Envelope end / NNA volume fadeout */
  13.138 +	UBYTE	dnc;			/* Duplicate note check */
  13.139 +	UBYTE	dca;			/* Duplicate check action */
  13.140 +	UBYTE	dct;			/* Duplicate check type */
  13.141 +	UBYTE	nna;			/* New Note Action [0,1,2,3] */
  13.142 +	UWORD	trkvers;		/* tracker version used to save [files only] */
  13.143 +	UBYTE	ppsep;			/* Pitch-pan Separation */
  13.144 +	UBYTE	ppcenter;		/* Pitch-pan Center */
  13.145 +	UBYTE	rvolvar;		/* random volume varations */
  13.146 +	UBYTE	rpanvar;		/* random panning varations */
  13.147 +	UWORD	numsmp;			/* Number of samples in instrument [files only] */
  13.148 +	CHAR	name[26];		/* Instrument name */
  13.149 +	UBYTE	blank01[6];
  13.150 +	UWORD	samptable[ITNOTECNT];/* sample for each note [note / samp pairs] */
  13.151 +	UBYTE	volenv[200];	     /* volume envelope (IT 1.x stuff) */
  13.152 +	UBYTE	oldvoltick[ITENVCNT];/* volume tick position (IT 1.x stuff) */
  13.153 +	UBYTE	volnode[ITENVCNT];   /* amplitude of volume nodes */
  13.154 +	UWORD	voltick[ITENVCNT];   /* tick value of volume nodes */
  13.155 +	SBYTE	pannode[ITENVCNT];   /* panenv - node points */
  13.156 +	UWORD	pantick[ITENVCNT];   /* tick value of panning nodes */
  13.157 +	SBYTE	pitnode[ITENVCNT];   /* pitchenv - node points */
  13.158 +	UWORD	pittick[ITENVCNT];   /* tick value of pitch nodes */
  13.159 +} ITINSTHEADER;
  13.160 +
  13.161 +/* unpacked note */
  13.162 +
  13.163 +typedef struct ITNOTE {
  13.164 +	UBYTE note,ins,volpan,cmd,inf;
  13.165  } ITNOTE;
  13.166  
  13.167 -UBYTE *IT_ConvertTrack(ITNOTE *tr,UWORD numrows);
  13.168 +/*========== Loader data */
  13.169  
  13.170 +static ULONG *paraptr=NULL;	/* parapointer array (see IT docs) */
  13.171 +static ITHEADER *mh=NULL;
  13.172 +static ITNOTE *itpat=NULL;	/* allocate to space for one full pattern */
  13.173 +static UBYTE *mask=NULL;	/* arrays allocated to 64 elements and used for */
  13.174 +static ITNOTE *last=NULL;	/* uncompressing IT's pattern information */
  13.175 +static int numtrk=0;
  13.176 +static int old_effect;		/* if set, use S3M old-effects stuffs */
  13.177  
  13.178 -/* Raw IT header struct: */
  13.179 +static CHAR* IT_Version[]={
  13.180 +	"ImpulseTracker  .  ",
  13.181 +	"Compressed ImpulseTracker  .  ",
  13.182 +	"ImpulseTracker 2.14p3",
  13.183 +	"Compressed ImpulseTracker 2.14p3",
  13.184 +	"ImpulseTracker 2.14p4",
  13.185 +	"Compressed ImpulseTracker 2.14p4",
  13.186 +};
  13.187  
  13.188 -typedef struct ITHEADER
  13.189 -{   CHAR  songname[26];
  13.190 -    UBYTE blank01[2];
  13.191 -    UWORD ordnum;
  13.192 -    UWORD insnum;
  13.193 -    UWORD smpnum;
  13.194 -    UWORD patnum;
  13.195 -    UWORD cwt;          /* Created with tracker (y.xx = 0x0yxx) */
  13.196 -    UWORD cmwt;         /* Compatable with tracker ver > than val. */
  13.197 -    UWORD flags;
  13.198 -    UWORD special;      /* bit 0 set = song message attached */
  13.199 -    UBYTE globvol;
  13.200 -    UBYTE mixvol;       /* mixing volume [ignored] */
  13.201 -    UBYTE initspeed;
  13.202 -    UBYTE inittempo;
  13.203 -    UBYTE pansep;       /* panning separation between channels */
  13.204 -    UBYTE zerobyte;       
  13.205 -    UWORD msglength;
  13.206 -    ULONG msgoffset;
  13.207 -    UBYTE blank02[4];
  13.208 - 
  13.209 -    UBYTE pantable[64];
  13.210 -    UBYTE voltable[64];
  13.211 -} ITHEADER;
  13.212 +/* table for porta-to-note command within volume/panning column */
  13.213 +static UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255};
  13.214  
  13.215 -
  13.216 -/* Raw IT sampleinfo struct: */
  13.217 -
  13.218 -typedef struct ITSAMPLE
  13.219 -{   CHAR  filename[12];
  13.220 -    UBYTE zerobyte;
  13.221 -    UBYTE globvol;
  13.222 -    UBYTE flag;
  13.223 -    UBYTE volume;
  13.224 -    UBYTE panning;
  13.225 -    CHAR  sampname[28];
  13.226 -    UWORD convert;        /* sample conversion flag */
  13.227 -    ULONG length;
  13.228 -    ULONG loopbeg;
  13.229 -    ULONG loopend;
  13.230 -    ULONG c5spd;
  13.231 -    ULONG susbegin;
  13.232 -    ULONG susend;
  13.233 -    ULONG sampoffset;
  13.234 -    UBYTE vibspeed;
  13.235 -    UBYTE vibdepth;
  13.236 -    UBYTE vibrate;
  13.237 -    UBYTE vibwave;    /* 0 = sine; 1 = rampdown; 2 = square; 3 = random (speed ignored) */
  13.238 -
  13.239 -    UBYTE noteindex;  /* for converting c5spd to finetune */
  13.240 -} ITSAMPLE;
  13.241 -
  13.242 -
  13.243 -typedef struct ITINSTHEADER
  13.244 -{   ULONG size;             /* (dword) Instrument size */
  13.245 -    CHAR  filename[12];     /* (char) Instrument filename */
  13.246 -    UBYTE zerobyte;         /* (byte) Instrument type (always 0) */
  13.247 -    UBYTE volflg;
  13.248 -    UBYTE volpts;   
  13.249 -    UBYTE volbeg;           /* (byte) Volume loop start (node) */
  13.250 -    UBYTE volend;           /* (byte) Volume loop end (node) */
  13.251 -    UBYTE volsusbeg;        /* (byte) Volume sustain begin (node) */
  13.252 -    UBYTE volsusend;        /* (byte) Volume Sustain end (node) */
  13.253 -    UBYTE panflg;
  13.254 -    UBYTE panpts;  
  13.255 -    UBYTE panbeg;           /* (byte) channel loop start (node) */
  13.256 -    UBYTE panend;           /* (byte) channel loop end (node) */
  13.257 -    UBYTE pansusbeg;        /* (byte) cahnnel sustain begin (node) */
  13.258 -    UBYTE pansusend;        /* (byte) channel Sustain end (node) */
  13.259 -    UBYTE pitflg;
  13.260 -    UBYTE pitpts;   
  13.261 -    UBYTE pitbeg;           /* (byte) pitch loop start (node) */
  13.262 -    UBYTE pitend;           /* (byte) pitch loop end (node) */
  13.263 -    UBYTE pitsusbeg;        /* (byte) pitch sustain begin (node) */
  13.264 -    UBYTE pitsusend;        /* (byte) pitch Sustain end (node) */
  13.265 -    UWORD blank;
  13.266 -    UBYTE globvol;
  13.267 -    UBYTE chanpan;
  13.268 -    UWORD fadeout;          /* Envelope end / NNA volume fadeout */
  13.269 -    UBYTE dnc;              /* Duplicate note check */
  13.270 -    UBYTE dca;              /* Duplicate check action */
  13.271 -    UBYTE dct;              /* Duplicate check type */
  13.272 -    UBYTE nna;              /* New Note Action [0,1,2,3] */
  13.273 -    UWORD trkvers;          /* tracker version used to save [in files only] */
  13.274 -    UBYTE ppsep;            /* Pitch-pan Separation */
  13.275 -    UBYTE ppcenter;         /* Pitch-pan Center */
  13.276 -    UBYTE rvolvar;          /* random volume varations */
  13.277 -    UBYTE rpanvar;          /* random panning varations */
  13.278 -    UWORD numsmp;           /* Number of samples in instrument [in files only] */
  13.279 -    CHAR  name[26];         /* Instrument name */
  13.280 -    UBYTE blank01[6];
  13.281 -    UWORD samptable[120];   /* sample for each note [note / samp pairs] */
  13.282 -
  13.283 -    UBYTE volenv[200];      /* volume envelope (IT 1.x stuff) */
  13.284 -    UBYTE oldvoltick[25];   /* volume tick position (IT 1.x stuff) */
  13.285 -    UBYTE volnode[25];      /* aplitude of volume nodes */
  13.286 -    UWORD voltick[25];      /* tick value of volume nodes */
  13.287 -    SBYTE pannode[25];      /* panenv - node points */
  13.288 -    UWORD pantick[25];      /* tick value of panning nodes */
  13.289 -    SBYTE pitnode[25];      /* pitchenv - node points */
  13.290 -    UWORD pittick[25];      /* tick value of pitch nodes */
  13.291 -} ITINSTHEADER;                       
  13.292 -
  13.293 -
  13.294 -/**************************************************************************
  13.295 -**************************************************************************/
  13.296 -
  13.297 -extern SBYTE    remap[64];        /* for removing empty channels */
  13.298 -extern UBYTE    *poslookup;       /* S3M/IT fix - removing blank patterns needs a */
  13.299 -                                  /* lookup table to fix position-jump commands */
  13.300 -static ULONG    *paraptr = NULL;  /* parapointer array (see IT docs) */
  13.301 -static ITHEADER *mh = NULL;
  13.302 -static ITNOTE   *itpat = NULL;    /* allocate to space for one full pattern */
  13.303 -static UBYTE    *mask = NULL;     /* arrays allocated to 64 elements and used for */
  13.304 -static ITNOTE   *last = NULL;     /* uncompressing IT's pattern information */
  13.305 -static int       numtrk = 0;
  13.306 -static int       old_effect;      /* if set, use S3M old-effects stuffs */
  13.307 -static int       *noteindex;
  13.308 -   
  13.309 -CHAR IT_Version[] = "ImpulseTracker x.xx";
  13.310 -
  13.311 +/*========== Loader code */
  13.312  
  13.313  BOOL IT_Test(void)
  13.314  {
  13.315 -    UBYTE id[4];
  13.316 -    
  13.317 -    if(!_mm_read_UBYTES(id,4,modfp)) return 0;
  13.318 -    if(!memcmp(id,"IMPM",4)) return 1;
  13.319 -    return 0;
  13.320 +	UBYTE id[4];
  13.321 +
  13.322 +	if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  13.323 +	if(!memcmp(id,"IMPM",4)) return 1;
  13.324 +	return 0;
  13.325  }
  13.326  
  13.327  BOOL IT_Init(void)
  13.328  {
  13.329 -    if((mh=(ITHEADER *)_mm_calloc(1,sizeof(ITHEADER)))==NULL) return 0;
  13.330 -    if((poslookup=(UBYTE *)_mm_malloc(256*sizeof(UBYTE)))==NULL) return 0;
  13.331 -    if((itpat=(ITNOTE *)_mm_malloc(200*64*sizeof(ITNOTE)))==NULL) return 0;
  13.332 -    if((mask=(UBYTE *)_mm_malloc(64*sizeof(UBYTE)))==NULL) return 0;
  13.333 -    if((last=(ITNOTE *)_mm_malloc(64*sizeof(ITNOTE)))==NULL) return 0;
  13.334 -    
  13.335 -    return 1;
  13.336 +	if(!(mh=(ITHEADER*)_mm_malloc(sizeof(ITHEADER)))) return 0;
  13.337 +	if(!(poslookup=(UBYTE*)_mm_malloc(256*sizeof(UBYTE)))) return 0;
  13.338 +	if(!(itpat=(ITNOTE*)_mm_malloc(200*64*sizeof(ITNOTE)))) return 0;
  13.339 +	if(!(mask=(UBYTE*)_mm_malloc(64*sizeof(UBYTE)))) return 0;
  13.340 +	if(!(last=(ITNOTE*)_mm_malloc(64*sizeof(ITNOTE)))) return 0;
  13.341 +
  13.342 +	return 1;
  13.343  }
  13.344  
  13.345  void IT_Cleanup(void)
  13.346  {
  13.347 -    if(mh!=NULL) free(mh);
  13.348 -    if(poslookup!=NULL) free(poslookup);
  13.349 -    if(itpat!=NULL) free(itpat);
  13.350 -    if(mask!=NULL) free(mask);
  13.351 -    if(last!=NULL) free(last);
  13.352 -    if(paraptr!=NULL) free(paraptr);
  13.353 -    if(noteindex!=NULL) free(noteindex);
  13.354 +	FreeLinear();
  13.355  
  13.356 -    mh        = NULL;
  13.357 -    poslookup = NULL;
  13.358 -    itpat     = NULL;
  13.359 -    mask      = NULL;
  13.360 -    last      = NULL;
  13.361 -    paraptr   = NULL;
  13.362 -    noteindex = NULL;
  13.363 +	_mm_free(mh);
  13.364 +	_mm_free(poslookup);
  13.365 +	_mm_free(itpat);
  13.366 +	_mm_free(mask);
  13.367 +	_mm_free(last);
  13.368 +	_mm_free(paraptr);
  13.369 +	_mm_free(origpositions);
  13.370  }
  13.371  
  13.372 +/* Because so many IT files have 64 channels as the set number used, but really
  13.373 +   only use far less (usually from 8 to 24 still), I had to make this function,
  13.374 +   which determines the number of channels that are actually USED by a pattern.
  13.375  
  13.376 -BOOL IT_GetNumChannels(UWORD patrows)
  13.377 +   NOTE: You must first seek to the file location of the pattern before calling
  13.378 +         this procedure.
  13.379  
  13.380 -/* Because so many IT files have 64 channels as the set number used, but really */
  13.381 -/* only use far less (usually 8 to 12 still), I had to make this function, */
  13.382 -/* which determines the number of channels that are actually USED by a pattern. */
  13.383 -/* */
  13.384 -/* For every channel that's used, it sets the appropriate array entry of the */
  13.385 -/* global varialbe 'isused' */
  13.386 -/* */
  13.387 -/* NOTE: You must first seek to the file location of the pattern before calling */
  13.388 -/*       this procedure. */
  13.389 -/* Returns 1 on error */
  13.390 +   Returns 1 on error
  13.391 +*/
  13.392 +static BOOL IT_GetNumChannels(UWORD patrows)
  13.393  {
  13.394 -    int  row=0,flag,ch;
  13.395 +	int row=0,flag,ch;
  13.396  
  13.397 -    do
  13.398 -    {   flag = _mm_read_UBYTE(modfp);
  13.399 -        if(flag == EOF)
  13.400 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  13.401 -            return 1;
  13.402 -        }
  13.403 +	do {
  13.404 +		if((flag=_mm_read_UBYTE(modreader))==EOF) {
  13.405 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.406 +			return 1;
  13.407 +		}
  13.408 +		if(!flag)
  13.409 +			row++;
  13.410 +		else {
  13.411 +			ch=(flag-1)&63;
  13.412 +			remap[ch]=0;
  13.413 +			if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader);
  13.414 +			if(mask[ch]&1)   _mm_read_UBYTE(modreader);
  13.415 +			if(mask[ch]&2)   _mm_read_UBYTE(modreader);
  13.416 +			if(mask[ch]&4)   _mm_read_UBYTE(modreader);
  13.417 +			if(mask[ch]&8) { _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader); }
  13.418 +		}
  13.419 +	} while(row<patrows);
  13.420  
  13.421 -        if(flag == 0)
  13.422 -        {   row++;
  13.423 -        } else
  13.424 -        {   ch = (flag-1) & 63;
  13.425 -            remap[ch] = 0;
  13.426 -            if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp);
  13.427 -            if(mask[ch] &   1) _mm_read_UBYTE(modfp);
  13.428 -            if(mask[ch] &   2) _mm_read_UBYTE(modfp);
  13.429 -            if(mask[ch] &   4) _mm_read_UBYTE(modfp);
  13.430 -            if(mask[ch] &   8) { _mm_read_UBYTE(modfp); _mm_read_UBYTE(modfp); }
  13.431 -        }
  13.432 -    } while(row < patrows);
  13.433 -
  13.434 -    return 0;
  13.435 +	return 0;
  13.436  }
  13.437  
  13.438 +static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows)
  13.439 +{
  13.440 +	int t;
  13.441 +	UBYTE note,ins,volpan;
  13.442  
  13.443 -BOOL IT_ReadPattern(UWORD patrows)
  13.444 -{
  13.445 -   int    blah;
  13.446 -   int    row=0,flag,ch;
  13.447 -   ITNOTE *itt = itpat, dummy,*n,*l;
  13.448 +	UniReset();
  13.449  
  13.450 -   memset(itt,255,patrows*of.numchn*sizeof(ITNOTE));
  13.451 +	for(t=0;t<numrows;t++) {
  13.452 +		note=tr[t*of.numchn].note;
  13.453 +		ins=tr[t*of.numchn].ins;
  13.454 +		volpan=tr[t*of.numchn].volpan;
  13.455  
  13.456 -   do 
  13.457 -   {   flag = _mm_read_UBYTE(modfp);
  13.458 -       if(feof(modfp))
  13.459 -       {   _mm_errno = MMERR_LOADING_PATTERN;
  13.460 -           return 0;
  13.461 -       }
  13.462 -       if(flag == 0)
  13.463 -       {   itt = &itt[of.numchn];
  13.464 -           row++;
  13.465 -       } else
  13.466 -       {   ch = remap[(flag-1) & 63];
  13.467 -           if(ch != -1)
  13.468 -           {   n = &itt[ch];
  13.469 -               l = &last[ch];
  13.470 -           } else
  13.471 -           {   n = l = &dummy;  }
  13.472 +		if(note!=255) {
  13.473 +			if(note==253)
  13.474 +				UniWriteByte(UNI_KEYOFF);
  13.475 +			else if(note==254) {
  13.476 +				UniPTEffect(0xc,-1);	/* note cut command */
  13.477 +				volpan=255;
  13.478 +			} else
  13.479 +				UniNote(note);
  13.480 +		}
  13.481  
  13.482 -           if(flag & 128) mask[ch] = _mm_read_UBYTE(modfp);
  13.483 -           if(mask[ch] &   1) if((l->note = n->note   = _mm_read_UBYTE(modfp)) == 255)
  13.484 -                              {   l->note = n->note   = 253; }
  13.485 -           if(mask[ch] &   2) l->ins      = n->ins    = _mm_read_UBYTE(modfp);
  13.486 -           if(mask[ch] &   4) l->volpan   = n->volpan = _mm_read_UBYTE(modfp);
  13.487 -           if(mask[ch] &   8) { l->cmd    = n->cmd    = _mm_read_UBYTE(modfp);
  13.488 -                                l->inf    = n->inf    = _mm_read_UBYTE(modfp); }
  13.489 -           if(mask[ch] &  16) n->note     = l->note;
  13.490 -           if(mask[ch] &  32) n->ins      = l->ins;
  13.491 -           if(mask[ch] &  64) n->volpan   = l->volpan;
  13.492 -           if(mask[ch] & 128) { n->cmd    = l->cmd;
  13.493 -                                n->inf    = l->inf; }
  13.494 -        }
  13.495 -   } while(row < patrows);
  13.496 +		if((ins)&&(ins<100))
  13.497 +			UniInstrument(ins-1);
  13.498 +		else if(ins==253)
  13.499 +			UniWriteByte(UNI_KEYOFF);
  13.500 +		else if(ins!=255) { /* crap */
  13.501 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.502 +			return NULL;
  13.503 +		}
  13.504  
  13.505 -   for(blah=0; blah<of.numchn; blah++)
  13.506 -       of.tracks[numtrk++] = IT_ConvertTrack(&itpat[blah],patrows);
  13.507 +		/* process volume / panning column
  13.508 +		   volume / panning effects do NOT all share the same memory address
  13.509 +		   yet. */
  13.510 +		if(volpan<=64)
  13.511 +			UniVolEffect(VOL_VOLUME,volpan);
  13.512 +		else if(volpan<=74)	/* fine volume slide up (65-74) */
  13.513 +			UniVolEffect(VOL_VOLSLIDE,0x0f+((volpan-65)<<4));
  13.514 +		else if(volpan<=84)	/* fine volume slide down (75-84) */
  13.515 +			UniVolEffect(VOL_VOLSLIDE,0xf0+(volpan-75));
  13.516 +		else if(volpan<=94)	/* volume slide up (85-94) */
  13.517 +			UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4));
  13.518 +		else if(volpan<=104)/* volume slide down (95-104) */
  13.519 +			UniVolEffect(VOL_VOLSLIDE,(volpan-95));
  13.520 +		else if(volpan<=114)/* pitch slide down (105-114) */
  13.521 +			UniVolEffect(VOL_PITCHSLIDEDN,(volpan-105));
  13.522 +		else if(volpan<=124)/* pitch slide up (115-124) */
  13.523 +			UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115));
  13.524 +		else if(volpan<=127) { /* crap */
  13.525 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.526 +			return NULL;
  13.527 +		} else if(volpan<=192)
  13.528 +			UniVolEffect(VOL_PANNING,((volpan-128)==64)?255:((volpan-128)<<2));
  13.529 +		else if(volpan<=202)/* portamento to note */
  13.530 +			UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]);
  13.531 +		else if(volpan<=212)/* vibrato */
  13.532 +			UniVolEffect(VOL_VIBRATO,(volpan-203));
  13.533 +		else if((volpan!=239)&&(volpan!=255)) { /* crap */
  13.534 +			_mm_errno=MMERR_LOADING_PATTERN;
  13.535 +			return NULL;
  13.536 +		}
  13.537  
  13.538 -   return 1;
  13.539 +		S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,old_effect|2);
  13.540 +
  13.541 +		UniNewline();
  13.542 +	}
  13.543 +	return UniDup();
  13.544  }
  13.545  
  13.546 +static BOOL IT_ReadPattern(UWORD patrows)
  13.547 +{
  13.548 +	int row=0,flag,ch,blah;
  13.549 +	ITNOTE *itt=itpat,dummy,*n,*l;
  13.550  
  13.551 -void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, BOOL oldeffect);
  13.552 +	memset(itt,255,200*64*sizeof(ITNOTE));
  13.553  
  13.554 -/* table for porta-to-note command within volume/panning column */
  13.555 -static UBYTE portatable[] = "1, 4, 8, 16, 32, 64, 96, 128, 255";
  13.556 +	do {
  13.557 +		if((flag=_mm_read_UBYTE(modreader))==EOF) {
  13.558 +			_mm_errno = MMERR_LOADING_PATTERN;
  13.559 +			return 0;
  13.560 +		}
  13.561 +		if(!flag) {
  13.562 +			itt=&itt[of.numchn];
  13.563 +			row++;
  13.564 +		} else {
  13.565 +			ch=remap[(flag-1)&63];
  13.566 +			if(ch!=-1) {
  13.567 +				n=&itt[ch];
  13.568 +				l=&last[ch];
  13.569 +			} else
  13.570 +				n=l=&dummy;
  13.571  
  13.572 -UBYTE *IT_ConvertTrack(ITNOTE *tr, UWORD numrows)
  13.573 -{
  13.574 -    int t;
  13.575 +			if(flag&128) mask[ch]=_mm_read_UBYTE(modreader);
  13.576 +			if(mask[ch]&1)
  13.577 +				/* convert IT note off to internal note off */
  13.578 +				if((l->note=n->note=_mm_read_UBYTE(modreader))==255)
  13.579 +					l->note=n->note=253;
  13.580 +			if(mask[ch]&2)
  13.581 +				l->ins=n->ins=_mm_read_UBYTE(modreader);
  13.582 +			if(mask[ch]&4)
  13.583 +				l->volpan=n->volpan=_mm_read_UBYTE(modreader);
  13.584 +			if(mask[ch]&8) {
  13.585 +				l->cmd=n->cmd=_mm_read_UBYTE(modreader);
  13.586 +				l->inf=n->inf=_mm_read_UBYTE(modreader);
  13.587 +			}
  13.588 +			if(mask[ch]&16)
  13.589 +				n->note=l->note;
  13.590 +			if(mask[ch]&32)
  13.591 +				n->ins=l->ins;
  13.592 +			if(mask[ch]&64)
  13.593 +				n->volpan=l->volpan;
  13.594 +			if(mask[ch]&128) {
  13.595 +				n->cmd=l->cmd;
  13.596 +				n->inf=l->inf;
  13.597 +			}
  13.598 +		}
  13.599 +	} while(row<patrows);
  13.600  
  13.601 -    UBYTE note,ins,volpan;
  13.602 +	for(blah=0;blah<of.numchn;blah++) {
  13.603 +		if(!(of.tracks[numtrk++]=IT_ConvertTrack(&itpat[blah],patrows)))
  13.604 +			return 0;
  13.605 +	}
  13.606  
  13.607 -    UniReset();
  13.608 -
  13.609 -    for(t=0; t<numrows; t++)
  13.610 -    {   note    = tr[t*of.numchn].note;
  13.611 -        ins     = tr[t*of.numchn].ins;
  13.612 -        volpan  = tr[t*of.numchn].volpan;
  13.613 -
  13.614 -        if(note!=255)
  13.615 -        {   if(note==253)
  13.616 -                UniWrite(UNI_KEYOFF);
  13.617 -            else if(note==254)
  13.618 -                UniPTEffect(0xc,0);   /* <- note cut command */
  13.619 -            else
  13.620 -                UniNote(note);
  13.621 -        }
  13.622 -
  13.623 -        if((ins != 0) && (ins < 100)) UniInstrument(ins-1);
  13.624 -
  13.625 -        /* process volume / panning column */
  13.626 -        /* volume / panning effects do NOT all share the same memory address */
  13.627 -        /* yet.  That requires more work than I care to apply at the moment ;) */
  13.628 -
  13.629 -        if(volpan<=64)
  13.630 -        {   UniVolEffect(VOL_VOLUME,volpan);
  13.631 -        } else if((volpan>=65) && (volpan<=74))        /* fine volume slide up (65-74) */
  13.632 -        {   UniVolEffect(VOL_VOLSLIDE,0x0f + ((volpan-65)<<4));
  13.633 -        } else if((volpan>=75) && (volpan<=84))        /* fine volume slide down   (75-84) */
  13.634 -        {   UniVolEffect(VOL_VOLSLIDE,0xf0 + (volpan-75));
  13.635 -        } else if((volpan>=85) && (volpan<=94))        /* volume slide up (85-94) */
  13.636 -        {   UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4));
  13.637 -        } else if((volpan>=95) && (volpan<=104))       /* volume slide down   (95-104) */
  13.638 -        {   UniVolEffect(VOL_VOLSLIDE,(volpan-95));
  13.639 -        } else if((volpan>=105) && (volpan<=114))      /* pitch slide up (105-114) */
  13.640 -        {   UniVolEffect(VOL_PITCHSLIDEDN,((volpan-105)<<4));
  13.641 -        } else if((volpan>=115) && (volpan<=124))      /* pitch slide down (115-124) */
  13.642 -        {   UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115));
  13.643 -        } else if((volpan>=128) && (volpan<=192))
  13.644 -        {   UniVolEffect(VOL_PANNING,((volpan-128) == 64) ? 255 : ((volpan-128) << 2));
  13.645 -        } else if((volpan>=193) && (volpan<=202))      /* portamento to note */
  13.646 -        {   UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]);
  13.647 -        } else if((volpan>=203) && (volpan<=212))      /* vibrato */
  13.648 -        {   UniVolEffect(VOL_VIBRATO,(volpan-203));
  13.649 -        }
  13.650 -
  13.651 -        S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,old_effect);
  13.652 -
  13.653 -        UniNewline();
  13.654 -    }
  13.655 -    return UniDup();
  13.656 -}
  13.657 -                                             
  13.658 -
  13.659 -int cvt_c5spd_to_finetune(ULONG c5spd, int sampnum)
  13.660 -{
  13.661 -    int ctmp=0,tmp,note=1,finetune=0;
  13.662 -
  13.663 -    c5spd/=2;
  13.664 -
  13.665 -    do
  13.666 -    {   tmp = getfrequency(of.flags,getlinearperiod(note,0));
  13.667 -        if(tmp >= c5spd) break;
  13.668 -        ctmp = tmp;
  13.669 -        note++;
  13.670 -    } while(1);
  13.671 -
  13.672 -    if(tmp != c5spd)
  13.673 -    {   if((tmp-c5spd) < (c5spd-ctmp))
  13.674 -            while(tmp>c5spd) tmp = getfrequency(of.flags,getlinearperiod(note,--finetune));
  13.675 -        else
  13.676 -        {   note--;
  13.677 -            while(ctmp<c5spd) ctmp = getfrequency(of.flags,getlinearperiod(note,++finetune));
  13.678 -        }
  13.679 -    }
  13.680 -
  13.681 -    noteindex[sampnum] = note-48;
  13.682 -    return finetune;
  13.683 -}       
  13.684 -
  13.685 -
  13.686 -BOOL IT_Load(void)
  13.687 -{
  13.688 -    int        t,u,lp;
  13.689 -    INSTRUMENT *d;
  13.690 -    SAMPLE     *q;
  13.691 -
  13.692 -    numtrk = 0;
  13.693 -
  13.694 -    /* try to read module header */
  13.695 -
  13.696 -    _mm_read_I_ULONG(modfp);   /* kill the 4 byte header */
  13.697 -    _mm_read_string(mh->songname,26,modfp);
  13.698 -    _mm_read_UBYTES(mh->blank01,2,modfp);
  13.699 -    mh->ordnum      =_mm_read_I_UWORD(modfp);
  13.700 -    mh->insnum      =_mm_read_I_UWORD(modfp);
  13.701 -    mh->smpnum      =_mm_read_I_UWORD(modfp);
  13.702 -    mh->patnum      =_mm_read_I_UWORD(modfp);
  13.703 -    mh->cwt         =_mm_read_I_UWORD(modfp);
  13.704 -    mh->cmwt        =_mm_read_I_UWORD(modfp);
  13.705 -    mh->flags       =_mm_read_I_UWORD(modfp);
  13.706 -    mh->special     =_mm_read_I_UWORD(modfp);
  13.707 -
  13.708 -    mh->globvol     =_mm_read_UBYTE(modfp);
  13.709 -    mh->mixvol      =_mm_read_UBYTE(modfp);
  13.710 -    mh->initspeed   =_mm_read_UBYTE(modfp);
  13.711 -    mh->inittempo   =_mm_read_UBYTE(modfp);
  13.712 -    mh->pansep      =_mm_read_UBYTE(modfp);
  13.713 -    mh->zerobyte    =_mm_read_UBYTE(modfp);
  13.714 -    mh->msglength   =_mm_read_I_UWORD(modfp);
  13.715 -    mh->msgoffset   =_mm_read_I_ULONG(modfp);
  13.716 -    _mm_read_UBYTES(mh->blank02,4,modfp);
  13.717 -    _mm_read_UBYTES(mh->pantable,64,modfp);
  13.718 -    _mm_read_UBYTES(mh->voltable,64,modfp);
  13.719 -
  13.720 -    if(feof(modfp))
  13.721 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.722 -        return 0;
  13.723 -    }
  13.724 -
  13.725 -    /* set module variables */
  13.726 -
  13.727 -    of.modtype     = strdup(IT_Version);
  13.728 -    of.modtype[15] = (mh->cwt >> 8) + 0x30;
  13.729 -    of.modtype[17] = ((mh->cwt >> 4) & 0xf) + 0x30;
  13.730 -    of.modtype[18] = ((mh->cwt) & 0xf) + 0x30;
  13.731 -    of.songname    = DupStr(mh->songname,26);    /* make a cstr of songname  */
  13.732 -    of.reppos      = 0;
  13.733 -    of.numpat      = mh->patnum;
  13.734 -    of.numins      = mh->insnum;
  13.735 -    of.numsmp      = mh->smpnum;
  13.736 -    of.initspeed   = mh->initspeed;
  13.737 -    of.inittempo   = mh->inittempo;
  13.738 -    of.initvolume  = mh->globvol;
  13.739 -
  13.740 -    old_effect = 0;
  13.741 -    if(mh->flags & 8) { of.flags |= (UF_XMPERIODS | UF_LINEAR); old_effect |= 2; }
  13.742 -    if((mh->cwt >= 0x106) && (mh->flags & 16))  old_effect |= 1;
  13.743 -
  13.744 -    /* set panning positions */
  13.745 -    for(t=0; t<64; t++)
  13.746 -    {   if(mh->pantable[t] < 64) of.panning[t] = mh->pantable[t] << 2;
  13.747 -        else if(mh->pantable[t]==64) of.panning[t] = 255;
  13.748 -        else if(mh->pantable[t]==100) of.panning[t] = PAN_SURROUND;
  13.749 -    }
  13.750 -
  13.751 -    /* set channel volumes */
  13.752 -    memcpy(of.chanvol,mh->voltable,64);
  13.753 -
  13.754 -    /* read the order data */
  13.755 -    if(!AllocPositions(mh->ordnum)) return 0;
  13.756 -
  13.757 -    for(t=0; t<mh->ordnum; t++)
  13.758 -        of.positions[t] = _mm_read_UBYTE(modfp);
  13.759 -
  13.760 -    if(feof(modfp))
  13.761 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.762 -        return 0;
  13.763 -    }
  13.764 -    
  13.765 -    of.numpos = 0;
  13.766 -    for(t=0; t<mh->ordnum; t++)
  13.767 -    {   of.positions[of.numpos] = of.positions[t];
  13.768 -        poslookup[t] = of.numpos;    /* bug fix for FREAKY S3Ms / ITs */
  13.769 -        if(of.positions[t]<254) of.numpos++;
  13.770 -    }
  13.771 -
  13.772 -    if((paraptr=(ULONG *)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*sizeof(ULONG))) == NULL) return 0;
  13.773 -
  13.774 -    /* read the instrument, sample, and pattern parapointers */
  13.775 -    _mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modfp);
  13.776 -
  13.777 -    /* now is a good time to check if the header was too short :) */
  13.778 -    if(feof(modfp))
  13.779 -    {   _mm_errno = MMERR_LOADING_HEADER;
  13.780 -        return 0;
  13.781 -    }
  13.782 -
  13.783 -    /* Check for and load song comment */
  13.784 -    if(mh->special & 1)
  13.785 -    {   _mm_fseek(modfp,(long)(mh->msgoffset),SEEK_SET);
  13.786 -        if(!ReadComment(mh->msglength)) return 0;
  13.787 -    }
  13.788 -
  13.789 -    if(!(mh->flags & 4)) of.numins = of.numsmp;
  13.790 -    if(!AllocSamples()) return 0;
  13.791 -
  13.792 -    if((noteindex=(int *)_mm_malloc(mh->smpnum*sizeof(int)))==NULL) return 0;
  13.793 -        
  13.794 -    q = of.samples;
  13.795 -
  13.796 -    /* Load all samples (they're used either way) */
  13.797 -    for(t=0; t<mh->smpnum; t++)
  13.798 -    {   ITSAMPLE s;
  13.799 -
  13.800 -        /* seek to sample position */
  13.801 -        _mm_fseek(modfp,(long)(paraptr[mh->insnum+t] + 4),SEEK_SET);
  13.802 -
  13.803 -        /* and load sample info */
  13.804 -        _mm_read_string(s.filename,12,modfp);
  13.805 -        s.zerobyte    = _mm_read_UBYTE(modfp);
  13.806 -        s.globvol     = _mm_read_UBYTE(modfp);
  13.807 -        s.flag        = _mm_read_UBYTE(modfp);
  13.808 -        s.volume      = _mm_read_UBYTE(modfp);
  13.809 -        _mm_read_string(s.sampname,26,modfp);
  13.810 -        s.convert     = _mm_read_UBYTE(modfp);
  13.811 -        s.panning     = _mm_read_UBYTE(modfp);
  13.812 -        s.length      = _mm_read_I_ULONG(modfp);
  13.813 -        s.loopbeg     = _mm_read_I_ULONG(modfp);
  13.814 -        s.loopend     = _mm_read_I_ULONG(modfp);
  13.815 -        s.c5spd       = _mm_read_I_ULONG(modfp);
  13.816 -        s.susbegin    = _mm_read_I_ULONG(modfp);
  13.817 -        s.susend      = _mm_read_I_ULONG(modfp);
  13.818 -        s.sampoffset  = _mm_read_I_ULONG(modfp);
  13.819 -        s.vibspeed    = _mm_read_UBYTE(modfp);
  13.820 -        s.vibdepth    = _mm_read_UBYTE(modfp);
  13.821 -        s.vibrate     = _mm_read_UBYTE(modfp);
  13.822 -        s.vibwave     = _mm_read_UBYTE(modfp);
  13.823 -
  13.824 - 
  13.825 -        /* Generate an error if c5spd is > 512k, or samplelength > 256 megs */
  13.826 -        /*  (nothing would EVER be that high) */
  13.827 -
  13.828 -        if(feof(modfp) || (s.c5spd > 0x7ffffL) || (s.length > 0xfffffffUL) ||
  13.829 -          (s.loopbeg > 0xfffffffUL) || (s.loopend > 0xfffffffUL))
  13.830 -        {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  13.831 -            return 0;
  13.832 -        }
  13.833 -
  13.834 -        q->samplename = DupStr(s.sampname,26);
  13.835 -
  13.836 -        q->speed      = s.c5spd / 2;
  13.837 -        q->panning    = ((s.panning & 127)==64) ? 255 : (s.panning & 127) << 2;
  13.838 -        q->length     = s.length;
  13.839 -        q->loopstart  = s.loopbeg;
  13.840 -        q->loopend    = s.loopend;
  13.841 -        q->volume     = s.volume;
  13.842 -        q->globvol    = s.globvol;
  13.843 -        q->seekpos    = s.sampoffset;
  13.844 -
  13.845 -        /* =================================== */
  13.846 -        /* Convert speed to XM linear finetune */
  13.847 -
  13.848 -        if(of.flags & UF_LINEAR)
  13.849 -            q->speed = cvt_c5spd_to_finetune(s.c5spd, t);
  13.850 -
  13.851 -        if(s.panning & 128) q->flags |= SF_OWNPAN;
  13.852 -
  13.853 -        if(s.vibrate)
  13.854 -        {   q->vibflags |= AV_IT;
  13.855 -            q->vibtype   = s.vibwave;
  13.856 -            q->vibsweep  = s.vibrate * 2;
  13.857 -            q->vibdepth  = s.vibdepth;
  13.858 -            q->vibrate   = s.vibspeed;
  13.859 -        }
  13.860 -
  13.861 -        if(s.flag & 2)  q->flags |= SF_16BITS;
  13.862 -        if(s.flag & 16) q->flags |= SF_LOOP;
  13.863 -        if(s.flag & 64) q->flags |= SF_BIDI;
  13.864 -
  13.865 -        if(mh->cwt >= 0x200)
  13.866 -        {   if(s.convert & 1) q->flags |= SF_SIGNED;
  13.867 -            if(s.convert & 4) q->flags |= SF_DELTA;   
  13.868 -        }
  13.869 -                              
  13.870 -        q++;
  13.871 -    }
  13.872 -
  13.873 -    /* Load instruments if instrument mode flag enabled */
  13.874 -
  13.875 -    if(mh->flags & 4)
  13.876 -    {   if(!AllocInstruments()) return 0;
  13.877 -        d = of.instruments;
  13.878 -        of.flags |= UF_NNA | UF_INST;
  13.879 -
  13.880 -        for(t=0; t<mh->insnum; t++)
  13.881 -        {   ITINSTHEADER ih;
  13.882 -
  13.883 -            /* seek to instrument position */
  13.884 -            _mm_fseek(modfp,paraptr[t]+4,SEEK_SET);
  13.885 -
  13.886 -            /* and load instrument info */
  13.887 -            _mm_read_string(ih.filename,12,modfp);
  13.888 -            ih.zerobyte  = _mm_read_UBYTE(modfp);
  13.889 -            if(mh->cwt < 0x200) /* load IT 1.xx inst header */
  13.890 -            {   ih.volflg    = _mm_read_UBYTE(modfp);
  13.891 -                ih.volbeg    = _mm_read_UBYTE(modfp);
  13.892 -                ih.volend    = _mm_read_UBYTE(modfp);
  13.893 -                ih.volsusbeg = _mm_read_UBYTE(modfp);
  13.894 -                ih.volsusend = _mm_read_UBYTE(modfp);
  13.895 -                _mm_read_I_UWORD(modfp);
  13.896 -                ih.fadeout   = _mm_read_I_UWORD(modfp);
  13.897 -                ih.nna       = _mm_read_UBYTE(modfp);
  13.898 -                ih.dnc       = _mm_read_UBYTE(modfp);
  13.899 -            } else   /* Read IT200+ header */
  13.900 -            {   ih.nna       = _mm_read_UBYTE(modfp);
  13.901 -                ih.dct       = _mm_read_UBYTE(modfp);
  13.902 -                ih.dca       = _mm_read_UBYTE(modfp);
  13.903 -                ih.fadeout   = _mm_read_I_UWORD(modfp);
  13.904 -                ih.ppsep     = _mm_read_UBYTE(modfp);
  13.905 -                ih.ppcenter  = _mm_read_UBYTE(modfp);
  13.906 -                ih.globvol   = _mm_read_UBYTE(modfp);
  13.907 -                ih.chanpan   = _mm_read_UBYTE(modfp);
  13.908 -                ih.rvolvar   = _mm_read_UBYTE(modfp);
  13.909 -                ih.rpanvar   = _mm_read_UBYTE(modfp);
  13.910 -            }
  13.911 -
  13.912 -            ih.trkvers   = _mm_read_I_UWORD(modfp);
  13.913 -            ih.numsmp    = _mm_read_UBYTE(modfp);
  13.914 -            _mm_read_UBYTE(modfp);
  13.915 -            _mm_read_string(ih.name,26,modfp);
  13.916 -            _mm_read_UBYTES(ih.blank01,6,modfp);
  13.917 -            _mm_read_I_UWORDS(ih.samptable,120,modfp);
  13.918 -            if(mh->cwt < 0x200)  /* load IT 1xx volume envelope */
  13.919 -            {   _mm_read_UBYTES(ih.volenv,200,modfp);
  13.920 -                for(lp=0; lp<25; lp++)
  13.921 -                {   ih.oldvoltick[lp] = _mm_read_UBYTE(modfp);
  13.922 -                    ih.volnode[lp]    = _mm_read_UBYTE(modfp);
  13.923 -                }
  13.924 -            } else /* load IT 2xx vol & chanpan & pitch envs */
  13.925 -            {   ih.volflg    = _mm_read_UBYTE(modfp);
  13.926 -                ih.volpts    = _mm_read_UBYTE(modfp);
  13.927 -                ih.volbeg    = _mm_read_UBYTE(modfp);
  13.928 -                ih.volend    = _mm_read_UBYTE(modfp);
  13.929 -                ih.volsusbeg = _mm_read_UBYTE(modfp);
  13.930 -                ih.volsusend = _mm_read_UBYTE(modfp);
  13.931 -                for(lp=0; lp<25; lp++)
  13.932 -                {   ih.volnode[lp] = _mm_read_UBYTE(modfp);
  13.933 -                    ih.voltick[lp] = _mm_read_I_UWORD(modfp);
  13.934 -                }
  13.935 -                _mm_read_UBYTE(modfp);
  13.936 -
  13.937 -                ih.panflg    = _mm_read_UBYTE(modfp);
  13.938 -                ih.panpts    = _mm_read_UBYTE(modfp);
  13.939 -                ih.panbeg    = _mm_read_UBYTE(modfp);
  13.940 -                ih.panend    = _mm_read_UBYTE(modfp);
  13.941 -                ih.pansusbeg = _mm_read_UBYTE(modfp);
  13.942 -                ih.pansusend = _mm_read_UBYTE(modfp);
  13.943 -                for(lp=0; lp<25; lp++)
  13.944 -                {   ih.pannode[lp] = _mm_read_SBYTE(modfp);
  13.945 -                    ih.pantick[lp] = _mm_read_I_UWORD(modfp);
  13.946 -                }
  13.947 -                _mm_read_UBYTE(modfp);
  13.948 -
  13.949 -                ih.pitflg    = _mm_read_UBYTE(modfp);
  13.950 -                ih.pitpts    = _mm_read_UBYTE(modfp);
  13.951 -                ih.pitbeg    = _mm_read_UBYTE(modfp);
  13.952 -                ih.pitend    = _mm_read_UBYTE(modfp);
  13.953 -                ih.pitsusbeg = _mm_read_UBYTE(modfp);
  13.954 -                ih.pitsusend = _mm_read_UBYTE(modfp);
  13.955 -                for(lp=0; lp<25; lp++)
  13.956 -                {   ih.pitnode[lp] = _mm_read_SBYTE(modfp);
  13.957 -                    ih.pittick[lp] = _mm_read_I_UWORD(modfp);
  13.958 -                }
  13.959 -                _mm_read_UBYTE(modfp);
  13.960 -            }
  13.961 - 
  13.962 -            if(feof(modfp))
  13.963 -            {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  13.964 -                return 0;
  13.965 -            }
  13.966 -
  13.967 -            d->volflg |= EF_VOLENV;
  13.968 -            d->insname = DupStr(ih.name,26);
  13.969 -            d->nnatype = ih.nna;
  13.970 -            
  13.971 -            if(mh->cwt < 0x200)
  13.972 -            {   d->volfade = ih.fadeout << 6;
  13.973 -                if(ih.dnc)
  13.974 -                {   d->dct = DCT_NOTE;
  13.975 -                    d->dca = DCA_CUT;
  13.976 -                }
  13.977 -
  13.978 -                if(ih.volflg & 1) d->volflg |= EF_ON;
  13.979 -                if(ih.volflg & 2) d->volflg |= EF_LOOP;
  13.980 -                if(ih.volflg & 4) d->volflg |= EF_SUSTAIN;      
  13.981 -               
  13.982 -                /* XM conversion of IT envelope Array */
  13.983 -                
  13.984 -                d->volbeg    = ih.volbeg;   
  13.985 -                d->volend    = ih.volend;
  13.986 -                d->volsusbeg = ih.volsusbeg;
  13.987 -                d->volsusend = ih.volsusend;
  13.988 -            
  13.989 -                if(ih.volflg & 1)
  13.990 -                {   for(u=0; u<25; u++)
  13.991 -                        if(ih.oldvoltick[d->volpts] != 0xff)
  13.992 -                        {   d->volenv[d->volpts].val = (ih.volnode[d->volpts] << 2);
  13.993 -                            d->volenv[d->volpts].pos = ih.oldvoltick[d->volpts];
  13.994 -                            d->volpts++;
  13.995 -                        } else break;
  13.996 -                }  
  13.997 -            } else
  13.998 -            {   d->panning = ((ih.chanpan&127) == 64) ? 255 : (ih.chanpan&127)<<2;
  13.999 -                if(!(ih.chanpan & 128)) d->flags |= IF_OWNPAN;
 13.1000 -
 13.1001 -                if(!(ih.ppsep & 128))
 13.1002 -                {   d->pitpansep = ih.ppsep << 2;
 13.1003 -                    d->pitpancenter= ih.ppcenter;
 13.1004 -                    d->flags |= IF_PITCHPAN;
 13.1005 -                }
 13.1006 -                d->globvol = ih.globvol >> 1;
 13.1007 -                d->volfade = ih.fadeout << 5;
 13.1008 -                d->dct     = ih.dct;
 13.1009 -                d->dca     = ih.dca;
 13.1010 -
 13.1011 -                if(mh->cwt >= 0x204)
 13.1012 -                {   d->rvolvar = ih.rvolvar;
 13.1013 -                    d->rpanvar = ih.rpanvar;
 13.1014 -                }
 13.1015 -
 13.1016 -                if(ih.volflg & 1) d->volflg |= EF_ON;
 13.1017 -                if(ih.volflg & 2) d->volflg |= EF_LOOP;
 13.1018 -                if(ih.volflg & 4) d->volflg |= EF_SUSTAIN;
 13.1019 -
 13.1020 -                if(ih.panflg & 1) d->panflg |= EF_ON;
 13.1021 -                if(ih.panflg & 2) d->panflg |= EF_LOOP;
 13.1022 -                if(ih.panflg & 4) d->panflg |= EF_SUSTAIN;      
 13.1023 -
 13.1024 -                if(ih.pitflg & 1) d->pitflg |= EF_ON;
 13.1025 -                if(ih.pitflg & 2) d->pitflg |= EF_LOOP;
 13.1026 -                if(ih.pitflg & 4) d->pitflg |= EF_SUSTAIN;      
 13.1027 -
 13.1028 -                d->volpts    = ih.volpts;
 13.1029 -                d->volbeg    = ih.volbeg;   
 13.1030 -                d->volend    = ih.volend;
 13.1031 -                d->volsusbeg = ih.volsusbeg;
 13.1032 -                d->volsusend = ih.volsusend;
 13.1033 -
 13.1034 -                for(u=0; u<ih.volpts; u++)
 13.1035 -                {   d->volenv[u].val = (ih.volnode[u] << 2);
 13.1036 -                    d->volenv[u].pos = ih.voltick[u];
 13.1037 -                }
 13.1038 -
 13.1039 -                d->panpts    = ih.panpts;
 13.1040 -                d->panbeg    = ih.panbeg;
 13.1041 -                d->panend    = ih.panend;
 13.1042 -                d->pansusbeg = ih.pansusbeg;
 13.1043 -                d->pansusend = ih.pansusend;
 13.1044 - 
 13.1045 -                for(u=0; u<ih.panpts; u++)                                               
 13.1046 -                {   d->panenv[u].val = (ih.pannode[u]+32) << 2;
 13.1047 -                    d->panenv[u].pos = ih.pantick[u];
 13.1048 -                }
 13.1049 -
 13.1050 -                d->pitpts    = ih.pitpts;
 13.1051 -                d->pitbeg    = ih.pitbeg;
 13.1052 -                d->pitend    = ih.pitend;
 13.1053 -                d->pitsusbeg = ih.pitsusbeg;
 13.1054 -                d->pitsusend = ih.pitsusend;
 13.1055 -
 13.1056 -                for(u=0; u<ih.pitpts; u++)
 13.1057 -                {   d->pitenv[u].val = (ih.pitnode[u]+32);
 13.1058 -                    d->pitenv[u].pos = ih.pittick[u];
 13.1059 -                }
 13.1060 -            }
 13.1061 -   
 13.1062 -            if(of.flags & UF_LINEAR)
 13.1063 -            {   for(u=0; u<120; u++)
 13.1064 -                {   d->samplenote[u]   = (ih.samptable[u] & 255);
 13.1065 -                    d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255;
 13.1066 -                    if(d->samplenumber[u]!=255)
 13.1067 -                        d->samplenote[u] += noteindex[d->samplenumber[u]];
 13.1068 -                }
 13.1069 -            } else
 13.1070 -            {   for(u=0; u<120; u++)
 13.1071 -                {   d->samplenote[u]   = (ih.samptable[u] & 255);
 13.1072 -                    d->samplenumber[u] = (ih.samptable[u] >> 8) ? ((ih.samptable[u] >> 8) - 1) : 255;
 13.1073 -                }
 13.1074 -            }
 13.1075 -
 13.1076 -            d++;                  
 13.1077 -        }
 13.1078 -    } else if(of.flags & UF_LINEAR)
 13.1079 -    {   if(!AllocInstruments()) return 0;
 13.1080 -        d = of.instruments;
 13.1081 -        of.flags |= UF_INST;
 13.1082 -
 13.1083 -        for(t=0; t<mh->smpnum; t++, d++)
 13.1084 -        {   for(u=0; u<120; u++)
 13.1085 -                d->samplenote[u] += noteindex[d->samplenumber[u]];
 13.1086 -        }
 13.1087 -    }
 13.1088 -
 13.1089 -
 13.1090 -    /* Figure out how many channels this blasted song actually uses (what */
 13.1091 -    /* ever happened to common courtesy of storing this simple value */
 13.1092 -    /* somewhere in the damn module, eh!?) */
 13.1093 -
 13.1094 -    of.numchn = 0;
 13.1095 -    memset(remap,-1,64*sizeof(UBYTE));
 13.1096 -    
 13.1097 -    for(t=0; t<of.numpat; t++)
 13.1098 -    {   UWORD packlen;
 13.1099 -
 13.1100 -        /* seek to pattern position */
 13.1101 -        if(paraptr[mh->insnum+mh->smpnum+t] != 0)  /* No parapointer = pattern of 64 rows, EMPTY */
 13.1102 -        {   _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET);
 13.1103 -            packlen = _mm_read_I_UWORD(modfp);
 13.1104 -            packlen = _mm_read_I_UWORD(modfp);    /* read pattern length (# of rows) */
 13.1105 -            _mm_read_I_ULONG(modfp);
 13.1106 -            if(IT_GetNumChannels(packlen)) return 0;
 13.1107 -        }
 13.1108 -    }
 13.1109 -
 13.1110 -    /* give each of them a different number */
 13.1111 -    for(t=0; t<64; t++)
 13.1112 -    {   if(remap[t]==0)
 13.1113 -        {   remap[t] = of.numchn;
 13.1114 -            of.numchn++;
 13.1115 -        }
 13.1116 -    }
 13.1117 -
 13.1118 -    of.numtrk = of.numpat*of.numchn;
 13.1119 -
 13.1120 -
 13.1121 -    if(!AllocPatterns()) return 0;
 13.1122 -    if(!AllocTracks()) return 0;
 13.1123 -
 13.1124 -    for(t=0; t<of.numpat; t++)
 13.1125 -    {   UWORD packlen;
 13.1126 -
 13.1127 -        /* seek to pattern position */
 13.1128 -        if(paraptr[mh->insnum+mh->smpnum+t] == 0)  /* No parapointer = pattern of 64 rows, EMPTY */
 13.1129 -        {  of.pattrows[t] = 64;
 13.1130 -           for(u=0; u<of.numchn; u++)
 13.1131 -           {  int k;
 13.1132 -              UniReset();
 13.1133 -              for(k=0; k<64; k++) UniNewline();
 13.1134 -              of.tracks[numtrk++] = UniDup();
 13.1135 -           }
 13.1136 -        } else
 13.1137 -        {  _mm_fseek(modfp,(((long)paraptr[mh->insnum+mh->smpnum+t])),SEEK_SET);
 13.1138 -           packlen = _mm_read_I_UWORD(modfp);
 13.1139 -           of.pattrows[t] = _mm_read_I_UWORD(modfp);
 13.1140 -           _mm_read_I_ULONG(modfp);
 13.1141 -
 13.1142 -           if(!IT_ReadPattern(of.pattrows[t])) return 0;
 13.1143 -        }
 13.1144 -    }
 13.1145 -
 13.1146 -    return 1;
 13.1147 +	return 1;
 13.1148  }
 13.1149  
 13.1150 +static void LoadMidiString(MREADER* modreader,CHAR* dest)
 13.1151 +{
 13.1152 +	CHAR *cur,*last;
 13.1153 +
 13.1154 +	_mm_read_UBYTES(dest,32,modreader);
 13.1155 +	cur=last=dest;
 13.1156 +	/* remove blanks and uppercase all */
 13.1157 +	while(*last) {
 13.1158 +		if(isalnum((int)*last)) *(cur++)=toupper((int)*last);
 13.1159 +		last++;
 13.1160 +	}
 13.1161 +	*cur=0;
 13.1162 +}
 13.1163 +
 13.1164 +/* Load embedded midi information for resonant filters */
 13.1165 +static void IT_LoadMidiConfiguration(MREADER* modreader)
 13.1166 +{
 13.1167 +	int i;
 13.1168 +
 13.1169 +	memset(filtermacros,0,sizeof(filtermacros));
 13.1170 +	memset(filtersettings,0,sizeof(filtersettings));
 13.1171 +
 13.1172 +	if (modreader) { /* information is embedded in file */
 13.1173 +		UWORD dat;
 13.1174 +		CHAR midiline[33];
 13.1175 +
 13.1176 +		dat=_mm_read_I_UWORD(modreader);
 13.1177 +		_mm_fseek(modreader,8*dat+0x120,SEEK_CUR);
 13.1178 +
 13.1179 +		/* read midi macros */
 13.1180 +		for(i=0;i<16;i++) {
 13.1181 +			LoadMidiString(modreader,midiline);
 13.1182 +			if((!strncmp(midiline,"F0F00",5))&&
 13.1183 +			   ((midiline[5]=='0')||(midiline[5]=='1')))
 13.1184 +					filtermacros[i]=(midiline[5]-'0')|0x80;
 13.1185 +		}
 13.1186 +
 13.1187 +		/* read standalone filters */
 13.1188 +		for(i=0x80;i<0x100;i++) {
 13.1189 +			LoadMidiString(modreader,midiline);
 13.1190 +			if((!strncmp(midiline,"F0F00",5))&&
 13.1191 +			   ((midiline[5]=='0')||(midiline[5]=='1'))) {
 13.1192 +				filtersettings[i].filter=(midiline[5]-'0')|0x80;
 13.1193 +				dat=(midiline[6])?(midiline[6]-'0'):0;
 13.1194 +				if(midiline[7])dat=(dat<<4)|(midiline[7]-'0');
 13.1195 +				filtersettings[i].inf=dat;
 13.1196 +			}
 13.1197 +		}
 13.1198 +	} else { /* use default information */
 13.1199 +		filtermacros[0]=FILT_CUT;
 13.1200 +		for(i=0x80;i<0x90;i++) {
 13.1201 +			filtersettings[i].filter=FILT_RESONANT;
 13.1202 +			filtersettings[i].inf=(i&0x7f)<<3;
 13.1203 +		}
 13.1204 +	}
 13.1205 +	activemacro=0;
 13.1206 +	for(i=0;i<0x80;i++) {
 13.1207 +		filtersettings[i].filter=filtermacros[0];
 13.1208 +		filtersettings[i].inf=i;
 13.1209 +	}
 13.1210 +}
 13.1211 +
 13.1212 +BOOL IT_Load(BOOL curious)
 13.1213 +{
 13.1214 +	int t,u,lp;
 13.1215 +	INSTRUMENT *d;
 13.1216 +	SAMPLE *q;
 13.1217 +	BOOL compressed=0;
 13.1218 +
 13.1219 +	numtrk=0;
 13.1220 +	filters=0;
 13.1221 +
 13.1222 +	/* try to read module header */
 13.1223 +	_mm_read_I_ULONG(modreader);	/* kill the 4 byte header */
 13.1224 +	_mm_read_string(mh->songname,26,modreader);
 13.1225 +	_mm_read_UBYTES(mh->blank01,2,modreader);
 13.1226 +	mh->ordnum      =_mm_read_I_UWORD(modreader);
 13.1227 +	mh->insnum      =_mm_read_I_UWORD(modreader);
 13.1228 +	mh->smpnum      =_mm_read_I_UWORD(modreader);
 13.1229 +	mh->patnum      =_mm_read_I_UWORD(modreader);
 13.1230 +	mh->cwt         =_mm_read_I_UWORD(modreader);
 13.1231 +	mh->cmwt        =_mm_read_I_UWORD(modreader);
 13.1232 +	mh->flags       =_mm_read_I_UWORD(modreader);
 13.1233 +	mh->special     =_mm_read_I_UWORD(modreader);
 13.1234 +	mh->globvol     =_mm_read_UBYTE(modreader);
 13.1235 +	mh->mixvol      =_mm_read_UBYTE(modreader);
 13.1236 +	mh->initspeed   =_mm_read_UBYTE(modreader);
 13.1237 +	mh->inittempo   =_mm_read_UBYTE(modreader);
 13.1238 +	mh->pansep      =_mm_read_UBYTE(modreader);
 13.1239 +	mh->zerobyte    =_mm_read_UBYTE(modreader);
 13.1240 +	mh->msglength   =_mm_read_I_UWORD(modreader);
 13.1241 +	mh->msgoffset   =_mm_read_I_ULONG(modreader);
 13.1242 +	_mm_read_UBYTES(mh->blank02,4,modreader);
 13.1243 +	_mm_read_UBYTES(mh->pantable,64,modreader);
 13.1244 +	_mm_read_UBYTES(mh->voltable,64,modreader);
 13.1245 +
 13.1246 +	if(_mm_eof(modreader)) {
 13.1247 +		_mm_errno=MMERR_LOADING_HEADER;
 13.1248 +		return 0;
 13.1249 +	}
 13.1250 +
 13.1251 +	/* set module variables */
 13.1252 +	of.songname    = DupStr(mh->songname,26,0); /* make a cstr of songname  */
 13.1253 +	of.reppos      = 0;
 13.1254 +	of.numpat      = mh->patnum;
 13.1255 +	of.numins      = mh->insnum;
 13.1256 +	of.numsmp      = mh->smpnum;
 13.1257 +	of.initspeed   = mh->initspeed;
 13.1258 +	of.inittempo   = mh->inittempo;
 13.1259 +	of.initvolume  = mh->globvol;
 13.1260 +	of.flags      |= UF_BGSLIDES|UF_ARPMEM;
 13.1261 +
 13.1262 +	if(mh->songname[25]) {
 13.1263 +		of.numvoices=1+mh->songname[25];
 13.1264 +#ifdef MIKMOD_DEBUG
 13.1265 +		fprintf(stderr,"Embedded IT limitation to %d voices\n",of.numvoices);
 13.1266 +#endif
 13.1267 +	}
 13.1268 +
 13.1269 +	/* set the module type */
 13.1270 +	/* 2.17 : IT 2.14p4 */
 13.1271 +	/* 2.16 : IT 2.14p3 with resonant filters */
 13.1272 +	/* 2.15 : IT 2.14p3 (improved compression) */
 13.1273 +	if((mh->cwt<=0x219)&&(mh->cwt>=0x217))
 13.1274 +		of.modtype=strdup(IT_Version[mh->cmwt<0x214?4:5]);
 13.1275 +	else if (mh->cwt>=0x215)
 13.1276 +		of.modtype=strdup(IT_Version[mh->cmwt<0x214?2:3]);
 13.1277 +	else {
 13.1278 +		of.modtype     = strdup(IT_Version[mh->cmwt<0x214?0:1]);
 13.1279 +		of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0';
 13.1280 +		of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0';
 13.1281 +		of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0';
 13.1282 +	}
 13.1283 +
 13.1284 +	if(mh->flags&8)
 13.1285 +		of.flags|=(UF_XMPERIODS | UF_LINEAR);
 13.1286 +
 13.1287 +	if((mh->cwt>=0x106)&&(mh->flags&16))
 13.1288 +		old_effect=1;
 13.1289 +	else
 13.1290 +		old_effect=0;
 13.1291 +
 13.1292 +	/* set panning positions */
 13.1293 +	for(t=0;t<64;t++) {
 13.1294 +		mh->pantable[t]&=0x7f;
 13.1295 +		if(mh->pantable[t]<64)
 13.1296 +			of.panning[t]=mh->pantable[t]<<2;
 13.1297 +		else if(mh->pantable[t]==64)
 13.1298 +			of.panning[t]=255;
 13.1299 +		else if(mh->pantable[t]==100)
 13.1300 +			of.panning[t]=PAN_SURROUND;
 13.1301 +		else if(mh->pantable[t]==127)
 13.1302 +			of.panning[t]=PAN_CENTER;
 13.1303 +		else {
 13.1304 +			_mm_errno=MMERR_LOADING_HEADER;
 13.1305 +			return 0;
 13.1306 +		}
 13.1307 +	}
 13.1308 +
 13.1309 +	/* set channel volumes */
 13.1310 +	memcpy(of.chanvol,mh->voltable,64);
 13.1311 +
 13.1312 +	/* read the order data */
 13.1313 +	if(!AllocPositions(mh->ordnum)) return 0;
 13.1314 +	if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
 13.1315 +
 13.1316 +	for(t=0;t<mh->ordnum;t++) {
 13.1317 +		origpositions[t]=_mm_read_UBYTE(modreader);
 13.1318 +		if((origpositions[t]>mh->patnum)&&(origpositions[t]<254))
 13.1319 +			origpositions[t]=255;
 13.1320 +	}
 13.1321 +
 13.1322 +	if(_mm_eof(modreader)) {
 13.1323 +		_mm_errno = MMERR_LOADING_HEADER;
 13.1324 +		return 0;
 13.1325 +	}
 13.1326 +
 13.1327 +	poslookupcnt=mh->ordnum;
 13.1328 +	S3MIT_CreateOrders(curious);
 13.1329 +
 13.1330 +	if(!(paraptr=(ULONG*)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*
 13.1331 +	                               sizeof(ULONG)))) return 0;
 13.1332 +
 13.1333 +	/* read the instrument, sample, and pattern parapointers */
 13.1334 +	_mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modreader);
 13.1335 +
 13.1336 +	if(_mm_eof(modreader)) {
 13.1337 +		_mm_errno = MMERR_LOADING_HEADER;
 13.1338 +		return 0;
 13.1339 +	}
 13.1340 +
 13.1341 +	/* Check for and load midi information for resonant filters */
 13.1342 +	if(mh->cmwt>=0x216) {
 13.1343 +		if(mh->special&8) {
 13.1344 +			IT_LoadMidiConfiguration(modreader);
 13.1345 +			if(_mm_eof(modreader)) {
 13.1346 +				_mm_errno = MMERR_LOADING_HEADER;
 13.1347 +				return 0;
 13.1348 +			}
 13.1349 +		} else
 13.1350 +			IT_LoadMidiConfiguration(NULL);
 13.1351 +		filters=1;
 13.1352 +	}
 13.1353 +
 13.1354 +	/* Check for and load song comment */
 13.1355 +	if((mh->special&1)&&(mh->cwt>=0x104)&&(mh->msglength)) {
 13.1356 +		_mm_fseek(modreader,(long)(mh->msgoffset),SEEK_SET);
 13.1357 +		if(!ReadComment(mh->msglength)) return 0;
 13.1358 +	}
 13.1359 +
 13.1360 +	if(!(mh->flags&4)) of.numins=of.numsmp;
 13.1361 +	if(!AllocSamples()) return 0;
 13.1362 +
 13.1363 +	if(!AllocLinear()) return 0;
 13.1364 +
 13.1365 +	/* Load all samples */
 13.1366 +	q = of.samples;
 13.1367 +	for(t=0;t<mh->smpnum;t++) {
 13.1368 +		ITSAMPLE s;
 13.1369 +
 13.1370 +		/* seek to sample position */
 13.1371 +		_mm_fseek(modreader,(long)(paraptr[mh->insnum+t]+4),SEEK_SET);
 13.1372 +
 13.1373 +		/* load sample info */
 13.1374 +		_mm_read_string(s.filename,12,modreader);
 13.1375 +		s.zerobyte    = _mm_read_UBYTE(modreader);
 13.1376 +		s.globvol     = _mm_read_UBYTE(modreader);
 13.1377 +		s.flag        = _mm_read_UBYTE(modreader);
 13.1378 +		s.volume      = _mm_read_UBYTE(modreader);
 13.1379 +		_mm_read_string(s.sampname,26,modreader);
 13.1380 +		s.convert     = _mm_read_UBYTE(modreader);
 13.1381 +		s.panning     = _mm_read_UBYTE(modreader);
 13.1382 +		s.length      = _mm_read_I_ULONG(modreader);
 13.1383 +		s.loopbeg     = _mm_read_I_ULONG(modreader);
 13.1384 +		s.loopend     = _mm_read_I_ULONG(modreader);
 13.1385 +		s.c5spd       = _mm_read_I_ULONG(modreader);
 13.1386 +		s.susbegin    = _mm_read_I_ULONG(modreader);
 13.1387 +		s.susend      = _mm_read_I_ULONG(modreader);
 13.1388 +		s.sampoffset  = _mm_read_I_ULONG(modreader);
 13.1389 +		s.vibspeed    = _mm_read_UBYTE(modreader);
 13.1390 +		s.vibdepth    = _mm_read_UBYTE(modreader);
 13.1391 +		s.vibrate     = _mm_read_UBYTE(modreader);
 13.1392 +		s.vibwave     = _mm_read_UBYTE(modreader);
 13.1393 +
 13.1394 +		/* Generate an error if c5spd is > 512k, or samplelength > 256 megs
 13.1395 +		   (nothing would EVER be that high) */
 13.1396 +
 13.1397 +		if(_mm_eof(modreader)||(s.c5spd>0x7ffffL)||(s.length>0xfffffffUL)||
 13.1398 +		   (s.loopbeg>0xfffffffUL)||(s.loopend>0xfffffffUL)) {
 13.1399 +			_mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1400 +			return 0;
 13.1401 +		}
 13.1402 +
 13.1403 +		q->samplename = DupStr(s.sampname,26,0);
 13.1404 +		q->speed      = s.c5spd / 2;
 13.1405 +		q->panning    = ((s.panning&127)==64)?255:(s.panning&127)<<2;
 13.1406 +		q->length     = s.length;
 13.1407 +		q->loopstart  = s.loopbeg;
 13.1408 +		q->loopend    = s.loopend;
 13.1409 +		q->volume     = s.volume;
 13.1410 +		q->globvol    = s.globvol;
 13.1411 +		q->seekpos    = s.sampoffset;
 13.1412 +
 13.1413 +		/* Convert speed to XM linear finetune */
 13.1414 +		if(of.flags&UF_LINEAR)
 13.1415 +			q->speed=speed_to_finetune(s.c5spd,t);
 13.1416 +
 13.1417 +		if(s.panning&128) q->flags|=SF_OWNPAN;
 13.1418 +
 13.1419 +		if(s.vibrate) {
 13.1420 +			q->vibflags |= AV_IT;
 13.1421 +			q->vibtype   = s.vibwave;
 13.1422 +			q->vibsweep  = s.vibrate * 2;
 13.1423 +			q->vibdepth  = s.vibdepth;
 13.1424 +			q->vibrate   = s.vibspeed;
 13.1425 +		}
 13.1426 +
 13.1427 +		if(s.flag&2) q->flags|=SF_16BITS;
 13.1428 +		if((s.flag&8)&&(mh->cwt>=0x214)) {
 13.1429 +			q->flags|=SF_ITPACKED;
 13.1430 +			compressed=1;
 13.1431 +		}
 13.1432 +		if(s.flag&16) q->flags|=SF_LOOP;
 13.1433 +		if(s.flag&64) q->flags|=SF_BIDI;
 13.1434 +
 13.1435 +		if(mh->cwt>=0x200) {
 13.1436 +			if(s.convert&1) q->flags|=SF_SIGNED;
 13.1437 +			if(s.convert&4) q->flags|=SF_DELTA;
 13.1438 +		}
 13.1439 +
 13.1440 +		q++;
 13.1441 +	}
 13.1442 +
 13.1443 +	/* Load instruments if instrument mode flag enabled */
 13.1444 +	if(mh->flags&4) {
 13.1445 +		if(!AllocInstruments()) return 0;
 13.1446 +		d=of.instruments;
 13.1447 +		of.flags|=UF_NNA|UF_INST;
 13.1448 +
 13.1449 +		for(t=0;t<mh->insnum;t++) {
 13.1450 +			ITINSTHEADER ih;
 13.1451 +
 13.1452 +			/* seek to instrument position */
 13.1453 +			_mm_fseek(modreader,paraptr[t]+4,SEEK_SET);
 13.1454 +
 13.1455 +			/* load instrument info */
 13.1456 +			_mm_read_string(ih.filename,12,modreader);
 13.1457 +			ih.zerobyte  = _mm_read_UBYTE(modreader);
 13.1458 +			if(mh->cwt<0x200) {
 13.1459 +				/* load IT 1.xx inst header */
 13.1460 +				ih.volflg    = _mm_read_UBYTE(modreader);
 13.1461 +				ih.volbeg    = _mm_read_UBYTE(modreader);
 13.1462 +				ih.volend    = _mm_read_UBYTE(modreader);
 13.1463 +				ih.volsusbeg = _mm_read_UBYTE(modreader);
 13.1464 +				ih.volsusend = _mm_read_UBYTE(modreader);
 13.1465 +				_mm_read_I_UWORD(modreader);
 13.1466 +				ih.fadeout   = _mm_read_I_UWORD(modreader);
 13.1467 +				ih.nna       = _mm_read_UBYTE(modreader);
 13.1468 +				ih.dnc       = _mm_read_UBYTE(modreader);
 13.1469 +			} else {
 13.1470 +				/* Read IT200+ header */
 13.1471 +				ih.nna       = _mm_read_UBYTE(modreader);
 13.1472 +				ih.dct       = _mm_read_UBYTE(modreader);
 13.1473 +				ih.dca       = _mm_read_UBYTE(modreader);
 13.1474 +				ih.fadeout   = _mm_read_I_UWORD(modreader);
 13.1475 +				ih.ppsep     = _mm_read_UBYTE(modreader);
 13.1476 +				ih.ppcenter  = _mm_read_UBYTE(modreader);
 13.1477 +				ih.globvol   = _mm_read_UBYTE(modreader);
 13.1478 +				ih.chanpan   = _mm_read_UBYTE(modreader);
 13.1479 +				ih.rvolvar   = _mm_read_UBYTE(modreader);
 13.1480 +				ih.rpanvar   = _mm_read_UBYTE(modreader);
 13.1481 +			}
 13.1482 +
 13.1483 +			ih.trkvers   = _mm_read_I_UWORD(modreader);
 13.1484 +			ih.numsmp    = _mm_read_UBYTE(modreader);
 13.1485 +			_mm_read_UBYTE(modreader);
 13.1486 +			_mm_read_string(ih.name,26,modreader);
 13.1487 +			_mm_read_UBYTES(ih.blank01,6,modreader);
 13.1488 +			_mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader);
 13.1489 +			if(mh->cwt<0x200) {
 13.1490 +				/* load IT 1xx volume envelope */
 13.1491 +				_mm_read_UBYTES(ih.volenv,200,modreader);
 13.1492 +				for(lp=0;lp<ITENVCNT;lp++) {
 13.1493 +					ih.oldvoltick[lp] = _mm_read_UBYTE(modreader);
 13.1494 +					ih.volnode[lp]    = _mm_read_UBYTE(modreader);
 13.1495 +				}
 13.1496 +			} else {
 13.1497 +				/* load IT 2xx volume, pan and pitch envelopes */
 13.1498 +#ifdef __STDC__
 13.1499 +#define IT_LoadEnvelope(name,type) 											\
 13.1500 +				ih.##name##flg   =_mm_read_UBYTE(modreader);				\
 13.1501 +				ih.##name##pts   =_mm_read_UBYTE(modreader);				\
 13.1502 +				ih.##name##beg   =_mm_read_UBYTE(modreader);				\
 13.1503 +				ih.##name##end   =_mm_read_UBYTE(modreader);				\
 13.1504 +				ih.##name##susbeg=_mm_read_UBYTE(modreader);				\
 13.1505 +				ih.##name##susend=_mm_read_UBYTE(modreader);				\
 13.1506 +				for(lp=0;lp<ITENVCNT;lp++) {								\
 13.1507 +					ih.##name##node[lp]=_mm_read_##type##(modreader);		\
 13.1508 +					ih.##name##tick[lp]=_mm_read_I_UWORD(modreader);		\
 13.1509 +				}															\
 13.1510 +				_mm_read_UBYTE(modreader);
 13.1511 +#else
 13.1512 +#define IT_LoadEnvelope(name,type) 											\
 13.1513 +				ih./**/name/**/flg   =_mm_read_UBYTE(modreader);			\
 13.1514 +				ih./**/name/**/pts   =_mm_read_UBYTE(modreader);			\
 13.1515 +				ih./**/name/**/beg   =_mm_read_UBYTE(modreader);			\
 13.1516 +				ih./**/name/**/end   =_mm_read_UBYTE(modreader);			\
 13.1517 +				ih./**/name/**/susbeg=_mm_read_UBYTE(modreader);			\
 13.1518 +				ih./**/name/**/susend=_mm_read_UBYTE(modreader);			\
 13.1519 +				for(lp=0;lp<ITENVCNT;lp++) {								\
 13.1520 +					ih./**/name/**/node[lp]=_mm_read_/**/type/**/(modreader);\
 13.1521 +					ih./**/name/**/tick[lp]=_mm_read_I_UWORD(modreader);	\
 13.1522 +				}															\
 13.1523 +				_mm_read_UBYTE(modreader);
 13.1524 +#endif
 13.1525 +
 13.1526 +				IT_LoadEnvelope(vol,UBYTE);
 13.1527 +				IT_LoadEnvelope(pan,SBYTE);
 13.1528 +				IT_LoadEnvelope(pit,SBYTE);
 13.1529 +#undef IT_LoadEnvelope
 13.1530 +			}
 13.1531 +
 13.1532 +			if(_mm_eof(modreader)) {
 13.1533 +				_mm_errno = MMERR_LOADING_SAMPLEINFO;
 13.1534 +				return 0;
 13.1535 +			}
 13.1536 +
 13.1537 +			d->volflg|=EF_VOLENV;
 13.1538 +			d->insname = DupStr(ih.name,26,0);
 13.1539 +			d->nnatype = ih.nna;
 13.1540 +
 13.1541 +			if(mh->cwt<0x200) {
 13.1542 +				d->volfade=ih.fadeout<< 6;
 13.1543 +				if(ih.dnc) {
 13.1544 +					d->dct=DCT_NOTE;
 13.1545 +					d->dca=DCA_CUT;
 13.1546 +				}
 13.1547 +
 13.1548 +				if(ih.volflg&1) d->volflg|=EF_ON;
 13.1549 +				if(ih.volflg&2) d->volflg|=EF_LOOP;
 13.1550 +				if(ih.volflg&4) d->volflg|=EF_SUSTAIN;
 13.1551 +
 13.1552 +				/* XM conversion of IT envelope Array */
 13.1553 +				d->volbeg    = ih.volbeg;
 13.1554 +				d->volend    = ih.volend;
 13.1555 +				d->volsusbeg = ih.volsusbeg;
 13.1556 +				d->volsusend = ih.volsusend;
 13.1557 +
 13.1558 +				if(ih.volflg&1) {
 13.1559 +					for(u=0;u<ITENVCNT;u++)
 13.1560 +						if(ih.oldvoltick[d->volpts]!=0xff) {
 13.1561 +							d->volenv[d->volpts].val=(ih.volnode[d->volpts]<<2);
 13.1562 +							d->volenv[d->volpts].pos=ih.oldvoltick[d->volpts];
 13.1563 +							d->volpts++;
 13.1564 +						} else
 13.1565 +							break;
 13.1566 +				}
 13.1567 +			} else {
 13.1568 +				d->panning=((ih.chanpan&127)==64)?255:(ih.chanpan&127)<<2;
 13.1569 +				if(!(ih.chanpan&128)) d->flags|=IF_OWNPAN;
 13.1570 +
 13.1571 +				if(!(ih.ppsep & 128)) {
 13.1572 +					d->pitpansep=ih.ppsep<<2;
 13.1573 +					d->pitpancenter=ih.ppcenter;
 13.1574 +					d->flags|=IF_PITCHPAN;
 13.1575 +				}
 13.1576 +				d->globvol=ih.globvol>>1;
 13.1577 +				d->volfade=ih.fadeout<<5;
 13.1578 +				d->dct    =ih.dct;
 13.1579 +				d->dca    =ih.dca;
 13.1580 +
 13.1581 +				if(mh->cwt>=0x204) {
 13.1582 +					d->rvolvar = ih.rvolvar;
 13.1583 +					d->rpanvar = ih.rpanvar;
 13.1584 +				}
 13.1585 +
 13.1586 +#ifdef __STDC__
 13.1587 +#define IT_ProcessEnvelope(name) 											\
 13.1588 +				if(ih.##name##flg&1) d->##name##flg|=EF_ON;					\
 13.1589 +				if(ih.##name##flg&2) d->##name##flg|=EF_LOOP;				\
 13.1590 +				if(ih.##name##flg&4) d->##name##flg|=EF_SUSTAIN;			\
 13.1591 +				d->##name##pts=ih.##name##pts;								\
 13.1592 +				d->##name##beg=ih.##name##beg;								\
 13.1593 +				d->##name##end=ih.##name##end;								\
 13.1594 +				d->##name##susbeg=ih.##name##susbeg;						\
 13.1595 +				d->##name##susend=ih.##name##susend;						\
 13.1596 +																			\
 13.1597 +				for(u=0;u<ih.##name##pts;u++)								\
 13.1598 +					d->##name##env[u].pos=ih.##name##tick[u];				\
 13.1599 +																			\
 13.1600 +				if((d->##name##flg&EF_ON)&&(d->##name##pts<2))				\
 13.1601 +					d->##name##flg&=~EF_ON;
 13.1602 +#else
 13.1603 +#define IT_ProcessEnvelope(name) 											\
 13.1604 +				if(ih./**/name/**/flg&1) d->/**/name/**/flg|=EF_ON;			\
 13.1605 +				if(ih./**/name/**/flg&2) d->/**/name/**/flg|=EF_LOOP;		\
 13.1606 +				if(ih./**/name/**/flg&4) d->/**/name/**/flg|=EF_SUSTAIN;	\
 13.1607 +				d->/**/name/**/pts=ih./**/name/**/pts;						\
 13.1608 +				d->/**/name/**/beg=ih./**/name/**/beg;						\
 13.1609 +				d->/**/name/**/end=ih./**/name/**/end;						\
 13.1610 +				d->/**/name/**/susbeg=ih./**/name/**/susbeg;				\
 13.1611 +				d->/**/name/**/susend=ih./**/name/**/susend;				\
 13.1612 +																			\
 13.1613 +				for(u=0;u<ih./**/name/**/pts;u++)							\
 13.1614 +					d->/**/name/**/env[u].pos=ih./**/name/**/tick[u];		\
 13.1615 +																			\
 13.1616 +				if((d->/**/name/**/flg&EF_ON)&&(d->/**/name/**/pts<2))		\
 13.1617 +					d->/**/name/**/flg&=~EF_ON;
 13.1618 +#endif
 13.1619 +
 13.1620 +				IT_ProcessEnvelope(vol);
 13.1621 +				for(u=0;u<ih.volpts;u++)
 13.1622 +					d->volenv[u].val=(ih.volnode[u]<<2);
 13.1623 +
 13.1624 +				IT_ProcessEnvelope(pan);
 13.1625 +				for(u=0;u<ih.panpts;u++)
 13.1626 +					d->panenv[u].val=
 13.1627 +					  ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2;
 13.1628 +
 13.1629 +				IT_ProcessEnvelope(pit);
 13.1630 +				for(u=0;u<ih.pitpts;u++)
 13.1631 +					d->pitenv[u].val=ih.pitnode[u]+32;
 13.1632 +#undef IT_ProcessEnvelope
 13.1633 +
 13.1634 +				if(ih.pitflg&0x80) {
 13.1635 +					/* filter envelopes not supported yet */
 13.1636 +					d->pitflg&=~EF_ON;
 13.1637 +					ih.pitpts=ih.pitbeg=ih.pitend=0;
 13.1638 +#ifdef MIKMOD_DEBUG
 13.1639 +					{
 13.1640 +						static int warn=0;
 13.1641 +
 13.1642 +						if(!warn)
 13.1643 +							fputs("\rFilter envelopes not supported yet\n",stderr);
 13.1644 +						warn=1;
 13.1645 +					}
 13.1646 +#endif
 13.1647 +				}
 13.1648 +
 13.1649 +				d->volpts    = ih.volpts;
 13.1650 +				d->volbeg    = ih.volbeg;
 13.1651 +				d->volend    = ih.volend;
 13.1652 +				d->volsusbeg = ih.volsusbeg;
 13.1653 +				d->volsusend = ih.volsusend;
 13.1654 +
 13.1655 +				for(u=0;u<ih.volpts;u++) {
 13.1656 +					d->volenv[u].val=(ih.volnode[u]<<2);
 13.1657 +					d->volenv[u].pos=ih.voltick[u];
 13.1658 +				}
 13.1659 +
 13.1660 +				d->panpts    = ih.panpts;
 13.1661 +				d->panbeg    = ih.panbeg;
 13.1662 +				d->panend    = ih.panend;
 13.1663 +				d->pansusbeg = ih.pansusbeg;
 13.1664 +				d->pansusend = ih.pansusend;
 13.1665 +
 13.1666 +				for(u=0;u<ih.panpts;u++) {
 13.1667 +					d->panenv[u].val=ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2;
 13.1668 +					d->panenv[u].pos=ih.pantick[u];
 13.1669 +				}
 13.1670 +
 13.1671 +				d->pitpts   =ih.pitpts;
 13.1672 +				d->pitbeg   =ih.pitbeg;
 13.1673 +				d->pitend   =ih.pitend;
 13.1674 +				d->pitsusbeg=ih.pitsusbeg;
 13.1675 +				d->pitsusend=ih.pitsusend;
 13.1676 +
 13.1677 +				for(u=0;u<ih.pitpts;u++) {
 13.1678 +					d->pitenv[u].val=ih.pitnode[u]+32;
 13.1679 +					d->pitenv[u].pos=ih.pittick[u];
 13.1680 +				}
 13.1681 +			}
 13.1682 +
 13.1683 +			for(u=0;u<ITNOTECNT;u++) {
 13.1684 +				d->samplenote[u]=(ih.samptable[u]&255);
 13.1685 +				d->samplenumber[u]=
 13.1686 +				  (ih.samptable[u]>>8)?((ih.samptable[u]>>8)-1):0xffff;
 13.1687 +				if(d->samplenumber[u]>=of.numsmp)
 13.1688 +					d->samplenote[u]=255;
 13.1689 +				else if (of.flags&UF_LINEAR) {
 13.1690 +					int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];
 13.1691 +					d->samplenote[u]=(note<0)?0:(note>255?255:note);
 13.1692 +				}
 13.1693 +			}
 13.1694 +
 13.1695 +			d++;
 13.1696 +		}
 13.1697 +	} else if(of.flags & UF_LINEAR) {
 13.1698 +		if(!AllocInstruments()) return 0;
 13.1699 +		d=of.instruments;
 13.1700 +		of.flags|=UF_INST;
 13.1701 +
 13.1702 +		for(t=0;t<mh->smpnum;t++,d++)
 13.1703 +			for(u=0;u<ITNOTECNT;u++) {
 13.1704 +				if(d->samplenumber[u]>=of.numsmp)
 13.1705 +					d->samplenote[u]=255;
 13.1706 +				else {
 13.1707 +					int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];
 13.1708 +					d->samplenote[u]=(note<0)?0:(note>255?255:note);
 13.1709 +				}
 13.1710 +			}
 13.1711 +	}
 13.1712 +
 13.1713 +	/* Figure out how many channels this song actually uses */
 13.1714 +	of.numchn=0;
 13.1715 +	memset(remap,-1,64*sizeof(UBYTE));
 13.1716 +	for(t=0;t<of.numpat;t++) {
 13.1717 +		UWORD packlen;
 13.1718 +
 13.1719 +		/* seek to pattern position */
 13.1720 +		if(paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */
 13.1721 +			_mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);
 13.1722 +			_mm_read_I_UWORD(modreader);
 13.1723 +			/* read pattern length (# of rows)
 13.1724 +			   Impulse Tracker never creates patterns with less than 32 rows,
 13.1725 +			   but some other trackers do, so we only check for more than 256
 13.1726 +			   rows */
 13.1727 +			packlen=_mm_read_I_UWORD(modreader);
 13.1728 +			if(packlen>256) {
 13.1729 +				_mm_errno=MMERR_LOADING_PATTERN;
 13.1730 +				return 0;
 13.1731 +			}
 13.1732 +			_mm_read_I_ULONG(modreader);
 13.1733 +			if(IT_GetNumChannels(packlen)) return 0;
 13.1734 +		}
 13.1735 +	}
 13.1736 +
 13.1737 +	/* give each of them a different number */
 13.1738 +	for(t=0;t<64;t++)
 13.1739 +		if(!remap[t])
 13.1740 +			remap[t]=of.numchn++;
 13.1741 +
 13.1742 +	of.numtrk = of.numpat*of.numchn;
 13.1743 +	if(of.numvoices)
 13.1744 +		if (of.numvoices<of.numchn) of.numvoices=of.numchn;
 13.1745 +
 13.1746 +	if(!AllocPatterns()) return 0;
 13.1747 +	if(!AllocTracks()) return 0;
 13.1748 +
 13.1749 +	for(t=0;t<of.numpat;t++) {
 13.1750 +		UWORD packlen;
 13.1751 +
 13.1752 +		/* seek to pattern position */
 13.1753 +		if(!paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */
 13.1754 +			of.pattrows[t]=64;
 13.1755 +			for(u=0;u<of.numchn;u++) {
 13.1756 +				int k;
 13.1757 +
 13.1758 +				UniReset();
 13.1759 +				for(k=0;k<64;k++) UniNewline();
 13.1760 +				of.tracks[numtrk++]=UniDup();
 13.1761 +			}
 13.1762 +		} else {
 13.1763 +			_mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);
 13.1764 +			packlen=_mm_read_I_UWORD(modreader);
 13.1765 +			of.pattrows[t]=_mm_read_I_UWORD(modreader);
 13.1766 +			_mm_read_I_ULONG(modreader);
 13.1767 +			if(!IT_ReadPattern(of.pattrows[t])) return 0;
 13.1768 +		}
 13.1769 +	}
 13.1770 +
 13.1771 +	return 1;
 13.1772 +}
 13.1773  
 13.1774  CHAR *IT_LoadTitle(void)
 13.1775  {
 13.1776 -   CHAR s[26];
 13.1777 +	CHAR s[26];
 13.1778  
 13.1779 -   _mm_fseek(modfp,4,SEEK_SET);
 13.1780 -   if(!fread(s,26,1,modfp)) return NULL;
 13.1781 -   
 13.1782 -   return(DupStr(s,26));
 13.1783 +	_mm_fseek(modreader,4,SEEK_SET);
 13.1784 +	if(!_mm_read_UBYTES(s,26,modreader)) return NULL;
 13.1785 +
 13.1786 +	return(DupStr(s,26,0));
 13.1787  }
 13.1788  
 13.1789 +/*========== Loader information */
 13.1790  
 13.1791 -MLOADER load_it =
 13.1792 -{   NULL,
 13.1793 -    "IT",
 13.1794 -    "Portable IT loader v0.2",
 13.1795 -    IT_Init,
 13.1796 -    IT_Test,
 13.1797 -    IT_Load,
 13.1798 -    IT_Cleanup,
 13.1799 -
 13.1800 -    IT_LoadTitle
 13.1801 +MLOADER load_it={
 13.1802 +	NULL,
 13.1803 +	"IT",
 13.1804 +	"IT (Impulse Tracker)",
 13.1805 +	IT_Init,
 13.1806 +	IT_Test,
 13.1807 +	IT_Load,
 13.1808 +	IT_Cleanup,
 13.1809 +	IT_LoadTitle
 13.1810  };
 13.1811  
 13.1812 +/* 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 -
   14.25 - If this module is found to not be portable to any particular platform,
   14.26 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   14.27 - more information on contacting the author).
   14.28 -
   14.29 +	You should have received a copy of the GNU Library General Public
   14.30 +	License along with this library; if not, write to the Free Software
   14.31 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   14.32 +	02111-1307, USA.
   14.33  */
   14.34  
   14.35 +/*==============================================================================
   14.36 +
   14.37 +  $Id$
   14.38 +
   14.39 +  Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
   14.40 +
   14.41 +==============================================================================*/
   14.42 +
   14.43 +#ifdef HAVE_CONFIG_H
   14.44 +#include "config.h"
   14.45 +#endif
   14.46 +
   14.47  #include <string.h>
   14.48 -#include "mikmod.h"
   14.49  
   14.50 -/*************************************************************************
   14.51 -*************************************************************************/
   14.52 +#include "mikmod_internals.h"
   14.53  
   14.54 +/*========== Module structure */
   14.55  
   14.56 -typedef struct MSAMPINFO                  /* sample header as it appears in a module */
   14.57 -{   CHAR  samplename[22];
   14.58 -    UWORD length;
   14.59 -    UBYTE finetune;
   14.60 -    UBYTE volume;
   14.61 -    UWORD reppos;
   14.62 -    UWORD replen;
   14.63 +typedef struct MSAMPINFO {
   14.64 +	CHAR  samplename[23];	/* 22 in module, 23 in memory */
   14.65 +	UWORD length;
   14.66 +	UBYTE finetune;
   14.67 +	UBYTE volume;
   14.68 +	UWORD reppos;
   14.69 +	UWORD replen;
   14.70  } MSAMPINFO;
   14.71  
   14.72 +typedef struct MODULEHEADER {
   14.73 +	CHAR      songname[21];		/* the songname.. 20 in module, 21 in memory */
   14.74 +	MSAMPINFO samples[31];		/* all sampleinfo */
   14.75 +	UBYTE     songlength;		/* number of patterns used */
   14.76 +	UBYTE     magic1;			/* should be 127 */
   14.77 +	UBYTE     positions[128];	/* which pattern to play at pos */
   14.78 +	UBYTE     magic2[4];		/* string "M.K." or "FLT4" or "FLT8" */
   14.79 +} MODULEHEADER;
   14.80  
   14.81 -typedef struct MODULEHEADER              /* verbatim module header */
   14.82 -{   CHAR       songname[20];             /* the songname.. */
   14.83 -    MSAMPINFO  samples[31];              /* all sampleinfo */
   14.84 -    UBYTE      songlength;               /* number of patterns used */
   14.85 -    UBYTE      magic1;                   /* should be 127 */
   14.86 -    UBYTE      positions[128];           /* which pattern to play at pos */
   14.87 -    UBYTE      magic2[4];                /* string "M.K." or "FLT4" or "FLT8" */
   14.88 -} MODULEHEADER;
   14.89 +typedef struct MODTYPE {
   14.90 +	CHAR  id[5];
   14.91 +	UBYTE channels;
   14.92 +	CHAR  *name;
   14.93 +} MODTYPE;
   14.94 +
   14.95 +typedef struct MODNOTE {
   14.96 +	UBYTE a,b,c,d;
   14.97 +} MODNOTE;
   14.98 +
   14.99 +/*========== Loader variables */
  14.100  
  14.101  #define MODULEHEADERSIZE 1084
  14.102  
  14.103 +static CHAR protracker[]   = "Protracker";
  14.104 +static CHAR startracker[]  = "Startracker";
  14.105 +static CHAR fasttracker[]  = "Fasttracker";
  14.106 +static CHAR ins15tracker[] = "15-instrument";
  14.107 +static CHAR oktalyzer[]    = "Oktalyzer";
  14.108 +static CHAR taketracker[]  = "TakeTracker";
  14.109 +static CHAR orpheus[]      = "Imago Orpheus (MOD format)";
  14.110  
  14.111 -typedef struct MODTYPE              /* struct to identify type of module */
  14.112 -{   CHAR    id[5];
  14.113 -    UBYTE   channels;
  14.114 -    CHAR    *name;
  14.115 -} MODTYPE;
  14.116 -
  14.117 -
  14.118 -typedef struct MODNOTE
  14.119 -{   UBYTE a,b,c,d;
  14.120 -} MODNOTE;
  14.121 -
  14.122 -
  14.123 -/*************************************************************************
  14.124 -*************************************************************************/
  14.125 -
  14.126 -
  14.127 -CHAR protracker[]   = "Protracker";
  14.128 -CHAR startracker[]  = "Startracker";
  14.129 -CHAR fasttracker[]  = "Fasttracker";
  14.130 -CHAR ins15tracker[] = "15-instrument";
  14.131 -CHAR oktalyzer[]    = "Oktalyzer";
  14.132 -CHAR taketracker[]  = "TakeTracker";
  14.133 -
  14.134 -
  14.135 -MODTYPE modtypes[] =
  14.136 -{   "M.K.",4,protracker,      /* protracker 4 channel */
  14.137 -    "M!K!",4,protracker,      /* protracker 4 channel */
  14.138 -    "FLT4",4,startracker,     /* startracker 4 channel */
  14.139 -    "2CHN",2,fasttracker,     /* fasttracker 2 channel */
  14.140 -    "4CHN",4,fasttracker,     /* fasttracker 4 channel */
  14.141 -    "6CHN",6,fasttracker,     /* fasttracker 6 channel */
  14.142 -    "8CHN",8,fasttracker,     /* fasttracker 8 channel */
  14.143 -    "10CH",10,fasttracker,    /* fasttracker 10 channel */
  14.144 -    "12CH",12,fasttracker,    /* fasttracker 12 channel */
  14.145 -    "14CH",14,fasttracker,    /* fasttracker 14 channel */
  14.146 -    "16CH",16,fasttracker,    /* fasttracker 16 channel */
  14.147 -    "18CH",18,fasttracker,    /* fasttracker 18 channel */
  14.148 -    "20CH",20,fasttracker,    /* fasttracker 20 channel */
  14.149 -    "22CH",22,fasttracker,    /* fasttracker 22 channel */
  14.150 -    "24CH",24,fasttracker,    /* fasttracker 24 channel */
  14.151 -    "26CH",26,fasttracker,    /* fasttracker 26 channel */
  14.152 -    "28CH",28,fasttracker,    /* fasttracker 28 channel */
  14.153 -    "30CH",30,fasttracker,    /* fasttracker 30 channel */
  14.154 -    "32CH",32,fasttracker,    /* fasttracker 32 channel */
  14.155 -    "CD81",8,oktalyzer,       /* atari oktalyzer 8 channel */
  14.156 -    "OKTA",8,oktalyzer,       /* atari oktalyzer 8 channel */
  14.157 -    "16CN",16,taketracker,    /* taketracker 16 channel */
  14.158 -    "32CN",32,taketracker,    /* taketracker 32 channel */
  14.159 -    "    ",4,ins15tracker     /* 15-instrument 4 channel     */
  14.160 +#define MODTYPE_COUNT 24
  14.161 +static MODTYPE modtypes[MODTYPE_COUNT+1]={
  14.162 +	{"M.K.", 4,  protracker},	/* protracker 4 channel */
  14.163 +	{"M!K!", 4,  protracker},	/* protracker 4 channel */
  14.164 +	{"FLT4", 4, startracker},	/* startracker 4 channel */
  14.165 +	{"2CHN", 2, fasttracker},	/* fasttracker 2 channel */
  14.166 +	{"4CHN", 4, fasttracker},	/* fasttracker 4 channel */
  14.167 +	{"6CHN", 6, fasttracker},	/* fasttracker 6 channel */
  14.168 +	{"8CHN", 8, fasttracker},	/* fasttracker 8 channel */
  14.169 +	{"10CH",10, fasttracker},	/* fasttracker 10 channel */
  14.170 +	{"12CH",12, fasttracker},	/* fasttracker 12 channel */
  14.171 +	{"14CH",14, fasttracker},	/* fasttracker 14 channel */
  14.172 +	{"15CH",15, fasttracker},	/* fasttracker 15 channel */
  14.173 +	{"16CH",16, fasttracker},	/* fasttracker 16 channel */
  14.174 +	{"18CH",18, fasttracker},	/* fasttracker 18 channel */
  14.175 +	{"20CH",20, fasttracker},	/* fasttracker 20 channel */
  14.176 +	{"22CH",22, fasttracker},	/* fasttracker 22 channel */
  14.177 +	{"24CH",24, fasttracker},	/* fasttracker 24 channel */
  14.178 +	{"26CH",26, fasttracker},	/* fasttracker 26 channel */
  14.179 +	{"28CH",28, fasttracker},	/* fasttracker 28 channel */
  14.180 +	{"30CH",30, fasttracker},	/* fasttracker 30 channel */
  14.181 +	{"32CH",32, fasttracker},	/* fasttracker 32 channel */
  14.182 +	{"CD81", 8,   oktalyzer},	/* atari oktalyzer 8 channel */
  14.183 +	{"OKTA", 8,   oktalyzer},	/* atari oktalyzer 8 channel */
  14.184 +	{"16CN",16, taketracker},	/* taketracker 16 channel */
  14.185 +	{"32CN",32, taketracker},	/* taketracker 32 channel */
  14.186 +	{"    ", 4,ins15tracker}	/* 15-instrument 4 channel */
  14.187  };
  14.188  
  14.189 -static MODULEHEADER *mh = NULL;        /* raw as-is module header */
  14.190 +static MODULEHEADER *mh = NULL;
  14.191  static MODNOTE *patbuf = NULL;
  14.192  static int modtype = 0;
  14.193  
  14.194 -BOOL MOD_Test(void)
  14.195 +/*========== Loader code */
  14.196 +
  14.197 +static BOOL MOD_Test(void)
  14.198  {
  14.199 -    UBYTE id[4];
  14.200 +	UBYTE id[4];
  14.201  
  14.202 -    _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
  14.203 -    if(!fread(id,4,1,modfp)) return 0;
  14.204 +	_mm_fseek(modreader,MODULEHEADERSIZE-4,SEEK_SET);
  14.205 +	if(!_mm_read_UBYTES(id,4,modreader)) return 0;
  14.206  
  14.207 -    /* find out which ID string */
  14.208 +	/* find out which ID string */
  14.209 +	for(modtype=0;modtype<MODTYPE_COUNT;modtype++)
  14.210 +		if(!memcmp(id,modtypes[modtype].id,4)) return 1;
  14.211  
  14.212 -    for(modtype=0; modtype<23; modtype++)
  14.213 -        if(!memcmp(id,modtypes[modtype].id,4)) return 1;
  14.214 -
  14.215 -    return 0;
  14.216 +	return 0;
  14.217  }
  14.218  
  14.219 -
  14.220 -BOOL MOD_Init(void)
  14.221 +static BOOL MOD_Init(void)
  14.222  {
  14.223 -    if(!(mh=(MODULEHEADER *)_mm_calloc(1,sizeof(MODULEHEADER)))) return 0;
  14.224 -    return 1;
  14.225 +	if(	!(mh=(MODULEHEADER*)_mm_malloc(sizeof(MODULEHEADER)))) return 0;
  14.226 +	return 1;
  14.227  }
  14.228  
  14.229 -
  14.230 -void MOD_Cleanup(void)
  14.231 +static void MOD_Cleanup(void)
  14.232  {
  14.233 -    if(mh!=NULL) free(mh);
  14.234 -    if(patbuf!=NULL) free(patbuf);
  14.235 -
  14.236 -    mh = NULL;
  14.237 -    patbuf = NULL;
  14.238 +	_mm_free(mh);
  14.239 +	_mm_free(patbuf);
  14.240  }
  14.241  
  14.242 -
  14.243  /*
  14.244  Old (amiga) noteinfo:
  14.245  
  14.246 - _____byte 1_____   byte2_    _____byte 3_____   byte4_
  14.247 +_____byte 1_____   byte2_    _____byte 3_____   byte4_
  14.248  /                \ /      \  /                \ /      \
  14.249  0000          0000-00000000  0000          0000-00000000
  14.250  
  14.251 @@ -144,198 +150,233 @@
  14.252  
  14.253  */
  14.254  
  14.255 +static void ConvertNote(MODNOTE* n)
  14.256 +{
  14.257 +	UBYTE instrument,effect,effdat,note;
  14.258 +	UWORD period;
  14.259 +	UBYTE lastnote=0;
  14.260  
  14.261 -void ConvertNote(MODNOTE *n)
  14.262 -{
  14.263 -    UBYTE instrument,effect,effdat,note;
  14.264 -    UWORD period;
  14.265 +	/* extract the various information from the 4 bytes that make up a note */
  14.266 +	instrument = (n->a&0x10)|(n->c>>4);
  14.267 +	period     = (((UWORD)n->a&0xf)<<8)+n->b;
  14.268 +	effect     = n->c&0xf;
  14.269 +	effdat     = n->d;
  14.270  
  14.271 -    /* extract the various information from the 4 bytes that */
  14.272 -    /* make up a single note */
  14.273 +	/* Convert the period to a note number */
  14.274 +	note=0;
  14.275 +	if(period) {
  14.276 +		for(note=0;note<7*OCTAVE;note++)
  14.277 +			if(period>=npertab[note]) break;
  14.278 +		if(note==7*OCTAVE) note=0;
  14.279 +		else note++;
  14.280 +	}
  14.281  
  14.282 -    instrument = (n->a&0x10)|(n->c>>4);
  14.283 -    period     = (((UWORD)n->a&0xf)<<8)+n->b;
  14.284 -    effect     = n->c&0xf;
  14.285 -    effdat     = n->d;
  14.286 +	if(instrument) {
  14.287 +		/* if instrument does not exist, note cut */
  14.288 +		if((instrument>31)||(!mh->samples[instrument-1].length)) {
  14.289 +			UniPTEffect(0xc,0);
  14.290 +			if(effect==0xc) effect=effdat=0;
  14.291 +		} else {
  14.292 +			/* Protracker handling */
  14.293 +			if(modtype<=2) {
  14.294 +				/* if we had a note, then change instrument... */
  14.295 +				if(note)
  14.296 +					UniInstrument(instrument-1);
  14.297 +				/* ...otherwise, only adjust volume... */
  14.298 +				else {
  14.299 +					/* ...unless an effect was specified, which forces a new
  14.300 +					   note to be played */
  14.301 +					if(effect||effdat) {
  14.302 +						UniInstrument(instrument-1);
  14.303 +						note=lastnote;
  14.304 +					} else
  14.305 +						UniPTEffect(0xc,mh->samples[instrument-1].volume&0x7f);
  14.306 +				}
  14.307 +			} else {
  14.308 +			/* Fasttracker handling */
  14.309 +				UniInstrument(instrument-1);
  14.310 +				if(!note) note=lastnote;
  14.311 +			}
  14.312 +		}
  14.313 +	}
  14.314 +	if(note) {
  14.315 +		UniNote(note+2*OCTAVE-1);
  14.316 +		lastnote=note;
  14.317 +	}
  14.318  
  14.319 -    /* Convert the period to a note number */
  14.320 +	/* Convert pattern jump from Dec to Hex */
  14.321 +	if(effect==0xd)
  14.322 +		effdat=(((effdat&0xf0)>>4)*10)+(effdat&0xf);
  14.323  
  14.324 -    note=0;
  14.325 -    if(period!=0)
  14.326 -    {   for(note=0; note<60; note++)
  14.327 -            if(period >= npertab[note]) break;
  14.328 -        note++;
  14.329 -        if(note==61) note = 0;
  14.330 -    }
  14.331 +	/* Volume slide, up has priority */
  14.332 +	if((effect==0xa)&&(effdat&0xf)&&(effdat&0xf0))
  14.333 +		effdat&=0xf0;
  14.334  
  14.335 -    if(instrument!=0) UniInstrument(instrument-1);
  14.336 -    if(note!=0) UniNote(note+23);
  14.337 -
  14.338 -    /* Convert pattern jump from Dec to Hex */
  14.339 -    if(effect == 0xd)
  14.340 -        effdat = (((effdat&0xf0)>>4)*10)+(effdat&0xf);
  14.341 -
  14.342 -    UniPTEffect(effect,effdat);
  14.343 +	UniPTEffect(effect,effdat);
  14.344  }
  14.345  
  14.346 +static UBYTE* ConvertTrack(MODNOTE* n)
  14.347 +{
  14.348 +	int t;
  14.349  
  14.350 -UBYTE *ConvertTrack(MODNOTE *n)
  14.351 -{
  14.352 -    int t;
  14.353 -
  14.354 -    UniReset();
  14.355 -    for(t=0;t<64;t++)
  14.356 -    {   ConvertNote(n);
  14.357 -        UniNewline();
  14.358 -        n+=of.numchn;
  14.359 -    }
  14.360 -    return UniDup();
  14.361 +	UniReset();
  14.362 +	for(t=0;t<64;t++) {
  14.363 +		ConvertNote(n);
  14.364 +		UniNewline();
  14.365 +		n+=of.numchn;
  14.366 +	}
  14.367 +	return UniDup();
  14.368  }
  14.369  
  14.370 +/* Loads all patterns of a modfile and converts them into the 3 byte format. */
  14.371 +static BOOL ML_LoadPatterns(void)
  14.372 +{
  14.373 +	int t,s,tracks = 0;
  14.374  
  14.375 -BOOL ML_LoadPatterns(void)
  14.376 -/*  Loads all patterns of a modfile and converts them into the */
  14.377 -/*  3 byte format. */
  14.378 -{
  14.379 -    int t,s,tracks = 0;
  14.380 +	if(!AllocPatterns()) return 0;
  14.381 +	if(!AllocTracks())   return 0;
  14.382  
  14.383 -    if(!AllocPatterns()) return 0;
  14.384 -    if(!AllocTracks())   return 0;
  14.385 +	/* Allocate temporary buffer for loading and converting the patterns */
  14.386 +	if(!(patbuf=(MODNOTE*)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  14.387  
  14.388 -    /* Allocate temporary buffer for loading */
  14.389 -    /* and converting the patterns */
  14.390 -
  14.391 -    if(!(patbuf=(MODNOTE *)_mm_calloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  14.392 -
  14.393 -    for(t=0; t<of.numpat; t++)
  14.394 -    {   /* Load the pattern into the temp buffer */
  14.395 -        /* and convert it */
  14.396 -
  14.397 -        for(s=0; s<(64U*of.numchn); s++)
  14.398 -        {   patbuf[s].a = _mm_read_UBYTE(modfp);
  14.399 -            patbuf[s].b = _mm_read_UBYTE(modfp);
  14.400 -            patbuf[s].c = _mm_read_UBYTE(modfp);
  14.401 -            patbuf[s].d = _mm_read_UBYTE(modfp);
  14.402 -        }
  14.403 -
  14.404 -        for(s=0; s<of.numchn; s++)
  14.405 -            if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  14.406 -    }
  14.407 -
  14.408 -    return 1;
  14.409 +	for(t=0;t<of.numpat;t++) {
  14.410 +		/* Load the pattern into the temp buffer and convert it */
  14.411 +		for(s=0;s<(64U*of.numchn);s++) {
  14.412 +			patbuf[s].a=_mm_read_UBYTE(modreader);
  14.413 +			patbuf[s].b=_mm_read_UBYTE(modreader);
  14.414 +			patbuf[s].c=_mm_read_UBYTE(modreader);
  14.415 +			patbuf[s].d=_mm_read_UBYTE(modreader);
  14.416 +		}
  14.417 +		for(s=0;s<of.numchn;s++)
  14.418 +			if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  14.419 +	}
  14.420 +	return 1;
  14.421  }
  14.422  
  14.423 +static BOOL MOD_Load(BOOL curious)
  14.424 +{
  14.425 +	int t,scan;
  14.426 +	SAMPLE *q;
  14.427 +	MSAMPINFO *s;
  14.428 +	BOOL is_orpheus=0;
  14.429  
  14.430 -BOOL MOD_Load(void)
  14.431 -{
  14.432 -    int       t;
  14.433 -    SAMPLE    *q;
  14.434 -    MSAMPINFO *s;           /* old module sampleinfo */
  14.435 +	/* try to read module header */
  14.436 +	_mm_read_string((CHAR*)mh->songname,20,modreader);
  14.437 +	mh->songname[20]=0;	/* just in case */
  14.438  
  14.439 -    /* try to read module header */
  14.440 +	for(t=0;t<31;t++) {
  14.441 +		s=&mh->samples[t];
  14.442 +		_mm_read_string(s->samplename,22,modreader);
  14.443 +		s->samplename[22]=0;	/* just in case */
  14.444 +		s->length   =_mm_read_M_UWORD(modreader);
  14.445 +		s->finetune =_mm_read_UBYTE(modreader);
  14.446 +		s->volume   =_mm_read_UBYTE(modreader);
  14.447 +		s->reppos   =_mm_read_M_UWORD(modreader);
  14.448 +		s->replen   =_mm_read_M_UWORD(modreader);
  14.449 +	}
  14.450  
  14.451 -    _mm_read_string((CHAR *)mh->songname,20,modfp);
  14.452 +	mh->songlength  =_mm_read_UBYTE(modreader);
  14.453 +	mh->magic1      =_mm_read_UBYTE(modreader);
  14.454 +	_mm_read_UBYTES(mh->positions,128,modreader);
  14.455 +	_mm_read_UBYTES(mh->magic2,4,modreader);
  14.456  
  14.457 -    for(t=0; t<31; t++)
  14.458 -    {   s = &mh->samples[t];
  14.459 -        _mm_read_string(s->samplename,22,modfp);
  14.460 -        s->length   =_mm_read_M_UWORD(modfp);
  14.461 -        s->finetune =_mm_read_UBYTE(modfp);
  14.462 -        s->volume   =_mm_read_UBYTE(modfp);
  14.463 -        s->reppos   =_mm_read_M_UWORD(modfp);
  14.464 -        s->replen   =_mm_read_M_UWORD(modfp);
  14.465 -    }
  14.466 +	if(_mm_eof(modreader)) {
  14.467 +		_mm_errno = MMERR_LOADING_HEADER;
  14.468 +		return 0;
  14.469 +	}
  14.470  
  14.471 -    mh->songlength  =_mm_read_UBYTE(modfp);
  14.472 -    mh->magic1      =_mm_read_UBYTE(modfp);
  14.473 +	/* set module variables */
  14.474 +	of.initspeed = 6;
  14.475 +	of.inittempo = 125;
  14.476 +	of.numchn    = modtypes[modtype].channels;
  14.477 +	of.songname  = DupStr(mh->songname,21,1);
  14.478 +	of.numpos    = mh->songlength;
  14.479 +	of.reppos    = 0;
  14.480  
  14.481 -    _mm_read_UBYTES(mh->positions,128,modfp);
  14.482 -    _mm_read_UBYTES(mh->magic2,4,modfp);
  14.483 +	/* Count the number of patterns */
  14.484 +	of.numpat = 0;
  14.485 +	for(t=0;t<of.numpos;t++)
  14.486 +		if(mh->positions[t]>of.numpat)
  14.487 +			of.numpat=mh->positions[t];
  14.488 +	/* since some old modules embed extra patterns, we have to check the
  14.489 +	   whole list to get the samples' file offsets right - however we can find
  14.490 +	   garbage here, so check carefully */
  14.491 +	scan=1;
  14.492 +	for(t=of.numpos;t<128;t++)
  14.493 +		if(mh->positions[t]>=0x80) scan=0;
  14.494 +	if (scan)
  14.495 +		for(t=of.numpos;t<128;t++) {
  14.496 +			if(mh->positions[t]>of.numpat)
  14.497 +				of.numpat=mh->positions[t];
  14.498 +			if((curious)&&(mh->positions[t])) of.numpos=t+1;
  14.499 +		}
  14.500 +	of.numpat++;
  14.501 +	of.numtrk = of.numpat*of.numchn;
  14.502  
  14.503 -    if(feof(modfp))
  14.504 -    {   _mm_errno = MMERR_LOADING_HEADER;
  14.505 -        return 0;
  14.506 -    }
  14.507 +	if(!AllocPositions(of.numpos)) return 0;
  14.508 +	for(t=0;t<of.numpos;t++)
  14.509 +		of.positions[t]=mh->positions[t];
  14.510  
  14.511 -    /* set module variables */
  14.512 +	/* Finally, init the sampleinfo structures  */
  14.513 +	of.numins=of.numsmp=31;
  14.514 +	if(!AllocSamples())     return 0;
  14.515 +	s = mh->samples;
  14.516 +	q = of.samples;
  14.517 +	for(t=0;t<of.numins;t++) {
  14.518 +		/* convert the samplename */
  14.519 +		q->samplename = DupStr(s->samplename,23,1);
  14.520 +		/* init the sampleinfo variables and convert the size pointers */
  14.521 +		q->speed     = finetune[s->finetune & 0xf];
  14.522 +		q->volume    = s->volume&0x7f;
  14.523 +		q->loopstart = (ULONG)s->reppos << 1;
  14.524 +		q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
  14.525 +		q->length    = (ULONG)s->length << 1;
  14.526 +		q->flags     = SF_SIGNED;
  14.527 +		/* Imago Orpheus creates MODs with 16 bit samples, check */
  14.528 +		if((modtypes[modtype].name==fasttracker)&&(s->volume&0x80)) {
  14.529 +			q->flags|=SF_16BITS;
  14.530 +			is_orpheus=1;
  14.531 +		}
  14.532  
  14.533 -    of.initspeed = 6;
  14.534 -    of.inittempo = 125;
  14.535 -    of.numchn    = modtypes[modtype].channels;      /* get number of channels */
  14.536 -    of.modtype   = strdup(modtypes[modtype].name);  /* get ascii type of mod */
  14.537 -    of.songname  = DupStr(mh->songname,20);         /* make a cstr of songname */
  14.538 -    of.numpos    = mh->songlength;                  /* copy the songlength */
  14.539 +		if(s->replen>1) q->flags |= SF_LOOP;
  14.540 +		/* fix replen if repend > length */
  14.541 +		if(q->loopend>q->length) q->loopend=q->length;
  14.542  
  14.543 -    if(!AllocPositions(of.numpos)) return 0;
  14.544 -    for(t=0; t<of.numpos; t++)
  14.545 -        of.positions[t] = mh->positions[t];
  14.546 +		s++;
  14.547 +		q++;
  14.548 +	}
  14.549  
  14.550 -    /* Count the number of patterns */
  14.551 +	if(is_orpheus)
  14.552 +		of.modtype=strdup(orpheus);
  14.553 +	else
  14.554 +		of.modtype=strdup(modtypes[modtype].name);
  14.555  
  14.556 -    of.numpat = 0;
  14.557 -
  14.558 -    for(t=0; t<of.numpos; t++)
  14.559 -    {   if(of.positions[t] > of.numpat)
  14.560 -            of.numpat = of.positions[t];
  14.561 -    }
  14.562 -    of.numpat++;
  14.563 -    of.numtrk = of.numpat*of.numchn;
  14.564 -    
  14.565 -    /* Finally, init the sampleinfo structures  */
  14.566 -    of.numins = of.numsmp = 31;
  14.567 -
  14.568 -    if(!AllocSamples())     return 0;
  14.569 -    
  14.570 -    s = mh->samples;       /* init source pointer  */
  14.571 -    q = of.samples;
  14.572 -    
  14.573 -    for(t=0; t<of.numins; t++)
  14.574 -    {   /* convert the samplename */
  14.575 -        q->samplename = DupStr(s->samplename, 22);
  14.576 -
  14.577 -        /* init the sampleinfo variables and */
  14.578 -        /* convert the size pointers to longword format */
  14.579 -
  14.580 -        q->speed     = finetune[s->finetune & 0xf];
  14.581 -        q->volume    = s->volume;
  14.582 -        q->loopstart = (ULONG)s->reppos << 1;
  14.583 -        q->loopend   = q->loopstart + ((ULONG)s->replen << 1);
  14.584 -        q->length    = (ULONG)s->length << 1;
  14.585 -
  14.586 -        q->flags     = SF_SIGNED;
  14.587 -        if(s->replen > 1) q->flags |= SF_LOOP;
  14.588 -
  14.589 -        /* fix replen if repend > length */
  14.590 -        if(q->loopend > q->length) q->loopend = q->length;
  14.591 -
  14.592 -        s++;    /* point to next source sampleinfo */
  14.593 -        q++;
  14.594 -    }
  14.595 -
  14.596 -    if(!ML_LoadPatterns()) return 0;
  14.597 -    return 1;
  14.598 +	if(!ML_LoadPatterns()) return 0;
  14.599 +	return 1;
  14.600  }
  14.601  
  14.602 +static CHAR *MOD_LoadTitle(void)
  14.603 +{
  14.604 +	CHAR s[21];
  14.605  
  14.606 -CHAR *MOD_LoadTitle(void)
  14.607 -{
  14.608 -   CHAR s[20];
  14.609 +	_mm_fseek(modreader,0,SEEK_SET);
  14.610 +	if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
  14.611 +	s[20]=0;	/* just in case */
  14.612  
  14.613 -   _mm_fseek(modfp,0,SEEK_SET);
  14.614 -   if(!fread(s,20,1,modfp)) return NULL;
  14.615 -   
  14.616 -   return(DupStr(s,20));
  14.617 +	return(DupStr(s,21,1));
  14.618  }
  14.619  
  14.620 +/*========== Loader information */
  14.621  
  14.622 -MLOADER load_mod =
  14.623 -{   NULL,
  14.624 -    "Standard module",
  14.625 -    "Portable MOD loader v0.11",
  14.626 -    MOD_Init,
  14.627 -    MOD_Test,
  14.628 -    MOD_Load,
  14.629 -    MOD_Cleanup,
  14.630 -    MOD_LoadTitle
  14.631 +MLOADER load_mod={
  14.632 +	NULL,
  14.633 +	"Standard module",
  14.634 +	"MOD (31 instrument)",
  14.635 +	MOD_Init,
  14.636 +	MOD_Test,
  14.637 +	MOD_Load,
  14.638 +	MOD_Cleanup,
  14.639 +	MOD_LoadTitle
  14.640  };
  14.641  
  14.642 +/* 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 +	This library is free software; you can redistribute it and/or modify
   15.11 +	it under the terms of the GNU Library General Public License as
   15.12 +	published by the Free Software Foundation; either version 2 of
   15.13 +	the License, or (at your option) any later version.
   15.14  
   15.15 - Description:
   15.16 - Screamtracker (S3M) module loader
   15.17 +	This program is distributed in the hope that it will be useful,
   15.18 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.19 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.20 +	GNU Library General Public License for more details.
   15.21  
   15.22 - Portability:
   15.23 - All systems - all compilers (hopefully)
   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 -/**************************************************************************
   15.51 -**************************************************************************/
   15.52 +#include "mikmod_internals.h"
   15.53  
   15.54 -typedef struct S3MNOTE
   15.55 -{   UBYTE note,ins,vol,cmd,inf;
   15.56 +/*========== Module structure */
   15.57 +
   15.58 +/* header */
   15.59 +typedef struct S3MHEADER {
   15.60 +	CHAR  songname[28];
   15.61 +	UBYTE t1a;
   15.62 +	UBYTE type;
   15.63 +	UBYTE unused1[2];
   15.64 +	UWORD ordnum;
   15.65 +	UWORD insnum;
   15.66 +	UWORD patnum;
   15.67 +	UWORD flags;
   15.68 +	UWORD tracker;
   15.69 +	UWORD fileformat;
   15.70 +	CHAR  scrm[4];
   15.71 +	UBYTE mastervol;
   15.72 +	UBYTE initspeed;
   15.73 +	UBYTE inittempo;
   15.74 +	UBYTE mastermult;
   15.75 +	UBYTE ultraclick;
   15.76 +	UBYTE pantable;
   15.77 +	UBYTE unused2[8];
   15.78 +	UWORD special;
   15.79 +	UBYTE channels[32];
   15.80 +} S3MHEADER;
   15.81 +
   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 -
  15.220 -    paraptr   = NULL;
  15.221 -    s3mbuf    = NULL;
  15.222 -    poslookup = NULL;
  15.223 -    mh        = NULL;
  15.224 +	_mm_free(s3mbuf);
  15.225 +	_mm_free(paraptr);
  15.226 +	_mm_free(poslookup);
  15.227 +	_mm_free(mh);
  15.228 +	_mm_free(origpositions);
  15.229  }
  15.230  
  15.231 +/* Because so many s3m files have 16 channels as the set number used, but really
  15.232 +   only use far less (usually 8 to 12 still), I had to make this function, which
  15.233 +   determines the number of channels that are actually USED by a pattern.
  15.234  
  15.235 -BOOL S3M_GetNumChannels(void)
  15.236 +   For every channel that's used, it sets the appropriate array entry of the
  15.237 +   global variable 'remap'
  15.238  
  15.239 -/* Because so many s3m files have 16 channels as the set number used, but really */
  15.240 -/* only use far less (usually 8 to 12 still), I had to make this function, */
  15.241 -/* which determines the number of channels that are actually USED by a pattern. */
  15.242 -/* */
  15.243 -/* For every channel that's used, it sets the appropriate array entry of the */
  15.244 -/* global varialbe 'isused' */
  15.245 -/* */
  15.246 -/* NOTE: You must first seek to the file location of the pattern before calling */
  15.247 -/*       this procedure. */
  15.248 -/* Returns 1 on fail. */
  15.249 +   NOTE: You must first seek to the file location of the pattern before calling
  15.250 +         this procedure.
  15.251  
  15.252 +   Returns 1 on fail.                                                         */
  15.253 +static BOOL S3M_GetNumChannels(void)
  15.254  {
  15.255 -    int row=0,flag,ch;
  15.256 +	int row=0,flag,ch;
  15.257  
  15.258 -    while(row<64)
  15.259 -    {   flag = _mm_read_UBYTE(modfp);
  15.260 +	while(row<64) {
  15.261 +		flag=_mm_read_UBYTE(modreader);
  15.262  
  15.263 -        if(feof(modfp))
  15.264 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  15.265 -            return 1;
  15.266 -        }
  15.267 +		if(_mm_eof(modreader)) {
  15.268 +			_mm_errno = MMERR_LOADING_PATTERN;
  15.269 +			return 1;
  15.270 +		}
  15.271  
  15.272 -        if(flag)
  15.273 -        {   ch = flag&31;
  15.274 -            if(mh->channels[ch] < 16) remap[ch] = 0;
  15.275 -            
  15.276 -            if(flag&32)
  15.277 -            {   _mm_read_UBYTE(modfp);
  15.278 -                _mm_read_UBYTE(modfp);
  15.279 -            }
  15.280 -
  15.281 -            if(flag&64)
  15.282 -                _mm_read_UBYTE(modfp);
  15.283 -
  15.284 -            if(flag&128)
  15.285 -            {   _mm_read_UBYTE(modfp);
  15.286 -                _mm_read_UBYTE(modfp);
  15.287 -            }
  15.288 -        } else row++;
  15.289 -    }
  15.290 -
  15.291 -    return 0;
  15.292 -}    
  15.293 -
  15.294 -
  15.295 -BOOL S3M_ReadPattern(void)
  15.296 -{
  15.297 -    int row=0,flag,ch;
  15.298 -    S3MNOTE *n;
  15.299 -    S3MNOTE dummy;
  15.300 -
  15.301 -    /* clear pattern data */
  15.302 -    memset(s3mbuf,255,16*64*sizeof(S3MNOTE));
  15.303 -
  15.304 -    while(row<64)
  15.305 -    {   flag = _mm_read_UBYTE(modfp);
  15.306 -
  15.307 -        if(flag==EOF)
  15.308 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  15.309 -            return 0;
  15.310 -        }
  15.311 -
  15.312 -        if(flag)
  15.313 -        {   ch = remap[flag&31];
  15.314 -
  15.315 -            if(ch != -1)
  15.316 -                n = &s3mbuf[(64U*ch)+row];
  15.317 -            else
  15.318 -                n = &dummy;
  15.319 -
  15.320 -            if(flag&32)
  15.321 -            {   n->note = _mm_read_UBYTE(modfp);
  15.322 -                n->ins  = _mm_read_UBYTE(modfp);
  15.323 -            }
  15.324 -
  15.325 -            if(flag&64)
  15.326 -                n->vol = _mm_read_UBYTE(modfp);
  15.327 -
  15.328 -            if(flag&128)
  15.329 -            {   n->cmd = _mm_read_UBYTE(modfp);
  15.330 -                n->inf = _mm_read_UBYTE(modfp);
  15.331 -            }
  15.332 -        } else row++;
  15.333 -    }
  15.334 -    return 1;
  15.335 +		if(flag) {
  15.336 +			ch=flag&31;
  15.337 +			if(mh->channels[ch]<32) remap[ch] = 0;
  15.338 +			if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  15.339 +			if(flag&64) _mm_read_UBYTE(modreader);
  15.340 +			if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
  15.341 +		} else row++;
  15.342 +	}
  15.343 +	return 0;
  15.344  }
  15.345  
  15.346 +static BOOL S3M_ReadPattern(void)
  15.347 +{
  15.348 +	int row=0,flag,ch;
  15.349 +	S3MNOTE *n,dummy;
  15.350  
  15.351 -void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, BOOL oldeffect);
  15.352 +	/* clear pattern data */
  15.353 +	memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
  15.354  
  15.355 -UBYTE *S3M_ConvertTrack(S3MNOTE *tr)
  15.356 -{
  15.357 -    int t;
  15.358 +	while(row<64) {
  15.359 +		flag=_mm_read_UBYTE(modreader);
  15.360  
  15.361 -    UBYTE note,ins,vol;
  15.362 +		if(_mm_eof(modreader)) {
  15.363 +			_mm_errno = MMERR_LOADING_PATTERN;
  15.364 +			return 0;
  15.365 +		}
  15.366  
  15.367 -    UniReset();
  15.368 -    for(t=0; t<64; t++)
  15.369 -    {
  15.370 -        note = tr[t].note;
  15.371 -        ins  = tr[t].ins;
  15.372 -        vol  = tr[t].vol;
  15.373 +		if(flag) {
  15.374 +			ch=remap[flag&31];
  15.375  
  15.376 +			if(ch!=-1)
  15.377 +				n=&s3mbuf[(64U*ch)+row];
  15.378 +			else
  15.379 +				n=&dummy;
  15.380  
  15.381 -        if(ins!=0 && ins!=255) UniInstrument(ins-1);
  15.382 -        if(note!=255)
  15.383 -        {   if(note==254) UniPTEffect(0xc,0);             /* <- note off command */
  15.384 -            else UniNote(((note>>4)*12)+(note&0xf));      /* <- normal note */
  15.385 -        }
  15.386 -
  15.387 -        if(vol<255)
  15.388 -            UniPTEffect(0xc,vol);
  15.389 -
  15.390 -        S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,1);
  15.391 -        UniNewline();
  15.392 -    }
  15.393 -
  15.394 -    return UniDup();
  15.395 +			if(flag&32) {
  15.396 +				n->note=_mm_read_UBYTE(modreader);
  15.397 +				n->ins=_mm_read_UBYTE(modreader);
  15.398 +			}
  15.399 +			if(flag&64)
  15.400 +				n->vol=_mm_read_UBYTE(modreader);
  15.401 +			if(flag&128) {
  15.402 +				n->cmd=_mm_read_UBYTE(modreader);
  15.403 +				n->inf=_mm_read_UBYTE(modreader);
  15.404 +			}
  15.405 +		} else row++;
  15.406 +	}
  15.407 +	return 1;
  15.408  }
  15.409  
  15.410 +static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
  15.411 +{
  15.412 +	int t;
  15.413  
  15.414 -BOOL S3M_Load(void)
  15.415 -{
  15.416 -    int    t,u,track = 0;
  15.417 -    SAMPLE *q;
  15.418 -    UBYTE  pan[32];
  15.419 +	UniReset();
  15.420 +	for(t=0;t<64;t++) {
  15.421 +		UBYTE note,ins,vol;
  15.422  
  15.423 -    /* try to read module header */
  15.424 +		note=tr[t].note;
  15.425 +		ins=tr[t].ins;
  15.426 +		vol=tr[t].vol;
  15.427  
  15.428 -    _mm_read_string(mh->songname,28,modfp);
  15.429 -    mh->t1a         =_mm_read_UBYTE(modfp);
  15.430 -    mh->type        =_mm_read_UBYTE(modfp);
  15.431 -    _mm_read_UBYTES(mh->unused1,2,modfp);
  15.432 -    mh->ordnum      =_mm_read_I_UWORD(modfp);
  15.433 -    mh->insnum      =_mm_read_I_UWORD(modfp);
  15.434 -    mh->patnum      =_mm_read_I_UWORD(modfp);
  15.435 -    mh->flags       =_mm_read_I_UWORD(modfp);
  15.436 -    mh->tracker     =_mm_read_I_UWORD(modfp);
  15.437 -    mh->fileformat  =_mm_read_I_UWORD(modfp);
  15.438 -    _mm_read_string(mh->scrm,4,modfp);
  15.439 +		if((ins)&&(ins!=255)) UniInstrument(ins-1);
  15.440 +		if(note!=255) {
  15.441 +			if(note==254) {
  15.442 +				UniPTEffect(0xc,0);	/* note cut command */
  15.443 +				vol=255;
  15.444 +			} else
  15.445 +				UniNote(((note>>4)*OCTAVE)+(note&0xf));	/* normal note */
  15.446 +		}
  15.447 +		if(vol<255) UniPTEffect(0xc,vol);
  15.448  
  15.449 -    mh->mastervol   =_mm_read_UBYTE(modfp);
  15.450 -    mh->initspeed   =_mm_read_UBYTE(modfp);
  15.451 -    mh->inittempo   =_mm_read_UBYTE(modfp);
  15.452 -    mh->mastermult  =_mm_read_UBYTE(modfp);
  15.453 -    mh->ultraclick  =_mm_read_UBYTE(modfp);
  15.454 -    mh->pantable    =_mm_read_UBYTE(modfp);
  15.455 -    _mm_read_UBYTES(mh->unused2,8,modfp);
  15.456 -    mh->special     =_mm_read_I_UWORD(modfp);
  15.457 -    _mm_read_UBYTES(mh->channels,32,modfp);
  15.458 -
  15.459 -    if(feof(modfp))
  15.460 -    {   _mm_errno = MMERR_LOADING_HEADER;
  15.461 -        return 0;
  15.462 -    }
  15.463 -
  15.464 -    /* set module variables */
  15.465 -
  15.466 -    of.modtype     = strdup(S3M_Version);
  15.467 -    of.modtype[14] = ((mh->tracker >> 8) &0xf) + 0x30;
  15.468 -    of.modtype[16] = ((mh->tracker >> 4)&0xf) + 0x30;
  15.469 -    of.modtype[17] = ((mh->tracker)&0xf) + 0x30;
  15.470 -    of.songname    = DupStr(mh->songname,28);
  15.471 -    of.numpat      = mh->patnum;
  15.472 -    of.reppos      = 0;
  15.473 -    of.numins      = of.numsmp = mh->insnum;
  15.474 -    of.initspeed   = mh->initspeed;
  15.475 -    of.inittempo   = mh->inittempo;
  15.476 -    of.initvolume  = mh->mastervol<<1;
  15.477 -
  15.478 -    /* read the order data */
  15.479 -    if(!AllocPositions(mh->ordnum)) return 0;
  15.480 -    for(t=0; t<mh->ordnum; t++)
  15.481 -        of.positions[t] = _mm_read_UBYTE(modfp);
  15.482 -
  15.483 -    of.numpos = 0;
  15.484 -    for(t=0; t<mh->ordnum; t++)
  15.485 -    {   of.positions[of.numpos] = of.positions[t];
  15.486 -        poslookup[t]            = of.numpos;   /* bug fix for FREAKY S3Ms */
  15.487 -        if(of.positions[t]<254) of.numpos++;        
  15.488 -    }
  15.489 -
  15.490 -    if((paraptr=(UWORD *)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD)))==NULL) return 0;
  15.491 -
  15.492 -    /* read the instrument+pattern parapointers */
  15.493 -    _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modfp);
  15.494 -
  15.495 -
  15.496 -    if(mh->pantable==252)
  15.497 -    {   /* read the panning table (ST 3.2 addition.  See below for further */
  15.498 -        /* portions of channel panning [past reampper]). */
  15.499 -        _mm_read_UBYTES(pan,32,modfp);
  15.500 -    }
  15.501 -
  15.502 -
  15.503 -    /* now is a good time to check if the header was too short :) */
  15.504 -
  15.505 -    if(feof(modfp))
  15.506 -    {   _mm_errno = MMERR_LOADING_HEADER;
  15.507 -        return 0;
  15.508 -    }
  15.509 -
  15.510 -
  15.511 -    /* ============================================== */
  15.512 -    /* Load those darned Samples!  (no insts in ST3) */
  15.513 -
  15.514 -    if(!AllocSamples()) return 0;
  15.515 -
  15.516 -    q = of.samples;
  15.517 -
  15.518 -    for(t=0; t<of.numins; t++)
  15.519 -    {   S3MSAMPLE s;
  15.520 -
  15.521 -        /* seek to instrument position */
  15.522 -
  15.523 -        _mm_fseek(modfp,((long)paraptr[t])<<4,SEEK_SET);
  15.524 -
  15.525 -        /* and load sample info */
  15.526 -
  15.527 -        s.type      =_mm_read_UBYTE(modfp);
  15.528 -        _mm_read_string(s.filename,12,modfp);
  15.529 -        s.memsegh   =_mm_read_UBYTE(modfp);
  15.530 -        s.memsegl   =_mm_read_I_UWORD(modfp);
  15.531 -        s.length    =_mm_read_I_ULONG(modfp);
  15.532 -        s.loopbeg   =_mm_read_I_ULONG(modfp);
  15.533 -        s.loopend   =_mm_read_I_ULONG(modfp);
  15.534 -        s.volume    =_mm_read_UBYTE(modfp);
  15.535 -        s.dsk       =_mm_read_UBYTE(modfp);
  15.536 -        s.pack      =_mm_read_UBYTE(modfp);
  15.537 -        s.flags     =_mm_read_UBYTE(modfp);
  15.538 -        s.c2spd     =_mm_read_I_ULONG(modfp);
  15.539 -        _mm_read_UBYTES(s.unused,12,modfp);
  15.540 -        _mm_read_string(s.sampname,28,modfp);
  15.541 -        _mm_read_string(s.scrs,4,modfp);
  15.542 -
  15.543 -        if(feof(modfp))
  15.544 -        {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  15.545 -            return 0;
  15.546 -        }
  15.547 -
  15.548 -        q->samplename = DupStr(s.sampname,28);
  15.549 -        q->speed      = s.c2spd;
  15.550 -        q->length     = s.length;
  15.551 -        q->loopstart  = s.loopbeg;
  15.552 -        q->loopend    = s.loopend;
  15.553 -        q->volume     = s.volume;
  15.554 -        q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  15.555 -
  15.556 -        if(s.flags&1) q->flags |= SF_LOOP;
  15.557 -        if(s.flags&4) q->flags |= SF_16BITS;
  15.558 -        if(mh->fileformat==1) q->flags |= SF_SIGNED;
  15.559 -
  15.560 -        /* DON'T load sample if it doesn't have the SCRS tag */
  15.561 -        if(memcmp(s.scrs,"SCRS",4)!=0) q->length = 0;
  15.562 -
  15.563 -        q++;
  15.564 -    }
  15.565 -
  15.566 -    /* ==================================== */
  15.567 -    /* Determine the number of channels actually used.  (what ever happened */
  15.568 -    /* to the concept of a single "numchn" variable, eh?! */
  15.569 -
  15.570 -    of.numchn = 0;
  15.571 -    memset(remap,-1,32*sizeof(UBYTE));
  15.572 -
  15.573 -    for(t=0; t<of.numpat; t++)
  15.574 -    {   /* seek to pattern position ( + 2 skip pattern length ) */
  15.575 -        _mm_fseek(modfp,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.576 -        if(S3M_GetNumChannels()) return 0;
  15.577 -    }
  15.578 -    
  15.579 -    /* build the remap array  */
  15.580 -    for(t=0; t<32; t++)
  15.581 -    {   if(remap[t]==0)
  15.582 -        {   remap[t] = of.numchn;
  15.583 -            of.numchn++;
  15.584 -        }
  15.585 -    }
  15.586 -
  15.587 -    /* ============================================================ */
  15.588 -    /* set panning positions AFTER building remap chart! */
  15.589 -
  15.590 -    for(t=0; t<32; t++)
  15.591 -    {   if((mh->channels[t]<16) && (remap[t]!=-1))
  15.592 -        {   if(mh->channels[t]<8)
  15.593 -                of.panning[remap[t]] = 0x20;     /* 0x30 = std s3m val */
  15.594 -            else
  15.595 -                of.panning[remap[t]] = 0xd0;     /* 0xc0 = std s3m val */
  15.596 -        }
  15.597 -    }
  15.598 -
  15.599 -    if(mh->pantable==252)
  15.600 -    {   /* set panning positions according to panning table (new for st3.2) */
  15.601 -        for(t=0; t<32; t++)
  15.602 -        {   if((pan[t]&0x20) && (mh->channels[t]<16) && (remap[t]!=-1))
  15.603 -                of.panning[remap[t]] = (pan[t]&0xf)<<4;
  15.604 -        }
  15.605 -    }
  15.606 -
  15.607 -
  15.608 -    /* ============================== */
  15.609 -    /* Load the pattern info now! */
  15.610 -    
  15.611 -    of.numtrk = of.numpat*of.numchn;
  15.612 -    if(!AllocTracks()) return 0;
  15.613 -    if(!AllocPatterns()) return 0;
  15.614 -
  15.615 -    for(t=0; t<of.numpat; t++)
  15.616 -    {   /* seek to pattern position ( + 2 skip pattern length ) */
  15.617 -        _mm_fseek(modfp,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.618 -        if(!S3M_ReadPattern()) return 0;
  15.619 -        for(u=0; u<of.numchn; u++)
  15.620 -            if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  15.621 -    }
  15.622 -
  15.623 -    return 1;
  15.624 +		S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,1);
  15.625 +		UniNewline();
  15.626 +	}
  15.627 +	return UniDup();
  15.628  }
  15.629  
  15.630 -         
  15.631 +BOOL S3M_Load(BOOL curious)
  15.632 +{
  15.633 +	int t,u,track = 0;
  15.634 +	SAMPLE *q;
  15.635 +	UBYTE pan[32];
  15.636 +
  15.637 +	/* try to read module header */
  15.638 +	_mm_read_string(mh->songname,28,modreader);
  15.639 +	mh->t1a         =_mm_read_UBYTE(modreader);
  15.640 +	mh->type        =_mm_read_UBYTE(modreader);
  15.641 +	_mm_read_UBYTES(mh->unused1,2,modreader);
  15.642 +	mh->ordnum      =_mm_read_I_UWORD(modreader);
  15.643 +	mh->insnum      =_mm_read_I_UWORD(modreader);
  15.644 +	mh->patnum      =_mm_read_I_UWORD(modreader);
  15.645 +	mh->flags       =_mm_read_I_UWORD(modreader);
  15.646 +	mh->tracker     =_mm_read_I_UWORD(modreader);
  15.647 +	mh->fileformat  =_mm_read_I_UWORD(modreader);
  15.648 +	_mm_read_string(mh->scrm,4,modreader);
  15.649 +	mh->mastervol   =_mm_read_UBYTE(modreader);
  15.650 +	mh->initspeed   =_mm_read_UBYTE(modreader);
  15.651 +	mh->inittempo   =_mm_read_UBYTE(modreader);
  15.652 +	mh->mastermult  =_mm_read_UBYTE(modreader);
  15.653 +	mh->ultraclick  =_mm_read_UBYTE(modreader);
  15.654 +	mh->pantable    =_mm_read_UBYTE(modreader);
  15.655 +	_mm_read_UBYTES(mh->unused2,8,modreader);
  15.656 +	mh->special     =_mm_read_I_UWORD(modreader);
  15.657 +	_mm_read_UBYTES(mh->channels,32,modreader);
  15.658 +
  15.659 +	if(_mm_eof(modreader)) {
  15.660 +		_mm_errno = MMERR_LOADING_HEADER;
  15.661 +		return 0;
  15.662 +	}
  15.663 +
  15.664 +	/* set module variables */
  15.665 +	of.songname    = DupStr(mh->songname,28,0);
  15.666 +	of.numpat      = mh->patnum;
  15.667 +	of.reppos      = 0;
  15.668 +	of.numins      = of.numsmp = mh->insnum;
  15.669 +	of.initspeed   = mh->initspeed;
  15.670 +	of.inittempo   = mh->inittempo;
  15.671 +	of.initvolume  = mh->mastervol<<1;
  15.672 +	of.flags      |= UF_ARPMEM;
  15.673 +	if((mh->tracker==0x1300)||(mh->flags&64))
  15.674 +		of.flags|=UF_S3MSLIDES;
  15.675 +
  15.676 +	/* read the order data */
  15.677 +	if(!AllocPositions(mh->ordnum)) return 0;
  15.678 +	if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
  15.679 +
  15.680 +	for(t=0;t<mh->ordnum;t++) {
  15.681 +		origpositions[t]=_mm_read_UBYTE(modreader);
  15.682 +		if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
  15.683 +			origpositions[t]=255/*mh->patnum-1*/;
  15.684 +	}
  15.685 +
  15.686 +	if(_mm_eof(modreader)) {
  15.687 +		_mm_errno = MMERR_LOADING_HEADER;
  15.688 +		return 0;
  15.689 +	}
  15.690 +
  15.691 +	poslookupcnt=mh->ordnum;
  15.692 +	S3MIT_CreateOrders(curious);
  15.693 +
  15.694 +	if(!(paraptr=(UWORD*)_mm_malloc((of.numins+of.numpat)*sizeof(UWORD))))
  15.695 +		return 0;
  15.696 +
  15.697 +	/* read the instrument+pattern parapointers */
  15.698 +	_mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
  15.699 +
  15.700 +	if(mh->pantable==252) {
  15.701 +		/* read the panning table (ST 3.2 addition.  See below for further
  15.702 +		   portions of channel panning [past reampper]). */
  15.703 +		_mm_read_UBYTES(pan,32,modreader);
  15.704 +	}
  15.705 +
  15.706 +	if(_mm_eof(modreader)) {
  15.707 +		_mm_errno = MMERR_LOADING_HEADER;
  15.708 +		return 0;
  15.709 +	}
  15.710 +
  15.711 +	/* load samples */
  15.712 +	if(!AllocSamples()) return 0;
  15.713 +	q = of.samples;
  15.714 +	for(t=0;t<of.numins;t++) {
  15.715 +		S3MSAMPLE s;
  15.716 +
  15.717 +		/* seek to instrument position */
  15.718 +		_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
  15.719 +		/* and load sample info */
  15.720 +		s.type      =_mm_read_UBYTE(modreader);
  15.721 +		_mm_read_string(s.filename,12,modreader);
  15.722 +		s.memsegh   =_mm_read_UBYTE(modreader);
  15.723 +		s.memsegl   =_mm_read_I_UWORD(modreader);
  15.724 +		s.length    =_mm_read_I_ULONG(modreader);
  15.725 +		s.loopbeg   =_mm_read_I_ULONG(modreader);
  15.726 +		s.loopend   =_mm_read_I_ULONG(modreader);
  15.727 +		s.volume    =_mm_read_UBYTE(modreader);
  15.728 +		s.dsk       =_mm_read_UBYTE(modreader);
  15.729 +		s.pack      =_mm_read_UBYTE(modreader);
  15.730 +		s.flags     =_mm_read_UBYTE(modreader);
  15.731 +		s.c2spd     =_mm_read_I_ULONG(modreader);
  15.732 +		_mm_read_UBYTES(s.unused,12,modreader);
  15.733 +		_mm_read_string(s.sampname,28,modreader);
  15.734 +		_mm_read_string(s.scrs,4,modreader);
  15.735 +
  15.736 +		if(_mm_eof(modreader)) {
  15.737 +			_mm_errno = MMERR_LOADING_SAMPLEINFO;
  15.738 +			return 0;
  15.739 +		}
  15.740 +
  15.741 +		q->samplename = DupStr(s.sampname,28,0);
  15.742 +		q->speed      = s.c2spd;
  15.743 +		q->length     = s.length;
  15.744 +		q->loopstart  = s.loopbeg>s.length?s.length:s.loopbeg;
  15.745 +		q->loopend    = s.loopend>s.length?s.length:s.loopend;
  15.746 +		q->volume     = s.volume;
  15.747 +		q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
  15.748 +
  15.749 +		if(s.flags&1) q->flags |= SF_LOOP;
  15.750 +		if(s.flags&4) q->flags |= SF_16BITS;
  15.751 +		if(mh->fileformat==1) q->flags |= SF_SIGNED;
  15.752 +
  15.753 +		/* don't load sample if it doesn't have the SCRS tag */
  15.754 +		if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
  15.755 +
  15.756 +		q++;
  15.757 +	}
  15.758 +
  15.759 +	/* determine the number of channels actually used. */
  15.760 +	of.numchn = 0;
  15.761 +	memset(remap,-1,32*sizeof(UBYTE));
  15.762 +	for(t=0;t<of.numpat;t++) {
  15.763 +		/* seek to pattern position (+2 skip pattern length) */
  15.764 +		_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.765 +		if(S3M_GetNumChannels()) return 0;
  15.766 +	}
  15.767 +	/* then we can decide the module type */
  15.768 +	t=mh->tracker>>12;
  15.769 +	if((!t)||(t>3))
  15.770 +		t=NUMTRACKERS-1; /* unknown tracker */
  15.771 +	else {
  15.772 +		if(mh->tracker>=0x3217)
  15.773 +			t=NUMTRACKERS+1; /* IT 2.14p4 */
  15.774 +		else if(mh->tracker>=0x3216)
  15.775 +			t=NUMTRACKERS; /* IT 2.14p3 */
  15.776 +		else t--;
  15.777 +	}
  15.778 +	of.modtype = strdup(S3M_Version[t]);
  15.779 +	if(t<NUMTRACKERS) {
  15.780 +		of.modtype[numeric[t]] = ((mh->tracker>>8) &0xf)+'0';
  15.781 +		of.modtype[numeric[t]+2] = ((mh->tracker>>4)&0xf)+'0';
  15.782 +		of.modtype[numeric[t]+3] = ((mh->tracker)&0xf)+'0';
  15.783 +	}
  15.784 +
  15.785 +	/* build the remap array  */
  15.786 +	for(t=0;t<32;t++)
  15.787 +		if(!remap[t])
  15.788 +			remap[t]=of.numchn++;
  15.789 +
  15.790 +	/* set panning positions after building remap chart! */
  15.791 +	for(t=0;t<32;t++)
  15.792 +		if((mh->channels[t]<32)&&(remap[t]!=-1)) {
  15.793 +			if(mh->channels[t]<8)
  15.794 +				of.panning[remap[t]]=0x20;	/* 0x30 = std s3m val */
  15.795 +			else
  15.796 +				of.panning[remap[t]]=0xd0;	/* 0xc0 = std s3m val */
  15.797 +		}
  15.798 +	if(mh->pantable==252)
  15.799 +		/* set panning positions according to panning table (new for st3.2) */
  15.800 +		for(t=0;t<32;t++)
  15.801 +			if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
  15.802 +				of.panning[remap[t]]=(pan[t]&0xf)<<4;
  15.803 +
  15.804 +	/* load pattern info */
  15.805 +	of.numtrk=of.numpat*of.numchn;
  15.806 +	if(!AllocTracks()) return 0;
  15.807 +	if(!AllocPatterns()) return 0;
  15.808 +
  15.809 +	for(t=0;t<of.numpat;t++) {
  15.810 +		/* seek to pattern position (+2 skip pattern length) */
  15.811 +		_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
  15.812 +		if(!S3M_ReadPattern()) return 0;
  15.813 +		for(u=0;u<of.numchn;u++)
  15.814 +			if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
  15.815 +	}
  15.816 +
  15.817 +	return 1;
  15.818 +}
  15.819 +
  15.820  CHAR *S3M_LoadTitle(void)
  15.821  {
  15.822 -   CHAR s[28];
  15.823 +	CHAR s[28];
  15.824  
  15.825 -   _mm_fseek(modfp,0,SEEK_SET);
  15.826 -   if(!fread(s,28,1,modfp)) return NULL;
  15.827 -   
  15.828 -   return(DupStr(s,28));
  15.829 +	_mm_fseek(modreader,0,SEEK_SET);
  15.830 +	if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
  15.831 +
  15.832 +	return(DupStr(s,28,0));
  15.833  }
  15.834  
  15.835 +/*========== Loader information */
  15.836  
  15.837 -MLOADER load_s3m =
  15.838 -{   NULL,
  15.839 -    "S3M",
  15.840 -    "S3M loader v0.3",
  15.841 -    S3M_Init,
  15.842 -    S3M_Test,
  15.843 -    S3M_Load,
  15.844 -    S3M_Cleanup,
  15.845 -
  15.846 -    S3M_LoadTitle
  15.847 +MLOADER load_s3m={
  15.848 +	NULL,
  15.849 +	"S3M",
  15.850 +	"S3M (Scream Tracker 3)",
  15.851 +	S3M_Init,
  15.852 +	S3M_Test,
  15.853 +	S3M_Load,
  15.854 +	S3M_Cleanup,
  15.855 +	S3M_LoadTitle
  15.856  };
  15.857  
  15.858 +/* 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 -
   16.25 - If this module is found to not be portable to any particular platform,
   16.26 - please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
   16.27 - more information on contacting the author).
   16.28 -
   16.29 +	You should have received a copy of the GNU Library General Public
   16.30 +	License along with this library; if not, write to the Free Software
   16.31 +	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   16.32 +	02111-1307, USA.
   16.33  */
   16.34  
   16.35 +/*==============================================================================
   16.36 +
   16.37 +  $Id$
   16.38 +
   16.39 +  Fasttracker (XM) module loader
   16.40 +
   16.41 +==============================================================================*/
   16.42 +
   16.43 +#ifdef HAVE_CONFIG_H
   16.44 +#include "config.h"
   16.45 +#endif
   16.46 +
   16.47  #include <string.h>
   16.48 -#include "mikmod.h"
   16.49  
   16.50 -/**************************************************************************
   16.51 -**************************************************************************/
   16.52 +#include "mikmod_internals.h"
   16.53  
   16.54 +/*========== Module structure */
   16.55  
   16.56 -typedef struct XMHEADER
   16.57 -{   CHAR  id[17];                   /* ID text: 'Extended module: ' */
   16.58 -    CHAR  songname[21];             /* Module name, padded with zeroes and 0x1a at the end */
   16.59 -    CHAR  trackername[20];          /* Tracker name */
   16.60 -    UWORD version;                  /* (word) Version number, hi-byte major and low-byte minor */
   16.61 -    ULONG headersize;               /* Header size */
   16.62 -    UWORD songlength;               /* (word) Song length (in patten order table) */
   16.63 -    UWORD restart;                  /* (word) Restart position */
   16.64 -    UWORD numchn;                   /* (word) Number of channels (2,4,6,8,10,...,32) */
   16.65 -    UWORD numpat;                   /* (word) Number of patterns (max 256) */
   16.66 -    UWORD numins;                   /* (word) Number of instruments (max 128) */
   16.67 -    UWORD flags;                    /* (word) Flags: bit 0: 0 = Amiga frequency table (see below) 1 = Linear frequency table */
   16.68 -    UWORD tempo;                    /* (word) Default tempo */
   16.69 -    UWORD bpm;                      /* (word) Default BPM */
   16.70 -    UBYTE orders[256];              /* (byte) Pattern order table  */
   16.71 +typedef struct XMHEADER {
   16.72 +	CHAR  id[17];          /* ID text: 'Extended module: ' */
   16.73 +	CHAR  songname[21];    /* Module name */
   16.74 +	CHAR  trackername[20]; /* Tracker name */
   16.75 +	UWORD version;         /* Version number */
   16.76 +	ULONG headersize;      /* Header size */
   16.77 +	UWORD songlength;      /* Song length (in patten order table) */
   16.78 +	UWORD restart;         /* Restart position */
   16.79 +	UWORD numchn;          /* Number of channels (2,4,6,8,10,...,32) */
   16.80 +	UWORD numpat;          /* Number of patterns (max 256) */
   16.81 +	UWORD numins;          /* Number of instruments (max 128) */
   16.82 +	UWORD flags;
   16.83 +	UWORD tempo;           /* Default tempo */
   16.84 +	UWORD bpm;             /* Default BPM */
   16.85 +	UBYTE orders[256];     /* Pattern order table  */
   16.86  } XMHEADER;
   16.87  
   16.88 -
   16.89 -typedef struct XMINSTHEADER
   16.90 -{   ULONG size;                     /* (dword) Instrument size */
   16.91 -    CHAR  name[22];                 /* (char) Instrument name */
   16.92 -    UBYTE type;                     /* (byte) Instrument type (always 0) */
   16.93 -    UWORD numsmp;                   /* (word) Number of samples in instrument */
   16.94 -    ULONG ssize;                    /* */
   16.95 +typedef struct XMINSTHEADER {
   16.96 +	ULONG size;     /* Instrument size */
   16.97 +	CHAR  name[22]; /* Instrument name */
   16.98 +	UBYTE type;     /* Instrument type (always 0) */
   16.99 +	UWORD numsmp;   /* Number of samples in instrument */
  16.100 +	ULONG ssize;
  16.101  } XMINSTHEADER;
  16.102  
  16.103 -
  16.104 -typedef struct XMPATCHHEADER
  16.105 -{   UBYTE what[96];         /* (byte) Sample number for all notes */
  16.106 -    UWORD volenv[24];       /* (byte) Points for volume envelope */
  16.107 -    UWORD panenv[24];       /* (byte) Points for panning envelope */
  16.108 -    UBYTE volpts;           /* (byte) Number of volume points */
  16.109 -    UBYTE panpts;           /* (byte) Number of panning points */
  16.110 -    UBYTE volsus;           /* (byte) Volume sustain point */
  16.111 -    UBYTE volbeg;           /* (byte) Volume loop start point */
  16.112 -    UBYTE volend;           /* (byte) Volume loop end point */
  16.113 -    UBYTE pansus;           /* (byte) Panning sustain point */
  16.114 -    UBYTE panbeg;           /* (byte) Panning loop start point */
  16.115 -    UBYTE panend;           /* (byte) Panning loop end point */
  16.116 -    UBYTE volflg;           /* (byte) Volume type: bit 0: On; 1: Sustain; 2: Loop */
  16.117 -    UBYTE panflg;           /* (byte) Panning type: bit 0: On; 1: Sustain; 2: Loop */
  16.118 -    UBYTE vibflg;           /* (byte) Vibrato type */
  16.119 -    UBYTE vibsweep;         /* (byte) Vibrato sweep */
  16.120 -    UBYTE vibdepth;         /* (byte) Vibrato depth */
  16.121 -    UBYTE vibrate;          /* (byte) Vibrato rate */
  16.122 -    UWORD volfade;          /* (word) Volume fadeout */
  16.123 -    UWORD reserved[11];     /* (word) Reserved */
  16.124 +#define XMENVCNT (12*2)
  16.125 +#define XMNOTECNT (8*OCTAVE)
  16.126 +typedef struct XMPATCHHEADER {
  16.127 +	UBYTE what[XMNOTECNT];  /*  Sample number for all notes */
  16.128 +	UWORD volenv[XMENVCNT]; /*  Points for volume envelope */
  16.129 +	UWORD panenv[XMENVCNT]; /*  Points for panning envelope */
  16.130 +	UBYTE volpts;      /*  Number of volume points */
  16.131 +	UBYTE panpts;      /*  Number of panning points */
  16.132 +	UBYTE volsus;      /*  Volume sustain point */
  16.133 +	UBYTE volbeg;      /*  Volume loop start point */
  16.134 +	UBYTE volend;      /*  Volume loop end point */
  16.135 +	UBYTE pansus;      /*  Panning sustain point */
  16.136 +	UBYTE panbeg;      /*  Panning loop start point */
  16.137 +	UBYTE panend;      /*  Panning loop end point */
  16.138 +	UBYTE volflg;      /*  Volume type: bit 0: On; 1: Sustain; 2: Loop */
  16.139 +	UBYTE panflg;      /*  Panning type: bit 0: On; 1: Sustain; 2: Loop */
  16.140 +	UBYTE vibflg;      /*  Vibrato type */
  16.141 +	UBYTE vibsweep;    /*  Vibrato sweep */
  16.142 +	UBYTE vibdepth;    /*  Vibrato depth */
  16.143 +	UBYTE vibrate;     /*  Vibrato rate */
  16.144 +	UWORD volfade;     /*  Volume fadeout */
  16.145  } XMPATCHHEADER;
  16.146  
  16.147 -
  16.148 -typedef struct XMWAVHEADER
  16.149 -{   ULONG length;           /* (dword) Sample length */
  16.150 -    ULONG loopstart;        /* (dword) Sample loop start */
  16.151 -    ULONG looplength;       /* (dword) Sample loop length */
  16.152 -    UBYTE volume;           /* (byte) Volume  */
  16.153 -    SBYTE finetune;         /* (byte) Finetune (signed byte -128..+127) */
  16.154 -    UBYTE type;             /* (byte) Type: Bit 0-1: 0 = No loop, 1 = Forward loop, */
  16.155 -                            /*                       2 = Ping-pong loop; */
  16.156 -                            /*                    4: 16-bit sampledata */
  16.157 -    UBYTE panning;          /* (byte) Panning (0-255) */
  16.158 -    SBYTE relnote;          /* (byte) Relative note number (signed byte) */
  16.159 -    UBYTE reserved;         /* (byte) Reserved */
  16.160 -    CHAR  samplename[22];   /* (char) Sample name */
  16.161 -
  16.162 -    UBYTE vibtype;          /* (byte) Vibrato type */
  16.163 -    UBYTE vibsweep;         /* (byte) Vibrato sweep */
  16.164 -    UBYTE vibdepth;         /* (byte) Vibrato depth */
  16.165 -    UBYTE vibrate;          /* (byte) Vibrato rate */
  16.166 +typedef struct XMWAVHEADER {
  16.167 +	ULONG length;         /* Sample length */
  16.168 +	ULONG loopstart;      /* Sample loop start */
  16.169 +	ULONG looplength;     /* Sample loop length */
  16.170 +	UBYTE volume;         /* Volume  */
  16.171 +	SBYTE finetune;       /* Finetune (signed byte -128..+127) */
  16.172 +	UBYTE type;           /* Loop type */
  16.173 +	UBYTE panning;        /* Panning (0-255) */
  16.174 +	SBYTE relnote;        /* Relative note number (signed byte) */
  16.175 +	UBYTE reserved;
  16.176 +	CHAR  samplename[22]; /* Sample name */
  16.177 +	UBYTE vibtype;        /* Vibrato type */
  16.178 +	UBYTE vibsweep;       /* Vibrato sweep */
  16.179 +	UBYTE vibdepth;       /* Vibrato depth */
  16.180 +	UBYTE vibrate;        /* Vibrato rate */
  16.181  } XMWAVHEADER;
  16.182  
  16.183 -
  16.184 -typedef struct XMPATHEADE
  16.185 -{   ULONG size;                     /* (dword) Pattern header length  */
  16.186 -    UBYTE packing;                  /* (byte) Packing type (always 0) */
  16.187 -    UWORD numrows;                  /* (word) Number of rows in pattern (1..256) */
  16.188 -    UWORD packsize;                 /* (word) Packed patterndata size */
  16.189 +typedef struct XMPATHEADER {
  16.190 +	ULONG size;     /* Pattern header length  */
  16.191 +	UBYTE packing;  /* Packing type (always 0) */
  16.192 +	UWORD numrows;  /* Number of rows in pattern (1..256) */
  16.193 +	SWORD packsize; /* Packed patterndata size */
  16.194  } XMPATHEADER;
  16.195  
  16.196 -typedef struct MTMNOTE
  16.197 -{    UBYTE a,b,c;
  16.198 -} MTMNOTE;
  16.199 +typedef struct XMNOTE {
  16.200 +	UBYTE note,ins,vol,eff,dat;
  16.201 +} XMNOTE;
  16.202  
  16.203 +/*========== Loader variables */
  16.204  
  16.205 -typedef struct XMNOTE
  16.206 -{    UBYTE note,ins,vol,eff,dat;
  16.207 -}XMNOTE;
  16.208 +static	XMNOTE *xmpat=NULL;
  16.209 +static	XMHEADER *mh=NULL;
  16.210  
  16.211 -/**************************************************************************
  16.212 -**************************************************************************/
  16.213 +/* increment unit for sample array reallocation */
  16.214 +#define XM_SMPINCR 64
  16.215 +static	ULONG *nextwav=NULL;
  16.216 +static	XMWAVHEADER *wh=NULL,*s=NULL;
  16.217  
  16.218 -static XMNOTE *xmpat = NULL;
  16.219 -static XMHEADER *mh = NULL;
  16.220 +/*========== Loader code */
  16.221  
  16.222  BOOL XM_Test(void)
  16.223  {
  16.224 -    UBYTE id[17];
  16.225 -    
  16.226 -    if(!_mm_read_UBYTES(id,17,modfp)) return 0;
  16.227 -    if(!memcmp(id,"Extended Module: ",17)) return 1;
  16.228 -    return 0;
  16.229 +	UBYTE id[38];
  16.230 +
  16.231 +	if(!_mm_read_UBYTES(id,38,modreader)) return 0;
  16.232 +	if(memcmp(id,"Extended Module: ",17)) return 0;
  16.233 +	if(id[37]==0x1a) return 1;
  16.234 +	return 0;
  16.235  }
  16.236  
  16.237 -
  16.238  BOOL XM_Init(void)
  16.239  {
  16.240 -    if(!(mh=(XMHEADER *)_mm_calloc(1,sizeof(XMHEADER)))) return 0;
  16.241 -    return 1;
  16.242 +	if(!(mh=(XMHEADER *)_mm_malloc(sizeof(XMHEADER)))) return 0;
  16.243 +	return 1;
  16.244  }
  16.245  
  16.246 -
  16.247  void XM_Cleanup(void)
  16.248  {
  16.249 -    if(mh!=NULL) free(mh);
  16.250 -    mh = NULL;
  16.251 +	_mm_free(mh);
  16.252  }
  16.253  
  16.254 +static int XM_ReadNote(XMNOTE* n)
  16.255 +{
  16.256 +	UBYTE cmp,result=1;
  16.257  
  16.258 -void XM_ReadNote(XMNOTE *n)
  16.259 -{
  16.260 -    UBYTE cmp;
  16.261 +	memset(n,0,sizeof(XMNOTE));
  16.262 +	cmp=_mm_read_UBYTE(modreader);
  16.263  
  16.264 -    memset(n,0,sizeof(XMNOTE));
  16.265 -
  16.266 -    cmp = _mm_read_UBYTE(modfp);
  16.267 -
  16.268 -    if(cmp&0x80)
  16.269 -    {   if(cmp&1)  n->note = _mm_read_UBYTE(modfp);
  16.270 -        if(cmp&2)  n->ins  = _mm_read_UBYTE(modfp);
  16.271 -        if(cmp&4)  n->vol  = _mm_read_UBYTE(modfp);
  16.272 -        if(cmp&8)  n->eff  = _mm_read_UBYTE(modfp);
  16.273 -        if(cmp&16) n->dat  = _mm_read_UBYTE(modfp);
  16.274 -    }
  16.275 -    else
  16.276 -    {   n->note = cmp;
  16.277 -        n->ins  = _mm_read_UBYTE(modfp);
  16.278 -        n->vol  = _mm_read_UBYTE(modfp);
  16.279 -        n->eff  = _mm_read_UBYTE(modfp);
  16.280 -        n->dat  = _mm_read_UBYTE(modfp);
  16.281 -    }
  16.282 +	if(cmp&0x80) {
  16.283 +		if(cmp&1)  { result++;n->note = _mm_read_UBYTE(modreader); }
  16.284 +		if(cmp&2)  { result++;n->ins  = _mm_read_UBYTE(modreader); }
  16.285 +		if(cmp&4)  { result++;n->vol  = _mm_read_UBYTE(modreader); }
  16.286 +		if(cmp&8)  { result++;n->eff  = _mm_read_UBYTE(modreader); }
  16.287 +		if(cmp&16) { result++;n->dat  = _mm_read_UBYTE(modreader); }
  16.288 +	} else {
  16.289 +		n->note = cmp;
  16.290 +		n->ins  = _mm_read_UBYTE(modreader);
  16.291 +		n->vol  = _mm_read_UBYTE(modreader);
  16.292 +		n->eff  = _mm_read_UBYTE(modreader);
  16.293 +		n->dat  = _mm_read_UBYTE(modreader);
  16.294 +		result += 4;
  16.295 +	}
  16.296 +	return result;
  16.297  }
  16.298  
  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  
  16.304 -UBYTE *XM_Convert(XMNOTE *xmtrack,UWORD rows)
  16.305 -{
  16.306 -    int t;
  16.307 -    UBYTE note,ins,vol,eff,dat;
  16.308 +	UniReset();
  16.309 +	for(t=0;t<rows;t++) {
  16.310 +		note = xmtrack->note;
  16.311 +		ins  = xmtrack->ins;
  16.312 +		vol  = xmtrack->vol;
  16.313 +		eff  = xmtrack->eff;
  16.314 +		dat  = xmtrack->dat;
  16.315  
  16.316 -    UniReset();
  16.317 +		if(note) {
  16.318 +			if(note>XMNOTECNT)
  16.319 +				UniEffect(UNI_KEYFADE,0);
  16.320 +			else
  16.321 +				UniNote(note-1);
  16.322 +		}
  16.323 +		if(ins) UniInstrument(ins-1);
  16.324  
  16.325 -    for(t=0; t<rows; t++)
  16.326 -    {   note = xmtrack->note;
  16.327 -        ins  = xmtrack->ins;
  16.328 -        vol  = xmtrack->vol;
  16.329 -        eff  = xmtrack->eff;
  16.330 -        dat  = xmtrack->dat;
  16.331 +		switch(vol>>4) {
  16.332 +			case 0x6: /* volslide down */
  16.333 +				if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
  16.334 +				break;
  16.335 +			case 0x7: /* volslide up */
  16.336 +				if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
  16.337 +				break;
  16.338  
  16.339 -        if(note!=0)
  16.340 -        {  if(note==97) 
  16.341 -           {   UniWrite(UNI_KEYFADE);
  16.342 -               UniWrite(0);
  16.343 -           } else
  16.344 -               UniNote(note-1);
  16.345 -        }
  16.346 +				/* volume-row fine volume slide is compatible with protracker
  16.347 +				   EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
  16.348 +				   opposed to 'take the last sliding value'. */
  16.349 +			case 0x8: /* finevol down */
  16.350 +				UniPTEffect(0xe,0xb0|(vol&0xf));
  16.351 +				break;
  16.352 +			case 0x9: /* finevol up */
  16.353 +				UniPTEffect(0xe,0xa0|(vol&0xf));
  16.354 +				break;
  16.355 +			case 0xa: /* set vibrato speed */
  16.356 +				UniPTEffect(0x4,vol<<4);
  16.357 +				break;
  16.358 +			case 0xb: /* vibrato */
  16.359 +				UniPTEffect(0x4,vol&0xf);
  16.360 +				break;
  16.361 +			case 0xc: /* set panning */
  16.362 +				UniPTEffect(0x8,vol<<4);
  16.363 +				break;
  16.364 +			case 0xd: /* panning slide left (only slide when data not zero) */
  16.365 +				if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
  16.366 +				break;
  16.367 +			case 0xe: /* panning slide right (only slide when data not zero) */
  16.368 +				if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
  16.369 +				break;
  16.370 +			case 0xf: /* tone porta */
  16.371 +				UniPTEffect(0x3,vol<<4);
  16.372 +				break;
  16.373 +			default:
  16.374 +				if((vol>=0x10)&&(vol<=0x50))
  16.375 +					UniPTEffect(0xc,vol-0x10);
  16.376 +		}
  16.377  
  16.378 -        if(ins!=0) UniInstrument(ins-1);
  16.379 -
  16.380 -        switch(vol>>4)
  16.381 -        {
  16.382 -            case 0x6:                   /* volslide down */
  16.383 -                if(vol&0xf)
  16.384 -                {   UniWrite(UNI_XMEFFECTA);
  16.385 -                    UniWrite(vol&0xf);
  16.386 -                }
  16.387 -                break;
  16.388 -
  16.389 -            case 0x7:                   /* volslide up */
  16.390 -                if(vol&0xf)
  16.391 -                {   UniWrite(UNI_XMEFFECTA);
  16.392 -                    UniWrite(vol<<4);
  16.393 -                }
  16.394 -                break;
  16.395 -
  16.396 -            /* volume-row fine volume slide is compatible with protracker */
  16.397 -            /* EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as */
  16.398 -            /* opposed to 'take the last sliding value'. */
  16.399 -
  16.400 -            case 0x8:                       /* finevol down */
  16.401 -                UniPTEffect(0xe,0xb0 | (vol&0xf));
  16.402 -                break;
  16.403 -
  16.404 -            case 0x9:                       /* finevol up */
  16.405 -                UniPTEffect(0xe,0xa0 | (vol&0xf));
  16.406 -                break;
  16.407 -
  16.408 -            case 0xa:                       /* set vibrato speed */
  16.409 -                UniPTEffect(0x4,vol<<4);
  16.410 -                break;
  16.411 -
  16.412 -            case 0xb:                       /* vibrato */
  16.413 -                UniPTEffect(0x4,vol&0xf);
  16.414 -                break;
  16.415 -
  16.416 -            case 0xc:                       /* set panning */
  16.417 -                UniPTEffect(0x8,vol<<4);
  16.418 -                break;
  16.419 -
  16.420 -            case 0xd:                       /* panning slide left */
  16.421 -                /* only slide when data nibble not zero: */
  16.422 -
  16.423 -                if(vol&0xf)
  16.424 -                {   UniWrite(UNI_XMEFFECTP);
  16.425 -                    UniWrite(vol&0xf);
  16.426 -                }
  16.427 -                break;
  16.428 -
  16.429 -            case 0xe:                       /* panning slide right */
  16.430 -                /* only slide when data nibble not zero: */
  16.431 -
  16.432 -                if(vol&0xf)
  16.433 -                {   UniWrite(UNI_XMEFFECTP);
  16.434 -                    UniWrite(vol<<4);
  16.435 -                }
  16.436 -             break;
  16.437 -
  16.438 -            case 0xf:                       /* tone porta */
  16.439 -                UniPTEffect(0x3,vol<<4);
  16.440 -            break;
  16.441 -
  16.442 -            default:
  16.443 -                if(vol>=0x10 && vol<=0x50)
  16.444 -                    UniPTEffect(0xc,vol-0x10);
  16.445 -        }
  16.446 -
  16.447 -        switch(eff)
  16.448 -        {
  16.449 -            case 0x4:                       /* Effect 4: Vibrato */
  16.450 -                UniWrite(UNI_XMEFFECT4);
  16.451 -                UniWrite(dat);
  16.452 -            break;
  16.453 -
  16.454 -            case 0xa:
  16.455 -                UniWrite(UNI_XMEFFECTA);
  16.456 -                UniWrite(dat);
  16.457 -            break;
  16.458 -
  16.459 -            case 0xe:
  16.460 -                switch(dat>>4)
  16.461 -                {  case 0x1:      /* XM fine porta up */
  16.462 -                      UniWrite(UNI_XMEFFECTE1);
  16.463 -                      UniWrite(dat&0xf);
  16.464 -                   break;
  16.465 -
  16.466 -                   case 0x2:      /* XM fine porta down */
  16.467 -                      UniWrite(UNI_XMEFFECTE2);
  16.468 -                      UniWrite(dat&0xf);
  16.469 -                   break;
  16.470 -
  16.471 -                   case 0xa:      /* XM fine volume up */
  16.472 -                      UniWrite(UNI_XMEFFECTEA);
  16.473 -                      UniWrite(dat&0xf);
  16.474 -                   break;
  16.475 -
  16.476 -                   case 0xb:      /* XM fine volume down */
  16.477 -                      UniWrite(UNI_XMEFFECTEB);
  16.478 -                      UniWrite(dat&0xf);
  16.479 -                   break;
  16.480 -
  16.481 -                   default:
  16.482 -                      UniPTEffect(0x0e,dat);
  16.483 -                }
  16.484 -            break;
  16.485 -
  16.486 -            case 'G'-55:                    /* G - set global volume */
  16.487 -                if(dat>64) dat = 64;
  16.488 -                UniWrite(UNI_XMEFFECTG);
  16.489 -                UniWrite(dat);
  16.490 -                break;
  16.491 -
  16.492 -            case 'H'-55:                    /* H - global volume slide */
  16.493 -                UniWrite(UNI_XMEFFECTH);
  16.494 -                UniWrite(dat);
  16.495 -                break;
  16.496 -
  16.497 -            case 'K'-55:                    /* K - keyOff and KeyFade */
  16.498 -                UniWrite(UNI_KEYFADE);
  16.499 -                UniWrite(dat);
  16.500 -                break;
  16.501 -
  16.502 -            case 'L'-55:                    /* L - set envelope position */
  16.503 -                UniWrite(UNI_XMEFFECTL);
  16.504 -                UniWrite(dat);
  16.505 -                break;
  16.506 -
  16.507 -            case 'P'-55:                    /* P - panning slide */
  16.508 -                UniWrite(UNI_XMEFFECTP);
  16.509 -                UniWrite(dat);
  16.510 -                break;
  16.511 -
  16.512 -            case 'R'-55:                    /* R - multi retrig note */
  16.513 -                UniWrite(UNI_S3MEFFECTQ);
  16.514 -                UniWrite(dat);
  16.515 -                break;
  16.516 -
  16.517 -            case 'T'-55:                    /* T - Tremor !! (== S3M effect I) */
  16.518 -                UniWrite(UNI_S3MEFFECTI);
  16.519 -                UniWrite(dat);
  16.520 -                break;
  16.521 -
  16.522 -            case 'X'-55:
  16.523 -                if((dat>>4) == 1)           /* X1 - Extra Fine Porta up */
  16.524 -                {  UniWrite(UNI_XMEFFECTX1);
  16.525 -                   UniWrite(dat & 0xf);
  16.526 -                } else if((dat>>4) == 2)    /* X2 - Extra Fine Porta down */
  16.527 -                {  UniWrite(UNI_XMEFFECTX2);
  16.528 -                   UniWrite(dat & 0xf);
  16.529 -                }
  16.530 -            break;
  16.531 -
  16.532 -            default:
  16.533 -                if(eff <= 0xf)
  16.534 -                {   /* Convert pattern jump from Dec to Hex */
  16.535 -                    if(eff == 0xd)
  16.536 -                        dat = (((dat&0xf0)>>4)*10)+(dat&0xf);
  16.537 -                    UniPTEffect(eff,dat);
  16.538 -                }
  16.539 -            break;
  16.540 -        }
  16.541 -
  16.542 -        UniNewline();
  16.543 -        xmtrack++;
  16.544 -    }
  16.545 -    return UniDup();
  16.546 +		switch(eff) {
  16.547 +			case 0x4:
  16.548 +				UniEffect(UNI_XMEFFECT4,dat);
  16.549 +				break;
  16.550 +			case 0xa:
  16.551 +				UniEffect(UNI_XMEFFECTA,dat);
  16.552 +				break;
  16.553 +			case 0xe: /* Extended effects */
  16.554 +				switch(dat>>4) {
  16.555 +					case 0x1: /* XM fine porta up */
  16.556 +						UniEffect(UNI_XMEFFECTE1,dat&0xf);
  16.557 +						break;
  16.558 +					case 0x2: /* XM fine porta down */
  16.559 +						UniEffect(UNI_XMEFFECTE2,dat&0xf);
  16.560 +						break;
  16.561 +					case 0xa: /* XM fine volume up */
  16.562 +						UniEffect(UNI_XMEFFECTEA,dat&0xf);
  16.563 +						break;
  16.564 +					case 0xb: /* XM fine volume down */
  16.565 +						UniEffect(UNI_XMEFFECTEB,dat&0xf);
  16.566 +						break;
  16.567 +					default:
  16.568 +						UniPTEffect(eff,dat);
  16.569 +				}
  16.570 +				break;
  16.571 +			case 'G'-55: /* G - set global volume */
  16.572 +				UniEffect(UNI_XMEFFECTG,dat>64?64:dat);
  16.573 +				break;
  16.574 +			case 'H'-55: /* H - global volume slide */
  16.575 +				UniEffect(UNI_XMEFFECTH,dat);
  16.576 +				break;
  16.577 +			case 'K'-55: /* K - keyOff and KeyFade */
  16.578 +				UniEffect(UNI_KEYFADE,dat);
  16.579 +				break;
  16.580 +			case 'L'-55: /* L - set envelope position */
  16.581 +				UniEffect(UNI_XMEFFECTL,dat);
  16.582 +				break;
  16.583 +			case 'P'-55: /* P - panning slide */
  16.584 +				UniEffect(UNI_XMEFFECTP,dat);
  16.585 +				break;
  16.586 +			case 'R'-55: /* R - multi retrig note */
  16.587 +				UniEffect(UNI_S3MEFFECTQ,dat);
  16.588 +				break;
  16.589 +			case 'T'-55: /* T - Tremor */
  16.590 +				UniEffect(UNI_S3MEFFECTI,dat);
  16.591 +				break;
  16.592 +			case 'X'-55:
  16.593 +				switch(dat>>4) {
  16.594 +					case 1: /* X1 - Extra Fine Porta up */
  16.595 +						UniEffect(UNI_XMEFFECTX1,dat&0xf);
  16.596 +						break;
  16.597 +					case 2: /* X2 - Extra Fine Porta down */
  16.598 +						UniEffect(UNI_XMEFFECTX2,dat&0xf);
  16.599 +						break;
  16.600 +				}
  16.601 +				break;
  16.602 +			default:
  16.603 +				if(eff<=0xf) {
  16.604 +					/* the pattern jump destination is written in decimal,
  16.605 +					   but it seems some poor tracker software writes them
  16.606 +					   in hexadecimal... (sigh) */
  16.607 +					if (eff==0xd)
  16.608 +						/* don't change anything if we're sure it's in hexa */
  16.609 +						if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
  16.610 +							/* otherwise, convert from dec to hex */
  16.611 +							dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
  16.612 +					UniPTEffect(eff,dat);
  16.613 +				}
  16.614 +				break;
  16.615 +		}
  16.616 +		UniNewline();
  16.617 +		xmtrack++;
  16.618 +	}
  16.619 +	return UniDup();
  16.620  }
  16.621  
  16.622 +static BOOL LoadPatterns(BOOL dummypat)
  16.623 +{
  16.624 +	int t,u,v,numtrk;
  16.625  
  16.626 +	if(!AllocTracks()) return 0;
  16.627 +	if(!AllocPatterns()) return 0;
  16.628  
  16.629 -BOOL XM_Load(void)
  16.630 -{
  16.631 -    INSTRUMENT *d;
  16.632 -    SAMPLE     *q;
  16.633 -    XMWAVHEADER *wh,*s;
  16.634 -    int   t,u,v,p,numtrk;
  16.635 -    long  next;
  16.636 -    ULONG nextwav[256];
  16.637 -    BOOL  dummypat=0;
  16.638 - 
  16.639 -    /* try to read module header */
  16.640 +	numtrk=0;
  16.641 +	for(t=0;t<mh->numpat;t++) {
  16.642 +		XMPATHEADER ph;
  16.643  
  16.644 -    _mm_read_string(mh->id,17,modfp);
  16.645 -    _mm_read_string(mh->songname,21,modfp);
  16.646 -    _mm_read_string(mh->trackername,20,modfp);
  16.647 -    mh->version     =_mm_read_I_UWORD(modfp);
  16.648 -    mh->headersize  =_mm_read_I_ULONG(modfp);
  16.649 -    mh->songlength  =_mm_read_I_UWORD(modfp);
  16.650 -    mh->restart     =_mm_read_I_UWORD(modfp);
  16.651 -    mh->numchn      =_mm_read_I_UWORD(modfp);
  16.652 -    mh->numpat      =_mm_read_I_UWORD(modfp);
  16.653 -    mh->numins      =_mm_read_I_UWORD(modfp);
  16.654 -    mh->flags       =_mm_read_I_UWORD(modfp);
  16.655 -    mh->tempo       =_mm_read_I_UWORD(modfp);
  16.656 -    mh->bpm         =_mm_read_I_UWORD(modfp);
  16.657 -    _mm_read_UBYTES(mh->orders,256,modfp);
  16.658 +		ph.size     =_mm_read_I_ULONG(modreader);
  16.659 +		if (ph.size<(mh->version==0x0102?8:9)) {
  16.660 +			_mm_errno=MMERR_LOADING_PATTERN;
  16.661 +			return 0;
  16.662 +		}
  16.663 +		ph.packing  =_mm_read_UBYTE(modreader);
  16.664 +		if(ph.packing) {
  16.665 +			_mm_errno=MMERR_LOADING_PATTERN;
  16.666 +			return 0;
  16.667 +		}
  16.668 +		if(mh->version==0x0102)
  16.669 +			ph.numrows  =_mm_read_UBYTE(modreader)+1;
  16.670 +		else
  16.671 +			ph.numrows  =_mm_read_I_UWORD(modreader);
  16.672 +		ph.packsize =_mm_read_I_UWORD(modreader);
  16.673  
  16.674 -    if(feof(modfp))
  16.675 -    {   _mm_errno = MMERR_LOADING_HEADER;
  16.676 -        return 0;
  16.677 -    }
  16.678 +		ph.size-=(mh->version==0x0102?8:9);
  16.679 +		if(ph.size)
  16.680 +			_mm_fseek(modreader,ph.size,SEEK_CUR);
  16.681  
  16.682 -    /* set module variables */
  16.683 -    of.initspeed = mh->tempo;         
  16.684 -    of.inittempo = mh->bpm;
  16.685 -    of.modtype   = DupStr(mh->trackername,20);
  16.686 -    of.numchn    = mh->numchn;
  16.687 -    of.numpat    = mh->numpat;
  16.688 -    of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
  16.689 -    of.songname  = DupStr(mh->songname,20);      /* make a cstr of songname */
  16.690 -    of.numpos    = mh->songlength;               /* copy the songlength */
  16.691 -    of.reppos    = mh->restart;
  16.692 -    of.numins    = mh->numins;
  16.693 -    of.flags |= UF_XMPERIODS | UF_INST;
  16.694 -    if(mh->flags&1) of.flags |= UF_LINEAR;
  16.695 +		of.pattrows[t]=ph.numrows;
  16.696  
  16.697 -    memset(of.chanvol,64,of.numchn);             /* store channel volumes */
  16.698 +		if(ph.numrows) {
  16.699 +			if(!(xmpat=(XMNOTE*)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
  16.700 +				return 0;
  16.701  
  16.702 -    if(!AllocPositions(of.numpos+3)) return 0;
  16.703 -    for(t=0; t<of.numpos; t++)
  16.704 -        of.positions[t] = mh->orders[t];
  16.705 +			/* when packsize is 0, don't try to load a pattern.. it's empty. */
  16.706 +			if(ph.packsize)
  16.707 +				for(u=0;u<ph.numrows;u++)
  16.708 +					for(v=0;v<of.numchn;v++) {
  16.709 +						if(!ph.packsize) break;
  16.710  
  16.711 -/*
  16.712 -   WHY THIS CODE HERE?? I CAN'T REMEMBER!
  16.713 -   
  16.714 -   Well, I do know why, mikmak!  Seems that FT2 doesn't always count blank 
  16.715 -   patterns AT ALL if they are at the END of the song.  So, we have to check
  16.716 -   for any patter numbers in the order list greater than the number of pat-
  16.717 -   terns total.  If one or more is found, we set it equal to the pattern total
  16.718 -   and make a dummy pattern to accomidate for the discrepency!
  16.719 -*/
  16.720 +						ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  16.721 +						if(ph.packsize<0) {
  16.722 +							free(xmpat);xmpat=NULL;
  16.723 +							_mm_errno=MMERR_LOADING_PATTERN;
  16.724 +							return 0;
  16.725 +						}
  16.726 +					}
  16.727  
  16.728 -    for(t=0; t<of.numpos; t++)
  16.729 -    {   if(of.positions[t] > of.numpat)
  16.730 -        {  of.positions[t] = of.numpat;
  16.731 -           dummypat = 1;
  16.732 -        }
  16.733 -    }      
  16.734 +			if(ph.packsize) {
  16.735 +				_mm_fseek(modreader,ph.packsize,SEEK_CUR);
  16.736 +			}
  16.737  
  16.738 -    if(dummypat) { of.numpat++; of.numtrk+=of.numchn; }
  16.739 +			if(_mm_eof(modreader)) {
  16.740 +				free(xmpat);xmpat=NULL;
  16.741 +				_mm_errno=MMERR_LOADING_PATTERN;
  16.742 +				return 0;
  16.743 +			}
  16.744  
  16.745 -    if(!AllocTracks()) return 0;
  16.746 -    if(!AllocPatterns()) return 0;
  16.747 +			for(v=0;v<of.numchn;v++)
  16.748 +				of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  16.749  
  16.750 -    numtrk = 0;
  16.751 -    for(t=0; t<mh->numpat; t++)
  16.752 -    {   XMPATHEADER ph;
  16.753 +			free(xmpat);xmpat=NULL;
  16.754 +		} else {
  16.755 +			for(v=0;v<of.numchn;v++)
  16.756 +				of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
  16.757 +		}
  16.758 +	}
  16.759  
  16.760 -        ph.size     =_mm_read_I_ULONG(modfp);
  16.761 -        ph.packing  =_mm_read_UBYTE(modfp);
  16.762 -        ph.numrows  =_mm_read_I_UWORD(modfp);
  16.763 -        ph.packsize =_mm_read_I_UWORD(modfp);
  16.764 +	if(dummypat) {
  16.765 +		of.pattrows[t]=64;
  16.766 +		if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
  16.767 +		for(v=0;v<of.numchn;v++)
  16.768 +			of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
  16.769 +		free(xmpat);xmpat=NULL;
  16.770 +	}
  16.771  
  16.772 -        of.pattrows[t] = ph.numrows;
  16.773 -
  16.774 -        /*  Gr8.. when packsize is 0, don't try to load a pattern.. it's empty. */
  16.775 -        /*  This bug was discovered thanks to Khyron's module.. */
  16.776 -
  16.777 -        if(!(xmpat=(XMNOTE *)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0;
  16.778 -
  16.779 -        if(ph.packsize>0)
  16.780 -        {   for(u=0; u<ph.numrows; u++)
  16.781 -            {   for(v=0; v<of.numchn; v++)
  16.782 -                    XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  16.783 -            }
  16.784 -        }
  16.785 -
  16.786 -        if(feof(modfp))
  16.787 -        {   _mm_errno = MMERR_LOADING_PATTERN;
  16.788 -            return 0;
  16.789 -        }
  16.790 -
  16.791 -        for(v=0; v<of.numchn; v++)                                           
  16.792 -           of.tracks[numtrk++] = XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  16.793 -
  16.794 -        free(xmpat);
  16.795 -    }
  16.796 -                                                          
  16.797 -    if(dummypat)
  16.798 -    {  of.pattrows[t] = 64;
  16.799 -       if(!(xmpat=(XMNOTE *)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
  16.800 -       for(v=0; v<of.numchn; v++)
  16.801 -           of.tracks[numtrk++] = XM_Convert(&xmpat[v*64],64);
  16.802 -       free(xmpat);
  16.803 -    }
  16.804 -
  16.805 -    if(!AllocInstruments()) return 0;
  16.806 -    if((wh = (XMWAVHEADER *)_mm_calloc(256,sizeof(XMWAVHEADER))) == NULL) return 0;
  16.807 -    d = of.instruments;
  16.808 -    s = wh;
  16.809 -
  16.810 -
  16.811 -    for(t=0; t<of.numins; t++)
  16.812 -    {   XMINSTHEADER ih;
  16.813 -        int          headend;
  16.814 -
  16.815 -        memset(d->samplenumber,255,120);
  16.816 -
  16.817 -        /* read instrument header */
  16.818 -
  16.819 -        headend     = _mm_ftell(modfp);
  16.820 -        ih.size     = _mm_read_I_ULONG(modfp);
  16.821 -        headend    += ih.size;
  16.822 -        _mm_read_string(ih.name, 22, modfp);
  16.823 -        ih.type     = _mm_read_UBYTE(modfp);
  16.824 -        ih.numsmp   = _mm_read_I_UWORD(modfp);
  16.825 -        d->insname  = DupStr(ih.name,22);
  16.826 -
  16.827 -        if(ih.size > 29)
  16.828 -        {   ih.ssize    = _mm_read_I_ULONG(modfp);
  16.829 -            if(ih.numsmp > 0)
  16.830 -            {   XMPATCHHEADER pth;
  16.831 -    
  16.832 -                _mm_read_UBYTES (pth.what, 96, modfp);
  16.833 -                _mm_read_I_UWORDS (pth.volenv, 24, modfp);
  16.834 -                _mm_read_I_UWORDS (pth.panenv, 24, modfp);
  16.835 -                pth.volpts      =  _mm_read_UBYTE(modfp);
  16.836 -                pth.panpts      =  _mm_read_UBYTE(modfp);
  16.837 -                pth.volsus      =  _mm_read_UBYTE(modfp);
  16.838 -                pth.volbeg      =  _mm_read_UBYTE(modfp);
  16.839 -                pth.volend      =  _mm_read_UBYTE(modfp);
  16.840 -                pth.pansus      =  _mm_read_UBYTE(modfp);
  16.841 -                pth.panbeg      =  _mm_read_UBYTE(modfp);
  16.842 -                pth.panend      =  _mm_read_UBYTE(modfp);
  16.843 -                pth.volflg      =  _mm_read_UBYTE(modfp);
  16.844 -                pth.panflg      =  _mm_read_UBYTE(modfp);
  16.845 -                pth.vibflg      =  _mm_read_UBYTE(modfp);
  16.846 -                pth.vibsweep    =  _mm_read_UBYTE(modfp);
  16.847 -                pth.vibdepth    =  _mm_read_UBYTE(modfp);
  16.848 -                pth.vibrate     =  _mm_read_UBYTE(modfp);
  16.849 -                pth.volfade     =  _mm_read_I_UWORD(modfp);
  16.850 -    
  16.851 -                /* read the remainder of the header */
  16.852 -                for(u=headend-_mm_ftell(modfp); u; u--)  _mm_read_UBYTE(modfp);
  16.853 -    
  16.854 -                if(feof(modfp))
  16.855 -                {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  16.856 -                    return 0;
  16.857 -                }
  16.858 -    
  16.859 -                for(u=0; u<96; u++)         
  16.860 -                   d->samplenumber[u] = pth.what[u] + of.numsmp;
  16.861 -    
  16.862 -                d->volfade = pth.volfade;
  16.863 -    
  16.864 -                memcpy(d->volenv,pth.volenv,24);
  16.865 -                if(pth.volflg & 1)  d->volflg |= EF_ON;
  16.866 -                if(pth.volflg & 2)  d->volflg |= EF_SUSTAIN;
  16.867 -                if(pth.volflg & 4)  d->volflg |= EF_LOOP;
  16.868 -                d->volsusbeg = d->volsusend = pth.volsus;
  16.869 -                d->volbeg    = pth.volbeg;
  16.870 -                d->volend    = pth.volend;
  16.871 -                d->volpts    = pth.volpts;
  16.872 -    
  16.873 -                /* scale volume envelope: */
  16.874 -    
  16.875 -                for(p=0; p<12; p++)
  16.876 -                    d->volenv[p].val <<= 2;
  16.877 -    
  16.878 -                if((d->volflg & EF_ON) && (d->volpts < 2))
  16.879 -                    d->volflg &= ~EF_ON;
  16.880 -    
  16.881 -                memcpy(d->panenv,pth.panenv,24);
  16.882 -                d->panflg    = pth.panflg;
  16.883 -                d->pansusbeg = d->pansusend = pth.pansus;
  16.884 -                d->panbeg    = pth.panbeg;
  16.885 -                d->panend    = pth.panend;
  16.886 -                d->panpts    = pth.panpts;
  16.887 -    
  16.888 -                /* scale panning envelope: */
  16.889 -    
  16.890 -                for(p=0; p<12; p++)
  16.891 -                    d->panenv[p].val <<= 2;
  16.892 -                if((d->panflg & EF_ON) && (d->panpts < 2))
  16.893 -                    d->panflg &= ~EF_ON;
  16.894 -    
  16.895 -                next = 0;
  16.896 -    
  16.897 -                /*  Samples are stored outside the instrument struct now, so we have */
  16.898 -                /*  to load them all into a temp area, count the of.numsmp along the */
  16.899 -                /*  way and then do an AllocSamples() and move everything over  */
  16.900 -    
  16.901 -                for(u=0; u<ih.numsmp; u++,s++)
  16.902 -                {   s->length       =_mm_read_I_ULONG (modfp);
  16.903 -                    s->loopstart    =_mm_read_I_ULONG (modfp);
  16.904 -                    s->looplength   =_mm_read_I_ULONG (modfp);
  16.905 -                    s->volume       =_mm_read_UBYTE (modfp);
  16.906 -                    s->finetune     =_mm_read_SBYTE (modfp);
  16.907 -                    s->type         =_mm_read_UBYTE (modfp);
  16.908 -                    s->panning      =_mm_read_UBYTE (modfp);
  16.909 -                    s->relnote      =_mm_read_SBYTE (modfp);
  16.910 -                    s->vibtype      = pth.vibflg;
  16.911 -                    s->vibsweep     = pth.vibsweep;
  16.912 -                    s->vibdepth     = pth.vibdepth*4;
  16.913 -                    s->vibrate      = pth.vibrate;
  16.914 -    
  16.915 -                    s->reserved =_mm_read_UBYTE (modfp);
  16.916 -                    _mm_read_string(s->samplename, 22, modfp);
  16.917 -    
  16.918 -                    nextwav[of.numsmp+u] = next;
  16.919 -                    next += s->length;
  16.920 -    
  16.921 -                    if(feof(modfp))
  16.922 -                    {   _mm_errno = MMERR_LOADING_SAMPLEINFO;
  16.923 -                        return 0;
  16.924 -                    }
  16.925 -                }
  16.926 -    
  16.927 -                for(u=0; u<ih.numsmp; u++) nextwav[of.numsmp++] += _mm_ftell(modfp);
  16.928 -                _mm_fseek(modfp,next,SEEK_CUR);
  16.929 -            }
  16.930 -        }
  16.931 -
  16.932 -        d++;
  16.933 -    }
  16.934 -
  16.935 -    if(!AllocSamples()) return 0;
  16.936 -    q = of.samples;
  16.937 -    s = wh;
  16.938 -
  16.939 -    for(u=0; u<of.numsmp; u++,q++,s++)
  16.940 -    {   q->samplename   = DupStr(s->samplename,22);
  16.941 -        q->length       = s->length;
  16.942 -        q->loopstart    = s->loopstart;
  16.943 -        q->loopend      = s->loopstart+s->looplength;
  16.944 -        q->volume       = s->volume;
  16.945 -        q->speed        = s->finetune+128;
  16.946 -        q->panning      = s->panning;
  16.947 -        q->seekpos      = nextwav[u];
  16.948 -        q->vibtype      = s->vibtype;
  16.949 -        q->vibsweep     = s->vibsweep;
  16.950 -        q->vibdepth     = s->vibdepth;
  16.951 -        q->vibrate      = s->vibrate;
  16.952 -
  16.953 -        if(s->type & 0x10)
  16.954 -        {   q->length    >>= 1;
  16.955 -            q->loopstart >>= 1;
  16.956 -            q->loopend   >>= 1;
  16.957 -        }
  16.958 -
  16.959 -        q->flags|=SF_OWNPAN;
  16.960 -        if(s->type&0x3) q->flags|=SF_LOOP;
  16.961 -        if(s->type&0x2) q->flags|=SF_BIDI;
  16.962 -
  16.963 -        if(s->type&0x10) q->flags|=SF_16BITS;
  16.964 -        q->flags|=SF_DELTA;
  16.965 -        q->flags|=SF_SIGNED;
  16.966 -    }
  16.967 -
  16.968 -    d = of.instruments;
  16.969 -    s = wh;
  16.970 -    for(u=0; u<of.numins; u++, d++)
  16.971 -    {  /*for(t=0; t<3; t++)
  16.972 -          if((s[d->samplenumber[t]].relnote / 12) > )
  16.973 -          {  s[d->samplenumber[t]].relnote -= 12;
  16.974 -             of.samples[d->samplenumber[t]].speed <<= 1;
  16.975 -          }
  16.976 -       */
  16.977 -       for(t=0; t<96; t++)
  16.978 -          d->samplenote[t] = (d->samplenumber[t]==of.numsmp) ? 255 : (t+s[d->samplenumber[t]].relnote);
  16.979 -    }
  16.980 -
  16.981 -    free(wh);
  16.982 -    return 1;
  16.983 +	return 1;
  16.984  }
  16.985  
  16.986 +static BOOL LoadInstruments(void)
  16.987 +{
  16.988 +	int t,u;
  16.989 +	INSTRUMENT *d;
  16.990 +	long next=0;
  16.991 +	UWORD wavcnt=0;
  16.992  
  16.993 +	if(!AllocInstruments()) return 0;
  16.994 +	d=of.instruments;
  16.995 +	for(t=0;t<of.numins;t++,d++) {
  16.996 +		XMINSTHEADER ih;
  16.997 +		long headend;
  16.998 +
  16.999 +		memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
 16.1000 +
 16.1001 +		/* read instrument header */
 16.1002 +		headend     = _mm_ftell(modreader);
 16.1003 +		ih.size     = _mm_read_I_ULONG(modreader);
 16.1004 +		headend    += ih.size;
 16.1005 +		_mm_read_string(ih.name, 22, modreader);
 16.1006 +		ih.type     = _mm_read_UBYTE(modreader);
 16.1007 +		ih.numsmp   = _mm_read_I_UWORD(modreader);
 16.1008 +
 16.1009 +		d->insname  = DupStr(ih.name,22,1);
 16.1010 +
 16.1011 +		if((SWORD)ih.size>29) {
 16.1012 +			ih.ssize    = _mm_read_I_ULONG(modreader);
 16.1013 +			if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
 16.1014 +				XMPATCHHEADER pth;
 16.1015 +				int p;
 16.1016 +
 16.1017 +				_mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
 16.1018 +				_mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
 16.1019 +				_mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
 16.1020 +				pth.volpts      =  _mm_read_UBYTE(modreader);
 16.1021 +				pth.panpts      =  _mm_read_UBYTE(modreader);
 16.1022 +				pth.volsus      =  _mm_read_UBYTE(modreader);
 16.1023 +				pth.volbeg      =  _mm_read_UBYTE(modreader);
 16.1024 +				pth.volend      =  _mm_read_UBYTE(modreader);
 16.1025 +				pth.pansus      =  _mm_read_UBYTE(modreader);
 16.1026 +				pth.panbeg      =  _mm_read_UBYTE(modreader);
 16.1027 +				pth.panend      =  _mm_read_UBYTE(modreader);
 16.1028 +				pth.volflg      =  _mm_read_UBYTE(modreader);
 16.1029 +				pth.panflg      =  _mm_read_UBYTE(modreader);
 16.1030 +				pth.vibflg      =  _mm_read_UBYTE(modreader);
 16.1031 +				pth.vibsweep    =  _mm_read_UBYTE(modreader);
 16.1032 +				pth.vibdepth    =  _mm_read_UBYTE(modreader);
 16.1033 +				pth.vibrate     =  _mm_read_UBYTE(modreader);
 16.1034 +				pth.volfade     =  _mm_read_I_UWORD(modreader);
 16.1035 +
 16.1036 +				/* read the remainder of the header
 16.1037 +				   (2 bytes for 1.03, 22 for 1.04) */
 16.1038 +				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
 16.1039 +
 16.1040 +				/* #@!$&% fix for K_OSPACE.XM */
 16.1041 +				if(pth.volpts==32) pth.volpts=XMENVCNT/2;
 16.1042 +
 16.1043 +				if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
 16.1044 +					if(nextwav) { free(nextwav);nextwav=NULL; }
 16.1045 +					if(wh) { free(wh);wh=NULL; }
 16.1046 +					_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1047 +					return 0;
 16.1048 +				}
 16.1049 +
 16.1050 +				for(u=0;u<XMNOTECNT;u++)
 16.1051 +					d->samplenumber[u]=pth.what[u]+of.numsmp;
 16.1052 +				d->volfade = pth.volfade;
 16.1053 +
 16.1054 +#ifdef __STDC__
 16.1055 +#define XM_ProcessEnvelope(name) 											\
 16.1056 +				memcpy(d->##name##env,pth.##name##env,XMENVCNT);			\
 16.1057 +				if (pth.##name##flg&1) d->##name##flg|=EF_ON;				\
 16.1058 +				if (pth.##name##flg&2) d->##name##flg|=EF_SUSTAIN;			\
 16.1059 +				if (pth.##name##flg&4) d->##name##flg|=EF_LOOP;				\
 16.1060 +				d->##name##susbeg=d->##name##susend=pth.##name##sus;		\
 16.1061 +				d->##name##beg=pth.##name##beg;								\
 16.1062 +				d->##name##end=pth.##name##end;								\
 16.1063 +				d->##name##pts=pth.##name##pts;								\
 16.1064 +																			\
 16.1065 +				/* scale envelope */										\
 16.1066 +				for (p=0;p<XMENVCNT/2;p++)									\
 16.1067 +					d->##name##env[p].val<<=2;								\
 16.1068 +																			\
 16.1069 +				if ((d->##name##flg&EF_ON)&&(d->##name##pts<2))				\
 16.1070 +					d->##name##flg&=~EF_ON;
 16.1071 +#else
 16.1072 +#define XM_ProcessEnvelope(name) 											\
 16.1073 +				memcpy(d->/**/name/**/env,pth./**/name/**/env,XMENVCNT);	\
 16.1074 +				if (pth./**/name/**/flg&1) d->/**/name/**/flg|=EF_ON;		\
 16.1075 +				if (pth./**/name/**/flg&2) d->/**/name/**/flg|=EF_SUSTAIN;	\
 16.1076 +				if (pth./**/name/**/flg&4) d->/**/name/**/flg|=EF_LOOP;		\
 16.1077 +				d->/**/name/**/susbeg=d->/**/name/**/susend=				\
 16.1078 +				                      pth./**/name/**/sus;					\
 16.1079 +				d->/**/name/**/beg=pth./**/name/**/beg;						\
 16.1080 +				d->/**/name/**/end=pth./**/name/**/end;						\
 16.1081 +				d->/**/name/**/pts=pth./**/name/**/pts;						\
 16.1082 +																			\
 16.1083 +				/* scale envelope */										\
 16.1084 +				for (p=0;p<XMENVCNT/2;p++)									\
 16.1085 +					d->/**/name/**/env[p].val<<=2;							\
 16.1086 +																			\
 16.1087 +				if ((d->/**/name/**/flg&EF_ON)&&(d->/**/name/**/pts<2))		\
 16.1088 +					d->/**/name/**/flg&=~EF_ON;
 16.1089 +#endif
 16.1090 +
 16.1091 +				XM_ProcessEnvelope(vol);
 16.1092 +				XM_ProcessEnvelope(pan);
 16.1093 +#undef XM_ProcessEnvelope
 16.1094 +
 16.1095 +				/* Samples are stored outside the instrument struct now, so we
 16.1096 +				   have to load them all into a temp area, count the of.numsmp
 16.1097 +				   along the way and then do an AllocSamples() and move
 16.1098 +				   everything over */
 16.1099 +				if(mh->version>0x0103) next = 0;
 16.1100 +				for(u=0;u<ih.numsmp;u++,s++) {
 16.1101 +					/* Allocate more room for sample information if necessary */
 16.1102 +					if(of.numsmp+u==wavcnt) {
 16.1103 +						wavcnt+=XM_SMPINCR;
 16.1104 +						if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
 16.1105 +							if(wh) { free(wh);wh=NULL; }
 16.1106 +							_mm_errno = MMERR_OUT_OF_MEMORY;
 16.1107 +							return 0;
 16.1108 +						}
 16.1109 +						if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
 16.1110 +							free(nextwav);nextwav=NULL;
 16.1111 +							_mm_errno = MMERR_OUT_OF_MEMORY;
 16.1112 +							return 0;
 16.1113 +						}
 16.1114 +						s=wh+(wavcnt-XM_SMPINCR);
 16.1115 +					}
 16.1116 +
 16.1117 +					s->length       =_mm_read_I_ULONG (modreader);
 16.1118 +					s->loopstart    =_mm_read_I_ULONG (modreader);
 16.1119 +					s->looplength   =_mm_read_I_ULONG (modreader);
 16.1120 +					s->volume       =_mm_read_UBYTE (modreader);
 16.1121 +					s->finetune     =_mm_read_SBYTE (modreader);
 16.1122 +					s->type         =_mm_read_UBYTE (modreader);
 16.1123 +					s->panning      =_mm_read_UBYTE (modreader);
 16.1124 +					s->relnote      =_mm_read_SBYTE (modreader);
 16.1125 +					s->vibtype      = pth.vibflg;
 16.1126 +					s->vibsweep     = pth.vibsweep;
 16.1127 +					s->vibdepth     = pth.vibdepth*4;
 16.1128 +					s->vibrate      = pth.vibrate;
 16.1129 +					s->reserved     =_mm_read_UBYTE (modreader);
 16.1130 +					_mm_read_string(s->samplename, 22, modreader);
 16.1131 +
 16.1132 +					nextwav[of.numsmp+u]=next;
 16.1133 +					next+=s->length;
 16.1134 +
 16.1135 +					if(_mm_eof(modreader)) {
 16.1136 +						free(nextwav);free(wh);
 16.1137 +						nextwav=NULL;wh=NULL;
 16.1138 +						_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1139 +						return 0;
 16.1140 +					}
 16.1141 +				}
 16.1142 +
 16.1143 +				if(mh->version>0x0103) {
 16.1144 +					for(u=0;u<ih.numsmp;u++)
 16.1145 +						nextwav[of.numsmp++]+=_mm_ftell(modreader);
 16.1146 +					_mm_fseek(modreader,next,SEEK_CUR);
 16.1147 +				} else
 16.1148 +					of.numsmp+=ih.numsmp;
 16.1149 +			} else {
 16.1150 +				/* read the remainder of the header */
 16.1151 +				for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
 16.1152 +
 16.1153 +				if(_mm_eof(modreader)) {
 16.1154 +					free(nextwav);free(wh);
 16.1155 +					nextwav=NULL;wh=NULL;
 16.1156 +					_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1157 +					return 0;
 16.1158 +				}
 16.1159 +			}
 16.1160 +		}
 16.1161 +	}
 16.1162 +
 16.1163 +	/* sanity check */
 16.1164 +	if(!of.numsmp) {
 16.1165 +		if(nextwav) { free(nextwav);nextwav=NULL; }
 16.1166 +		if(wh) { free(wh);wh=NULL; }
 16.1167 +		_mm_errno = MMERR_LOADING_SAMPLEINFO;
 16.1168 +		return 0;
 16.1169 +	}
 16.1170 +
 16.1171 +	return 1;
 16.1172 +}
 16.1173 +
 16.1174 +BOOL XM_Load(BOOL curious)
 16.1175 +{
 16.1176 +	INSTRUMENT *d;
 16.1177 +	SAMPLE *q;
 16.1178 +	int t,u;
 16.1179 +	BOOL dummypat=0;
 16.1180 +	char tracker[21],modtype[60];
 16.1181 +
 16.1182 +	/* try to read module header */
 16.1183 +	_mm_read_string(mh->id,17,modreader);
 16.1184 +	_mm_read_string(mh->songname,21,modreader);
 16.1185 +	_mm_read_string(mh->trackername,20,modreader);
 16.1186 +	mh->version     =_mm_read_I_UWORD(modreader);
 16.1187 +	if((mh->version<0x102)||(mh->version>0x104)) {
 16.1188 +		_mm_errno=MMERR_NOT_A_MODULE;
 16.1189 +		return 0;
 16.1190 +	}
 16.1191 +	mh->headersize  =_mm_read_I_ULONG(modreader);
 16.1192 +	mh->songlength  =_mm_read_I_UWORD(modreader);
 16.1193 +	mh->restart     =_mm_read_I_UWORD(modreader);
 16.1194 +	mh->numchn      =_mm_read_I_UWORD(modreader);
 16.1195 +	mh->numpat      =_mm_read_I_UWORD(modreader);
 16.1196 +	mh->numins      =_mm_read_I_UWORD(modreader);
 16.1197 +	mh->flags       =_mm_read_I_UWORD(modreader);
 16.1198 +	mh->tempo       =_mm_read_I_UWORD(modreader);
 16.1199 +	mh->bpm         =_mm_read_I_UWORD(modreader);
 16.1200 +	if(!mh->bpm) {
 16.1201 +		_mm_errno=MMERR_NOT_A_MODULE;
 16.1202 +		return 0;
 16.1203 +	}
 16.1204 +	_mm_read_UBYTES(mh->orders,256,modreader);
 16.1205 +
 16.1206 +	if(_mm_eof(modreader)) {
 16.1207 +		_mm_errno = MMERR_LOADING_HEADER;
 16.1208 +		return 0;
 16.1209 +	}
 16.1210 +
 16.1211 +	/* set module variables */
 16.1212 +	of.initspeed = mh->tempo;
 16.1213 +	of.inittempo = mh->bpm;
 16.1214 +	strncpy(tracker,mh->trackername,20);tracker[20]=0;
 16.1215 +	for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
 16.1216 +
 16.1217 +	/* some modules have the tracker name empty */
 16.1218 +	if (!tracker[0])
 16.1219 +		strcpy(tracker,"Unknown tracker");
 16.1220 +
 16.1221 +#ifdef HAVE_SNPRINTF
 16.1222 +	snprintf(modtype,60,"%s (XM format %d.%02d)",
 16.1223 +	                    tracker,mh->version>>8,mh->version&0xff);
 16.1224 +#else
 16.1225 +	sprintf(modtype,"%s (XM format %d.%02d)",
 16.1226 +	                tracker,mh->version>>8,mh->version&0xff);
 16.1227 +#endif
 16.1228 +	of.modtype   = strdup(modtype);
 16.1229 +	of.numchn    = mh->numchn;
 16.1230 +	of.numpat    = mh->numpat;
 16.1231 +	of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
 16.1232 +	of.songname  = DupStr(mh->songname,20,1);
 16.1233 +	of.numpos    = mh->songlength;               /* copy the songlength */
 16.1234 +	of.reppos    = mh->restart<mh->songlength?mh->restart:0;
 16.1235 +	of.numins    = mh->numins;
 16.1236 +	of.flags    |= UF_XMPERIODS|UF_INST|UF_BGSLIDES|UF_NOWRAP|UF_FT2QUIRKS;
 16.1237 +	if(mh->flags&1) of.flags |= UF_LINEAR;
 16.1238 +
 16.1239 +	memset(of.chanvol,64,of.numchn);             /* store channel volumes */
 16.1240 +
 16.1241 +	if(!AllocPositions(of.numpos+1)) return 0;
 16.1242 +	for(t=0;t<of.numpos;t++)
 16.1243 +		of.positions[t]=mh->orders[t];
 16.1244 +
 16.1245 +	/* We have to check for any pattern numbers in the order list greater than
 16.1246 +	   the number of patterns total. If one or more is found, we set it equal to
 16.1247 +	   the pattern total and make a dummy pattern to workaround the problem */
 16.1248 +	for(t=0;t<of.numpos;t++) {
 16.1249 +		if(of.positions[t]>=of.numpat) {
 16.1250 +			of.positions[t]=of.numpat;
 16.1251 +			dummypat=1;
 16.1252 +		}
 16.1253 +	}
 16.1254 +	if(dummypat) {
 16.1255 +		of.numpat++;of.numtrk+=of.numchn;
 16.1256 +	}
 16.1257 +
 16.1258 +	if(mh->version<0x0104) {
 16.1259 +		if(!LoadInstruments()) return 0;
 16.1260 +		if(!LoadPatterns(dummypat)) return 0;
 16.1261 +		for(t=0;t<of.numsmp;t++)
 16.1262 +			nextwav[t]+=_mm_ftell(modreader);
 16.1263 +	} else {
 16.1264 +		if(!LoadPatterns(dummypat)) return 0;
 16.1265 +		if(!LoadInstruments()) return 0;
 16.1266 +	}
 16.1267 +
 16.1268 +	if(!AllocSamples()) {
 16.1269 +		free(nextwav);free(wh);
 16.1270 +		nextwav=NULL;wh=NULL;
 16.1271 +		return 0;
 16.1272 +	}
 16.1273 +	q = of.samples;
 16.1274 +	s = wh;
 16.1275 +	for(u=0;u<of.numsmp;u++,q++,s++) {
 16.1276 +		q->samplename   = DupStr(s->samplename,22,1);
 16.1277 +		q->length       = s->length;
 16.1278 +		q->loopstart    = s->loopstart;
 16.1279 +		q->loopend      = s->loopstart+s->looplength;
 16.1280 +		q->volume       = s->volume;
 16.1281 +		q->speed        = s->finetune+128;
 16.1282 +		q->panning      = s->panning;
 16.1283 +		q->seekpos      = nextwav[u];
 16.1284 +		q->vibtype      = s->vibtype;
 16.1285 +		q->vibsweep     = s->vibsweep;
 16.1286 +		q->vibdepth     = s->vibdepth;
 16.1287 +		q->vibrate      = s->vibrate;
 16.1288 +
 16.1289 +		if(s->type & 0x10) {
 16.1290 +			q->length    >>= 1;
 16.1291 +			q->loopstart >>= 1;
 16.1292 +			q->loopend   >>= 1;
 16.1293 +		}
 16.1294 +
 16.1295 +		q->flags|=SF_OWNPAN;
 16.1296 +		if(s->type&0x3) q->flags|=SF_LOOP;
 16.1297 +		if(s->type&0x2) q->flags|=SF_BIDI;
 16.1298 +		if(s->type&0x10) q->flags|=SF_16BITS;
 16.1299 +		q->flags|=SF_DELTA|SF_SIGNED;
 16.1300 +	}
 16.1301 +
 16.1302 +	d=of.instruments;
 16.1303 +	s=wh;
 16.1304 +	for(u=0;u<of.numins;u++,d++)
 16.1305 +		for(t=0;t<XMNOTECNT;t++) {
 16.1306 +			if (d->samplenumber[t]>=of.numsmp)
 16.1307 +				d->samplenote[t]=255;
 16.1308 +			else {
 16.1309 +				int note=t+s[d->samplenumber[t]].relnote;
 16.1310 +				d->samplenote[t]=(note<0)?0:note;
 16.1311 +			}
 16.1312 +		}
 16.1313 +
 16.1314 +	free(wh);free(nextwav);
 16.1315 +	wh=NULL;nextwav=NULL;
 16.1316 +	return 1;
 16.1317 +}
 16.1318  
 16.1319  CHAR *XM_LoadTitle(void)
 16.1320  {
 16.1321 -    CHAR s[21];
 16.1322 +	CHAR s[21];
 16.1323  
 16.1324 -    _mm_fseek(modfp,17,SEEK_SET);
 16.1325 -    if(!fread(s,21,1,modfp)) return NULL;
 16.1326 -  
 16.1327 -    return(DupStr(s,21));
 16.1328 +	_mm_fseek(modreader,17,SEEK_SET);
 16.1329 +	if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
 16.1330 +
 16.1331 +	return(DupStr(s,21,1));
 16.1332  }
 16.1333  
 16.1334 +/*========== Loader information */
 16.1335  
 16.1336 +MLOADER load_xm={
 16.1337 +	NULL,
 16.1338 +	"XM",
 16.1339 +	"XM (FastTracker 2)",
 16.1340 +	XM_Init,
 16.1341 +	XM_Test,
 16.1342 +	XM_Load,
 16.1343 +	XM_Cleanup,
 16.1344 +	XM_LoadTitle
 16.1345 +};
 16.1346  
 16.1347 -MLOADER load_xm =
 16.1348 -{   NULL,
 16.1349 -    "XM",
 16.1350 -    "Portable XM loader v0.5",
 16.1351 -    XM_Init,
 16.1352 -    XM_Test,
 16.1353 -    XM_Load,
 16.1354 -    XM_Cleanup,
 16.1355 -    XM_LoadTitle
 16.1356 -};
 16.1357 +/* 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 +/*	MikMod sound library
    17.6 +	(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
    17.7 +	complete list.
    17.8  
    17.9 - Name:  MDREG.C
   17.10 +	This library is free software; you can redistribute it and/or modify
   17.11 +	it under the terms of the GNU Library General Public License as
   17.12 +	published by the Free Software Foundation; either version 2 of
   17.13 +	the License, or (at your option) any later version.
   17.14  
   17.15 - Description:
   17.16 - A single routine for registering all drivers in MikMod for the current
   17.17 - platform.
   17.18 +	This program is distributed in the hope that it will be useful,
   17.19 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.20 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.21 +	GNU Library General Public License for more details.
   17.22  
   17.23 - Portability:
   17.24 - DOS, WIN95, OS2, SunOS, Solaris,
   17.25 - Linux, HPUX, AIX, SGI, Alpha
   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 -MDRIVER *firstdriver = NULL, *md_driver = &drv_nos;
   18.35 -extern UNIMOD     *pf;           /* <- this modfile is being played */
   18.36 +  $Id$
   18.37  
   18.38 -UWORD md_device         = 0;
   18.39 -UWORD md_mixfreq        = 44100;
   18.40 -UWORD md_mode           = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND;
   18.41 -UWORD md_dmabufsize     = 50;
   18.42 -UBYTE md_pansep         = 128;      /* 128 == 100% (full left/right) */
   18.43 +  These routines are used to access the available soundcard drivers.
   18.44  
   18.45 -UBYTE md_reverb         = 6;       /* Reverb */
   18.46 +==============================================================================*/
   18.47  
   18.48 -UBYTE md_volume         = 96;       /* Global sound volume (0-128) */
   18.49 -UBYTE md_musicvolume    = 128;      /* volume of song */
   18.50 -UBYTE md_sndfxvolume    = 128;      /* volume of sound effects */
   18.51 +#ifdef HAVE_CONFIG_H
   18.52 +#include "config.h"
   18.53 +#endif
   18.54  
   18.55 -UBYTE md_bpm            = 125;
   18.56 +#ifdef HAVE_UNISTD_H
   18.57 +#include <unistd.h>
   18.58 +#endif
   18.59  
   18.60 +#ifdef unix
   18.61 +#include <pwd.h>
   18.62 +#include <sys/stat.h>
   18.63 +#endif
   18.64 +
   18.65 +#include "mikmod_internals.h"
   18.66 +
   18.67 +#include <string.h>
   18.68 +#ifdef HAVE_STRINGS_H
   18.69 +#include <strings.h>
   18.70 +#endif
   18.71 +
   18.72 +static	MDRIVER *firstdriver=NULL;
   18.73 +		MDRIVER *md_driver=NULL;
   18.74 +extern	MODULE *pf; /* modfile being played */
   18.75 +
   18.76 +		UWORD md_device         = 0;
   18.77 +		UWORD md_mixfreq        = 44100;
   18.78 +		UWORD md_mode           = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND
   18.79 +		                         |DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
   18.80 +		UBYTE md_pansep         = 128; /* 128 == 100% (full left/right) */
   18.81 +		UBYTE md_reverb         = 6; /* Reverb */
   18.82 +		UBYTE md_volume         = 128;  /* Global sound volume (0-128) */
   18.83 +		UBYTE md_musicvolume    = 128; /* volume of song */
   18.84 +		UBYTE md_sndfxvolume    = 128; /* volume of sound effects */
   18.85 +		UWORD md_bpm            = 125;
   18.86  
   18.87  /* Do not modify the numchn variables yourself!  use MD_SetVoices() */
   18.88 +		UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0;
   18.89 +		UBYTE md_hardchn=0,md_softchn=0;
   18.90  
   18.91 -UBYTE md_numchn = 0,  md_sngchn = 0,  md_sfxchn = 0;
   18.92 -UBYTE md_hardchn = 0, md_softchn = 0;
   18.93 +		void (*md_player)(void) = Player_HandleTick;
   18.94 +static	BOOL  isplaying=0, initialized = 0;
   18.95 +static	UBYTE *sfxinfo;
   18.96 +static	int sfxpool;
   18.97  
   18.98 +static	SAMPLE **md_sample = NULL;
   18.99  
  18.100 -void (*md_player)(void) = Player_HandleTick;
  18.101 -static BOOL  isplaying = 0, initialized = 0;
  18.102 -static UBYTE *sfxinfo;
  18.103 -static int   sfxpool;
  18.104 +/* Previous driver in use */
  18.105 +static	UWORD idevice;
  18.106  
  18.107 -static SAMPLE **md_sample = NULL;
  18.108 +/* Limits the number of hardware voices to the specified amount.
  18.109 +   This function should only be used by the low-level drivers. */
  18.110 +static	void LimitHardVoices(int limit)
  18.111 +{
  18.112 +	int t=0;
  18.113  
  18.114 -/* Backup variables.  This way, the end programmer can fiddle with the */
  18.115 -/* main globals without mikmod blowing up. */
  18.116 +	if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
  18.117 +	if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
  18.118  
  18.119 -static UWORD idevice, imixfreq, imode, idmabufsize;
  18.120 +	if (!(md_mode & DMODE_SOFT_SNDFX))
  18.121 +		md_hardchn=md_sfxchn;
  18.122 +	else
  18.123 +		md_hardchn=0;
  18.124  
  18.125 +	if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn += md_sngchn;
  18.126  
  18.127 -static void LimitHardVoices(int limit)
  18.128 +	while (md_hardchn>limit) {
  18.129 +		if (++t & 1) {
  18.130 +			if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
  18.131 +		} else {
  18.132 +			if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
  18.133 +		}
  18.134  
  18.135 -/* Limits the number of hardware voices to the specified amount. */
  18.136 -/* This function should only be used by the low-level drivers. */
  18.137 +		if (!(md_mode & DMODE_SOFT_SNDFX))
  18.138 +			md_hardchn=md_sfxchn;
  18.139 +		else
  18.140 +			md_hardchn=0;
  18.141  
  18.142 -{
  18.143 -    int t = 0;
  18.144 -
  18.145 -    if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit;
  18.146 -    if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit;
  18.147 -
  18.148 -    if(!(md_mode & DMODE_SOFT_SNDFX))
  18.149 -       md_hardchn = md_sfxchn;
  18.150 -    else
  18.151 -       md_hardchn = 0;
  18.152 -
  18.153 -    if(!(md_mode & DMODE_SOFT_MUSIC))
  18.154 -       md_hardchn += md_sngchn;
  18.155 -    
  18.156 -    while(md_hardchn > limit)
  18.157 -    {
  18.158 -        if(++t & 1)
  18.159 -            if(!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--;
  18.160 -        else
  18.161 -            if(!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--;
  18.162 -
  18.163 -        if(!(md_mode & DMODE_SOFT_SNDFX))
  18.164 -           md_hardchn = md_sfxchn;
  18.165 -        else
  18.166 -           md_hardchn = 0;
  18.167 -
  18.168 -        if(!(md_mode & DMODE_SOFT_MUSIC))
  18.169 -           md_hardchn += md_sngchn;
  18.170 -    }
  18.171 -
  18.172 -    md_numchn = md_hardchn + md_softchn;
  18.173 +		if (!(md_mode & DMODE_SOFT_MUSIC))
  18.174 +			md_hardchn+=md_sngchn;
  18.175 +	}
  18.176 +	md_numchn=md_hardchn+md_softchn;
  18.177  }
  18.178  
  18.179 +/* Limits the number of hardware voices to the specified amount.
  18.180 +   This function should only be used by the low-level drivers. */
  18.181 +static	void LimitSoftVoices(int limit)
  18.182 +{
  18.183 +	int t=0;
  18.184  
  18.185 -static void LimitSoftVoices(int limit)
  18.186 +	if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit;
  18.187 +	if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit;
  18.188  
  18.189 -/* Limits the number of hardware voices to the specified amount. */
  18.190 -/* This function should only be used by the low-level drivers. */
  18.191 +	if (md_mode & DMODE_SOFT_SNDFX)
  18.192 +		md_softchn=md_sfxchn;
  18.193 +	else
  18.194 +		md_softchn=0;
  18.195  
  18.196 -{
  18.197 -    int t = 0;
  18.198 +	if (md_mode & DMODE_SOFT_MUSIC) md_softchn+=md_sngchn;
  18.199  
  18.200 -    if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > limit)) md_sfxchn = limit;
  18.201 -    if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > limit)) md_sngchn = limit;
  18.202 +	while (md_softchn>limit) {
  18.203 +		if (++t & 1) {
  18.204 +			if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--;
  18.205 +		} else {
  18.206 +			if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--;
  18.207 +		}
  18.208  
  18.209 -    if(md_mode & DMODE_SOFT_SNDFX)
  18.210 -       md_softchn = md_sfxchn;
  18.211 -    else
  18.212 -       md_softchn = 0;
  18.213 +		if (!(md_mode & DMODE_SOFT_SNDFX))
  18.214 +			md_softchn=md_sfxchn;
  18.215 +		else
  18.216 +			md_softchn=0;
  18.217  
  18.218 -    if(md_mode & DMODE_SOFT_MUSIC)
  18.219 -       md_softchn += md_sngchn;
  18.220 -    
  18.221 -    while(md_softchn > limit)
  18.222 -    {
  18.223 -        if(++t & 1)
  18.224 -            if((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn > 4)) md_sfxchn--;
  18.225 -        else
  18.226 -            if((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn > 8)) md_sngchn--;
  18.227 -
  18.228 -        if(!(md_mode & DMODE_SOFT_SNDFX))
  18.229 -           md_softchn = md_sfxchn;
  18.230 -        else
  18.231 -           md_softchn = 0;
  18.232 -
  18.233 -        if(!(md_mode & DMODE_SOFT_MUSIC))
  18.234 -           md_softchn += md_sngchn;
  18.235 -    }
  18.236 -
  18.237 -    md_numchn = md_hardchn + md_softchn;
  18.238 +		if (!(md_mode & DMODE_SOFT_MUSIC))
  18.239 +			md_softchn+=md_sngchn;
  18.240 +	}
  18.241 +	md_numchn=md_hardchn+md_softchn;
  18.242  }
  18.243  
  18.244 -
  18.245 -/* Note: 'type' indicates whether the returned value should be for music */
  18.246 -/*       or for sound effects. */
  18.247 -
  18.248 +/* Note: 'type' indicates whether the returned value should be for music or for
  18.249 +   sound effects. */
  18.250  ULONG MD_SampleSpace(int type)
  18.251  {
  18.252 -    if(type==MD_MUSIC)
  18.253 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.254 -    else if(type==MD_SNDFX)
  18.255 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.256 +	if(type==MD_MUSIC)
  18.257 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.258 +	else if(type==MD_SNDFX)
  18.259 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.260  
  18.261 -    return md_driver->FreeSampleSpace(type);
  18.262 +	return md_driver->FreeSampleSpace(type);
  18.263  }
  18.264  
  18.265 +ULONG MD_SampleLength(int type,SAMPLE* s)
  18.266 +{
  18.267 +	if(type==MD_MUSIC)
  18.268 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.269 +	else
  18.270 +	  if(type==MD_SNDFX)
  18.271 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.272  
  18.273 -ULONG MD_SampleLength(int type, SAMPLE *s)
  18.274 -{
  18.275 -    if(type==MD_MUSIC)
  18.276 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.277 -    else if(type==MD_SNDFX)
  18.278 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.279 -
  18.280 -    return md_driver->RealSampleLength(type, s);
  18.281 +	return md_driver->RealSampleLength(type,s);
  18.282  }
  18.283  
  18.284 +CHAR* MikMod_InfoDriver(void)
  18.285 +{
  18.286 +	int t,len=0;
  18.287 +	MDRIVER *l;
  18.288 +	CHAR *list=NULL;
  18.289  
  18.290 -UWORD MD_SetDMA(int secs)
  18.291 +	MUTEX_LOCK(lists);
  18.292 +	/* compute size of buffer */
  18.293 +	for(l=firstdriver;l;l=l->next) len+=4+(l->next?1:0)+strlen(l->Version);
  18.294  
  18.295 -/* Converts the given number of 1/10th seconds into the number of bytes of */
  18.296 -/* audio that a sample # 1/10th seconds long would require at the current md_* */
  18.297 -/* settings. */
  18.298 -
  18.299 -{
  18.300 -    ULONG result;
  18.301 -
  18.302 -    result = (md_mixfreq * ((md_mode & DMODE_STEREO) ? 2 : 1) *
  18.303 -             ((md_mode & DMODE_16BITS) ? 2 : 1) * secs) * 10;
  18.304 -
  18.305 -    if(result > 32000) result = 32000;
  18.306 -    return(md_dmabufsize = (result & ~3));  /* round it off to an 8 byte boundry */
  18.307 +	if(len)
  18.308 +		if((list=_mm_malloc(len*sizeof(CHAR)))) {
  18.309 +			list[0]=0;
  18.310 +			/* list all registered device drivers : */
  18.311 +			for(t=1,l=firstdriver;l;l=l->next,t++)
  18.312 +				sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s",list,t,l->Version);
  18.313 +		}
  18.314 +	MUTEX_UNLOCK(lists);
  18.315 +	return list;
  18.316  }
  18.317  
  18.318 +void _mm_registerdriver(struct MDRIVER* drv)
  18.319 +{
  18.320 +	MDRIVER *cruise = firstdriver;
  18.321  
  18.322 -void MD_InfoDriver(void)
  18.323 -{
  18.324 -    int t;
  18.325 -    MDRIVER *l;
  18.326 -
  18.327 -    /* list all registered devicedrivers: */
  18.328 -    for(t=1,l=firstdriver; l!=NULL; l=l->next, t++)
  18.329 -        printf("%d. %s\n",t,l->Version);
  18.330 +	if(cruise) {
  18.331 +		while(cruise->next) cruise=cruise->next;
  18.332 +		cruise->next=drv;
  18.333 +	} else
  18.334 +		firstdriver = drv;
  18.335  }
  18.336  
  18.337 +void MikMod_RegisterDriver(struct MDRIVER* drv)
  18.338 +{
  18.339 +	/* if we try to register an invalid driver, or an already registered driver,
  18.340 +	   ignore this attempt */
  18.341 +	if ((!drv)||(drv->next))
  18.342 +		return;
  18.343  
  18.344 -void MD_RegisterDriver(MDRIVER *drv)
  18.345 -{
  18.346 -    MDRIVER *cruise = firstdriver;
  18.347 -
  18.348 -    if(cruise!=NULL)
  18.349 -    {   while(cruise->next!=NULL)  cruise = cruise->next;
  18.350 -        cruise->next = drv;
  18.351 -    } else
  18.352 -        firstdriver = drv; 
  18.353 +	MUTEX_LOCK(lists);
  18.354 +	_mm_registerdriver(drv);
  18.355 +	MUTEX_UNLOCK(lists);
  18.356  }
  18.357  
  18.358 +int MikMod_DriverFromAlias(CHAR *alias)
  18.359 +{
  18.360 +	int rank=1;
  18.361 +	MDRIVER *cruise;
  18.362  
  18.363 -SWORD MD_SampleLoad(SAMPLOAD *s, int type, FILE *fp)
  18.364 -/*  type - sample type .. MD_MUSIC or MD_SNDFX */
  18.365 -{
  18.366 -    SWORD result;
  18.367 +	MUTEX_LOCK(lists);
  18.368 +	cruise=firstdriver;
  18.369 +	while(cruise) {
  18.370 +		if (!(strcasecmp(alias,cruise->Alias))) break;
  18.371 +		cruise=cruise->next;rank++;
  18.372 +	}
  18.373 +	if(!cruise) rank=0;
  18.374 +	MUTEX_UNLOCK(lists);
  18.375  
  18.376 -    if(type==MD_MUSIC)
  18.377 -       type = (md_mode & DMODE_SOFT_MUSIC) ? MD_SOFTWARE : MD_HARDWARE;
  18.378 -    else if(type==MD_SNDFX)
  18.379 -       type = (md_mode & DMODE_SOFT_SNDFX) ? MD_SOFTWARE : MD_HARDWARE;
  18.380 -
  18.381 -    SL_Init(s);
  18.382 -    result = md_driver->SampleLoad(s, type);
  18.383 -    SL_Exit(s);
  18.384 -
  18.385 -    return result;
  18.386 +	return rank;
  18.387  }
  18.388  
  18.389 +SWORD MD_SampleLoad(SAMPLOAD* s, int type)
  18.390 +{
  18.391 +	SWORD result;
  18.392  
  18.393 -void MD_SampleUnLoad(SWORD handle)
  18.394 -{
  18.395 -    md_driver->SampleUnLoad(handle);
  18.396 +	if(type==MD_MUSIC)
  18.397 +		type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE;
  18.398 +	else if(type==MD_SNDFX)
  18.399 +		type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE;
  18.400 +
  18.401 +	SL_Init(s);
  18.402 +	result=md_driver->SampleLoad(s,type);
  18.403 +	SL_Exit(s);
  18.404 +
  18.405 +	return result;
  18.406  }
  18.407  
  18.408 -
  18.409 -void MD_SetBPM(UBYTE bpm)
  18.410 +void MD_SampleUnload(SWORD handle)
  18.411  {
  18.412 -    md_bpm = bpm;
  18.413 +	md_driver->SampleUnload(handle);
  18.414  }
  18.415  
  18.416 +MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player)
  18.417 +{
  18.418 +	MikMod_player_t result;
  18.419  
  18.420 -void MikMod_RegisterPlayer(void (*player)(void))
  18.421 -{
  18.422 -    md_player = player;
  18.423 +	MUTEX_LOCK(vars);
  18.424 +	result=md_player;
  18.425 +	md_player=player;
  18.426 +	MUTEX_UNLOCK(vars);
  18.427 +
  18.428 +	return result;
  18.429  }
  18.430  
  18.431 -
  18.432  void MikMod_Update(void)
  18.433  {
  18.434 -    if(isplaying && !(pf->forbid)) md_driver->Update();
  18.435 +	MUTEX_LOCK(vars);
  18.436 +	if(isplaying) {
  18.437 +		if((!pf)||(!pf->forbid))
  18.438 +			md_driver->Update();
  18.439 +		else {
  18.440 +			if (md_driver->Pause)
  18.441 +				md_driver->Pause();
  18.442 +		}
  18.443 +	}
  18.444 +	MUTEX_UNLOCK(vars);
  18.445  }
  18.446  
  18.447 +void Voice_SetVolume_internal(SBYTE voice,UWORD vol)
  18.448 +{
  18.449 +	ULONG  tmp;
  18.450  
  18.451 -void Voice_SetVolume(int voice, UWORD vol)
  18.452 -{
  18.453 -    ULONG  tmp;
  18.454 +	if((voice<0)||(voice>=md_numchn)) return;
  18.455  
  18.456 -    if((voice<0) || (voice>=md_numchn)) return;
  18.457 -    tmp = (ULONG)vol * (ULONG)md_volume * ((voice < md_sngchn) ? (ULONG)md_musicvolume : (ULONG)md_sndfxvolume);
  18.458 -    md_driver->VoiceSetVolume(voice,tmp/16384UL);
  18.459 +	/* range checks */
  18.460 +	if(md_musicvolume>128) md_musicvolume=128;
  18.461 +	if(md_sndfxvolume>128) md_sndfxvolume=128;
  18.462 +	if(md_volume>128) md_volume=128;
  18.463 +
  18.464 +	tmp=(ULONG)vol*(ULONG)md_volume*
  18.465 +	     ((voice<md_sngchn)?(ULONG)md_musicvolume:(ULONG)md_sndfxvolume);
  18.466 +	md_driver->VoiceSetVolume(voice,tmp/16384UL);
  18.467  }
  18.468  
  18.469 -
  18.470 -void Voice_SetFrequency(int voice, ULONG frq)
  18.471 +void Voice_SetVolume(SBYTE voice,UWORD vol)
  18.472  {
  18.473 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.474 -    if(md_sample[voice]!=NULL && md_sample[voice]->divfactor!=0) frq/=md_sample[voice]->divfactor;
  18.475 -    md_driver->VoiceSetFrequency(voice, frq);
  18.476 +	MUTEX_LOCK(vars);
  18.477 +	Voice_SetVolume_internal(voice,vol);
  18.478 +	MUTEX_UNLOCK(vars);
  18.479  }
  18.480  
  18.481 +UWORD Voice_GetVolume(SBYTE voice)
  18.482 +{
  18.483 +	UWORD result=0;
  18.484  
  18.485 -void Voice_SetPanning(int voice, ULONG pan)
  18.486 -{
  18.487 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.488 -    if(pan!=PAN_SURROUND)
  18.489 -    {   if(md_mode & DMODE_REVERSE) pan = 255-pan;
  18.490 -        pan = (((SWORD)(pan-128)*md_pansep) / 128)+128;
  18.491 -    }
  18.492 -    md_driver->VoiceSetPanning(voice, pan);
  18.493 +	MUTEX_LOCK(vars);
  18.494 +	if((voice>=0)&&(voice<md_numchn))
  18.495 +		result=md_driver->VoiceGetVolume(voice);
  18.496 +	MUTEX_UNLOCK(vars);
  18.497 +
  18.498 +	return result;
  18.499  }
  18.500  
  18.501 -
  18.502 -void Voice_Play(int voice, SAMPLE *s, ULONG start)
  18.503 +void Voice_SetFrequency_internal(SBYTE voice,ULONG frq)
  18.504  {
  18.505 -    ULONG  repend;
  18.506 -    
  18.507 -    if((voice < 0) || (voice >= md_numchn) || (start >= s->length)) return;
  18.508 -
  18.509 -    md_sample[voice] = s;
  18.510 -    repend = s->loopend;
  18.511 -
  18.512 -    if(s->flags&SF_LOOP)
  18.513 -       if(repend > s->length) repend = s->length;    /* repend can't be bigger than size */
  18.514 -
  18.515 -    md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
  18.516 +	if((voice<0)||(voice>=md_numchn)) return;
  18.517 +	if((md_sample[voice])&&(md_sample[voice]->divfactor))
  18.518 +		frq/=md_sample[voice]->divfactor;
  18.519 +	md_driver->VoiceSetFrequency(voice,frq);
  18.520  }
  18.521  
  18.522 -
  18.523 -void Voice_Stop(int voice)
  18.524 +void Voice_SetFrequency(SBYTE voice,ULONG frq)
  18.525  {
  18.526 -    if((voice < 0) || (voice >= md_numchn)) return;
  18.527 -    if(voice >= md_sngchn)
  18.528 -    {   /* It is a sound effects channel, so flag the voice as non-critical! */
  18.529 -        sfxinfo[voice-md_sngchn] = 0;
  18.530 -    }
  18.531 -
  18.532 -    md_driver->VoiceStop(voice);
  18.533 +	MUTEX_LOCK(vars);
  18.534 +	Voice_SetFrequency_internal(voice,frq);
  18.535 +	MUTEX_UNLOCK(vars);
  18.536  }
  18.537  
  18.538 - 
  18.539 -BOOL Voice_Stopped(int voice)
  18.540 +ULONG Voice_GetFrequency(SBYTE voice)
  18.541  {
  18.542 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.543 -    return(md_driver->VoiceStopped(voice));
  18.544 +	ULONG result=0;
  18.545 +
  18.546 +	MUTEX_LOCK(vars);
  18.547 +	if((voice>=0)&&(voice<md_numchn))
  18.548 +		result=md_driver->VoiceGetFrequency(voice);
  18.549 +	MUTEX_UNLOCK(vars);
  18.550 +
  18.551 +	return result;
  18.552  }
  18.553  
  18.554 -
  18.555 -SLONG Voice_GetPosition(int voice)
  18.556 +void Voice_SetPanning_internal(SBYTE voice,ULONG pan)
  18.557  {
  18.558 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.559 -    return(md_driver->VoiceGetPosition(voice));
  18.560 +	if((voice<0)||(voice>=md_numchn)) return;
  18.561 +	if(pan!=PAN_SURROUND) {
  18.562 +		if(md_pansep>128) md_pansep=128;
  18.563 +		if(md_mode & DMODE_REVERSE) pan=255-pan;
  18.564 +		pan = (((SWORD)(pan-128)*md_pansep)/128)+128;
  18.565 +	}
  18.566 +	md_driver->VoiceSetPanning(voice, pan);
  18.567  }
  18.568  
  18.569 +void Voice_SetPanning(SBYTE voice,ULONG pan)
  18.570 +{
  18.571 +#ifdef MIKMOD_DEBUG
  18.572 +	if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255)))
  18.573 +		fprintf(stderr,"\rVoice_SetPanning called with pan=%ld\n",(long)pan);
  18.574 +#endif
  18.575  
  18.576 -ULONG Voice_RealVolume(int voice)
  18.577 -{
  18.578 -    if((voice < 0) || (voice >= md_numchn)) return 0;
  18.579 -    return(md_driver->VoiceRealVolume(voice));
  18.580 +	MUTEX_LOCK(vars);
  18.581 +	Voice_SetPanning_internal(voice,pan);
  18.582 +	MUTEX_UNLOCK(vars);
  18.583  }
  18.584  
  18.585 +ULONG Voice_GetPanning(SBYTE voice)
  18.586 +{
  18.587 +	ULONG result=PAN_CENTER;
  18.588  
  18.589 -/* ================================ */
  18.590 -/*  Functions prefixed with MikMod */
  18.591 -/* ================================ */
  18.592 +	MUTEX_LOCK(vars);
  18.593 +	if((voice>=0)&&(voice<md_numchn))
  18.594 +		result=md_driver->VoiceGetPanning(voice);
  18.595 +	MUTEX_UNLOCK(vars);
  18.596  
  18.597 -BOOL MikMod_Init(void)
  18.598 -{
  18.599 -    UWORD t;
  18.600 -
  18.601 -    _mm_critical = 1;
  18.602 -
  18.603 -    /* if md_device==0, try to find a device number */
  18.604 -
  18.605 -    if(md_device==0)
  18.606 -    {   for(t=1,md_driver=firstdriver; md_driver!=NULL; md_driver=md_driver->next, t++)
  18.607 -        {   if(md_driver->IsPresent()) break;
  18.608 -        }
  18.609 -
  18.610 -        if(md_driver==NULL)
  18.611 -        {   _mm_errno = MMERR_DETECTING_DEVICE;
  18.612 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.613 -            md_driver = &drv_nos;
  18.614 -            return 1;
  18.615 -        }
  18.616 -
  18.617 -        md_device = t;
  18.618 -    } else
  18.619 -    {   /* if n>0 use that driver */
  18.620 -        for(t=1,md_driver=firstdriver; (md_driver!=NULL) && (t!=md_device); md_driver=md_driver->next, t++);
  18.621 -
  18.622 -        if(md_driver==NULL)
  18.623 -        {   _mm_errno = MMERR_INVALID_DEVICE;
  18.624 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.625 -            md_driver = &drv_nos;
  18.626 -            return 1;
  18.627 -        }
  18.628 -    
  18.629 -        if(!md_driver->IsPresent())
  18.630 -        {   _mm_errno = MMERR_DETECTING_DEVICE;
  18.631 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.632 -            md_driver = &drv_nos;
  18.633 -            return 1;
  18.634 -        }
  18.635 -    }
  18.636 -
  18.637 -    if(md_driver->Init())
  18.638 -    {   MikMod_Exit();
  18.639 -        if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.640 -        return 1;
  18.641 -    }
  18.642 -
  18.643 -    idevice  = md_device;   imode       = md_mode;
  18.644 -    imixfreq = md_mixfreq;  idmabufsize = md_dmabufsize;
  18.645 -    initialized = 1;
  18.646 -    _mm_critical = 0;
  18.647 -
  18.648 -    return 0;
  18.649 +	return result;
  18.650  }
  18.651  
  18.652 +void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start)
  18.653 +{
  18.654 +	ULONG  repend;
  18.655 +
  18.656 +	if((voice<0)||(voice>=md_numchn)) return;
  18.657 +
  18.658 +	md_sample[voice]=s;
  18.659 +	repend=s->loopend;
  18.660 +
  18.661 +	if(s->flags&SF_LOOP)
  18.662 +		/* repend can't be bigger than size */
  18.663 +		if(repend>s->length) repend=s->length;
  18.664 +
  18.665 +	md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags);
  18.666 +}
  18.667 +
  18.668 +void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start)
  18.669 +{
  18.670 +	if(start>s->length) return;
  18.671 +
  18.672 +	MUTEX_LOCK(vars);
  18.673 +	Voice_Play_internal(voice,s,start);
  18.674 +	MUTEX_UNLOCK(vars);
  18.675 +}
  18.676 +
  18.677 +void Voice_Stop_internal(SBYTE voice)
  18.678 +{
  18.679 +	if((voice<0)||(voice>=md_numchn)) return;
  18.680 +	if(voice>=md_sngchn)
  18.681 +		/* It is a sound effects channel, so flag the voice as non-critical! */
  18.682 +		sfxinfo[voice-md_sngchn]=0;
  18.683 +	md_driver->VoiceStop(voice);
  18.684 +}
  18.685 +
  18.686 +void Voice_Stop(SBYTE voice)
  18.687 +{
  18.688 +	MUTEX_LOCK(vars);
  18.689 +	Voice_Stop_internal(voice);
  18.690 +	MUTEX_UNLOCK(vars);
  18.691 +}
  18.692 +
  18.693 +BOOL Voice_Stopped_internal(SBYTE voice)
  18.694 +{
  18.695 +	if((voice<0)||(voice>=md_numchn)) return 0;
  18.696 +	return(md_driver->VoiceStopped(voice));
  18.697 +}
  18.698 +
  18.699 +BOOL Voice_Stopped(SBYTE voice)
  18.700 +{
  18.701 +	BOOL result;
  18.702 +
  18.703 +	MUTEX_LOCK(vars);
  18.704 +	result=Voice_Stopped_internal(voice);
  18.705 +	MUTEX_UNLOCK(vars);
  18.706 +
  18.707 +	return result;
  18.708 +}
  18.709 +
  18.710 +SLONG Voice_GetPosition(SBYTE voice)
  18.711 +{
  18.712 +	SLONG result=0;
  18.713 +
  18.714 +	MUTEX_LOCK(vars);
  18.715 +	if((voice>=0)&&(voice<md_numchn))
  18.716 +		result=(md_driver->VoiceGetPosition(voice));
  18.717 +	MUTEX_UNLOCK(vars);
  18.718 +
  18.719 +	return result;
  18.720 +}
  18.721 +
  18.722 +ULONG Voice_RealVolume(SBYTE voice)
  18.723 +{
  18.724 +	ULONG result=0;
  18.725 +
  18.726 +	MUTEX_LOCK(vars);
  18.727 +	if((voice>=0)&&(voice<md_numchn))
  18.728 +		result=(md_driver->VoiceRealVolume(voice));
  18.729 +	MUTEX_UNLOCK(vars);
  18.730 +
  18.731 +	return result;
  18.732 +}
  18.733 +
  18.734 +static BOOL _mm_init(CHAR *cmdline)
  18.735 +{
  18.736 +	UWORD t;
  18.737 +
  18.738 +	_mm_critical = 1;
  18.739 +
  18.740 +	/* if md_device==0, try to find a device number */
  18.741 +	if(!md_device) {
  18.742 +		cmdline=NULL;
  18.743 +
  18.744 +		for(t=1,md_driver=firstdriver;md_driver;md_driver=md_driver->next,t++)
  18.745 +			if(md_driver->IsPresent()) break;
  18.746 +
  18.747 +		if(!md_driver) {
  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 +		md_device = t;
  18.755 +	} else {
  18.756 +		/* if n>0, use that driver */
  18.757 +		for(t=1,md_driver=firstdriver;(md_driver)&&(t!=md_device);md_driver=md_driver->next,t++);
  18.758 +
  18.759 +		if(!md_driver) {
  18.760 +			_mm_errno = MMERR_INVALID_DEVICE;
  18.761 +			if(_mm_errorhandler) _mm_errorhandler();
  18.762 +			md_driver = &drv_nos;
  18.763 +			return 1;
  18.764 +		}
  18.765 +
  18.766 +		/* arguments here might be necessary for the presence check to succeed */
  18.767 +		if(cmdline&&(md_driver->CommandLine))
  18.768 +			md_driver->CommandLine(cmdline);
  18.769 +
  18.770 +		if(!md_driver->IsPresent()) {
  18.771 +			_mm_errno = MMERR_DETECTING_DEVICE;
  18.772 +			if(_mm_errorhandler) _mm_errorhandler();
  18.773 +			md_driver = &drv_nos;
  18.774 +			return 1;
  18.775 +		}
  18.776 +	}
  18.777 +
  18.778 +	if(md_driver->Init()) {
  18.779 +		md_driver->Exit();
  18.780 +		MikMod_Exit_internal();
  18.781 +		if(_mm_errorhandler) _mm_errorhandler();
  18.782 +		return 1;
  18.783 +	}
  18.784 +
  18.785 +	initialized=1;
  18.786 +	_mm_critical=0;
  18.787 +
  18.788 +	return 0;
  18.789 +}
  18.790 +
  18.791 +BOOL MikMod_Init(CHAR *cmdline)
  18.792 +{
  18.793 +	BOOL result;
  18.794 +
  18.795 +	MUTEX_LOCK(vars);
  18.796 +	MUTEX_LOCK(lists);
  18.797 +	result=_mm_init(cmdline);
  18.798 +	MUTEX_UNLOCK(lists);
  18.799 +	MUTEX_UNLOCK(vars);
  18.800 +
  18.801 +	return result;
  18.802 +}
  18.803 +
  18.804 +void MikMod_Exit_internal(void)
  18.805 +{
  18.806 +	MikMod_DisableOutput_internal();
  18.807 +	md_driver->Exit();
  18.808 +	md_numchn = md_sfxchn = md_sngchn = 0;
  18.809 +	md_driver = &drv_nos;
  18.810 +
  18.811 +	if(sfxinfo) free(sfxinfo);
  18.812 +	if(md_sample) free(md_sample);
  18.813 +	md_sample  = NULL;
  18.814 +	sfxinfo    = NULL;
  18.815 +
  18.816 +	initialized = 0;
  18.817 +}
  18.818  
  18.819  void MikMod_Exit(void)
  18.820  {
  18.821 -    MikMod_DisableOutput();
  18.822 -    md_driver->Exit();
  18.823 -    md_numchn = md_sfxchn = md_sngchn = 0;
  18.824 -    md_driver = &drv_nos;
  18.825 -    initialized = 0;
  18.826 +	MUTEX_LOCK(vars);
  18.827 +	MUTEX_LOCK(lists);
  18.828 +	MikMod_Exit_internal();
  18.829 +	MUTEX_UNLOCK(lists);
  18.830 +	MUTEX_UNLOCK(vars);
  18.831  }
  18.832  
  18.833 +/* Reset the driver using the new global variable settings.
  18.834 +   If the driver has not been initialized, it will be now. */
  18.835 +static BOOL _mm_reset(CHAR *cmdline)
  18.836 +{
  18.837 +	if(!initialized) return _mm_init(cmdline);
  18.838  
  18.839 -BOOL MikMod_Reset(void)
  18.840 -
  18.841 -/* Reset the driver using the new global variable settings. */
  18.842 -/* If the driver has not been initialized, it will be now. */
  18.843 -
  18.844 -{
  18.845 -    if(!initialized) return MikMod_Init();
  18.846 -    if((md_driver->Reset == NULL) || (md_device != idevice))
  18.847 -    {   /* md_driver->Reset was NULL, or md_device was changed, */
  18.848 -        /* so do a full reset of the driver. */
  18.849 -
  18.850 -        if(isplaying) md_driver->PlayStop();
  18.851 -        md_driver->Exit();
  18.852 -        if(MikMod_Init())
  18.853 -        {   MikMod_Exit();
  18.854 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.855 -            return 1;
  18.856 -        }
  18.857 -        if(isplaying) md_driver->PlayStart();
  18.858 -    } else
  18.859 -    {   if(md_driver->Reset())
  18.860 -        {   MikMod_Exit();
  18.861 -            if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.862 -            return 1;
  18.863 -        }
  18.864 -    }
  18.865 -    
  18.866 -    return 0;
  18.867 +	if((!md_driver->Reset)||(md_device != idevice)) {
  18.868 +		/* md_driver->Reset was NULL, or md_device was changed, so do a full
  18.869 +		   reset of the driver. */
  18.870 +		if(isplaying) md_driver->PlayStop();
  18.871 +		md_driver->Exit();
  18.872 +		if(_mm_init(cmdline)) {
  18.873 +			MikMod_Exit_internal();
  18.874 +			if(_mm_errno)
  18.875 +				if(_mm_errorhandler) _mm_errorhandler();
  18.876 +			return 1;
  18.877 +		}
  18.878 +		if(isplaying) md_driver->PlayStart();
  18.879 +	} else {
  18.880 +		if(md_driver->Reset()) {
  18.881 +			MikMod_Exit_internal();
  18.882 +			if(_mm_errno)
  18.883 +				if(_mm_errorhandler) _mm_errorhandler();
  18.884 +			return 1;
  18.885 +		}
  18.886 +	}
  18.887 +	return 0;
  18.888  }
  18.889  
  18.890 +BOOL MikMod_Reset(CHAR *cmdline)
  18.891 +{
  18.892 +	BOOL result;
  18.893 +
  18.894 +	MUTEX_LOCK(vars);
  18.895 +	MUTEX_LOCK(lists);
  18.896 +	result=_mm_reset(cmdline);
  18.897 +	MUTEX_UNLOCK(lists);
  18.898 +	MUTEX_UNLOCK(vars);
  18.899 +
  18.900 +	return result;
  18.901 +}
  18.902 +
  18.903 +/* If either parameter is -1, the current set value will be retained. */
  18.904 +BOOL MikMod_SetNumVoices_internal(int music, int sfx)
  18.905 +{
  18.906 +	BOOL resume = 0;
  18.907 +	int t, oldchn = 0;
  18.908 +
  18.909 +	if((!music)&&(!sfx)) return 1;
  18.910 +	_mm_critical = 1;
  18.911 +	if(isplaying) {
  18.912 +		MikMod_DisableOutput_internal();
  18.913 +		oldchn = md_numchn;
  18.914 +		resume = 1;
  18.915 +	}
  18.916 +
  18.917 +	if(sfxinfo) free(sfxinfo);
  18.918 +	if(md_sample) free(md_sample);
  18.919 +	md_sample  = NULL;
  18.920 +	sfxinfo    = NULL;
  18.921 +
  18.922 +	if(music!=-1) md_sngchn = music;
  18.923 +	if(sfx!=-1)   md_sfxchn = sfx;
  18.924 +	md_numchn = md_sngchn + md_sfxchn;
  18.925 +
  18.926 +	LimitHardVoices(md_driver->HardVoiceLimit);
  18.927 +	LimitSoftVoices(md_driver->SoftVoiceLimit);
  18.928 +
  18.929 +	if(md_driver->SetNumVoices()) {
  18.930 +		MikMod_Exit_internal();
  18.931 +		if(_mm_errno)
  18.932 +			if(_mm_errorhandler!=NULL) _mm_errorhandler();
  18.933 +		md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
  18.934 +		return 1;
  18.935 +	}
  18.936 +
  18.937 +	if(md_sngchn+md_sfxchn)
  18.938 +		md_sample=(SAMPLE**)_mm_calloc(md_sngchn+md_sfxchn,sizeof(SAMPLE*));
  18.939 +	if(md_sfxchn)
  18.940 +		sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn,sizeof(UBYTE));
  18.941 +
  18.942 +	/* make sure the player doesn't start with garbage */
  18.943 +	for(t=oldchn;t<md_numchn;t++)  Voice_Stop_internal(t);
  18.944 +
  18.945 +	sfxpool = 0;
  18.946 +	if(resume) MikMod_EnableOutput_internal();
  18.947 +	_mm_critical = 0;
  18.948 +
  18.949 +	return 0;
  18.950 +}
  18.951  
  18.952  BOOL MikMod_SetNumVoices(int music, int sfx)
  18.953 +{
  18.954 +	BOOL result;
  18.955  
  18.956 -/* If either parameter is -1, the current set value will be retained. */
  18.957 +	MUTEX_LOCK(vars);
  18.958 +	result=MikMod_SetNumVoices_internal(music,sfx);
  18.959 +	MUTEX_UNLOCK(vars);
  18.960  
  18.961 -{
  18.962 -    BOOL resume = 0;
  18.963 -    int  t, oldchn = 0;
  18.964 -
  18.965 -    if((music==0) && (sfx==0)) return 0;
  18.966 -
  18.967 -    _mm_critical = 1;
  18.968 -
  18.969 -    if(isplaying)
  18.970 -    {   MikMod_DisableOutput();
  18.971 -        oldchn = md_numchn;
  18.972 -        resume = 1;
  18.973 -    }
  18.974 -
  18.975 -    if(sfxinfo!=NULL)   free(sfxinfo);
  18.976 -    if(md_sample!=NULL) free(md_sample);
  18.977 -    md_sample  = NULL;
  18.978 -    sfxinfo    = NULL;
  18.979 -
  18.980 -    /*md_softchn = md_hardchn = 0;
  18.981 -
  18.982 -    if(md_mode & DMODE_SOFT_SNDFX)
  18.983 -       md_softchn = sfx; else md_hardchn = sfx;
  18.984 -
  18.985 -    if(md_mode & DMODE_SOFT_MUSIC)
  18.986 -       md_softchn += music; else md_hardchn += music;
  18.987 -    */
  18.988 -
  18.989 -    if(music != -1) md_sngchn = music;
  18.990 -    if(sfx != -1)   md_sfxchn = sfx;
  18.991 -
  18.992 -    md_numchn = md_sngchn + md_sfxchn;
  18.993 -
  18.994 -    LimitHardVoices(md_driver->HardVoiceLimit);
  18.995 -    LimitSoftVoices(md_driver->SoftVoiceLimit);
  18.996 -
  18.997 -    if(md_driver->SetNumVoices())
  18.998 -    {   MikMod_Exit();
  18.999 -        md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0;
 18.1000 -        if(_mm_errorhandler!=NULL) _mm_errorhandler();
 18.1001 -        return 1;
 18.1002 -    }
 18.1003 -
 18.1004 -    if(md_sngchn || md_sfxchn)
 18.1005 -        md_sample = (SAMPLE **)_mm_calloc(md_sngchn+md_sfxchn, sizeof(SAMPLE *));
 18.1006 -    if(md_sfxchn)
 18.1007 -        sfxinfo = (UBYTE *)_mm_calloc(md_sfxchn, sizeof(UBYTE));
 18.1008 -
 18.1009 -    /* make sure the player doesn't start with garbage */
 18.1010 -    for(t=oldchn; t<md_numchn; t++)  Voice_Stop(t);
 18.1011 -
 18.1012 -    sfxpool = 0;
 18.1013 -
 18.1014 -    if(resume) MikMod_EnableOutput();
 18.1015 -    _mm_critical = 0;
 18.1016 -
 18.1017 -    return 0;
 18.1018 +	return result;
 18.1019  }
 18.1020  
 18.1021 +BOOL MikMod_EnableOutput_internal(void)
 18.1022 +{
 18.1023 +	_mm_critical = 1;
 18.1024 +	if(!isplaying) {
 18.1025 +		if(md_driver->PlayStart()) return 1;
 18.1026 +		isplaying = 1;
 18.1027 +	}
 18.1028 +	_mm_critical = 0;
 18.1029 +	return 0;
 18.1030 +}
 18.1031  
 18.1032  BOOL MikMod_EnableOutput(void)
 18.1033  {
 18.1034 -    /* safety valve, prevents entering */
 18.1035 -    /* playstart twice: */
 18.1036 +	BOOL result;
 18.1037  
 18.1038 -    _mm_critical = 1;
 18.1039 -    if(!isplaying)
 18.1040 -    {   if(md_driver->PlayStart()) return 1;
 18.1041 -        isplaying = 1;
 18.1042 -    }
 18.1043 -    _mm_critical = 0;
 18.1044 -    return 0;
 18.1045 +	MUTEX_LOCK(vars);
 18.1046 +	result=MikMod_EnableOutput_internal();
 18.1047 +	MUTEX_UNLOCK(vars);
 18.1048 +
 18.1049 +	return result;
 18.1050  }
 18.1051  
 18.1052 +void MikMod_DisableOutput_internal(void)
 18.1053 +{
 18.1054 +	if(isplaying && md_driver) {
 18.1055 +		isplaying = 0;
 18.1056 +		md_driver->PlayStop();
 18.1057 +	}
 18.1058 +}
 18.1059  
 18.1060  void MikMod_DisableOutput(void)
 18.1061  {
 18.1062 -    /* safety valve, prevents calling playStop when playstart */
 18.1063 -    /* hasn't been called: */
 18.1064 -
 18.1065 -    if(isplaying && md_driver!=NULL)
 18.1066 -    {   isplaying = 0;
 18.1067 -        md_driver->PlayStop();
 18.1068 -    }
 18.1069 +	MUTEX_LOCK(vars);
 18.1070 +	MikMod_DisableOutput_internal();
 18.1071 +	MUTEX_UNLOCK(vars);
 18.1072  }
 18.1073  
 18.1074 +BOOL MikMod_Active_internal(void)
 18.1075 +{
 18.1076 +	return isplaying;
 18.1077 +}
 18.1078  
 18.1079  BOOL MikMod_Active(void)
 18.1080  {
 18.1081 -    return isplaying;
 18.1082 +	BOOL result;
 18.1083 +
 18.1084 +	MUTEX_LOCK(vars);
 18.1085 +	result=MikMod_Active_internal();
 18.1086 +	MUTEX_UNLOCK(vars);
 18.1087 +
 18.1088 +	return result;
 18.1089  }
 18.1090  
 18.1091 +/* Plays a sound effects sample.  Picks a voice from the number of voices
 18.1092 +   allocated for use as sound effects (loops through voices, skipping all active
 18.1093 +   criticals).
 18.1094  
 18.1095 -int MikMod_PlaySample(SAMPLE *s, ULONG start, UBYTE flags)
 18.1096 +   Returns the voice that the sound is being played on.                       */
 18.1097 +SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags)
 18.1098 +{
 18.1099 +	int orig=sfxpool;/* for cases where all channels are critical */
 18.1100 +	int c;
 18.1101  
 18.1102 -/* Plays a sound effects sample.  Picks a voice from the number of voices */
 18.1103 -/* allocated for use as sound effects (loops through voices, skipping all */
 18.1104 -/* active criticals). */
 18.1105 -/* */
 18.1106 -/* Returns the voice that the sound is being played on. */
 18.1107 +	if(!md_sfxchn) return -1;
 18.1108 +	if(s->volume>64) s->volume = 64;
 18.1109  
 18.1110 -{
 18.1111 -    int orig = sfxpool;    /* for cases where all channels are critical */
 18.1112 -    int c;
 18.1113 +	/* check the first location after sfxpool */
 18.1114 +	do {
 18.1115 +		if(sfxinfo[sfxpool]&SFX_CRITICAL) {
 18.1116 +			if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) {
 18.1117 +				sfxinfo[sfxpool]=flags;
 18.1118 +				Voice_Play_internal(c,s,start);
 18.1119 +				md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1120 +				Voice_SetPanning_internal(c,s->panning);
 18.1121 +				md_driver->VoiceSetFrequency(c,s->speed);
 18.1122 +				sfxpool++;
 18.1123 +				if(sfxpool>=md_sfxchn) sfxpool=0;
 18.1124 +				return c;
 18.1125 +			}
 18.1126 +		} else {
 18.1127 +			sfxinfo[sfxpool]=flags;
 18.1128 +			Voice_Play_internal(c=sfxpool+md_sngchn,s,start);
 18.1129 +			md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1130 +			Voice_SetPanning_internal(c,s->panning);
 18.1131 +			md_driver->VoiceSetFrequency(c,s->speed);
 18.1132 +			sfxpool++;
 18.1133 +			if(sfxpool>=md_sfxchn) sfxpool=0;
 18.1134 +			return c;
 18.1135 +		}
 18.1136  
 18.1137 -    if(md_sfxchn==0) return -1;
 18.1138 -    if(s->volume > 64) s->volume = 64;
 18.1139 -    
 18.1140 -    /* check the first location after sfxpool */
 18.1141 -    do
 18.1142 -    {   if(sfxinfo[sfxpool] & SFX_CRITICAL)
 18.1143 -        {   if(md_driver->VoiceStopped(c=sfxpool+md_sngchn))
 18.1144 -            {   sfxinfo[sfxpool] = flags;
 18.1145 -                Voice_Play(c, s, start);
 18.1146 -                md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1147 -                md_driver->VoiceSetPanning(c,s->panning);
 18.1148 -                md_driver->VoiceSetFrequency(c,s->speed);
 18.1149 -                sfxpool++;
 18.1150 -                if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1151 -                return c;
 18.1152 -            }
 18.1153 -        } else
 18.1154 -        {   sfxinfo[sfxpool] = flags;
 18.1155 -            Voice_Play(c=sfxpool+md_sngchn, s, start);
 18.1156 -            md_driver->VoiceSetVolume(c,s->volume<<2);
 18.1157 -            md_driver->VoiceSetPanning(c,s->panning);
 18.1158 -            md_driver->VoiceSetFrequency(c,s->speed);
 18.1159 -            sfxpool++;
 18.1160 -            if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1161 -            return c;
 18.1162 -        }
 18.1163 +		sfxpool++;
 18.1164 +		if(sfxpool>=md_sfxchn) sfxpool = 0;
 18.1165 +	} while(sfxpool!=orig);
 18.1166  
 18.1167 -        sfxpool++;
 18.1168 -        if(sfxpool >= md_sfxchn) sfxpool = 0;
 18.1169 -    } while(sfxpool!=orig);
 18.1170 -
 18.1171 -    return -1;
 18.1172 +	return -1;
 18.1173  }
 18.1174  
 18.1175 +SBYTE Sample_Play(SAMPLE *s,ULONG start,UBYTE flags)
 18.1176 +{
 18.1177 +	SBYTE result;
 18.1178 +
 18.1179 +	MUTEX_LOCK(vars);
 18.1180 +	result=Sample_Play_internal(s,start,flags);
 18.1181 +	MUTEX_UNLOCK(vars);
 18.1182 +
 18.1183 +	return result;
 18.1184 +}
 18.1185 +
 18.1186 +long MikMod_GetVersion(void)
 18.1187 +{
 18.1188 +	return LIBMIKMOD_VERSION;
 18.1189 +}
 18.1190 +
 18.1191 +/*========== MT-safe stuff */
 18.1192 +
 18.1193 +#ifdef HAVE_PTHREAD
 18.1194 +#define INIT_MUTEX(name) \
 18.1195 +	pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER
 18.1196 +#elif defined(__OS2__)||defined(__EMX__)
 18.1197 +#define INIT_MUTEX(name) \
 18.1198 +	HMTX _mm_mutex_##name
 18.1199 +#elif defined(WIN32)
 18.1200 +#define INIT_MUTEX(name) \
 18.1201 +	HANDLE _mm_mutex_##name
 18.1202 +#else
 18.1203 +#define INIT_MUTEX(name)
 18.1204 +#endif
 18.1205 +
 18.1206 +INIT_MUTEX(vars);
 18.1207 +INIT_MUTEX(lists);
 18.1208 +
 18.1209 +BOOL MikMod_InitThreads(void)
 18.1210 +{
 18.1211 +	static int firstcall=1;
 18.1212 +	static int result=0;
 18.1213 +
 18.1214 +	if (firstcall) {
 18.1215 +		firstcall=0;
 18.1216 +#ifdef HAVE_PTHREAD
 18.1217 +		result=1;
 18.1218 +#elif defined(__OS2__)||defined(__EMX__)
 18.1219 +		if(DosCreateMutexSem((PSZ)NULL,&_mm_mutex_lists,0,0) ||
 18.1220 +		   DosCreateMutexSem((PSZ)NULL,&_mm_mutex_vars,0,0)) {
 18.1221 +			_mm_mutex_lists=_mm_mutex_vars=(HMTX)NULL;
 18.1222 +			result=0;
 18.1223 +		} else
 18.1224 +			result=1;
 18.1225 +#elif defined(WIN32)
 18.1226 +		if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))||
 18.1227 +		   (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)"))))
 18.1228 +			result=0;
 18.1229 +		else
 18.1230 +			result=1;
 18.1231 +#endif
 18.1232 +	}
 18.1233 +	return result;
 18.1234 +}
 18.1235 +
 18.1236 +void MikMod_Unlock(void)
 18.1237 +{
 18.1238 +	MUTEX_UNLOCK(lists);
 18.1239 +	MUTEX_UNLOCK(vars);
 18.1240 +}
 18.1241 +
 18.1242 +void MikMod_Lock(void)
 18.1243 +{
 18.1244 +	MUTEX_LOCK(vars);
 18.1245 +	MUTEX_LOCK(lists);
 18.1246 +}
 18.1247 +
 18.1248 +/*========== Parameter extraction helper */
 18.1249 +
 18.1250 +CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,BOOL implicit)
 18.1251 +{
 18.1252 +	CHAR *ret=NULL;
 18.1253 +
 18.1254 +	if(cmdline) {
 18.1255 +		CHAR *buf=strstr(cmdline,atomname);
 18.1256 +
 18.1257 +		if((buf)&&((buf==cmdline)||(*(buf-1)==','))) {
 18.1258 +			CHAR *ptr=buf+strlen(atomname);
 18.1259 +
 18.1260 +			if(*ptr=='=') {
 18.1261 +				for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++);
 18.1262 +				ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
 18.1263 +				if(ret)
 18.1264 +					strncpy(ret,buf,ptr-buf);
 18.1265 +			} else if((*ptr==',')||(!*ptr)) {
 18.1266 +				if(implicit) {
 18.1267 +					ret=_mm_malloc((1+ptr-buf)*sizeof(CHAR));
 18.1268 +					if(ret)
 18.1269 +						strncpy(ret,buf,ptr-buf);
 18.1270 +				}
 18.1271 +			}
 18.1272 +		}
 18.1273 +	}
 18.1274 +	return ret;
 18.1275 +}
 18.1276 +
 18.1277 +#ifdef unix
 18.1278 +
 18.1279 +#include <unistd.h>
 18.1280 +
 18.1281 +/*========== Posix helper functions */
 18.1282 +
 18.1283 +/* Check if the file is a regular or nonexistant file (or a link to a such a
 18.1284 +   file), and that, should the calling program be setuid, the access rights are
 18.1285 +   reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise.
 18.1286 +   The goal is to prevent a setuid root libmikmod application from overriding
 18.1287 +   files like /etc/passwd with digital sound... */
 18.1288 +BOOL MD_Access(CHAR *filename)
 18.1289 +{
 18.1290 +	struct stat buf;
 18.1291 +
 18.1292 +	if(!stat(filename,&buf)) {
 18.1293 +		/* not a regular file ? */
 18.1294 +		if(!S_ISREG(buf.st_mode)) return 0;
 18.1295 +		/* more than one hard link to the file ? */
 18.1296 +		if(buf.st_nlink>1) return 0;
 18.1297 +		/* check access rights with the real user and group id */
 18.1298 +		if(getuid()==buf.st_uid) {
 18.1299 +			if(!(buf.st_mode&S_IWUSR)) return 0;
 18.1300 +		} else if(getgid()==buf.st_gid) {
 18.1301 +			if(!(buf.st_mode&S_IWGRP)) return 0;
 18.1302 +		} else
 18.1303 +			if(!(buf.st_mode&S_IWOTH)) return 0;
 18.1304 +	}
 18.1305 +
 18.1306 +	return 1;
 18.1307 +}
 18.1308 +
 18.1309 +/* Drop all root privileges we might have */
 18.1310 +BOOL MD_DropPrivileges(void)
 18.1311 +{
 18.1312 +	if(!geteuid()) {
 18.1313 +		if(getuid()) {
 18.1314 +			/* we are setuid root -> drop setuid to become the real user */
 18.1315 +			if(setuid(getuid())) return 1;
 18.1316 +		} else {
 18.1317 +			/* we are run as root -> drop all and become user 'nobody' */
 18.1318 +			struct passwd *nobody;
 18.1319 +			int uid;
 18.1320 +
 18.1321 +			if(!(nobody=getpwnam("nobody"))) return 1; /* no such user ? */
 18.1322 +			uid=nobody->pw_uid;
 18.1323 +			if (!uid) /* user 'nobody' has root privileges ? weird... */
 18.1324 +				return 1;
 18.1325 +			if (setuid(uid)) return 1;
 18.1326 +		}
 18.1327 +	}
 18.1328 +	return 0;
 18.1329 +}
 18.1330 +
 18.1331 +#endif
 18.1332 +
 18.1333 +/* 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 -#include "mmio.h"
   19.11 +	This library is free software; you can redistribute it and/or modify
   19.12 +	it under the terms of the GNU Library General Public License as
   19.13 +	published by the Free Software Foundation; either version 2 of
   19.14 +	the License, or (at your option) any later version.
   19.15 +
   19.16 +	This program is distributed in the hope that it will be useful,
   19.17 +	but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.18 +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.19 +	GNU Library General Public License for more details.
   19.20 +
   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 + *	========== Drivers
  19.565 + */
  19.566  
  19.567 -
  19.568 -#define MikMod_RegisterDriver(x) MD_RegisterDriver(&x)
  19.569 -#define MikMod_RegisterLoader(x) ML_RegisterLoader(&x)
  19.570 -#define MikMod_RegisterErrorHandler(x) _mm_RegisterErrorHandler(x)
  19.571 -
  19.572 -
  19.573 -/* The following #define macros are for retaining API compatiability */
  19.574 -/* with the beta version of MikMod 3.0, and are TEMPORARY!  They WILL */
  19.575 -/* be removed in the future! */
  19.576 -
  19.577 -#define MD_RegisterPlayer(x)      MikMod_RegisterPlayer(x)
  19.578 -#define MD_Init                   MikMod_Init
  19.579 -#define MD_Exit                   MikMod_Exit
  19.580 -#define MD_Update                 MikMod_Update
  19.581 -#define ML_Free(x)                MikMod_FreeSong(x)
  19.582 -#define MD_SetNumChannels(x,y)    MikMod_SetNumVoices(x,y)
  19.583 -#define MD_SetNumVoices(x,y)      MikMod_SetNumVoices(x,y)
  19.584 -#define MD_PlayStart              MikMod_EnableOutput
  19.585 -#define MD_PlayStop               MikMod_DisableOutput
  19.586 -
  19.587 -#define MD_VoiceSetVolume(x,y)    Voice_SetVolume(x,y)
  19.588 -#define MD_VoiceSetFrequency(x,y) Voice_SetFrequency(x,y)
  19.589 -#define MD_VoiceSetPanning(x,y)   Voice_SetPanning(x,y)
  19.590 -#define MD_VoicePlay(x,y,z)       Voice_Play(x,y,z)
  19.591 -#define MD_VoiceStop(x)           Voice_Stop(x)
  19.592 -#define MD_VoiceReleaseSustain(x) Voice_ReleaseSustain(x)
  19.593 -#define MD_VoiceStopped(x)        Voice_Stopped(x)
  19.594 -#define MD_VoiceGetPosition(x)    Voice_GetPosition(x)
  19.595 -#define MD_VoiceRealVolume(x)     Voice_RealVolume(x)
  19.596 -
  19.597 -
  19.598 -#define SFX_CRITICAL  1
  19.599 -
  19.600 -
  19.601 -/**************************************************************************
  19.602 -****** mikmod types: ******************************************************
  19.603 -**************************************************************************/
  19.604 -
  19.605 -/* Sample format [loading and in-memory] flags: */
  19.606 -#define SF_16BITS       1
  19.607 -#define SF_SIGNED       2
  19.608 -#define SF_STEREO       4
  19.609 -#define SF_DELTA        8
  19.610 -#define SF_BIG_ENDIAN   16
  19.611 -
  19.612 -/* General Playback flags */
  19.613 -
  19.614 -#define SF_LOOP         32
  19.615 -#define SF_BIDI         64
  19.616 -#define SF_SUSTAIN      128
  19.617 -#define SF_REVERSE      256
  19.618 -
  19.619 -/* Module-only Playback Flags */
  19.620 -
  19.621 -#define SF_OWNPAN       512
  19.622 -#define SF_UST_LOOP     1024
  19.623 -
  19.624 -
  19.625 -typedef struct SAMPLE
  19.626 -{   ULONG  speed;            /* Base playing speed/frequency of note (Middle C in player) */
  19.627 -    UBYTE  volume;           /* volume 0-64 */
  19.628 -    UWORD  panning;          /* panning (0-255 or PAN_SURROUND) */
  19.629 -    ULONG  length;           /* length of sample (in samples!) */
  19.630 -    ULONG  loopstart;        /* repeat position (relative to start, in samples) */
  19.631 -    ULONG  loopend;          /* repeat end */
  19.632 -    ULONG  susbegin;         /* sustain loop begin (in samples) \  Not Supported */
  19.633 -    ULONG  susend;           /* sustain loop end                /      Yet! */
  19.634 -
  19.635 -    UWORD  flags;            /* sample format in memory */
  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 +/* Mixing flags */
  19.726  
  19.727 -/* possible mixing mode bits: */
  19.728 -/* -------------------------- */
  19.729 -/* These take effect only after MikMod_Init or MikMod_Reset. */
  19.730 +/* These ones take effect only after MikMod_Init or MikMod_Reset */
  19.731 +#define DMODE_16BITS     0x0001 /* enable 16 bit output */
  19.732 +#define DMODE_STEREO     0x0002 /* enable stereo output */
  19.733 +#define DMODE_SOFT_SNDFX 0x0004 /* Process sound effects via software mixer */
  19.734 +#define DMODE_SOFT_MUSIC 0x0008 /* Process music via software mixer */
  19.735 +#define DMODE_HQMIXER    0x0010 /* Use high-quality (slower) software mixer */
  19.736 +/* These take effect immediately. */
  19.737 +#define DMODE_SURROUND   0x0100 /* enable surround sound */
  19.738 +#define DMODE_INTERP     0x0200 /* enable interpolation */
  19.739 +#define DMODE_REVERSE    0x0400 /* reverse stereo */
  19.740  
  19.741 -#define DMODE_16BITS       1         /* enable 16 bit output */
  19.742 -#define DMODE_SURROUND     2         /* enable Dolby surround sound (not yet supported) */
  19.743 -#define DMODE_SOFT_SNDFX   4         /* Process sound effects via software mixer (not yet supported) */
  19.744 -#define DMODE_SOFT_MUSIC   8         /* Process music via software mixer (not yet supported) */
  19.745 +struct SAMPLOAD;
  19.746 +typedef struct MDRIVER {
  19.747 +struct MDRIVER* next;
  19.748 +	CHAR*       Name;
  19.749 +	CHAR*       Version;
  19.750  
  19.751 -/* These take effect immidiately. */
  19.752 +	UBYTE       HardVoiceLimit; /* Limit of hardware mixer voices */
  19.753 +	UBYTE       SoftVoiceLimit; /* Limit of software mixer voices */
  19.754  
  19.755 -#define DMODE_STEREO      16         /* enable stereo output */
  19.756 -#define DMODE_REVERSE     32         /* reverse stereo */
  19.757 -#define DMODE_INTERP      64         /* enable interpolation (not yet supported) */
  19.758 +	CHAR*       Alias;
  19.759  
  19.760 -
  19.761 -/* driver structure: */
  19.762 -
  19.763 -typedef struct MDRIVER
  19.764 -{   struct MDRIVER *next;
  19.765 -    CHAR    *Name;
  19.766 -    CHAR    *Version;
  19.767 -    UBYTE   HardVoiceLimit,       /* Limit of hardware mixer voices for this driver */
  19.768 -            SoftVoiceLimit;       /* Limit of software mixer voices for this driver */
  19.769 -
  19.770 -    BOOL    (*IsPresent)          (void);
  19.771 -    SWORD   (*SampleLoad)         (SAMPLOAD *s, int type);
  19.772 -    void    (*SampleUnLoad)       (SWORD handle);
  19.773 -    ULONG   (*FreeSampleSpace)    (int type);
  19.774 -    ULONG   (*RealSampleLength)   (int type, SAMPLE *s);
  19.775 -    BOOL    (*Init)               (void);
  19.776 -    void    (*Exit)               (void);
  19.777 -    BOOL    (*Reset)              (void);
  19.778 -    BOOL    (*SetNumVoices)       (void);
  19.779 -    BOOL    (*PlayStart)          (void);
  19.780 -    void    (*PlayStop)           (void);
  19.781 -    void    (*Update)             (void);
  19.782 -    void    (*VoiceSetVolume)     (UBYTE voice, UWORD vol);
  19.783 -    void    (*VoiceSetFrequency)  (UBYTE voice, ULONG frq);
  19.784 -    void    (*VoiceSetPanning)    (UBYTE voice, ULONG pan);
  19.785 -    void    (*VoicePlay)          (UBYTE voice, SWORD handle, ULONG start, ULONG size, ULONG reppos, ULONG repend, UWORD flags);
  19.786 -    void    (*VoiceStop)          (UBYTE voice);
  19.787 -    BOOL    (*VoiceStopped)       (UBYTE voice);
  19.788 -    void    (*VoiceReleaseSustain)(UBYTE voice);
  19.789 -    SLONG   (*VoiceGetPosition)   (UBYTE voice);
  19.790 -    ULONG   (*VoiceRealVolume)    (UBYTE voice);
  19.791 -
  19.792 -    BOOL    (*StreamInit)         (ULONG speed, UWORD flags);
  19.793 -    void    (*StreamExit)         (void);
  19.794 -    void    (*StreamSetSpeed)     (ULONG speed);
  19.795 -    SLONG   (*StreamGetPosition)  (void);
  19.796 -    void    (*StreamLoadFP)       (FILE *fp);
  19.797 +	void        (*CommandLine)      (CHAR*);
  19.798 +	BOOL        (*IsPresent)        (void);
  19.799 +	SWORD       (*SampleLoad)       (struct SAMPLOAD*,int);
  19.800 +	void        (*SampleUnload)     (SWORD);
  19.801 +	ULONG       (*FreeSampleSpace)  (int);
  19.802 +	ULONG       (*RealSampleLength) (int,struct SAMPLE*);
  19.803 +	BOOL        (*Init)             (void);
  19.804 +	void        (*Exit)             (void);
  19.805 +	BOOL        (*Reset)            (void);
  19.806 +	BOOL        (*SetNumVoices)     (void);
  19.807 +	BOOL        (*PlayStart)        (void);
  19.808 +	void        (*PlayStop)         (void);
  19.809 +	void        (*Update)           (void);
  19.810 +	void		(*Pause)			(void);
  19.811 +	void        (*VoiceSetVolume)   (UBYTE,UWORD);
  19.812 +	UWORD       (*VoiceGetVolume)   (UBYTE);
  19.813 +	void        (*VoiceSetFrequency)(UBYTE,ULONG);
  19.814 +	ULONG       (*VoiceGetFrequency)(UBYTE);
  19.815 +	void        (*VoiceSetPanning)  (UBYTE,ULONG);
  19.816 +	ULONG       (*VoiceGetPanning)  (UBYTE);
  19.817 +	void        (*VoicePlay)        (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
  19.818 +	void        (*VoiceStop)        (UBYTE);
  19.819 +	BOOL        (*VoiceStopped)     (UBYTE);
  19.820 +	SLONG       (*VoiceGetPosition) (UBYTE);
  19.821 +	ULONG       (*VoiceRealVolume)  (UBYTE);
  19.822  } MDRIVER;
  19.823  
  19.824 +/* These variables can be changed at ANY time and results will be immediate */
  19.825 +MIKMODAPI extern UBYTE md_volume;      /* global sound volume (0-128) */
  19.826 +MIKMODAPI extern UBYTE md_musicvolume; /* volume of song */
  19.827 +MIKMODAPI extern UBYTE md_sndfxvolume; /* volume of sound effects */
  19.828 +MIKMODAPI extern UBYTE md_reverb;      /* 0 = none;  15 = chaos */
  19.829 +MIKMODAPI extern UBYTE md_pansep;      /* 0 = mono;  128 == 100% (full left/right) */
  19.830  
  19.831 -/* These variables can be changed at ANY time and results */
  19.832 -/* will be immidiate: */
  19.833 +/* The variables below can be changed at any time, but changes will not be
  19.834 +   implemented until MikMod_Reset is called. A call to MikMod_Reset may result
  19.835 +   in a skip or pop in audio (depending on the soundcard driver and the settings
  19.836 +   changed). */
  19.837 +MIKMODAPI extern UWORD md_device;      /* device */
  19.838 +MIKMODAPI extern UWORD md_mixfreq;     /* mixing frequency */
  19.839 +MIKMODAPI extern UWORD md_mode;        /* mode. See DMODE_? flags above */
  19.840  
  19.841 -extern UBYTE md_bpm;            /* current song / hardware BPM rate */
  19.842 -extern UBYTE md_volume;         /* Global sound volume (0-128) */
  19.843 -extern UBYTE md_musicvolume;    /* volume of song */
  19.844 -extern UBYTE md_sndfxvolume;    /* volume of sound effects */
  19.845 -extern UBYTE md_reverb;         /* 0 = none;  15 = chaos */
  19.846 -extern UBYTE md_pansep;         /* 0 = mono;  128 == 100% (full left/right) */
  19.847 +/* The following variable should not be changed! */
  19.848 +MIKMODAPI extern MDRIVER* md_driver;   /* Current driver in use. */
  19.849  
  19.850 +/* Known drivers list */
  19.851  
  19.852 -/* The variables below can be changed at any time, but changes will */
  19.853 -/* not be implimented until MikMod_Reset is called.  A call to */
  19.854 -/* MikMod_Reset may result in a skip or pop in audio (depending on */
  19.855 -/* the soundcard driver and the settings changed). */
  19.856 +MIKMODAPI extern struct MDRIVER drv_nos;    /* no sound */
  19.857 +MIKMODAPI extern struct MDRIVER drv_pipe;   /* piped output */
  19.858 +MIKMODAPI extern struct MDRIVER drv_raw;    /* raw file disk writer [music.raw] */
  19.859 +MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */
  19.860 +MIKMODAPI extern struct MDRIVER drv_wav;    /* RIFF WAVE file disk writer [music.wav] */
  19.861  
  19.862 -extern UWORD md_device;         /* Device.  0 = autodetect, other # depend on driver register order. */
  19.863 -extern UWORD md_mixfreq;        /* mixing frequency.  Valid 5000 -> 44100 */
  19.864 -extern UWORD md_dmabufsize;     /* DMA buffer size.  Valid 512 -> 32000 */
  19.865 -extern UWORD md_mode;           /* Mode.  See DMODE_? flags above */
  19.866 +MIKMODAPI extern struct MDRIVER drv_ultra;  /* Linux Ultrasound driver */
  19.867  
  19.868 +MIKMODAPI extern struct MDRIVER drv_AF;     /* Dec Alpha AudioFile */
  19.869 +MIKMODAPI extern struct MDRIVER drv_aix;    /* AIX audio device */
  19.870 +MIKMODAPI extern struct MDRIVER drv_alsa;   /* Advanced Linux Sound Architecture (ALSA) */
  19.871 +MIKMODAPI extern struct MDRIVER drv_esd;    /* Enlightened sound daemon (EsounD) */
  19.872 +MI