r239 - in tags: . rott-1.1 rott-1.1/doc rott-1.1/mac rott-1.1/mac/English.lproj rott-1.1/mac/Rise of the Triad.pbproj rott-1.1/misc rott-1.1/rott rott-1.1/rott/audiolib rott-1.1/vs.net

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Jul 14 13:09:17 EDT 2008


Author: fabian
Date: 2008-07-14 13:09:15 -0400 (Mon, 14 Jul 2008)
New Revision: 239

Added:
   tags/rott-1.1/
   tags/rott-1.1/COPYING
   tags/rott-1.1/README
   tags/rott-1.1/doc/
   tags/rott-1.1/doc/13todo.txt
   tags/rott-1.1/doc/cheats.txt
   tags/rott-1.1/doc/cmdline.txt
   tags/rott-1.1/doc/hacker.txt
   tags/rott-1.1/doc/readme.txt
   tags/rott-1.1/doc/rott.6
   tags/rott-1.1/doc/wad.txt
   tags/rott-1.1/mac/
   tags/rott-1.1/mac/English.lproj/
   tags/rott-1.1/mac/English.lproj/InfoPlist.strings
   tags/rott-1.1/mac/Rise of the Triad.pbproj/
   tags/rott-1.1/mac/Rise of the Triad.pbproj/project.pbxproj
   tags/rott-1.1/mac/SDLMain.h
   tags/rott-1.1/mac/SDLMain.m
   tags/rott-1.1/misc/
   tags/rott-1.1/misc/rott.xpm
   tags/rott-1.1/misc/runrott.sh
   tags/rott-1.1/rott/
   tags/rott-1.1/rott/Makefile
   tags/rott-1.1/rott/WinRott.h
   tags/rott-1.1/rott/_engine.h
   tags/rott-1.1/rott/_isr.h
   tags/rott-1.1/rott/_rt_acto.h
   tags/rott-1.1/rott/_rt_buil.h
   tags/rott-1.1/rott/_rt_com.h
   tags/rott-1.1/rott/_rt_dman.h
   tags/rott-1.1/rott/_rt_door.h
   tags/rott-1.1/rott/_rt_draw.h
   tags/rott-1.1/rott/_rt_floo.h
   tags/rott-1.1/rott/_rt_game.h
   tags/rott-1.1/rott/_rt_in.h
   tags/rott-1.1/rott/_rt_main.h
   tags/rott-1.1/rott/_rt_map.h
   tags/rott-1.1/rott/_rt_menu.h
   tags/rott-1.1/rott/_rt_msg.h
   tags/rott-1.1/rott/_rt_net.h
   tags/rott-1.1/rott/_rt_play.h
   tags/rott-1.1/rott/_rt_rand.h
   tags/rott-1.1/rott/_rt_scal.h
   tags/rott-1.1/rott/_rt_soun.h
   tags/rott-1.1/rott/_rt_spba.h
   tags/rott-1.1/rott/_rt_stat.h
   tags/rott-1.1/rott/_rt_str.h
   tags/rott-1.1/rott/_rt_swft.h
   tags/rott-1.1/rott/_rt_ted.h
   tags/rott-1.1/rott/_rt_util.h
   tags/rott-1.1/rott/_rt_vid.h
   tags/rott-1.1/rott/_w_wad.h
   tags/rott-1.1/rott/_z_zone.h
   tags/rott-1.1/rott/audiolib/
   tags/rott-1.1/rott/audiolib/Makefile
   tags/rott-1.1/rott/audiolib/_al_midi.h
   tags/rott-1.1/rott/audiolib/_blaster.h
   tags/rott-1.1/rott/audiolib/_guswave.h
   tags/rott-1.1/rott/audiolib/_midi.h
   tags/rott-1.1/rott/audiolib/_multivc.h
   tags/rott-1.1/rott/audiolib/_pas16.h
   tags/rott-1.1/rott/audiolib/_sndscap.h
   tags/rott-1.1/rott/audiolib/adlibfx.c
   tags/rott-1.1/rott/audiolib/adlibfx.h
   tags/rott-1.1/rott/audiolib/al_midi.c
   tags/rott-1.1/rott/audiolib/al_midi.h
   tags/rott-1.1/rott/audiolib/assert.h
   tags/rott-1.1/rott/audiolib/awe32.c
   tags/rott-1.1/rott/audiolib/awe32.h
   tags/rott-1.1/rott/audiolib/blaster.c
   tags/rott-1.1/rott/audiolib/blaster.h
   tags/rott-1.1/rott/audiolib/ctaweapi.h
   tags/rott-1.1/rott/audiolib/debugio.c
   tags/rott-1.1/rott/audiolib/debugio.h
   tags/rott-1.1/rott/audiolib/dma.c
   tags/rott-1.1/rott/audiolib/dma.h
   tags/rott-1.1/rott/audiolib/dpmi.c
   tags/rott-1.1/rott/audiolib/dpmi.h
   tags/rott-1.1/rott/audiolib/dsl.c
   tags/rott-1.1/rott/audiolib/dsl.h
   tags/rott-1.1/rott/audiolib/fx_man.c
   tags/rott-1.1/rott/audiolib/fx_man.h
   tags/rott-1.1/rott/audiolib/gmtimbre.c
   tags/rott-1.1/rott/audiolib/gus.c
   tags/rott-1.1/rott/audiolib/gusmidi.c
   tags/rott-1.1/rott/audiolib/gusmidi.h
   tags/rott-1.1/rott/audiolib/guswave.c
   tags/rott-1.1/rott/audiolib/guswave.h
   tags/rott-1.1/rott/audiolib/interrup.h
   tags/rott-1.1/rott/audiolib/irq.c
   tags/rott-1.1/rott/audiolib/irq.h
   tags/rott-1.1/rott/audiolib/leetimbr.c
   tags/rott-1.1/rott/audiolib/linklist.h
   tags/rott-1.1/rott/audiolib/ll_man.c
   tags/rott-1.1/rott/audiolib/ll_man.h
   tags/rott-1.1/rott/audiolib/midi.c
   tags/rott-1.1/rott/audiolib/midi.h
   tags/rott-1.1/rott/audiolib/mpu401.c
   tags/rott-1.1/rott/audiolib/mpu401.h
   tags/rott-1.1/rott/audiolib/multivoc.c
   tags/rott-1.1/rott/audiolib/multivoc.h
   tags/rott-1.1/rott/audiolib/music.c
   tags/rott-1.1/rott/audiolib/music.h
   tags/rott-1.1/rott/audiolib/mv_mix.asm
   tags/rott-1.1/rott/audiolib/mv_mix.c
   tags/rott-1.1/rott/audiolib/mv_mix16.asm
   tags/rott-1.1/rott/audiolib/mvreverb.asm
   tags/rott-1.1/rott/audiolib/mvreverb.c
   tags/rott-1.1/rott/audiolib/myprint.c
   tags/rott-1.1/rott/audiolib/myprint.h
   tags/rott-1.1/rott/audiolib/newgf1.h
   tags/rott-1.1/rott/audiolib/nodpmi.c
   tags/rott-1.1/rott/audiolib/nomusic.c
   tags/rott-1.1/rott/audiolib/pas16.c
   tags/rott-1.1/rott/audiolib/pas16.h
   tags/rott-1.1/rott/audiolib/pitch.c
   tags/rott-1.1/rott/audiolib/pitch.h
   tags/rott-1.1/rott/audiolib/platform.h
   tags/rott-1.1/rott/audiolib/sndcards.h
   tags/rott-1.1/rott/audiolib/sndscape.c
   tags/rott-1.1/rott/audiolib/sndscape.h
   tags/rott-1.1/rott/audiolib/sndsrc.c
   tags/rott-1.1/rott/audiolib/sndsrc.h
   tags/rott-1.1/rott/audiolib/standard.h
   tags/rott-1.1/rott/audiolib/task_man.c
   tags/rott-1.1/rott/audiolib/task_man.h
   tags/rott-1.1/rott/audiolib/user.c
   tags/rott-1.1/rott/audiolib/user.h
   tags/rott-1.1/rott/audiolib/usrhooks.c
   tags/rott-1.1/rott/audiolib/usrhooks.h
   tags/rott-1.1/rott/audiolib/util.h
   tags/rott-1.1/rott/byteordr.c
   tags/rott-1.1/rott/byteordr.h
   tags/rott-1.1/rott/cin_actr.c
   tags/rott-1.1/rott/cin_actr.h
   tags/rott-1.1/rott/cin_def.h
   tags/rott-1.1/rott/cin_efct.c
   tags/rott-1.1/rott/cin_efct.h
   tags/rott-1.1/rott/cin_evnt.c
   tags/rott-1.1/rott/cin_evnt.h
   tags/rott-1.1/rott/cin_glob.c
   tags/rott-1.1/rott/cin_glob.h
   tags/rott-1.1/rott/cin_main.c
   tags/rott-1.1/rott/cin_main.h
   tags/rott-1.1/rott/cin_util.c
   tags/rott-1.1/rott/cin_util.h
   tags/rott-1.1/rott/develop.h
   tags/rott-1.1/rott/dosutil.c
   tags/rott-1.1/rott/dukemusc.c
   tags/rott-1.1/rott/engine.c
   tags/rott-1.1/rott/engine.h
   tags/rott-1.1/rott/f_scale.asm
   tags/rott-1.1/rott/f_scale.h
   tags/rott-1.1/rott/fli_def.h
   tags/rott-1.1/rott/fli_glob.h
   tags/rott-1.1/rott/fli_main.c
   tags/rott-1.1/rott/fli_main.h
   tags/rott-1.1/rott/fli_type.h
   tags/rott-1.1/rott/fli_util.c
   tags/rott-1.1/rott/fli_util.h
   tags/rott-1.1/rott/fx_man.c
   tags/rott-1.1/rott/fx_man.h
   tags/rott-1.1/rott/gmove.h
   tags/rott-1.1/rott/isr.c
   tags/rott-1.1/rott/isr.h
   tags/rott-1.1/rott/keyb.h
   tags/rott-1.1/rott/lookups.c
   tags/rott-1.1/rott/lumpy.h
   tags/rott-1.1/rott/memcheck.h
   tags/rott-1.1/rott/modexlib.c
   tags/rott-1.1/rott/modexlib.h
   tags/rott-1.1/rott/music.h
   tags/rott-1.1/rott/myprint.h
   tags/rott-1.1/rott/profile.h
   tags/rott-1.1/rott/r_scale.asm
   tags/rott-1.1/rott/rottnet.h
   tags/rott-1.1/rott/rt_actor.c
   tags/rott-1.1/rott/rt_actor.h
   tags/rott-1.1/rott/rt_battl.c
   tags/rott-1.1/rott/rt_battl.h
   tags/rott-1.1/rott/rt_build.c
   tags/rott-1.1/rott/rt_build.h
   tags/rott-1.1/rott/rt_cfg.c
   tags/rott-1.1/rott/rt_cfg.h
   tags/rott-1.1/rott/rt_com.c
   tags/rott-1.1/rott/rt_com.h
   tags/rott-1.1/rott/rt_crc.c
   tags/rott-1.1/rott/rt_crc.h
   tags/rott-1.1/rott/rt_debug.c
   tags/rott-1.1/rott/rt_debug.h
   tags/rott-1.1/rott/rt_def.h
   tags/rott-1.1/rott/rt_dmand.c
   tags/rott-1.1/rott/rt_dmand.h
   tags/rott-1.1/rott/rt_door.c
   tags/rott-1.1/rott/rt_door.h
   tags/rott-1.1/rott/rt_dr_a.asm
   tags/rott-1.1/rott/rt_dr_a.h
   tags/rott-1.1/rott/rt_draw.c
   tags/rott-1.1/rott/rt_draw.h
   tags/rott-1.1/rott/rt_err.c
   tags/rott-1.1/rott/rt_error.c
   tags/rott-1.1/rott/rt_error.h
   tags/rott-1.1/rott/rt_fc_a.asm
   tags/rott-1.1/rott/rt_fc_a.h
   tags/rott-1.1/rott/rt_floor.c
   tags/rott-1.1/rott/rt_floor.h
   tags/rott-1.1/rott/rt_game.c
   tags/rott-1.1/rott/rt_game.h
   tags/rott-1.1/rott/rt_in.c
   tags/rott-1.1/rott/rt_in.h
   tags/rott-1.1/rott/rt_main.c
   tags/rott-1.1/rott/rt_main.h
   tags/rott-1.1/rott/rt_map.c
   tags/rott-1.1/rott/rt_map.h
   tags/rott-1.1/rott/rt_menu.c
   tags/rott-1.1/rott/rt_menu.h
   tags/rott-1.1/rott/rt_msg.c
   tags/rott-1.1/rott/rt_msg.h
   tags/rott-1.1/rott/rt_net.c
   tags/rott-1.1/rott/rt_net.h
   tags/rott-1.1/rott/rt_playr.c
   tags/rott-1.1/rott/rt_playr.h
   tags/rott-1.1/rott/rt_rand.c
   tags/rott-1.1/rott/rt_rand.h
   tags/rott-1.1/rott/rt_sc_a.asm
   tags/rott-1.1/rott/rt_sc_a.h
   tags/rott-1.1/rott/rt_scale.c
   tags/rott-1.1/rott/rt_scale.h
   tags/rott-1.1/rott/rt_sound.c
   tags/rott-1.1/rott/rt_sound.h
   tags/rott-1.1/rott/rt_spbal.c
   tags/rott-1.1/rott/rt_spbal.h
   tags/rott-1.1/rott/rt_sqrt.c
   tags/rott-1.1/rott/rt_sqrt.h
   tags/rott-1.1/rott/rt_stat.c
   tags/rott-1.1/rott/rt_stat.h
   tags/rott-1.1/rott/rt_state.c
   tags/rott-1.1/rott/rt_str.c
   tags/rott-1.1/rott/rt_str.h
   tags/rott-1.1/rott/rt_swift.c
   tags/rott-1.1/rott/rt_swift.h
   tags/rott-1.1/rott/rt_table.h
   tags/rott-1.1/rott/rt_ted.c
   tags/rott-1.1/rott/rt_ted.h
   tags/rott-1.1/rott/rt_util.c
   tags/rott-1.1/rott/rt_util.h
   tags/rott-1.1/rott/rt_vh_a.asm
   tags/rott-1.1/rott/rt_vh_a.h
   tags/rott-1.1/rott/rt_vid.c
   tags/rott-1.1/rott/rt_vid.h
   tags/rott-1.1/rott/rt_view.c
   tags/rott-1.1/rott/rt_view.h
   tags/rott-1.1/rott/sbconfig.c
   tags/rott-1.1/rott/sbconfig.h
   tags/rott-1.1/rott/scriplib.c
   tags/rott-1.1/rott/scriplib.h
   tags/rott-1.1/rott/snd_reg.h
   tags/rott-1.1/rott/snd_shar.h
   tags/rott-1.1/rott/sndcards.h
   tags/rott-1.1/rott/splib.h
   tags/rott-1.1/rott/sprites.h
   tags/rott-1.1/rott/states.h
   tags/rott-1.1/rott/task_man.h
   tags/rott-1.1/rott/version.h
   tags/rott-1.1/rott/w_wad.c
   tags/rott-1.1/rott/w_wad.h
   tags/rott-1.1/rott/watcom.c
   tags/rott-1.1/rott/watcom.h
   tags/rott-1.1/rott/winrott.c
   tags/rott-1.1/rott/z_zone.c
   tags/rott-1.1/rott/z_zone.h
   tags/rott-1.1/vs.net/
   tags/rott-1.1/vs.net/rott.vcproj
Log:
Tagging 1.1 release.


Added: tags/rott-1.1/COPYING
===================================================================
--- tags/rott-1.1/COPYING	                        (rev 0)
+++ tags/rott-1.1/COPYING	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,342 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+

Added: tags/rott-1.1/README
===================================================================
--- tags/rott-1.1/README	                        (rev 0)
+++ tags/rott-1.1/README	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,101 @@
+================
+ROTT Port README
+================
+
+This is a port of Apogee's 3D action title Rise of the Triad, originally
+released in 1994.  This port duplicates the functionality of the original
+game on modern operating systems, including Linux, Win32, and Mac OS X.
+
+This port makes use of the Simple Direct Media Layer, or SDL, and an additional
+library named SDL_mixer.  If you do not have these libraries installed, check
+the links section below.
+
+This software is distributed in source code format and is licensed under the
+terms of the GNU General Public License.  A copy of this license is included
+with the software in the file COPYING.
+
+This software is not supported by 3D Realms, Apogee, or the porters.
+
+For reference, the primary contributors to this port are:
+
+Steven Fuller
+Ryan C. Gordon
+John Hall
+Dan Olson
+
+
+-------------------------
+Notes for the 1.1 Release
+-------------------------
+
+Thanks to the effort of the contributors listed below (and probably many more),
+lots of bug fixes, portability improvements and new features have found their
+way into the 1.1 release. Many changes have been ported over from the WinRott
+port (not WinRottGL but plain WinRott) with the high resolution software
+rendering support being the main feature of all these changes. Portability
+fixes include support for 64-bit and big-endian systems.
+
+Birger N. Andreasen (author of the WinRott port
+  <http://home14.inet.tele.dk/Bna-Info/>, initial work by Jonathan Bailey)
+Hans de Goede (porting of the WinRott high resolution renderer,
+  lots of bug and portability fixes for the Fedora package)
+Alexander Thomas aka Dr. Lex (author of the OS X port
+  <http://www.dr-lex.be/software/rott.html>, thanks Filippo Giunchedi for
+  creating the appropriate patch for the Debian package)
+Michael Karcher (lots of bug and portability fixes for the Debian package)
+Fabian Greffrath (some minor improvements)
+
+Getting network play working is considered the release goal for the 2.0
+version.
+
+
+-------------
+General Hints
+-------------
+
+To compile the source code under Linux, change to the rott/ directory and type:
+
+make clean
+make
+
+The source code is setup to use shareware binaries.  If you want to use the
+registered version of ROTT, edit rott/develop.h and make the following changes:
+
+change
+#define SHAREWARE   1
+#define SUPERROTT   0
+to
+#define SHAREWARE   0
+#define SUPERROTT   1
+
+After this, save your changes and compile as normal.
+
+If you experience difficulty with sound, you may need to download a CVS version
+of SDL_mixer.  Instructions for doing this can be found at the SDL_mixer site,
+linked below.
+
+
+------------
+Known Issues
+------------
+
+- Demos go out of sync.
+- No netplay support.
+
+
+-------------
+Helpful Links
+-------------
+
+ROTT Port site:
+http://icculus.org/rott/
+
+The Simple Direct Media Layer:
+http://www.libsdl.org/
+
+SDL_mixer:
+http://www.libsdl.org/projects/SDL_mixer
+
+3D Realms official forum on ROTT source code:
+http://forums.3drealms.com/ubb/ultimatebb.php?ubb=forum;f=24
+

Added: tags/rott-1.1/doc/13todo.txt
===================================================================
--- tags/rott-1.1/doc/13todo.txt	                        (rev 0)
+++ tags/rott-1.1/doc/13todo.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,35 @@
+( ) NME does not always exit level upon killing him
+( ) Game locks when firing Darkstaff or Dog Mode at El Oscuro
+( ) Network server locks up when exiting net game
+( ) Stand( )alone server doesn't work consistently
+( ) Break out with error message if ROTT is run with no sound.rot
+( ) Quickload question should have (Y/N) on end
+( ) Phone number length needs to be lengthed.
+( ) Network packets need checksum word added to their packets
+( ) VR gear new mouse sub functions
+( ) Dog mode still locks up as well as some bat blast stuff
+( ) Fix Live Remote Ridicule
+( ) Wall can push you into platform so you fall down inside of it and be
+    stuck.
+( ) Hanging at menu after a few network/modem games
+( ) Hanging at warp menu prompt
+( ) Warp Menu: chose level, screen went black, some how still in level select
+( ) Unexpect Interrupt
+( ) Generat random levels and battle levels.  Choose alternate both.
+    New game End Game New Game Kaboom
+( ) Make snake heads hurt to touch (fixes snake trapping you)
+( ) Fix missiles not hitting enemy when standing face to face
+( ) lockup on snake with one head left
+( ) gamepad enabled before joystick enabled
+( ) bark blast under dog walls and stuff
+( ) config files saved in alternat RTS directory
+( ) people complaining about reconfiging joystick each time
+( ) Panic mapping over modem glass in 8 megs not in 4 megs
+( ) Voice credit for OverPatrol (CHuck) Lightning guard (william)
+
+MAP Stuff
+( ) level 1( )3 in random powerup crossroads room, two different wall types
+( ) Krist, if led outside of room, goes up disks, but can't go down them.
+  So he winds up running around sky.  Fix map to lock door so Krist cannot
+  come out...
+

Added: tags/rott-1.1/doc/cheats.txt
===================================================================
--- tags/rott-1.1/doc/cheats.txt	                        (rev 0)
+++ tags/rott-1.1/doc/cheats.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,106 @@
+  DISPSTICK                // enable cheats
+  \ECC                     // enable cheats
+  SLACKER                  // three keys, more health
+  \BUM                     // three keys, more health
+  CHOJIN                   // normal god mode
+  \WWW                     // normal god mode
+  GOTO                     // warp
+  \GTL                     // warp
+  SIXTOYS                  // all keys, armor, 100% health
+  \GAI                     // all keys, armor, 100% health
+  TOOSAD                   // god mode powerup
+  \GOD                     // god mode powerup
+
+  // Register only
+  WOOF                     // dog mode powerup
+  \DOG                     // dog mode powerup
+  // end
+
+  FLYBOY                   // mercury mode powerup
+  \MER                     // mercury mode powerup
+  BADTRIP                  // shrooms mode powerup
+  \SHR                     // shrooms mode powerup
+  BOING                    // elasto mode powerup
+  \ELA                     // elasto mode powerup
+  GOOBERS                  // warp to level 1, start with pistol
+  \GOO                     // warp to level 1, start with pistol
+  WHACK                    // hurt player 10%
+  \OOF                     // hurt player 10%
+  SPEED                    // run fast all the time
+  \RFA                     // run fast all the time
+  PANIC                    // back to normal
+  \PAN                     // back to normal
+  DIMON                    // light diminishing on
+  \DON                     // light diminishing on
+  DIMOFF                   // light diminishing off
+  \DOF                     // light diminishing off
+  LONDON                   // fog on (0x00 - 0x80 minmax)
+  \FON                     // fog on (0x00 - 0x80 minmax)
+  NODNOL                   // fog off (0x80 - 0xFF minmax)
+  \FOF                     // fog off (0x80 - 0xFF minmax)
+  GOGATES                  // blow out of game
+  \L8R                     // blow out of game
+  GOARCH                   // end the current level
+  \ECL                     // end the current level
+  GOTA386                  // floor and ceiling off
+  \CON                     // floor and ceiling off
+  GOTA486                  // floor and ceiling on
+  \COF                     // floor and ceiling on
+  SHOOTME                  // bullet proof armor
+  \BAR                     // bullet proof armor
+  BURNME                   // fire proof armor
+  \FAR                     // fire proof armor
+  LUNGDUNG                 // gas mask
+  \GAR                     // gas mask
+  HUNTPACK                 // all keys, armor, 100% health, MP40,
+  \OFP                     // all keys, armor, 100% health, MP40,
+  86ME                     // kill player
+  \DIE                     // kill player
+  NEER                     // re-enter level
+  \REL                     // re-enter level
+  JOHNWOO                  // give double pistol
+  \GW2                     // give double pistol
+  PLUGME                   // give mp40
+  \GW3                     // give mp40
+  VANILLA                  // give bazooka
+  \GW4                     // give bazooka
+  HOTTIMES                 // give heatseeker
+  \GW5                     // give heatseeker
+  BOOZE                    // give drunk missile
+  \GW6                     // give drunk missile
+  FIREBOMB                 // give firebomb
+  \GW7                     // give firebomb
+  BONES                    // give firewall
+  \GW8                     // give firewall
+  SEEYA                    // give god hand
+  \GW9                     // give god hand
+
+  // Register Only
+  SPLIT                    // give split missile
+  \GWA                     // give split missile
+  KESOFDEATH               // give kes
+  \GWB                     // give kes
+  HOMERUN                  // give bat
+  \GWC                     // give bat
+  CUJO                     // give dog weapon
+  \GWD                     // give dog weapon
+  // end
+
+  RIDE                     // give MISSILE CAM
+  \CAM                     // give Missile Cam
+  WHERE                    // turn where am i on/off
+  \HUD                     // give hud
+  \FUN                     // Rotation fun
+  RECORD                   // Demo RECORD
+  STOP                     // Demo stop recording
+  PLAY                     // Demo Playback
+  \EKG                     // Engine Killing Gibs
+  MAESTRO                  // JukeBox
+  \LEE                     // JukeBox
+  CARTIER                  // Map Cheat
+  \MAP                     // Map Cheat
+  \YOU                     // Secret Message
+  HAVE                     // Secret Message
+  \NO                      // Secret Message
+  LIFE                     // Secret Message
+

Added: tags/rott-1.1/doc/cmdline.txt
===================================================================
--- tags/rott-1.1/doc/cmdline.txt	                        (rev 0)
+++ tags/rott-1.1/doc/cmdline.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,75 @@
+
+ROTT.EXE
+========
+
+NOWAIT       go to menu, skip intro
+NOSOUND      no music no sound
+NOW          go immediately into game default difficulty default level 1
+DOPEFISH     Scott Head intro, random sounds in credits, burping while
+             caching, silly strings, eluder/deluder as scott's head,
+             silly death cam, silly menu sounds
+
+MAPSTATS     Print out map statistics to MAPDEBUG.TXT
+TILESTATS    Print out tile statistics to MAPDEBUG.TXT
+VER          Rott version number
+PAUSE        Pause after printing startup info
+SOUNDSETUP   Launch sound Setup WARP [level] Launch to any level (1 based)
+LEVELSIZE    compute memory needed for level
+SLOWDEATH    slow down death rotation
+QUIET        get rid of all start up text except for errors
+FILE
+FILE1        add external wads for graphic replacement
+FILE2
+NOJOYS       disable joystick test
+NOMOUSE      disable mouse test
+SPACEBALL    enable spaceball avenger
+CYBERMAN     enable cyberman
+ASSASSIN     enable wingman assassin
+NOECHO       turn off reverb effect
+DEMOEXIT     exit the game when demo is interrupted
+TIMELIMIT    play for a certain amount of time in seconds
+             once time is gone game ends (unlimited lives)
+             get more time by killing guards and picking up ankhs
+             must use MAXTIMELIMIT as well
+MAXTIMELIMIT the max time to count down from so if you keep killing
+             guards you cannot get an infinite amount of time
+             must use TIMELIMIT as well
+ENABLEVR     enable Virtual Reality support for HMD's (Head mounted disp)
+WARP         warp to a specific level 1 based level 1 is 1
+NET          Used by ROTTSER and ROTTIPX
+IS8250       Used by ROTTSER whether you have an 8250 or not
+TEDLEVEL     Ted stuff
+(DEV ONLY) MONO         enable mono-monitor support (Development only)
+(DEV ONLY) TRANSPORT    Warp to any x,y,angle in level (Development only)
+(DEV ONLY) SCREENSHOTS  get rid of screen title stuff (Development only)
+
+
+ROTTSER.EXE
+========
+
+VECTOR       interrupt vector with which to communicate with ROTT
+ANSWER       answer mode
+DIAL         dial mode
+PAUSE        pause before launching
+STATS        print out run time stats after ROTT returns
+PLAYER       0 - makes you the master
+             1 - makes you not the master
+             must be used on both systems with different values, to work
+             properly
+
+
+ROTTIPX.EXE
+========
+
+VECTOR       interrupt vector with which to communicate with ROTT
+PAUSE        pause before launching
+NODES        number of players in game
+SOCKET       network socket to use
+SERVER       specify this computer to be a server
+STANDALONE   specify this server to be standalone
+             else client on top of server
+MASTER       used by client to make yourself the master
+REMOTERIDICULE turn on remote ridicule support
+
+
+

Added: tags/rott-1.1/doc/hacker.txt
===================================================================
--- tags/rott-1.1/doc/hacker.txt	                        (rev 0)
+++ tags/rott-1.1/doc/hacker.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,508 @@
+
+                              Rise of the Triad
+
+                                 Version 1.1
+
+                                 Hacker Info
+
+RTL & RTC File format:
+----------------------
+
+Rise of the Triad (ROTT) uses two file extensions for levels data, RTL
+and RTC.  RTC indicates that the file is for Comm-bat (multiplayer) play
+only and does not contain any enemies or exits.  RTL indicates the file
+can can be used for both Comm-bat and standard game levels.  In Comm-bat,
+the enemies in RTL maps in standard play are not present during Comm-bat
+games and the exit and entrance arches behave like teleporters.  Other than
+these differences, the two files are alike.
+
+The RTL/RTC file format changed with the release of ROTT version 1.1.
+Since the shareware version of ROTT cannot use alternate levels, this
+should not be a problem for map designers.  The new format is much more
+formal.  If any changes are made in the format in the future,  the first 8
+bytes of the file will inform you if it is compatible with your editor/viewer.
+
+The RTL/RTC file is broken into three sections:  Version info, Header block,
+and Data block.
+
+
+                            RTL/RTC version info
+
+This 8 byte block of data indicates what type of file it is and which
+version of the RTL/RTC file format it is.
+
+  Offset   Size    Description
+-------------------------------------------------------------
+    0        4     Format signature
+    4        4     Version number
+
+Format signature :
+
+This is used to indicate what type of levels are contained within the
+file.  This is a null-terminated string containing either "RTL" or "RTC".
+
+Version number :
+
+0101h for version 1.1.  If this value is higher, it indicates that the file
+format has changed.  This is NOT the ROTT version.
+
+
+                            RTL/RTC Header block
+
+The header block contains an array of 100 structures with the following
+format:
+
+  Offset   Size    Explanation
+-------------------------------------------------------------
+    0        4     Used flag
+    4        4     CRC
+    8        4     RLEWtag
+   12        4     MapSpecials
+   12        4     Offset in file of Wall plane
+   16        4     Offset in file of Sprite plane
+   20        4     Offset in file of Info plane
+   24        4     Length of Wall plane
+   28        4     Length of Sprite plane
+   32        4     Length of Info plane
+   36       24     Name of level
+
+
+Used flag :
+
+This is non-zero if a map exists at this position.
+
+CRC :
+
+This value is used to determine if all the players in a multiplayer game
+are using the same maps.  You can use any method you like to calculate this
+value.
+
+RLEWtag :
+
+This is the run-length encoding tag used for compressing and decompressing
+the map data.  The use of this will be described below.
+
+MapSpecials :
+
+This is used for flags that describe special conditions for the level.
+Currently only one flag is used.  If Bit 0 is set, then all the pushwalls
+will be activated in Comm-bat mode.  This is done in case there are player
+start locations within hidden areas and the player would be trapped until
+a pushwall was activated.
+
+Offsets :
+
+The Wall, Sprite, and Info plane offsets are each absolute offsets of the
+data from the beginning of the file.
+
+Lengths :
+
+The Wall, Sprite, and Info plane lengths are each lengths of the
+uncompressed data.
+
+Name of level :
+
+This is a null-terminated string containing the name of the level.
+Although there is 24 bytes available, level names should be at most 22
+bytes long.
+
+                             RTL/RTC Data block
+
+When expanded, ROTT maps contain 3 planes of 128 by 128 word sized data.
+They are stored in the RTL/RTC files as 3 blocks of run-length encoded
+data.  The procedure for decompressing them is as follows:
+
+    1) Allocate 128 * 128 words of memory (32768 bytes)
+    2) Read one word from compressed block
+    3) If word is equal to RLEWTag, then the next two words are a compressed
+       run of data.  The first word is the number of words to write.
+       The second word is the value to write map.
+       If word was not equal to RLEWTag, then simply write that word
+       to the map.
+    4) Go back to 2 until all data is written.
+
+Here's an example of the procedure in C.
+
+
+/*---------------------------------------------------------------------
+   Function: RLEW_Expand
+
+   Run-length encoded word decompression.
+---------------------------------------------------------------------*/
+
+void RLEW_Expand
+   (
+   unsigned short *source,
+   unsigned short *dest,
+   long length,
+   unsigned short rlewtag
+   )
+
+   {
+   unsigned short value;
+   unsigned short count;
+   unsigned short *end;
+
+   end = dest + length;
+
+   while( dest < end );
+      {
+      value = *source;
+      source++;
+
+      if ( value != rlewtag )
+         {
+         //
+         // uncompressed data
+         //
+         *dest = value;
+         dest++;
+         }
+      else
+         {
+         //
+         // compressed string
+         //
+         count = *source;
+         source++;
+
+         value = *source;
+         source++;
+
+         //
+         // expand the data
+         //
+         while( count > 0 )
+            {
+            *dest = value;
+            dest++;
+            count--;
+            }
+         }
+      }
+   }
+
+
+Here is sample code for loading a ROTT map.
+
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <io.h>
+
+/*---------------------------------------------------------------------
+   Map constants
+---------------------------------------------------------------------*/
+
+#define MAXLEVELNAMELENGTH           23
+#define ALLOCATEDLEVELNAMELENGTH     24
+#define NUMPLANES                    3
+#define NUMHEADEROFFSETS             100
+#define MAPWIDTH                     128
+#define MAPHEIGHT                    128
+#define MAP_SPECIAL_TOGGLE_PUSHWALLS 0x0001
+
+#define WALL_PLANE    0
+#define SPRITE_PLANE  1
+#define INFO_PLANE    2
+
+/*---------------------------------------------------------------------
+   Type definitions
+---------------------------------------------------------------------*/
+
+typedef struct
+   {
+   unsigned long used;
+   unsigned long CRC;
+   unsigned long RLEWtag;
+   unsigned long MapSpecials;
+   unsigned long planestart[ NUMPLANES ];
+   unsigned long planelength[ NUMPLANES ];
+   char          Name[ ALLOCATEDLEVELNAMELENGTH ];
+   } RTLMAP;
+
+
+/*---------------------------------------------------------------------
+   Global variables
+---------------------------------------------------------------------*/
+
+unsigned short *mapplanes[ NUMPLANES ];
+
+
+/*---------------------------------------------------------------------
+   Macros
+---------------------------------------------------------------------*/
+
+#define MAPSPOT( x, y, plane ) \
+   ( mapplanes[ plane ][ MAPWIDTH * ( y ) + ( x ) ] )
+
+#define WALL_AT( x, y )   ( MAPSPOT( ( x ), ( y ), WALL_PLANE ) )
+#define SPRITE_AT( x, y ) ( MAPSPOT( ( x ), ( y ), SPRITE_PLANE ) )
+#define INFO_AT( x, y )   ( MAPSPOT( ( x ), ( y ), INFO_PLANE ) )
+
+
+/*---------------------------------------------------------------------
+   Function: ReadROTTMap
+
+   Read a map from a RTL/RTC file.
+---------------------------------------------------------------------*/
+
+void ReadROTTMap
+   (
+   char *filename,
+   int mapnum
+   )
+
+   {
+   char            RTLSignature[ 4 ];
+   unsigned long   RTLVersion;
+   RTLMAP          RTLMap;
+   int             filehandle;
+   long            pos;
+   long            compressed;
+   long            expanded;
+   int             plane;
+   unsigned short *buffer;
+
+   filehandle = open( filename, O_RDONLY | O_BINARY );
+
+   //
+   // Load RTL signature
+   //
+   read( filehandle, RTLSignature, sizeof( RTLSignature ) );
+
+   //
+   // Read the version number
+   //
+   read( filehandle, &RTLVersion, sizeof( RTLVersion ) );
+
+   //
+   // Load map header
+   //
+   lseek( filehandle, mapnum * sizeof( RTLMap ), SEEK_CUR );
+   read( filehandle, &RTLMap, sizeof( RTLMap ) );
+
+   if ( !RTLMap.used )
+      {
+      //
+      // Exit on error
+      //
+      printf( "ReadROTTMap: Tried to load a non existent map!" );
+      exit( 1 );
+      }
+
+   //
+   // load the planes in
+   //
+   expanded = MAPWIDTH * MAPHEIGHT * 2;
+
+	for( plane = 0; plane <= 2; plane++ )
+      {
+      pos        = RTLMap.planestart[ plane ];
+      compressed = RTLMap.planelength[ plane ];
+      buffer     = malloc( compressed );
+
+      lseek( filehandle, pos, SEEK_SET );
+      read( filehandle, buffer, compressed );
+
+      mapplanes[ plane ] = malloc( expanded );
+
+      RLEW_Expand( buffer, mapplanes[ plane ], expanded >> 1, RTLMap.RLEWtag );
+
+      free( buffer );
+      }
+
+   close( filehandle );
+   }
+
+
+MAP WEIRDNESS
+-------------
+You can pretty much figure out most of the map data easily, but there are
+a few things in the map which are a little oddly set up.  Here's a few
+helpful items.
+
+
+THE UPPER CORNER
+The first row of a map contains vital information to setting up a map.
+
+In the first plane (WALLS) are these values:
+
+0,0   FLOOR # (0xB4 through 0xC3, though we might cut some)
+1,0   CEILING # (0xC6 through 0xD5, or skies: 0xEA to 0xEE)
+2,0   BRIGHTNESS LEVEL (0xD8 to 0xDF, from dark to light)
+3,0   RATE AT WHICH LIGHT FADES OUT WITH DISTANCE
+        (0xFC to 0x010B, fast to slow)
+
+In the second plane (SPRITES) are these:
+
+0,0   Height of level
+	(1-8 ranges from 0x5A to 0x61, 9-16 is from 0x01C2 to 0x01C9)
+1,0   Height that sky is at relative to level (with same 1-16 arrangement)
+        (not needed for level with a ceiling)
+2,0   Icon for NO FOG (0x68) or FOG (0x69)
+3,0   Light sourcing icon (0x8B: if present, lights illuminate walls)
+
+Optional items in the upper corner are:
+
+Second Plane
+	Lightning icon (0x0179)
+	Timer icon (0x79: third plane points 0xXXYY to X,Y location of
+	  timed thing--time in minutes/seconds there is MMSS in decimal
+	  digits, so 0130 is 1 minute thirty seconds--and to one side of
+	  that timed thing is the end time in the same format. This, for
+	  instance, would say when to shut the door that opened at the
+	  start time)
+
+Third Plane (INFO)
+	Song number: 0xBAnn, where nn is song number.  If not present,
+	 the game will choose song 0.  If greater than the number of
+	 level songs (18 in shareware), the game will blow out.
+
+
+DISKS
+Gravitational Anomaly Disks (GADS) are set up with a GAD icon in the
+second plane and a height in the third plane.  The actual graphic has a
+disk in the top quarter, so to put one on the floor, you sort of have to
+put the object IN the floor, so the disk will be at the right height.
+Heights for objects start with 0xB0 and have that last byte as a
+tiles-off-the-floor nybble and sixteenths-of-a-tile fraction.
+
+So 0xB000 is, for normal sprites, resting on the floor.
+
+For disks, that would be a disk you could stand on to be one story
+(eight feet) in the air. The heights of disks usually go by sixes (that's
+the maximum they can be apart and you can still climb them like stairs) or
+fours (for a more gradual ascension).  Here are three sets of height
+values.  The values of 0xB0F1-$B0FE are into the floor, and $B0F6 is right
+about floor height.
+
+by 6     by 4     by 2
+B0F6     B0F6     B0F6
+B0FC     B0FA     B0F8
+B002     B0FE     B0FA
+B008     B002     B0FC
+B00E     B006     B0FE
+B014     B00A     B010
+B01A     B00E     B012
+B020     B012     B014
+B026     B016     ...
+B02C     B01A
+B032     B01E
+B038     B022
+B03E     B026
+B044     B02A
+B04A     B02E
+B050     B032
+B056     B036
+B05C     B03A
+B062     B03E
+B068     B042
+B06E     B046
+B074     B04A
+B07A     B04E
+
+If you need higher ones, calculate them yourself, man.
+
+
+SWITCHES AND TOUCHPLATES
+
+Everything activated by a switch or touchplates points to the switch or
+touchplate that activates it, with the standard 0xXXYY format.  This way
+tons of things can be activated by one switch.  To make a door open with
+multiple switches/touchplates, make it a few tiles wide and have different
+parts of the door point to the different switches.
+
+LOCKED DOORS
+Locked doors are normal doors with a key sprite icon placed on them.
+
+
+============================================================================
+
+The ROTT WAD Format
+-------------------
+
+        Most of you out there are probably very familiar with the WAD file
+format developed by Id Software.  We borrowed the format with their
+consent and use it for all the data in Rise of the Triad.
+
+        The WAD structure itself is identical to that of other WAD's,
+where the WAD header is as follows:
+
+typedef struct
+{
+	char	identification[4];
+	long	numlumps;
+	long	infotableofs;
+} wadinfo_t;
+
+and the WAD directory is made up of [numlumps] of:
+
+typedef struct
+{
+	long		filepos;
+	long		size;
+	char		name[8];
+} lumpinfo_t;
+
+
+ROTT Specific Data
+------------------
+
+WALLS - Walls are stored in the WAD between the two labels "WALLSTRT" and
+"WALLSTOP".  The format of each wall is a 4,096 block of data with no
+header.  The bitmaps are grabbed in vertical posts so that drawing in
+modex is more straight format.  All walls must be 64 x 64. The walls must
+be the first few lumps in the WAD.
+
+MASKED OBJECTS - Masked objects in the wad comprise all actors and
+sprites.  They can be found as weapons, objects, actors etc.  They use the
+following headers and structures:
+
+typedef struct
+{
+   short          origsize;         // the orig size of "grabbed" gfx
+   short          width;            // bounding box size
+   short          height;
+   short          leftoffset;       // pixels to the left of origin
+   short          topoffset;        // pixels above the origin
+   unsigned short collumnofs[320];  // only [width] used, the [0] is &collumnofs[width]
+} patch_t;
+
+These are extremely similar to the patches used in another game, except
+for the addition of the origsize parameter.
+
+typedef struct
+{
+   short origsize;         // the orig size of "grabbed" gfx
+   short width;            // bounding box size
+   short height;
+   short leftoffset;       // pixels to the left of origin
+   short topoffset;        // pixels above the origin
+   short translevel;
+   short collumnofs[320];  // only [width] used, the [0] is &collumnofs[width]
+} transpatch_t;
+
+Certain objects in the game like masked walls and touch plates will use
+the second type of patch which acts like a translucent patch.
+
+SKYS, FLOORS and CEILINGS - Skys are larger than the screen and are made
+up of two 256X200 grabs in posts similar to the walls.  The first grab
+represents the bottom part of the sky and the second part the top of the
+sky.  The skys are denoted by the labels SKYSTRT and SKYSTOP.  Floors and
+ceilings use the following structure:
+
+typedef struct
+{
+   short     width,height;
+   short     orgx,orgy;
+   byte     data;
+} lpic_t;
+
+They can be found between the labels UPDNSTRT and UPDNSTOP.
+
+
+Okay, enough hints!  Have fun figuring stuff out.
+
+--THE DEVELOPERS OF INCREDIBLE POWER

Added: tags/rott-1.1/doc/readme.txt
===================================================================
--- tags/rott-1.1/doc/readme.txt	                        (rev 0)
+++ tags/rott-1.1/doc/readme.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,86 @@
+Rise of the Triad (v1.3 CD Version) Source Code Release - December 20, 2002.
+(If you can't read this right in your editor, turn on word wrap)
+
+Please note that this is being released without any kind of support from Apogee Software, Ltd / 3D Realms Entertainment.  We cannot and will not help in getting this running.  We do not guarantee that you will be able to get it to work, nor do we guarantee that it won't blow up your computer if you do try and use it.  Caveat Emptor - Use at your own risk.  Having said that, this source code release was compiled on December 7, 2002 using the materials in this archive.  Here's a note from one of the original ROTT programmers (Jim Dose) as to what will be needed to get this compiled:
+
+------
+
+You will need Watcom C v10.0b, which is what was used to compile the game originally.  This source code release was tested with that version.  Other versions are not guaranteed to work.  Later versions such as v11.0 are known to most likely not work because of changes in the way data types are handled.
+
+You also need Borland's Turbo Assembler (TASM), but it is not required to build the full game if you use the .obj files that are already included.  To do a full rebuild of the C code without having TASM, delete all the .obj files except for the following files:
+
+F_SCALE.OBJ
+RT_DR_A.OBJ
+RT_FC_A.OBJ
+RT_SC_A.OBJ
+RT_VH_A.OBJ
+
+To compile ROTT, type "wmake all".  To compile the audio library, run "wmake.bat".
+
+(You'll also need a registered CD version of Rise of the Triad, too.)
+
+-----
+
+Please note that while we are releasing the source code to Rise of the Triad, the game itself has not been released in the same manner (in other words, Rise of the Triad is still commercial software).  You can still buy the game from us by visiting http://www.3drealms.com.
+
+Thanks to all the fans who have hung in there and waited for us to do something like this, we hope you enjoy it.  If you produce something cool with this source code, drop us a line at rott at 3drealms.com.   In honor of the source code release, we contacted Tom Hall to reminicse a bit about the game, and we have some history from Scott Miller, President of Apogee. Their thoughts are below.
+
+Furthermore, the release of the Rise of the Triad source code is dedicated to our late friend and cohort, William Scarboro.  William was one of the original Rise of the Triad programmers, and he unfortunately died of an asthma attack on August 9, 2002.
+
+William was born March 2, 1971 in El Paso, TX. He was a graduate of Texas A&M with a degree in Computer Science. He came to work here back in 1993, and was the first programmer we hired back then when we started doing in house development. He was mainly known for his work on Rise of the Triad where he worked on actor code, weapon stuff, and the gibs. In fact, William was directly responsible for the /EKG gib cheat in ROTT.
+
+Joe Siegler
+Apogee Software / 3D Realms
+Dec 20, 2002
+
+==============================================================================================
+
+RISE OF THE TRIAD: The Source Code Release
+A Note from Tom Hall
+
+It was 1992.  I had just worked through half of DOOM, a creative guy in a technologically-oriented company.  We parted ways and I left to start up "In-House Development" at Apogee (later 3D Realms). We started accruing a programmer here, and artist there. Soon we had a team.  I came in with a memo about something (like bonus dough for library functions or something), and at the end I said something like, "And once we complete all these, we will be... THE DEVELOPERS OF INCREDIBLE POWER!" The guys laughed and liked this a lot.  And thus we became the DIPs. :)
+
+With a game called ROTT, and a bunch of DIPs, you're heading for some derision. :) We had a fairly inexperienced crew: me, inexperienced at management; the rest of the guys, fairly new to the industry. It started as WOLFENSTEIN 3D, Part 2 -- a "transition project" my heart wasn't in, really.  It wasn't my idea to do it, but it was something to do. Once we parted ways with that idea and id's involvement, things got rewritten, changed, and we came up with s-Quake functionality crammed into a Wolfenstein Plus/sub-DOOM engine.  It was an example of pushing a technology to do what it really can't do well.  We had a fun engine, but one that looked ugly, especially in the masked platforms -- they were paper thin!  You could have had a fun game without doing what it couldn't do... but we were trying to beat the Joneses. And once we split ways with the id thing, I made three bad decisions: a) to keep the art we had already, b) to not redesign a new game and c) not to move over to the Build engine, where we could have had a Duke/DOOM level game going decently quickly.
+
+Ah well. Hindsight's 20/20.  I am too nice, I guess. Yet, ROTT, for all its tortured technology, all its semi-justified graphics, did have some stuff that there was to be proud of. It was the first game with Rocket Jumping, the first game with Jumppads, the first game with parental password and Violence level adjustment, the first game with Capture the Flag...  Plus, I believe, the record for the most cheat codes ever in a game!  And a Random Level creator!  And what about all those cool Deathmatch options! And speaking of Deathmatch, I recall William's wonderful Corpseyard deathmatch map, and his "totally heinous" insane Drunk Missiles!  Mr. Scarboro, you, and your tuna, egg, salsa, and Omega 3 fatty acid bowls of goo will be missed.  Wah-bgsht! To Mark, Jim, Nolan, Steve, Tim, Chuck, Susan, JoeSke, Big Joe, Marianna, Lee, Bobby, Robert and all, thanks for sharing a strange time with me, and so many crazy memories!  "Uh, guys... um...."  The Disturbathon.  "50 kills!" "Ooooooooooh...  Mmmmmmm..."  Going to that crazy Bazaar to digitize old weapons.  "Check out what I got the boulders to do now."  "Ass!" "Use the fish." "Bowooooooooo!"  "I'm lookin' for some hot buns..."
+
+And on and on... And thanks to Scott and George, for providing a place for us to be crazy together, and sticking with it even though it wasn't blockbuster stuff. I do owe you a debt in what was an odd, disorienting time for me. In the end, a couple hundred thousand folks seem to have enjoyed it, so there was something there that they liked. "See, Charlie Brown?  It wasn't such a bad tree after all."
+
+======
+
+A little history...
+by Scott Miller
+
+ROTT, as it quickly became known, marked a turning point for Apogee.  It was our first in-house game since I started the company in 1987 with my home grown Kroz games, the games that started the shareware revolution that resulted in the launch of three of the most successful independent PC developers, Epic, Id, and us -- all three still kicking after 12+ years (as of Dec. '02).  It's hard to believe we're among the oldest of all surviving independent PC developers in the world now.  Before ROTT, Apogee, as we were then known, solely worked with outside development teams, often funding and helping organize these teams, and helping guide their game designs using our experience.  But around 1993 it was evident that this method wasn't going to work out much longer because as games got larger and more complicated to make, team sizes had to grow, too.  So, in 1994 we started hiring developers to form our own internal team, with the first of those hires including William Scarboro, Nolan Martin, Mark Dochtermann, Jim Dosé, and the ever creative Tom Hall to run the show.
+
+As Tom notes above, ROTT was originally an Id-approved sequel to Wolfenstein 3-D, using the original Wolf engine.  The game was going to be called, Wolfenstein: Rise of the Triad, and explore what happened after Hitler's demise.  About 4-5 months into development, though, a surprise call from John Romero ended the project, and we were left with a lot of content specific to the Wolfenstein premise, which had to be rolled into a new game concept so that we didn't waste all that we'd done.  The result was a bit of a mish-mash, and as Tom says above, the project probably should've been restarted using our new Build engine, which our second internal team down the hall was using, making Duke Nukem 3D.
+
+ROTT ended up selling several hundred thousand copies and making enough money to keep Duke 3D funded.  But it was at this time that we knew we  had to make a radical company change to shift with the times, and so we created the 3D Realms label, and began phasing out Apogee, which we were leaving behind with the glory days of shareware, and the arcade-style games Apogee was best known for.
+
+We get a lot of requests to release the source code to many of the older Apogee games, but the problem is that Apogee does not own these games that were developed by external teams.
+
+This source release is a long time coming, and hopefully it's not the last time we're able to do this.
+
+Scott Miller, CEO / Founder
+
+======
+
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/

Added: tags/rott-1.1/doc/rott.6
===================================================================
--- tags/rott-1.1/doc/rott.6	                        (rev 0)
+++ tags/rott-1.1/doc/rott.6	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,90 @@
+.TH ROTT 6 "2008-04-23" "1.0" "Rise of the Triad"
+
+.SH NAME
+rott \- Rise of the Triad
+
+.SH SYNOPSIS
+.B rott
+.RI [ options ]
+
+.SH DESCRIPTION
+.B ROTT
+is a port of Apogee's 3D action title Rise of the Triad, originally released in 1994.
+This port duplicates the functionality of the original game on modern operating systems, including Linux, Win32, and Mac OS X.
+
+.SH OPTIONS
+.TP
+.BR aim
+Give aim crosshair.
+.TP
+.BR fullscreen
+Start in fullscreen mode.
+.TP
+.BR window
+Start in windowed mode.
+.TP
+.BR resolution\  \fIwidth\fPx\fIheight\fP
+Specify the screen resolution to use (next parameter is widthxheight).
+Valid resolutions are 320x200, 640x480 and 800x600.
+.TP
+.BR spaceball
+Enable check for Spaceball.
+.TP
+.BR nojoys
+Disable check for joystick.
+.TP
+.BR nomouse
+Disable check for mouse.
+.TP
+.BR cyberman
+Enable check for Cyberman.
+.TP
+.BR assassin
+Enable check for Wingman Assassin.
+.TP
+.BR ver
+Version number.
+.TP
+.BR mapstats
+Dump Map statistics to ERROR.
+.TP
+.BR tilestats
+Dump Tile statistics to ERROR.
+.TP
+.BR mono
+Enable mono-monitor support.
+.TP
+.BR screenshots
+Clean screen capture for shots.
+.TP
+.BR pause
+Pauses startup screen information.
+.TP
+.BR enablevr
+Enable VR helmet input devices.
+.TP
+.BR noecho
+Turn off sound reverb.
+.TP
+.BR demoexit
+Exit program when demo is terminated.
+.TP
+.BR warp\  \fIlevel\fP
+Warp to specific ROTT level (next paramater is level to start on).
+.TP
+.BR timelimit\  \fItime\fP
+Play ROTT in time limit mode (next paramater is time in seconds).
+.TP
+.BR maxtimelimit\  \fItime\fP
+Maximimum time to count down from (next paramater is time in seconds).
+.TP
+.BR dopefish
+?
+
+.SH AUTHORS
+ROTT was created and published as shareware by Apogee Software, Ltd. and was published commercially by FormGen, Inc.
+.PP
+The primary contributors to the icculus.org port are: Steven Fuller, Ryan C. Gordon, John Hall and Dan Olson.
+.PP
+This manual page was written by Fabian Greffrath <fabian at debian-unofficial.org>
+for the Debian project (but may be used by others).

Added: tags/rott-1.1/doc/wad.txt
===================================================================
--- tags/rott-1.1/doc/wad.txt	                        (rev 0)
+++ tags/rott-1.1/doc/wad.txt	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,82 @@
+The ROTT WAD Format
+-------------------
+
+        Most of you out there are probably very familiar with the WAD file
+format developed by Id Software.  We borrowed the format with their
+consent and use it for all the data in Rise of the Triad.
+
+        The WAD structure itself is identical to that of other WAD's,
+where the WAD header is as follows:
+
+typedef struct
+{
+	char	identification[4];
+	long	numlumps;
+	long	infotableofs;
+} wadinfo_t;
+
+and the WAD directory is made up of [numlumps] of:
+
+typedef struct
+{
+	long		filepos;
+	long		size;
+	char		name[8];
+} lumpinfo_t;
+
+
+ROTT Specific Data
+------------------
+
+WALLS - Walls are stored in the WAD between the two labels "WALLSTRT" and
+"WALLSTOP".  The format of each wall is a 4,096 block of data with no
+header.  The bitmaps are grabbed in vertical posts so that drawing in
+modex is more straight format.  All walls must be 64 x 64. The walls must
+be the first few lumps in the WAD.
+
+MASKED OBJECTS - Masked objects in the wad comprise all actors and
+sprites.  They can be found as weapons, objects, actors etc.  They use the
+following headers and structures:
+
+typedef struct
+{
+   short          origsize;         // the orig size of "grabbed" gfx
+   short          width;            // bounding box size
+   short          height;
+   short          leftoffset;       // pixels to the left of origin
+   short          topoffset;        // pixels above the origin
+   unsigned short collumnofs[320];  // only [width] used, the [0] is &collumnofs[width]
+} patch_t;
+
+These are extremely similar to the patches used in another game, except
+for the addition of the origsize parameter.
+
+typedef struct
+{
+   short origsize;         // the orig size of "grabbed" gfx
+   short width;            // bounding box size
+   short height;
+   short leftoffset;       // pixels to the left of origin
+   short topoffset;        // pixels above the origin
+   short translevel;
+   short collumnofs[320];  // only [width] used, the [0] is &collumnofs[width]
+} transpatch_t;
+
+Certain objects in the game like masked walls and touch plates will use
+the second type of patch which acts like a translucent patch.
+
+SKYS, FLOORS and CEILINGS - Skys are larger than the screen and are made
+up of two 256X200 grabs in posts similar to the walls.  The first grab
+represents the bottom part of the sky and the second part the top of the
+sky.  The skys are denoted by the labels SKYSTRT and SKYSTOP.  Floors and
+ceilings use the following structure:
+
+typedef struct
+{
+   short     width,height;
+   short     orgx,orgy;
+   byte     data;
+} lpic_t;
+
+They can be found between the labels UPDNSTRT and UPDNSTOP.
+

Added: tags/rott-1.1/mac/English.lproj/InfoPlist.strings
===================================================================
(Binary files differ)


Property changes on: tags/rott-1.1/mac/English.lproj/InfoPlist.strings
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: tags/rott-1.1/mac/Rise of the Triad.pbproj/project.pbxproj
===================================================================
--- tags/rott-1.1/mac/Rise of the Triad.pbproj/project.pbxproj	                        (rev 0)
+++ tags/rott-1.1/mac/Rise of the Triad.pbproj/project.pbxproj	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1187 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 38;
+	objects = {
+		080E96DDFE201D6D7F000001 = {
+			children = (
+				F5A47A9D01A0482F01D3D55B,
+				F5A47A9E01A0483001D3D55B,
+			);
+			isa = PBXGroup;
+			name = Classes;
+			refType = 4;
+		};
+		089C165CFE840E0CC02AAC07 = {
+			children = (
+				089C165DFE840E0CC02AAC07,
+			);
+			isa = PBXVariantGroup;
+			name = InfoPlist.strings;
+			refType = 4;
+		};
+		089C165DFE840E0CC02AAC07 = {
+			fileEncoding = 10;
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/InfoPlist.strings;
+			refType = 4;
+		};
+		089C165EFE840E0CC02AAC07 = {
+			fileRef = 089C165CFE840E0CC02AAC07;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//080
+//081
+//082
+//083
+//084
+//100
+//101
+//102
+//103
+//104
+		1058C7A0FEA54F0111CA2CBB = {
+			children = (
+				1058C7A1FEA54F0111CA2CBB,
+			);
+			isa = PBXGroup;
+			name = "Linked Frameworks";
+			refType = 4;
+		};
+		1058C7A1FEA54F0111CA2CBB = {
+			isa = PBXFrameworkReference;
+			name = Cocoa.framework;
+			path = /System/Library/Frameworks/Cocoa.framework;
+			refType = 0;
+		};
+		1058C7A2FEA54F0111CA2CBB = {
+			children = (
+				29B97325FDCFA39411CA2CEA,
+				29B97324FDCFA39411CA2CEA,
+			);
+			isa = PBXGroup;
+			name = "Other Frameworks";
+			refType = 4;
+		};
+		1058C7A3FEA54F0111CA2CBB = {
+			fileRef = 1058C7A1FEA54F0111CA2CBB;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//100
+//101
+//102
+//103
+//104
+//170
+//171
+//172
+//173
+//174
+		17587328FF379C6511CA2CBB = {
+			isa = PBXApplicationReference;
+			path = "Rise of the Triad.app";
+			refType = 3;
+		};
+//170
+//171
+//172
+//173
+//174
+//190
+//191
+//192
+//193
+//194
+		19C28FACFE9D520D11CA2CBB = {
+			children = (
+				17587328FF379C6511CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Products;
+			refType = 4;
+		};
+//190
+//191
+//192
+//193
+//194
+//290
+//291
+//292
+//293
+//294
+		29B97313FDCFA39411CA2CEA = {
+			buildStyles = (
+				4A9504CCFFE6A4B311CA0CBA,
+				4A9504CDFFE6A4B311CA0CBA,
+			);
+			isa = PBXProject;
+			mainGroup = 29B97314FDCFA39411CA2CEA;
+			projectDirPath = "";
+			targets = (
+				29B97326FDCFA39411CA2CEA,
+			);
+		};
+		29B97314FDCFA39411CA2CEA = {
+			children = (
+				080E96DDFE201D6D7F000001,
+				29B97315FDCFA39411CA2CEA,
+				29B97317FDCFA39411CA2CEA,
+				29B97323FDCFA39411CA2CEA,
+				19C28FACFE9D520D11CA2CBB,
+				F5A3D67703BAB75001000002,
+				F5A3D67803BAB75001000002,
+				F5A3D67903BAB75001000002,
+				F5A3D67A03BAB75001000002,
+				F5A3D67B03BAB75001000002,
+				F5A3D67C03BAB75001000002,
+				F5A3D67D03BAB75001000002,
+				F5A3D67E03BAB75001000002,
+				F5A3D67F03BAB75001000002,
+				F5A3D68003BAB75001000002,
+				F5A3D68103BAB75001000002,
+				F5A3D68203BAB75001000002,
+			);
+			isa = PBXGroup;
+			name = "SDL App";
+			path = "";
+			refType = 4;
+		};
+		29B97315FDCFA39411CA2CEA = {
+			children = (
+				F5C71B7403B6FF1D01000002,
+				F5C71B7503B6FF1D01000002,
+				F5C71B7603B6FF1D01000002,
+				F5C71B7703B6FF1D01000002,
+				F5C71B7803B6FF1D01000002,
+				F5C71B7903B6FF1D01000002,
+				F5C71B7A03B6FF1D01000002,
+				F5C71B7D03B6FF1D01000002,
+				F5C71B7E03B6FF1D01000002,
+				F5C71B8003B6FF1D01000002,
+				F5C71B8103B6FF1D01000002,
+				F5C71B8203B6FF1D01000002,
+				F5C71B8303B6FF1D01000002,
+				F5C71B8403B6FF1D01000002,
+				F5C71B8503B6FF1D01000002,
+				F5C71B8603B6FF1D01000002,
+				F5C71B8703B6FF1D01000002,
+				F5C71B8803B6FF1D01000002,
+				F5C71B8903B6FF1D01000002,
+				F5C71B8A03B6FF1D01000002,
+				F5C71B8B03B6FF1D01000002,
+				F5C71B8E03B6FF1D01000002,
+				F5C71B8F03B6FF1D01000002,
+				F5C71B9003B6FF1D01000002,
+				F5C71B9103B6FF1D01000002,
+				F5C71B9203B6FF1D01000002,
+				F5C71B9303B6FF1D01000002,
+				F5C71B9403B6FF1D01000002,
+				F5C71B9503B6FF1D01000002,
+				F5C71B9603B6FF1D01000002,
+				F5C71B9703B6FF1D01000002,
+				F5C71B9803B6FF1D01000002,
+				F5C71B9A03B6FF1D01000002,
+				F5C71B9B03B6FF1D01000002,
+				F5C71B9C03B6FF1D01000002,
+				F5C71B9D03B6FF1D01000002,
+				F5C71B9E03B6FF1D01000002,
+				F5C71B9F03B6FF1D01000002,
+				F5C71BA003B6FF1D01000002,
+				F5C71BA103B6FF1D01000002,
+				F5C71BA303B6FF1D01000002,
+				F5C71BA503B6FF1D01000002,
+				F5C71BA603B6FF1D01000002,
+				F5C71BA803B6FF1D01000002,
+				F5C71BAB03B6FF1D01000002,
+				F5C71BAC03B6FF1D01000002,
+				F5C71BAD03B6FF1D01000002,
+				F5C71BF203B713D201000002,
+				F5C71BFF03B79CF301000002,
+			);
+			isa = PBXGroup;
+			name = "Other Sources";
+			path = "";
+			refType = 4;
+		};
+		29B97317FDCFA39411CA2CEA = {
+			children = (
+				089C165CFE840E0CC02AAC07,
+			);
+			isa = PBXGroup;
+			name = Resources;
+			path = "";
+			refType = 4;
+		};
+		29B97323FDCFA39411CA2CEA = {
+			children = (
+				1058C7A0FEA54F0111CA2CBB,
+				1058C7A2FEA54F0111CA2CBB,
+			);
+			isa = PBXGroup;
+			name = Frameworks;
+			path = "";
+			refType = 4;
+		};
+		29B97324FDCFA39411CA2CEA = {
+			isa = PBXFrameworkReference;
+			name = AppKit.framework;
+			path = /System/Library/Frameworks/AppKit.framework;
+			refType = 0;
+		};
+		29B97325FDCFA39411CA2CEA = {
+			isa = PBXFrameworkReference;
+			name = Foundation.framework;
+			path = /System/Library/Frameworks/Foundation.framework;
+			refType = 0;
+		};
+		29B97326FDCFA39411CA2CEA = {
+			buildPhases = (
+				29B97327FDCFA39411CA2CEA,
+				29B97328FDCFA39411CA2CEA,
+				29B9732BFDCFA39411CA2CEA,
+				29B9732DFDCFA39411CA2CEA,
+			);
+			buildSettings = {
+				FRAMEWORK_SEARCH_PATHS = "\"$(HOME)/Library/Frameworks\" /Users/overcode/Library/Frameworks";
+				HEADER_SEARCH_PATHS = "\"$(HOME)/Library/Frameworks/SDL.framework/Headers\" \"$(HOME)/Library/Frameworks/SDL_mixer.framework/Headers\"";
+				INSTALL_PATH = "$(HOME)/Applications";
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "-DUSE_SDL=1 -DPLATFORM_UNIX=1 -DPLATFORM_MACOSX=1 -DUSE_C_SQRT=1";
+				OTHER_LDFLAGS = "-framework SDL -framework SDL_mixer";
+				PRODUCT_NAME = "Rise of the Triad";
+				SECTORDER_FLAGS = "";
+				WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas -Wno-unused -Wno-switch";
+				WRAPPER_EXTENSION = app;
+			};
+			dependencies = (
+			);
+			isa = PBXApplicationTarget;
+			name = "Rise of the Triad";
+			productInstallPath = "$(HOME)/Applications";
+			productName = "SDL App";
+			productReference = 17587328FF379C6511CA2CBB;
+			productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>Rise of the Triad</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
+";
+			shouldUseHeadermap = 1;
+		};
+		29B97327FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F5A47AA101A0483001D3D55B,
+			);
+			isa = PBXHeadersBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B97328FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				089C165EFE840E0CC02AAC07,
+				F5A3D68303BAB75001000002,
+				F5A3D68403BAB75001000002,
+				F5A3D68503BAB75001000002,
+				F5A3D68603BAB75001000002,
+				F5A3D68703BAB75001000002,
+				F5A3D68803BAB75001000002,
+				F5A3D68903BAB75001000002,
+				F5A3D68A03BAB75001000002,
+				F5A3D68B03BAB75001000002,
+				F5A3D68C03BAB75001000002,
+				F5A3D68D03BAB75001000002,
+				F5A3D68E03BAB75001000002,
+			);
+			isa = PBXResourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732BFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F5A47AA301A0483001D3D55B,
+				F5C71BAE03B6FF1D01000002,
+				F5C71BAF03B6FF1D01000002,
+				F5C71BB003B6FF1D01000002,
+				F5C71BB103B6FF1D01000002,
+				F5C71BB203B6FF1D01000002,
+				F5C71BB303B6FF1D01000002,
+				F5C71BB403B6FF1D01000002,
+				F5C71BB703B6FF1D01000002,
+				F5C71BB803B6FF1D01000002,
+				F5C71BBA03B6FF1D01000002,
+				F5C71BBB03B6FF1D01000002,
+				F5C71BBC03B6FF1D01000002,
+				F5C71BBD03B6FF1D01000002,
+				F5C71BBE03B6FF1D01000002,
+				F5C71BBF03B6FF1D01000002,
+				F5C71BC003B6FF1D01000002,
+				F5C71BC103B6FF1D01000002,
+				F5C71BC203B6FF1D01000002,
+				F5C71BC303B6FF1D01000002,
+				F5C71BC403B6FF1D01000002,
+				F5C71BC503B6FF1D01000002,
+				F5C71BC803B6FF1D01000002,
+				F5C71BC903B6FF1D01000002,
+				F5C71BCA03B6FF1D01000002,
+				F5C71BCB03B6FF1D01000002,
+				F5C71BCC03B6FF1D01000002,
+				F5C71BCD03B6FF1D01000002,
+				F5C71BCE03B6FF1D01000002,
+				F5C71BCF03B6FF1D01000002,
+				F5C71BD003B6FF1D01000002,
+				F5C71BD103B6FF1D01000002,
+				F5C71BD203B6FF1D01000002,
+				F5C71BD403B6FF1D01000002,
+				F5C71BD503B6FF1D01000002,
+				F5C71BD603B6FF1D01000002,
+				F5C71BD703B6FF1D01000002,
+				F5C71BD803B6FF1D01000002,
+				F5C71BD903B6FF1D01000002,
+				F5C71BDA03B6FF1D01000002,
+				F5C71BDB03B6FF1D01000002,
+				F5C71BDD03B6FF1D01000002,
+				F5C71BDF03B6FF1D01000002,
+				F5C71BE003B6FF1D01000002,
+				F5C71BE203B6FF1D01000002,
+				F5C71BE503B6FF1D01000002,
+				F5C71BE603B6FF1D01000002,
+				F5C71BE703B6FF1D01000002,
+				F5C71BF303B713D201000002,
+				F5C71C0003B79CF301000002,
+			);
+			isa = PBXSourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732DFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				1058C7A3FEA54F0111CA2CBB,
+			);
+			isa = PBXFrameworksBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+//290
+//291
+//292
+//293
+//294
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+		4A9504CCFFE6A4B311CA0CBA = {
+			buildRules = (
+			);
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				OPTIMIZATION_CFLAGS = "-O0";
+			};
+			isa = PBXBuildStyle;
+			name = Development;
+		};
+		4A9504CDFFE6A4B311CA0CBA = {
+			buildRules = (
+			);
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				OPTIMIZATION_CFLAGS = "-O3";
+			};
+			isa = PBXBuildStyle;
+			name = Deployment;
+		};
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+//F50
+//F51
+//F52
+//F53
+//F54
+		F5A3D67703BAB75001000002 = {
+			isa = PBXFileReference;
+			name = DEMO1_3.DMO;
+			path = /Users/overcode/Code/rott/swdata/DEMO1_3.DMO;
+			refType = 0;
+		};
+		F5A3D67803BAB75001000002 = {
+			isa = PBXFileReference;
+			name = DEMO2_3.DMO;
+			path = /Users/overcode/Code/rott/swdata/DEMO2_3.DMO;
+			refType = 0;
+		};
+		F5A3D67903BAB75001000002 = {
+			isa = PBXFileReference;
+			name = DEMO3_3.DMO;
+			path = /Users/overcode/Code/rott/swdata/DEMO3_3.DMO;
+			refType = 0;
+		};
+		F5A3D67A03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = DEMO4_3.DMO;
+			path = /Users/overcode/Code/rott/swdata/DEMO4_3.DMO;
+			refType = 0;
+		};
+		F5A3D67B03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = HUNTBGIN.RTC;
+			path = /Users/overcode/Code/rott/swdata/HUNTBGIN.RTC;
+			refType = 0;
+		};
+		F5A3D67C03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = HUNTBGIN.RTL;
+			path = /Users/overcode/Code/rott/swdata/HUNTBGIN.RTL;
+			refType = 0;
+		};
+		F5A3D67D03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = HUNTBGIN.WAD;
+			path = /Users/overcode/Code/rott/swdata/HUNTBGIN.WAD;
+			refType = 0;
+		};
+		F5A3D67E03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = MODEM.PCK;
+			path = /Users/overcode/Code/rott/swdata/MODEM.PCK;
+			refType = 0;
+		};
+		F5A3D67F03BAB75001000002 = {
+			isa = PBXFileReference;
+			name = ORDER.FRM;
+			path = /Users/overcode/Code/rott/swdata/ORDER.FRM;
+			refType = 0;
+		};
+		F5A3D68003BAB75001000002 = {
+			isa = PBXFileReference;
+			name = README;
+			path = /Users/overcode/Code/rott/swdata/README;
+			refType = 0;
+		};
+		F5A3D68103BAB75001000002 = {
+			isa = PBXFileReference;
+			name = REMOTE1.RTS;
+			path = /Users/overcode/Code/rott/swdata/REMOTE1.RTS;
+			refType = 0;
+		};
+		F5A3D68203BAB75001000002 = {
+			isa = PBXFileReference;
+			name = VENDOR.DOC;
+			path = /Users/overcode/Code/rott/swdata/VENDOR.DOC;
+			refType = 0;
+		};
+		F5A3D68303BAB75001000002 = {
+			fileRef = F5A3D67703BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68403BAB75001000002 = {
+			fileRef = F5A3D67803BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68503BAB75001000002 = {
+			fileRef = F5A3D67903BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68603BAB75001000002 = {
+			fileRef = F5A3D67A03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68703BAB75001000002 = {
+			fileRef = F5A3D67B03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68803BAB75001000002 = {
+			fileRef = F5A3D67C03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68903BAB75001000002 = {
+			fileRef = F5A3D67D03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68A03BAB75001000002 = {
+			fileRef = F5A3D67E03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68B03BAB75001000002 = {
+			fileRef = F5A3D67F03BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68C03BAB75001000002 = {
+			fileRef = F5A3D68003BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68D03BAB75001000002 = {
+			fileRef = F5A3D68103BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A3D68E03BAB75001000002 = {
+			fileRef = F5A3D68203BAB75001000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A47A9D01A0482F01D3D55B = {
+			isa = PBXFileReference;
+			path = SDLMain.h;
+			refType = 2;
+		};
+		F5A47A9E01A0483001D3D55B = {
+			isa = PBXFileReference;
+			path = SDLMain.m;
+			refType = 2;
+		};
+		F5A47AA101A0483001D3D55B = {
+			fileRef = F5A47A9D01A0482F01D3D55B;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5A47AA301A0483001D3D55B = {
+			fileRef = F5A47A9E01A0483001D3D55B;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71B7403B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_actr.c;
+			path = /Users/overcode/Code/rott/rott/cin_actr.c;
+			refType = 0;
+		};
+		F5C71B7503B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_efct.c;
+			path = /Users/overcode/Code/rott/rott/cin_efct.c;
+			refType = 0;
+		};
+		F5C71B7603B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_evnt.c;
+			path = /Users/overcode/Code/rott/rott/cin_evnt.c;
+			refType = 0;
+		};
+		F5C71B7703B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_glob.c;
+			path = /Users/overcode/Code/rott/rott/cin_glob.c;
+			refType = 0;
+		};
+		F5C71B7803B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_main.c;
+			path = /Users/overcode/Code/rott/rott/cin_main.c;
+			refType = 0;
+		};
+		F5C71B7903B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = cin_util.c;
+			path = /Users/overcode/Code/rott/rott/cin_util.c;
+			refType = 0;
+		};
+		F5C71B7A03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = engine.c;
+			path = /Users/overcode/Code/rott/rott/engine.c;
+			refType = 0;
+		};
+		F5C71B7D03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = fx_man.c;
+			path = /Users/overcode/Code/rott/rott/fx_man.c;
+			refType = 0;
+		};
+		F5C71B7E03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = isr.c;
+			path = /Users/overcode/Code/rott/rott/isr.c;
+			refType = 0;
+		};
+		F5C71B8003B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = modexlib.c;
+			path = /Users/overcode/Code/rott/rott/modexlib.c;
+			refType = 0;
+		};
+		F5C71B8103B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_actor.c;
+			path = /Users/overcode/Code/rott/rott/rt_actor.c;
+			refType = 0;
+		};
+		F5C71B8203B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_battl.c;
+			path = /Users/overcode/Code/rott/rott/rt_battl.c;
+			refType = 0;
+		};
+		F5C71B8303B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_build.c;
+			path = /Users/overcode/Code/rott/rott/rt_build.c;
+			refType = 0;
+		};
+		F5C71B8403B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_cfg.c;
+			path = /Users/overcode/Code/rott/rott/rt_cfg.c;
+			refType = 0;
+		};
+		F5C71B8503B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_com.c;
+			path = /Users/overcode/Code/rott/rott/rt_com.c;
+			refType = 0;
+		};
+		F5C71B8603B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_crc.c;
+			path = /Users/overcode/Code/rott/rott/rt_crc.c;
+			refType = 0;
+		};
+		F5C71B8703B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_debug.c;
+			path = /Users/overcode/Code/rott/rott/rt_debug.c;
+			refType = 0;
+		};
+		F5C71B8803B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_dmand.c;
+			path = /Users/overcode/Code/rott/rott/rt_dmand.c;
+			refType = 0;
+		};
+		F5C71B8903B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_door.c;
+			path = /Users/overcode/Code/rott/rott/rt_door.c;
+			refType = 0;
+		};
+		F5C71B8A03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_draw.c;
+			path = /Users/overcode/Code/rott/rott/rt_draw.c;
+			refType = 0;
+		};
+		F5C71B8B03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_err.c;
+			path = /Users/overcode/Code/rott/rott/rt_err.c;
+			refType = 0;
+		};
+		F5C71B8E03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_floor.c;
+			path = /Users/overcode/Code/rott/rott/rt_floor.c;
+			refType = 0;
+		};
+		F5C71B8F03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_game.c;
+			path = /Users/overcode/Code/rott/rott/rt_game.c;
+			refType = 0;
+		};
+		F5C71B9003B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_in.c;
+			path = /Users/overcode/Code/rott/rott/rt_in.c;
+			refType = 0;
+		};
+		F5C71B9103B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_main.c;
+			path = /Users/overcode/Code/rott/rott/rt_main.c;
+			refType = 0;
+		};
+		F5C71B9203B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_map.c;
+			path = /Users/overcode/Code/rott/rott/rt_map.c;
+			refType = 0;
+		};
+		F5C71B9303B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_menu.c;
+			path = /Users/overcode/Code/rott/rott/rt_menu.c;
+			refType = 0;
+		};
+		F5C71B9403B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_msg.c;
+			path = /Users/overcode/Code/rott/rott/rt_msg.c;
+			refType = 0;
+		};
+		F5C71B9503B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_net.c;
+			path = /Users/overcode/Code/rott/rott/rt_net.c;
+			refType = 0;
+		};
+		F5C71B9603B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_playr.c;
+			path = /Users/overcode/Code/rott/rott/rt_playr.c;
+			refType = 0;
+		};
+		F5C71B9703B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_rand.c;
+			path = /Users/overcode/Code/rott/rott/rt_rand.c;
+			refType = 0;
+		};
+		F5C71B9803B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_scale.c;
+			path = /Users/overcode/Code/rott/rott/rt_scale.c;
+			refType = 0;
+		};
+		F5C71B9A03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_sound.c;
+			path = /Users/overcode/Code/rott/rott/rt_sound.c;
+			refType = 0;
+		};
+		F5C71B9B03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_spbal.c;
+			path = /Users/overcode/Code/rott/rott/rt_spbal.c;
+			refType = 0;
+		};
+		F5C71B9C03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_sqrt.c;
+			path = /Users/overcode/Code/rott/rott/rt_sqrt.c;
+			refType = 0;
+		};
+		F5C71B9D03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_stat.c;
+			path = /Users/overcode/Code/rott/rott/rt_stat.c;
+			refType = 0;
+		};
+		F5C71B9E03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_state.c;
+			path = /Users/overcode/Code/rott/rott/rt_state.c;
+			refType = 0;
+		};
+		F5C71B9F03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_str.c;
+			path = /Users/overcode/Code/rott/rott/rt_str.c;
+			refType = 0;
+		};
+		F5C71BA003B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_swift.c;
+			path = /Users/overcode/Code/rott/rott/rt_swift.c;
+			refType = 0;
+		};
+		F5C71BA103B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_ted.c;
+			path = /Users/overcode/Code/rott/rott/rt_ted.c;
+			refType = 0;
+		};
+		F5C71BA303B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_util.c;
+			path = /Users/overcode/Code/rott/rott/rt_util.c;
+			refType = 0;
+		};
+		F5C71BA503B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_vid.c;
+			path = /Users/overcode/Code/rott/rott/rt_vid.c;
+			refType = 0;
+		};
+		F5C71BA603B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = rt_view.c;
+			path = /Users/overcode/Code/rott/rott/rt_view.c;
+			refType = 0;
+		};
+		F5C71BA803B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = scriplib.c;
+			path = /Users/overcode/Code/rott/rott/scriplib.c;
+			refType = 0;
+		};
+		F5C71BAB03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = w_wad.c;
+			path = /Users/overcode/Code/rott/rott/w_wad.c;
+			refType = 0;
+		};
+		F5C71BAC03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = watcom.c;
+			path = /Users/overcode/Code/rott/rott/watcom.c;
+			refType = 0;
+		};
+		F5C71BAD03B6FF1D01000002 = {
+			isa = PBXFileReference;
+			name = z_zone.c;
+			path = /Users/overcode/Code/rott/rott/z_zone.c;
+			refType = 0;
+		};
+		F5C71BAE03B6FF1D01000002 = {
+			fileRef = F5C71B7403B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BAF03B6FF1D01000002 = {
+			fileRef = F5C71B7503B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB003B6FF1D01000002 = {
+			fileRef = F5C71B7603B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB103B6FF1D01000002 = {
+			fileRef = F5C71B7703B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB203B6FF1D01000002 = {
+			fileRef = F5C71B7803B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB303B6FF1D01000002 = {
+			fileRef = F5C71B7903B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB403B6FF1D01000002 = {
+			fileRef = F5C71B7A03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB703B6FF1D01000002 = {
+			fileRef = F5C71B7D03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BB803B6FF1D01000002 = {
+			fileRef = F5C71B7E03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBA03B6FF1D01000002 = {
+			fileRef = F5C71B8003B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBB03B6FF1D01000002 = {
+			fileRef = F5C71B8103B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBC03B6FF1D01000002 = {
+			fileRef = F5C71B8203B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBD03B6FF1D01000002 = {
+			fileRef = F5C71B8303B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBE03B6FF1D01000002 = {
+			fileRef = F5C71B8403B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BBF03B6FF1D01000002 = {
+			fileRef = F5C71B8503B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC003B6FF1D01000002 = {
+			fileRef = F5C71B8603B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC103B6FF1D01000002 = {
+			fileRef = F5C71B8703B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC203B6FF1D01000002 = {
+			fileRef = F5C71B8803B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC303B6FF1D01000002 = {
+			fileRef = F5C71B8903B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC403B6FF1D01000002 = {
+			fileRef = F5C71B8A03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC503B6FF1D01000002 = {
+			fileRef = F5C71B8B03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC803B6FF1D01000002 = {
+			fileRef = F5C71B8E03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BC903B6FF1D01000002 = {
+			fileRef = F5C71B8F03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCA03B6FF1D01000002 = {
+			fileRef = F5C71B9003B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCB03B6FF1D01000002 = {
+			fileRef = F5C71B9103B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCC03B6FF1D01000002 = {
+			fileRef = F5C71B9203B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCD03B6FF1D01000002 = {
+			fileRef = F5C71B9303B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCE03B6FF1D01000002 = {
+			fileRef = F5C71B9403B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BCF03B6FF1D01000002 = {
+			fileRef = F5C71B9503B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD003B6FF1D01000002 = {
+			fileRef = F5C71B9603B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD103B6FF1D01000002 = {
+			fileRef = F5C71B9703B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD203B6FF1D01000002 = {
+			fileRef = F5C71B9803B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD403B6FF1D01000002 = {
+			fileRef = F5C71B9A03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD503B6FF1D01000002 = {
+			fileRef = F5C71B9B03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD603B6FF1D01000002 = {
+			fileRef = F5C71B9C03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD703B6FF1D01000002 = {
+			fileRef = F5C71B9D03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD803B6FF1D01000002 = {
+			fileRef = F5C71B9E03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BD903B6FF1D01000002 = {
+			fileRef = F5C71B9F03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BDA03B6FF1D01000002 = {
+			fileRef = F5C71BA003B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BDB03B6FF1D01000002 = {
+			fileRef = F5C71BA103B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BDD03B6FF1D01000002 = {
+			fileRef = F5C71BA303B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BDF03B6FF1D01000002 = {
+			fileRef = F5C71BA503B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BE003B6FF1D01000002 = {
+			fileRef = F5C71BA603B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BE203B6FF1D01000002 = {
+			fileRef = F5C71BA803B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BE503B6FF1D01000002 = {
+			fileRef = F5C71BAB03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BE603B6FF1D01000002 = {
+			fileRef = F5C71BAC03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BE703B6FF1D01000002 = {
+			fileRef = F5C71BAD03B6FF1D01000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BF203B713D201000002 = {
+			isa = PBXFileReference;
+			name = dosutil.c;
+			path = /Users/overcode/Code/rott/rott/dosutil.c;
+			refType = 0;
+		};
+		F5C71BF303B713D201000002 = {
+			fileRef = F5C71BF203B713D201000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		F5C71BFF03B79CF301000002 = {
+			isa = PBXFileReference;
+			name = byteordr.c;
+			path = /Users/overcode/Code/rott/rott/byteordr.c;
+			refType = 0;
+		};
+		F5C71C0003B79CF301000002 = {
+			fileRef = F5C71BFF03B79CF301000002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA;
+}


Property changes on: tags/rott-1.1/mac/Rise of the Triad.pbproj/project.pbxproj
___________________________________________________________________
Name: svn:executable
   + *

Added: tags/rott-1.1/mac/SDLMain.h
===================================================================
--- tags/rott-1.1/mac/SDLMain.h	                        (rev 0)
+++ tags/rott-1.1/mac/SDLMain.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,12 @@
+/*   SDLMain.m - main entry point for our Cocoa-ized SDL app
+       Initial Version: Darrell Walisser <dwaliss1 at purdue.edu>
+       Non-NIB-Code & other changes: Max Horn <max at quendi.de>
+
+    Feel free to customize this file to suit your needs
+*/
+
+#import <Cocoa/Cocoa.h>
+
+ at interface SDLMain : NSObject
+ at end
+


Property changes on: tags/rott-1.1/mac/SDLMain.h
___________________________________________________________________
Name: svn:executable
   + *

Added: tags/rott-1.1/mac/SDLMain.m
===================================================================
--- tags/rott-1.1/mac/SDLMain.m	                        (rev 0)
+++ tags/rott-1.1/mac/SDLMain.m	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,278 @@
+/*   SDLMain.m - main entry point for our Cocoa-ized SDL app
+       Initial Version: Darrell Walisser <dwaliss1 at purdue.edu>
+       Non-NIB-Code & other changes: Max Horn <max at quendi.de>
+
+    Feel free to customize this file to suit your needs
+*/
+
+#import "SDL.h"
+#import "SDLMain.h"
+#import <sys/param.h> /* for MAXPATHLEN */
+#import <unistd.h>
+
+/* Use this flag to determine whether we use SDLMain.nib or not */
+#define		SDL_USE_NIB_FILE	0
+
+
+static int    gArgc;
+static char  **gArgv;
+static BOOL   gFinderLaunch;
+
+#if SDL_USE_NIB_FILE
+/* A helper category for NSString */
+ at interface NSString (ReplaceSubString)
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
+ at end
+#else
+/* An internal Apple class used to setup Apple menus */
+ at interface NSAppleMenuController:NSObject {}
+- (void)controlMenu:(NSMenu *)aMenu;
+ at end
+#endif
+
+ at interface SDLApplication : NSApplication
+ at end
+
+ at implementation SDLApplication
+/* Invoked from the Quit menu item */
+- (void)terminate:(id)sender
+{
+    /* Post a SDL_QUIT event */
+    SDL_Event event;
+    event.type = SDL_QUIT;
+    SDL_PushEvent(&event);
+}
+ at end
+
+
+/* The main class of the application, the application's delegate */
+ at implementation SDLMain
+
+/* Set the working directory to the .app's parent directory */
+- (void) setupWorkingDirectory:(BOOL)shouldChdir
+{
+    char parentdir[MAXPATHLEN];
+    char *c;
+    
+    strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
+    c = (char*) parentdir;
+
+    while (*c != '\0')     /* go to end */
+        c++;
+    
+    while (*c != '/')      /* back up to parent */
+        c--;
+    
+    *c++ = '\0';             /* cut off last part (binary name) */
+  
+    if (shouldChdir)
+    {
+      assert ( chdir (parentdir) == 0 );   /* chdir to the binary app's parent */
+      assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
+    }
+}
+
+#if SDL_USE_NIB_FILE
+
+/* Fix menu to contain the real app name instead of "SDL App" */
+- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
+{
+    NSRange aRange;
+    NSEnumerator *enumerator;
+    NSMenuItem *menuItem;
+
+    aRange = [[aMenu title] rangeOfString:@"SDL App"];
+    if (aRange.length != 0)
+        [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
+
+    enumerator = [[aMenu itemArray] objectEnumerator];
+    while ((menuItem = [enumerator nextObject]))
+    {
+        aRange = [[menuItem title] rangeOfString:@"SDL App"];
+        if (aRange.length != 0)
+            [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
+        if ([menuItem hasSubmenu])
+            [self fixMenu:[menuItem submenu] withAppName:appName];
+    }
+    [ aMenu sizeToFit ];
+}
+
+#else
+
+void setupAppleMenu(void)
+{
+    /* warning: this code is very odd */
+    NSAppleMenuController *appleMenuController;
+    NSMenu *appleMenu;
+    NSMenuItem *appleMenuItem;
+
+    appleMenuController = [[NSAppleMenuController alloc] init];
+    appleMenu = [[NSMenu alloc] initWithTitle:@""];
+    appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+    
+    [appleMenuItem setSubmenu:appleMenu];
+
+    /* yes, we do need to add it and then remove it --
+       if you don't add it, it doesn't get displayed
+       if you don't remove it, you have an extra, titleless item in the menubar
+       when you remove it, it appears to stick around
+       very, very odd */
+    [[NSApp mainMenu] addItem:appleMenuItem];
+    [appleMenuController controlMenu:appleMenu];
+    [[NSApp mainMenu] removeItem:appleMenuItem];
+    [appleMenu release];
+    [appleMenuItem release];
+}
+
+/* Create a window menu */
+void setupWindowMenu(void)
+{
+    NSMenu		*windowMenu;
+    NSMenuItem	*windowMenuItem;
+    NSMenuItem	*menuItem;
+
+
+    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+    
+    /* "Minimize" item */
+    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+    [windowMenu addItem:menuItem];
+    [menuItem release];
+    
+    /* Put menu into the menubar */
+    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+    [windowMenuItem setSubmenu:windowMenu];
+    [[NSApp mainMenu] addItem:windowMenuItem];
+    
+    /* Tell the application object that this is now the window menu */
+    [NSApp setWindowsMenu:windowMenu];
+
+    /* Finally give up our references to the objects */
+    [windowMenu release];
+    [windowMenuItem release];
+}
+
+/* Replacement for NSApplicationMain */
+void CustomApplicationMain (argc, argv)
+{
+    NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
+    SDLMain				*sdlMain;
+
+    /* Ensure the application object is initialised */
+    [SDLApplication sharedApplication];
+    
+    /* Set up the menubar */
+    [NSApp setMainMenu:[[NSMenu alloc] init]];
+    setupAppleMenu();
+    setupWindowMenu();
+    
+    /* Create SDLMain and make it the app delegate */
+    sdlMain = [[SDLMain alloc] init];
+    [NSApp setDelegate:sdlMain];
+    
+    /* Start the main event loop */
+    [NSApp run];
+    
+    [sdlMain release];
+    [pool release];
+}
+
+#endif
+
+/* Called when the internal event loop has just started running */
+- (void) applicationDidFinishLaunching: (NSNotification *) note
+{
+    int status;
+
+    /* Set the working directory to the .app's parent directory */
+    [self setupWorkingDirectory:gFinderLaunch];
+
+#if SDL_USE_NIB_FILE
+    /* Set the main menu to contain the real app name instead of "SDL App" */
+    [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]];
+#endif
+
+    /* Hand off to main application code */
+    status = SDL_main (gArgc, gArgv);
+
+    /* We're done, thank you for playing */
+    exit(status);
+}
+ at end
+
+
+ at implementation NSString (ReplaceSubString)
+
+- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
+{
+    unsigned int bufferSize;
+    unsigned int selfLen = [self length];
+    unsigned int aStringLen = [aString length];
+    unichar *buffer;
+    NSRange localRange;
+    NSString *result;
+
+    bufferSize = selfLen + aStringLen - aRange.length;
+    buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
+    
+    /* Get first part into buffer */
+    localRange.location = 0;
+    localRange.length = aRange.location;
+    [self getCharacters:buffer range:localRange];
+    
+    /* Get middle part into buffer */
+    localRange.location = 0;
+    localRange.length = aStringLen;
+    [aString getCharacters:(buffer+aRange.location) range:localRange];
+     
+    /* Get last part into buffer */
+    localRange.location = aRange.location + aRange.length;
+    localRange.length = selfLen - localRange.location;
+    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
+    
+    /* Build output string */
+    result = [NSString stringWithCharacters:buffer length:bufferSize];
+    
+    NSDeallocateMemoryPages(buffer, bufferSize);
+    
+    return result;
+}
+
+ at end
+
+
+
+#ifdef main
+#  undef main
+#endif
+
+
+/* Main entry point to executable - should *not* be SDL_main! */
+int main (int argc, char **argv)
+{
+
+    /* Copy the arguments into a global variable */
+    int i;
+    
+    /* This is passed if we are launched by double-clicking */
+    if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
+        gArgc = 1;
+	gFinderLaunch = YES;
+    } else {
+        gArgc = argc;
+	gFinderLaunch = NO;
+    }
+    gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1));
+    assert (gArgv != NULL);
+    for (i = 0; i < gArgc; i++)
+        gArgv[i] = argv[i];
+    gArgv[i] = NULL;
+
+#if SDL_USE_NIB_FILE
+    [SDLApplication poseAsClass:[NSApplication class]];
+    NSApplicationMain (argc, argv);
+#else
+    CustomApplicationMain (argc, argv);
+#endif
+    return 0;
+}


Property changes on: tags/rott-1.1/mac/SDLMain.m
___________________________________________________________________
Name: svn:executable
   + *

Added: tags/rott-1.1/misc/rott.xpm
===================================================================
--- tags/rott-1.1/misc/rott.xpm	                        (rev 0)
+++ tags/rott-1.1/misc/rott.xpm	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,67 @@
+/* XPM */
+static char * rott_xpm[] = {
+"32 29 35 1",
+" 	c None",
+".	c #240000",
+"+	c #242424",
+"@	c #926D6D",
+"#	c #000000",
+"$	c #6D4949",
+"%	c #926D49",
+"&	c #494924",
+"*	c #6D6D49",
+"=	c #494949",
+"-	c #49496D",
+";	c #92926D",
+">	c #242449",
+",	c #49246D",
+"'	c #494992",
+")	c #242492",
+"!	c #492424",
+"~	c #242400",
+"{	c #6D4900",
+"]	c #24246D",
+"^	c #924900",
+"/	c #926D00",
+"(	c #492449",
+"_	c #6D4924",
+":	c #B69200",
+"<	c #929200",
+"[	c #B6B600",
+"}	c #494900",
+"|	c #000049",
+"1	c #240024",
+"2	c #002449",
+"3	c #492400",
+"4	c #000024",
+"5	c #6D6D00",
+"6	c #B6DB00",
+"               ..               ",
+"              +@@.              ",
+"             #$%@&              ",
+"             +*+=&.             ",
+"            #**+-*=             ",
+"            &;+>>=%+            ",
+"           .@$>>+,*$#           ",
+"          #=%>'&+)=@!           ",
+"          ~;=>,{&]>$*#          ",
+"         #&@>'>^{>]=%!          ",
+"         +@=])=^{>]]=*.         ",
+"        #$@>']!//+]](*&#        ",
+"        +%+)]]_:<!]>]=%~        ",
+"       .*=>)]]{[:}|]>>$&#       ",
+"       &@>)]]({[[{>]>|=$+       ",
+"      .@=]])]+^</{12||>$$#      ",
+"     #=@>]]]]>3{{!|||||($+      ",
+"     ~@(]])]]>]|||]||||>&&#     ",
+"    #$$>]]2>>]]>]>|+>|||=$!     ",
+"    + at +|]>+{^!||>|}{}4|||&$~    ",
+"   #$$|]]+{:<{1||+{/5}1||+&!    ",
+"   !*+]>+{:6[^~||!{<<5}1||!&.   ",
+"  #$&||({/:/{34||+3}{5{}141&!#  ",
+"  !$12!/{{3+4||||||4+33}}14+&+# ",
+" .*+|!}!+|||||||||||4441~3#4&&. ",
+"#&$1111||||||||4||44444444#4+&+ ",
+"~$!$$=======&=&&&&&&!!&&!!!!!&&#",
+"~$$$$*$*$%$*$$$$$$$$$&$$$&$&&&&.",
+" .....~...####~~.........#.###. "};

Added: tags/rott-1.1/misc/runrott.sh
===================================================================
--- tags/rott-1.1/misc/runrott.sh	                        (rev 0)
+++ tags/rott-1.1/misc/runrott.sh	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,28 @@
+#!/bin/sh
+# quick hack rott.rot generation in sh v0.1 by Steven Fuller
+# inspired by Delphi Dude's RUNROTT:
+# http://www.delphidude.com/personal/utilities/games/
+
+CONFIG=$HOME/.rott/darkwar/rott.rot
+EXE=./rott
+
+if [ $# != 1 ]; then
+	echo "usage: "$0" <RTL or RTC filename>"
+	exit 1
+fi
+
+if [ ! -r $1 ]; then
+	echo "error: "$1" does not exist"
+	exit 1
+fi
+
+cat > $CONFIG <<!END!
+; Rise of the Triad Game Information File
+; (c) 1997
+PHONENUMBER          ~
+REMOTESOUNDFILE      ~
+GAMELEVELFILE        $1
+COMMBATLEVELFILE     ~
+!END!
+
+exec $EXE


Property changes on: tags/rott-1.1/misc/runrott.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: tags/rott-1.1/rott/Makefile
===================================================================
--- tags/rott-1.1/rott/Makefile	                        (rev 0)
+++ tags/rott-1.1/rott/Makefile	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,123 @@
+#-----------------------------------------------------------------------------#
+# ROTT makefile.
+#-----------------------------------------------------------------------------#
+
+
+#-----------------------------------------------------------------------------#
+# If this makefile fails to detect Cygwin correctly, or you want to force
+#  the build process's behaviour, set it to "true" or "false" (w/o quotes).
+#-----------------------------------------------------------------------------#
+#cygwin := true
+#cygwin := false
+cygwin := autodetect
+
+# you only need to set these for Cygwin at the moment.
+SDL_INC_DIR = /cygdrive/c/SDL/include
+SDL_LIB_DIR = /cygdrive/c/SDL/lib
+
+
+# Don't touch anything below this line unless you know what you're doing.
+
+ifeq ($(strip $(cygwin)),autodetect)
+  ifneq ($(strip $(shell gcc -v 2>&1 |grep "cygwin")),)
+    cygwin := true
+  else
+    cygwin := false
+  endif
+endif
+
+
+ifeq ($(strip $(cygwin)),true)
+  ifeq ($(strip $(SDL_INC_DIR)),please_set_me_cygwin_users)
+    $(error Cygwin users need to set the SDL_INC_DIR envr var.)
+  else
+    SDL_CFLAGS := -I$(SDL_INC_DIR)
+  endif
+
+  ifeq ($(strip $(SDL_LIB_DIR)),please_set_me_cygwin_users)
+    $(error Cygwin users need to set the SDL_LIB_DIR envr var.)
+  else
+    SDL_LDFLAGS := -L$(SDL_LIB_DIR) -lSDL
+  endif
+else
+  SDL_CFLAGS := $(shell sdl-config --cflags)
+  SDL_LDFLAGS := $(shell sdl-config --libs)
+  EXTRACFLAGS += -DUSE_EXECINFO=1
+endif
+
+
+CC = gcc
+CFLAGS += -g -W -Wall -Wno-unused -Wno-pointer-sign
+ALL_CFLAGS = $(SDL_CFLAGS) -DUSE_SDL=1 -DPLATFORM_UNIX=1 $(CFLAGS) $(EXTRACFLAGS)
+LDFLAGS += -Wl,-E
+LDLIBS = $(LDFLAGS) $(SDL_LDFLAGS) -lSDL -lSDL_mixer $(EXTRALDFLAGS)
+
+%.o: %.c
+	$(CC) $(ALL_CFLAGS) -c $< -o $@
+
+all: rott
+
+audiolib/audiolib.a:
+	$(MAKE) -C audiolib CC="$(CC)" CFLAGS="$(ALL_CFLAGS)" LDLIBS="$(LDLIBS)"
+
+rott: 	\
+	cin_actr.o \
+	cin_efct.o \
+	cin_evnt.o \
+	cin_glob.o \
+	cin_main.o \
+	cin_util.o \
+	dosutil.o \
+	engine.o \
+	isr.o \
+	modexlib.o \
+	rt_actor.o \
+	rt_battl.o \
+	rt_build.o \
+	rt_cfg.o \
+	rt_crc.o \
+	rt_com.o \
+	rt_debug.o \
+	rt_dmand.o \
+	rt_door.o \
+	rt_draw.o \
+	rt_floor.o \
+	rt_game.o \
+	rt_in.o \
+	rt_main.o \
+	rt_map.o \
+	rt_menu.o \
+	rt_msg.o \
+	rt_net.o \
+	rt_playr.o \
+	rt_rand.o \
+	rt_scale.o \
+	rt_sound.o \
+	rt_spbal.o \
+	rt_sqrt.o \
+	rt_stat.o \
+	rt_state.o \
+	rt_str.o \
+	rt_swift.o \
+	rt_ted.o \
+	rt_util.o \
+	rt_view.o \
+	rt_vid.o \
+	rt_err.o \
+	scriplib.o \
+	w_wad.o \
+	watcom.o \
+	z_zone.o \
+	byteordr.o \
+	dukemusc.o \
+	audiolib/audiolib.a \
+	winrott.o
+	$(CC) $^ $(LDLIBS) -o $@
+
+clean:
+	$(MAKE) -C audiolib clean
+	rm -rf rott *.o
+
+distclean: clean
+	$(MAKE) -C audiolib distclean
+	rm -rf *~

Added: tags/rott-1.1/rott/WinRott.h
===================================================================
--- tags/rott-1.1/rott/WinRott.h	                        (rev 0)
+++ tags/rott-1.1/rott/WinRott.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,55 @@
+
+
+// winrott.h
+
+
+//husk at rette i winrott.c
+
+extern int iGLOBAL_SCREENWIDTH;//bna val 800
+extern int iGLOBAL_SCREENHEIGHT;//bna val 600
+extern int iGLOBAL_SCREENBWIDE ;
+extern int iG_SCREENWIDTH;// default screen width in bytes
+
+extern int iGLOBAL_HEALTH_X;
+extern int iGLOBAL_HEALTH_Y;
+extern int iGLOBAL_AMMO_X;
+extern int iGLOBAL_AMMO_Y;
+
+extern int iGLOBAL_FOCALWIDTH;
+extern double dGLOBAL_FPFOCALWIDTH;
+
+void EnableScreenStretch(void);
+void DisableScreenStretch(void);
+
+/*
+double dYZANGLELIMIT;
+
+#define FOCALWIDTH 160//160
+#define FPFOCALWIDTH 160.0//160.0
+
+
+
+#define MAXSCREENHEIGHT    480//600//     200*2
+#define MAXSCREENWIDTH     640//800//     320*2
+#define SCREENBWIDE        640*(96/320)//800*(96/320)//     96*2
+#define MAXVIEWWIDTH       640//     320*2
+#define SCREENWIDTH        640*(96/320)//800*(96/320)//     96*2              // default screen width in bytes
+
+
+#define MAXSCREENHEIGHT    600
+#define MAXSCREENWIDTH     800
+#define SCREENBWIDE        800*(96/320)
+#define MAXVIEWWIDTH       800
+#define SCREENWIDTH        800*(96/320)// default screen width in bytes
+
+*/
+//#define VIEWWIDTH               MAXSCREENWIDTH//320*2             // size of view window
+//#define VIEWHEIGHT              MAXSCREENHEIGHT//200*2
+//#define MAXSCANLINES            MAXSCREENHEIGHT//200*2             // size of ylookup table
+
+
+
+
+
+
+

Added: tags/rott-1.1/rott/_engine.h
===================================================================
--- tags/rott-1.1/rott/_engine.h	                        (rev 0)
+++ tags/rott-1.1/rott/_engine.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,27 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _engine_private
+#define _engine_private
+
+#define NOTSAMETILE(x1,x2)     ( (posts[(x1)].posttype!=posts[(x2)].posttype) || \
+                                 (posts[(x1)].offset!=posts[(x2)].offset))
+#define SGN(x)                 (x>0 ? 1 : -1)
+
+#endif

Added: tags/rott-1.1/rott/_isr.h
===================================================================
--- tags/rott-1.1/rott/_isr.h	                        (rev 0)
+++ tags/rott-1.1/rott/_isr.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,32 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+//    ISR Constants
+//
+//***************************************************************************
+
+#ifndef _isr_private
+#define _isr_private
+
+#define TIMERINT                0x08
+#define KEYBOARDINT             0x09
+
+#endif

Added: tags/rott-1.1/rott/_rt_acto.h
===================================================================
--- tags/rott-1.1/rott/_rt_acto.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_acto.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,296 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_actor_private
+#define _rt_actor_private
+
+#define MAXGIBS            600
+#define HAAPT              24
+#define VAAPT              24
+#define GODHAPT            1024
+#define GODVAPT            1024
+#define MAXDELTAYZSHOOT    (((5*FINEANGLES)/360))
+#define MAXDELTAYZSEE      (((15*FINEANGLES)/360))
+#define MAXSHOOTOFFSET     (((15*FINEANGLES)/360))
+#define MAXSHOOTSHIFT      (1)
+#define MAXDAMAGE          (64)
+#define MAXYZANGLE         (((30*FINEANGLES)/360))
+#define SMOKEWALLOFFSET    (0x800)
+#define MZADJUST           0x30000;
+#define MAXSTEPHEIGHT      24
+#define SIGN(x)            ((x)>=0)?(1):(-1)
+#define MAXRAIN            128
+#define SG_PSTAT      0x4000
+#define SG_PSTATE     0x2000
+#define EXPLOSION_DAMAGE   50
+#define LOWFALLCLIPZ       (maxheight - 96)
+#define HIGHFALLCLIPZ      -5
+#define LOWRISECLIPZ       (nominalheight)
+#define HIGHRISECLIPZ      64
+#define NORMALGIBSPEED     0x2f00
+
+#define FL_PLEADING        0x400
+#define FL_EYEBALL         0x400
+#define FL_UNDEAD          0x8000
+
+#define NME_DRUNKTYPE       0x01
+#define NME_HEATSEEKINGTYPE 0x02
+
+#define NUMSTATES 11
+
+enum {
+  STAND,
+  PATH,
+  COLLIDE1,
+  COLLIDE2,
+  CHASE,
+  USE,
+  AIM,
+  DIE,
+  FIRE,
+  WAIT,
+  CRUSH
+  };
+
+#define SHOTMOM                0x200l
+#define NEXT                   1
+#define PREV                   0
+#define ANGLEMOVE              0x2b000l
+#define PAINTIME               5l
+#define LOOKAHEAD              (20 << 16)
+#define DRAINTIME              70l
+#define EXPLOSION_IMPULSE      0x2600l
+#define ZEROMOM                ob->momentumx = ob->momentumy = 0
+#define NOMOM                  ((!ob->momentumx) && (!ob->momentumy))
+#define WHICHACTOR             (ob->obclass-lowguardobj)
+#define SPDPATROL              0x600l
+//#define ENEMYRUNSPEED          (3*SPDPATROL)
+#define ENEMYRUNSPEED          (0xc00)
+#define ENEMYFASTRUNSPEED      (5*SPDPATROL)
+#define ENEMYINSANESPEED       (7*SPDPATROL)
+#define MAXMOVE                0x2000l
+#define PROJECTILESIZE         0x6000l
+#define DEADFRICTION           0x6000l
+#define ROLLMOMENTUM           0x920l
+#define PROJSIZE               0x4000l
+#define PILLARMOM              0x800l
+#define HALFGLOBAL1            (TILEGLOBAL/2)
+#define TOUCHDIST              0xb000l
+#define STANDDIST              0x5000l
+#define SNAKERAD               0x4000l
+#define MINSIGHT               0x18000l
+#define HBM                    -2
+#define SNEAKY                 -3
+#define GIBVALUE               -3
+#define DISKMOMZ               4
+
+//=========================== macros =============================
+
+#define M_ISWALL(x)           ((x->which == WALL) || (x->which == PWALL) || (x->which == MWALL))
+#define M_DISTOK(p1,p2,d)     (abs((p1)-(p2)) <= d)
+#define M_NONS(x)             ((x->obclass == wallfireobj) || (x->obclass == pillarobj))
+#define M_CHOOSETIME(x)       ((int)(TILEGLOBAL/((x->speed))))
+#define M_DIST(x1,x2,y1,y2)   (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
+#define M_S(x)                (UPDATE_STATES[x][ob->obclass-lowguardobj])
+#define Fix(a)                (a &= (FINEANGLES - 1))
+
+
+#define STOPACTOR(ob)                   \
+   {                                    \
+   ob->momentumx = ob->momentumy = 0;   \
+   ob->dirchoosetime = 0;               \
+   }
+
+
+#define M_CHECKDIR(ob,tdir)             \
+   {                                    \
+   ob->dir = tdir;                      \
+   ParseMomentum(ob,dirangle8[tdir]);   \
+   ActorMovement(ob);                   \
+   if (ob->momentumx || ob->momentumy)  \
+      return;                           \
+   }                                    \
+
+
+#define M_CHECKTURN(x,ndir)                             \
+   {                                                    \
+   if (ndir == olddir)                                  \
+      ZEROMOM;                                          \
+   ParseMomentum(x,dirangle8[ndir]);                    \
+   ActorMovement(x);                                    \
+   if (!NOMOM)                                          \
+      {                                                 \
+      if (ndir != olddir)                               \
+         {                                              \
+         next = dirorder[olddir][NEXT];                 \
+         prev = dirorder[olddir][PREV];                 \
+         x->temp1 = ndir;                               \
+         if (dirdiff[ndir][next] < dirdiff[ndir][prev]) \
+            NewState(x,&s_kristleft);                   \
+         else                                           \
+            NewState(x,&s_kristright);                  \
+         }                                              \
+      return;                                           \
+      }                                                 \
+   }                                                    \
+
+#define M_CheckDoor(ob)                          \
+   {                                             \
+   door = ob->door_to_open;                      \
+   if (door != -1)                               \
+      {                                          \
+      if ((ob->obclass > shurikenobj) &&         \
+          (ob->obclass != collectorobj)          \
+         )                                       \
+         Error("you got it !!!");                \
+      LinkedOpenDoor(door);                      \
+      if (doorobjlist[door]->action != dr_open)  \
+         return;                                 \
+      ob->door_to_open = -1;                     \
+      }                                          \
+   }                                             \
+
+#define M_CheckBossSounds(ob)                                 \
+   {                                                          \
+   if ((ob->obclass >= b_darianobj) &&                        \
+       (ob->obclass <= b_darksnakeobj) &&                     \
+       (ob->flags & FL_ATTACKMODE)  &&                        \
+       (ob->obclass != b_robobossobj) &&                      \
+       (!(ob->flags & FL_DYING))                              \
+      )                                                       \
+      {                                                       \
+      if (MISCVARS->SOUNDTIME)                                \
+         MISCVARS->SOUNDTIME --;                              \
+      else                                                    \
+         {                                                    \
+         MISCVARS->SOUNDTIME = 5*VBLCOUNTER;                  \
+         if (GameRandomNumber("boss sound check",0)<160)      \
+            {                                                 \
+            int rand,sound;                                   \
+                                                              \
+            rand = GameRandomNumber("boss sounds",0);         \
+            sound = BAS[ob->obclass].operate;                 \
+            if (rand < 160)                                   \
+               sound ++;                                      \
+            if (rand < 80)                                    \
+               sound ++;                                      \
+                                                              \
+            SD_PlaySoundRTP(sound,ob->x,ob->y);               \
+            }                                                 \
+         }                                                    \
+      if (MISCVARS->REDTIME)                                  \
+         {                                                    \
+         MISCVARS->REDTIME --;                                \
+         MISCVARS->redindex = ((MISCVARS->REDTIME >> 1) & 15);\
+         }                                                    \
+      }                                                       \
+   }
+
+
+
+
+#define SET_DEATH_SHAPEOFFSET(ob)                     \
+   {                                                  \
+   ob->flags |= FL_ALTERNATE;                         \
+   ob->shapeoffset += deathshapeoffset[ob->obclass];  \
+   }
+
+
+#define RESET_DEATH_SHAPEOFFSET(ob)                   \
+   {                                                  \
+   ob->flags &= ~FL_ALTERNATE;                        \
+   ob->shapeoffset -= deathshapeoffset[ob->obclass];  \
+   }
+
+#define LOW_VIOLENCE_DEATH_SHOULD_BE_SET(ob)          \
+     ((gamestate.violence < vl_high) &&               \
+      (ob->obclass >= lowguardobj) &&                 \
+      (ob->obclass <= triadenforcerobj) &&            \
+      (!(ob->flags & FL_ALTERNATE))                   \
+     )                                                \
+
+#define LOW_VIOLENCE_DEATH_IS_SET(ob)   (ob->flags & FL_ALTERNATE)
+
+#define LOW_VIOLENCE_PAIN_SHOULD_BE_SET  LOW_VIOLENCE_DEATH_SHOULD_BE_SET
+
+#define LOW_VIOLENCE_PAIN_IS_SET  LOW_VIOLENCE_DEATH_IS_SET
+
+#define SET_PAIN_SHAPEOFFSET  SET_DEATH_SHAPEOFFSET
+
+#define RESET_PAIN_SHAPEOFFSET  RESET_DEATH_SHAPEOFFSET
+
+
+// default = actor
+
+typedef struct  sat
+ { int          x,y,z;
+	unsigned     flags;
+	int          hitpoints;
+	int          targetx,targety;
+	int          angle;
+	int          yzangle;
+	int          speed;
+	int          momentumx,momentumy,momentumz;
+	int          temp1,temp2,temp3;
+	int          whateverindex,targetindex;
+
+	short        ticcount;
+	short        shapeoffset;
+	short        stateindex;
+	short        dirchoosetime;
+
+	byte         areanumber;
+	byte         obclass;
+	signed char  door_to_open;
+	signed char  dir;
+
+ }saved_actor_type;
+
+
+typedef struct
+ {thingtype which;
+  byte tilex,tiley;
+  fixed x,y,z;
+ }tpoint;
+
+
+//========================== Function Prototypes ==============================
+
+void     MissileMovement(objtype*);
+boolean  MissileTryMove(objtype*,int,int,int);
+void     T_DarkSnakeChase(objtype*);
+void     HeatSeek(objtype*);
+boolean  CheckDoor(objtype *ob,doorobj_t*,int,int);
+boolean  NextToDoor(objtype*ob);
+void     MissileHit (objtype *ob,void*);
+int      Near(objtype*,void*,int);
+void     FirstSighting(objtype*);
+void     SelectOrobotChaseDir(objtype*);
+void     SelectPathDir(objtype*);
+void     SelectChaseDir(objtype*);
+void     SelectRoboChaseDir(objtype*);
+void     SelectDodgeDir(objtype*);
+void     SelectRollDir (objtype*);
+void     SelectTouchDir(objtype*);
+void     SelectMineDir(objtype*);
+boolean  WallCheck(int,int);
+boolean  NMEspincheck(objtype*);
+void     TurnActorIntoSprite(objtype*ob);
+void     ActivateEnemy(objtype*);
+#endif

Added: tags/rott-1.1/rott/_rt_buil.h
===================================================================
--- tags/rott-1.1/rott/_rt_buil.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_buil.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,48 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_build_private
+#define _rt_build_private
+
+#define MAX(x,y)               ((x>y) ? (x) : (y))
+#define MAXPLANES 10
+
+// Should be 10 with titles
+#define MENUOFFY     (10)
+#define MENUBACKNAME ("plane")
+#define MENUTITLEY 10
+#define TEXTUREW     (288)
+#define TEXTUREWIDTH ((TEXTUREW*1024)-1)
+#define TEXTUREHEIGHT (158)
+#define NORMALVIEW   (0x40400L)
+#define NORMALHEIGHTDIVISOR   (156000000)
+#define NORMALWIDTHMULTIPLIER (241)
+#define FLIPTIME     20//60
+
+
+typedef struct
+{
+   int   x1, y1;
+   int   x2, y2;
+   int   texturewidth;
+   int   texture;
+   int   origheight;
+} plane_t;
+
+#endif

Added: tags/rott-1.1/rott/_rt_com.h
===================================================================
--- tags/rott-1.1/rott/_rt_com.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_com.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,53 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_com_private
+#define _rt_com_private
+
+
+#define SYNCPACKETSIZE 32
+
+#define SYNC_PHASE0 6
+#define SYNC_PHASE1 0
+#define SYNC_PHASE2 1
+#define SYNC_PHASE3 2
+#define SYNC_PHASE4 3
+#define SYNC_PHASE5 4
+#define SYNC_MEMO   99
+#define NUMSYNCPHASES 5
+
+#define SYNCTIME    15
+
+typedef struct
+{
+   byte type;
+   int  phase;
+   int  clocktime;
+   int  delta;
+   byte data[SYNCPACKETSIZE];
+} syncpackettype;
+
+typedef struct
+{
+   int  sendtime;
+   int  deltatime;
+   syncpackettype pkt;
+} synctype;
+
+#endif

Added: tags/rott-1.1/rott/_rt_dman.h
===================================================================
--- tags/rott-1.1/rott/_rt_dman.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_dman.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,29 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_dmand_private
+#define _rt_dmand_private
+
+#define RECORDINGSAMPLERATE 7000
+#define RECORDINGBUFFERSIZE 16384
+#define PLAYBACKBUFFERSIZE 16384
+#define PLAYBACKDELTASIZE  256
+
+#endif
+

Added: tags/rott-1.1/rott/_rt_door.h
===================================================================
--- tags/rott-1.1/rott/_rt_door.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_door.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,48 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_door_private
+#define _rt_door_private
+
+#define OPENTICS	165
+
+typedef struct tp
+ {
+  signed char actionindex;
+  signed char swapactionindex;
+  int         whichobj;
+  byte        tictime;
+  byte        ticcount;
+  byte        triggered;
+  byte        complete;
+  byte        done;
+ } saved_touch_type;
+
+
+#define NUMTOUCHPLATEACTIONS 8
+
+#define FL_TACT 0x4000
+#define FL_TSTAT 0x8000
+
+#define PUSHWALLSPEED 10
+
+#define AMW_NUMFRAMES 9
+#define AMW_TICCOUNT  3
+
+#endif

Added: tags/rott-1.1/rott/_rt_draw.h
===================================================================
--- tags/rott-1.1/rott/_rt_draw.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_draw.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,74 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_draw_private
+#define _rt_draw_private
+
+#include "develop.h"
+
+#define MINZ                            0x2700
+#define MAXBOB                          0x9000
+
+#define GOLOWER  0x38000
+#define GOHIGHER 0x20000
+
+#define MAXVISIBLEDOORS 30
+
+#define DHEIGHTFRACTION 8
+
+#define MINZ                            0x2700
+#define MAXDRAWNTICS                    40
+
+#define W_CHANGE  (WEAPONUPTICS || WEAPONDOWNTICS)
+
+#if (SHAREWARE == 0)
+ #define NUMWEAPGRAPHICS 16
+#else
+ #define NUMWEAPGRAPHICS 9
+#endif
+
+#define HFRACTION (6+HEIGHTFRACTION)
+
+#define FIXEDTRANSLEVEL (30)
+
+typedef struct
+{
+   int x;
+   int y;
+   int angle;
+   int scale;
+   int dx;
+   int dy;
+   int dangle;
+   int dscale;
+   int phase;
+   int time;
+   int pausetime;
+   int pausex;
+   int pausey;
+} screensaver_t;
+
+void  DrawPlayerWeapon(void);
+boolean TransformPlane (int x1, int y1, int x2, int y2, visobj_t * plane);
+int   CalcRotate (objtype *ob);
+void  DrawScaleds (void);
+void  FixOfs (void);
+void SetSpriteLightLevel (int x, int y, visobj_t * sprite, int dir, int fullbright);
+
+#endif

Added: tags/rott-1.1/rott/_rt_floo.h
===================================================================
--- tags/rott-1.1/rott/_rt_floo.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_floo.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,28 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_floor_private
+#define _rt_floor_private
+
+//#define	MAXVIEWHEIGHT MAXSCREENHEIGHT	
+#define MAXSKYSEGS    2048
+#define MAXSKYDATA    8
+#define MINSKYHEIGHT  0//148 //bna++ sky change here
+
+#endif

Added: tags/rott-1.1/rott/_rt_game.h
===================================================================
--- tags/rott-1.1/rott/_rt_game.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_game.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,165 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_game_private
+#define _rt_game_private
+
+//******************************************************************************
+//
+// Private header for RT_GAME.C
+//
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// TYPEDEFS
+//
+//******************************************************************************
+
+typedef struct {
+   char str[10];
+   int length;
+} STR;
+
+//******************************************************************************
+//
+// DEFINES
+//
+//******************************************************************************
+
+#define MENUSHADELEVEL  105
+
+#define KILLS_X      0
+#define KILLS_Y      176
+#define KILLS_WIDTH  32
+#define KILLS_HEIGHT 24
+#define KILLS_OFFSET 14
+#define KILLS_NAME_Y ( KILLS_Y + 16 )
+#define MAXKILLBOXES 10
+#define PLAYERS_Y      ( 107 + ( gamestate.teamplay ? 0 : 4 ) )
+#define PLAYERS_NAME_Y ( PLAYERS_Y + 16 )
+#define PLAYERS_TEAM_Y ( PLAYERS_Y + 24 )
+
+#define LEADER_X      0
+#define LEADER_Y      0
+#define LEADER_NUM_X  61
+#define LEADER_NUM_Y  ( LEADER_Y )
+#define LEADER_NAME_X ( LEADER_X + 3 )
+#define LEADER_NAME_Y ( LEADER_Y + 2 )
+#define LEADER_WIDTH  88
+#define LEADER_HEIGHT 16
+/* bna++
+#define HEALTH_X  20
+#define HEALTH_Y  185
+
+#define AMMO_X    300
+#define AMMO_Y    184
+*/
+//--------------------
+#define HEALTH_X  20*2
+#define HEALTH_Y  (185*2)+16
+
+#define AMMO_X    300*2
+#define AMMO_Y    (184*2)+16
+//--------------------
+
+#define SCORE_X   4
+#define SCORE_Y   0
+
+/*
+#define KEY1_X    152
+#define KEY2_X    160
+#define KEY3_X    168
+#define KEY4_X    176
+#define KEY_Y     0
+
+#define POWER_X   184
+#define POWER_Y   0
+
+#define ARMOR_X   200
+#define ARMOR_Y   0
+
+#define MEN_X     216
+#define MEN_Y     0
+*/
+//--------------------
+#define KEY1_X    152
+#define KEY2_X    160
+#define KEY3_X    168
+#define KEY4_X    176
+#define KEY_Y     0
+
+#define POWER_X   (184)
+#define POWER_Y   0
+
+#define ARMOR_X   200
+#define ARMOR_Y   0
+
+#define MEN_X     216
+#define MEN_Y     0
+//--------------------
+#define HOUR_X    7
+#define MIN_X     26
+#define SEC_X     45
+#define TIME_Y    0
+
+#define GAMETIME_X 88
+#define GAMETIME_Y 0
+
+#define TALLYTIME_X 130
+#define TALLYTIME_Y 8
+
+#define LIVES_X   288
+#define LIVES_Y   0
+
+#define TRIAD_X   308
+#define TRIAD_Y   6
+
+#define POWERUP1X 184
+#define POWERUP2X 200
+#define POWERUPY  0
+
+#define EXTRAPOINTS        50000
+#define ADRENALINEBONUS    5
+
+#define STR_SAVECHT1 "Your Save Game file is,"
+#define STR_SAVECHT2 "shall we say, \"corrupted\"."
+#define STR_SAVECHT3 "But I'll let you go on and"
+#define STR_SAVECHT4 "play anyway...."
+
+#define MAXSAVEDGAMESIZE 120000
+
+#if (SHAREWARE == 0)
+#define WEAPON_IS_MAGICAL(x) (((x) == wp_dog) || ((x) == wp_godhand))
+#else
+#define WEAPON_IS_MAGICAL(x) ((x) == wp_godhand)
+#endif
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void DrawMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly);
+void DrawHighScores (void);
+void GM_MemToScreen (byte *source, int width, int height, int x, int y);
+
+#endif

Added: tags/rott-1.1/rott/_rt_in.h
===================================================================
--- tags/rott-1.1/rott/_rt_in.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_in.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,61 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//****************************************************************************
+//
+// Private header for RT_IN.C
+//
+//****************************************************************************
+
+#ifndef _rt_in_private
+#define _rt_in_private
+
+
+//****************************************************************************
+//
+// TYPEDEFS
+//
+//****************************************************************************
+
+
+//****************************************************************************
+//
+// DEFINES
+//
+//****************************************************************************
+
+#define  KeyInt         9  // The keyboard ISR number
+#define  MReset         0
+#define  MButtons       3
+#define  MDelta         11
+#define  MouseInt       0x33
+#define  JoyScaleMax    32768
+#define  JoyScaleShift  8
+#define  MaxJoyValue    5000
+
+void Mouse (int x);
+
+#if defined(__WATCOMC__)
+#pragma aux Mouse =  \
+   "int  33h"        \
+   parm [EAX]        \
+   modify [EAX]
+#endif
+
+#endif

Added: tags/rott-1.1/rott/_rt_main.h
===================================================================
--- tags/rott-1.1/rott/_rt_main.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_main.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,74 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_main_private
+#define _rt_main_private
+
+#include "develop.h"
+
+void GameLoop (void);
+void PlayLoop (void);
+void PollKeyboard(void);
+void FixColorMap( void );
+
+#define QUITTIMEINTERVAL ((35*6)-5)
+boolean CheckForQuickLoad ( void );
+
+#if SAVE_SCREEN
+
+void WriteLBMfile (char *filename, byte *data, int width, int height);
+void GetFileName (boolean saveLBM);
+void DrawRottTitle ( void );
+
+void WritePCX (char * file, byte * source);
+int PutBytes (unsigned char *ptr, unsigned int bytes);
+
+typedef struct
+{
+	unsigned short w,h;
+	short          x,y;
+	unsigned char  nPlanes;
+	unsigned char  masking;
+	unsigned char  compression;
+	unsigned char  pad1;
+	unsigned short transparentColor;
+	unsigned char  xAspect,yAspect;
+	short          pageWidth,pageHeight;
+} bmhd_t;
+
+
+typedef struct {
+   unsigned char manufacturer;
+   unsigned char version;
+   unsigned char encoding;
+   unsigned char bitsperpixel;
+   unsigned short int  xmin, ymin, xmax, ymax;
+   unsigned short int  hres, vres;
+   unsigned char colormap[16][3];
+   unsigned char reserved;
+   unsigned char nplanes;
+   unsigned short int  bytesperline;
+} PCX_HEADER;
+
+#define GAP_SIZE  (128 - sizeof (PCX_HEADER))
+
+
+#endif
+
+#endif

Added: tags/rott-1.1/rott/_rt_map.h
===================================================================
--- tags/rott-1.1/rott/_rt_map.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_map.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,44 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_map_private
+#define _rt_map_private
+
+#if defined(__WATCOM__)
+#pragma aux FastFill =  \
+        "rep stosb"       \
+        parm    [edi] [eax] [ecx] \
+        modify exact [ecx]
+#endif
+void FastFill(byte * buf, int color, int count);
+
+
+#define MAP_PLAYERCOLOR 4
+#define MAP_MWALLCOLOR 13
+#define MAP_PWALLCOLOR 8
+#define MAP_AWALLCOLOR 9
+#define MAP_WALLCOLOR 7
+#define MAP_DOORCOLOR 3
+#define MAP_SPRITECOLOR 2
+#define MAP_ACTORCOLOR 15
+#define MAP_SKYCOLOR 11
+
+#define FULLMAP_SCALE 5
+
+#endif

Added: tags/rott-1.1/rott/_rt_menu.h
===================================================================
--- tags/rott-1.1/rott/_rt_menu.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_menu.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,369 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_menu_private
+#define _rt_menu_private
+
+//******************************************************************************
+//
+// Private Header for RT_MENU.C
+//
+//******************************************************************************
+
+#include "rt_in.h"
+
+//
+// Specific Menu defines
+//
+
+#define BORDCOLOR       0x29
+#define BORD2COLOR      0x23
+#define DEACTIVE        0x2b
+#define BKGDCOLOR       0x2d
+#define STRIPE          0x2c
+
+
+#define SENSITIVE       60
+#define CENTER          SENSITIVE*2
+
+
+#define MENU_X          32
+#define MENU_Y          16
+#define MENU_W          235
+#define MENU_H          14*9+4
+
+
+#define LSM_X           180      //32
+#define LSM_Y           16
+#define LSM_W           80       //176
+#define LSM_H           10*14+8
+
+#define LSA_X           96
+#define LSA_Y           80
+#define LSA_W           130
+#define LSA_H           42
+
+
+#define SM_X            32
+#define SM_Y            52
+#define SM_W            252
+#define SM_H            35
+
+#define SM_Y1           20
+#define SM_H1           4*14-9
+#define SM_Y2           SM_Y1+5*14
+#define SM_H2           4*14-9
+#define SM_Y3           SM_Y2+5*14
+#define SM_H3           3*14-9
+
+
+#define CTL_X           19
+#define CTL_Y           32
+#define CTL_W           284
+#define CTL_H           105
+
+
+#define CST_X           20
+#define CST_Y           43
+#define CST_START       60
+#define CST_SPC         60
+
+
+#define TUF_X           0
+#define TUF_Y           32
+
+
+#define HLP_X           34
+#define HLP_Y           63
+#define HLP_W           264
+#define HLP_H           51
+
+
+#define MU_X            32
+#define MU_Y            22
+#define MU_W            252
+#define MU_H            118
+
+
+#define FX_X            32
+#define FX_Y            16
+#define FX_W            252
+#define FX_H            130
+
+
+#define MP_X            55//32
+#define MP_Y            60
+#define MP_W            252
+#define MP_H            35
+
+
+#define X1_X            55
+#define X1_Y            25
+#define X1_W            252
+
+#define X2_X            55
+#define X2_Y            65
+#define X2_W            252
+#define X2_H            35
+
+#define X3_X            55
+#define X3_Y            65
+#define X3_W            252
+#define X3_H            35
+
+#define LEVSEL_X            32
+#define LEVSEL_Y            22
+#define LEVSEL_W            252
+#define LEVSEL_H            118
+#define MAXCUSTOM       12
+
+#define STARTITEM       newgame
+
+//
+// General defines
+//
+#define CP_SemiActive      4
+#define CP_Highlight       5
+
+#define OUTOFRANGE         100
+#define ESCPRESSED         -1
+#define PAGEUP             -2
+#define PAGEDOWN           -3
+#define NOTAVAILABLECOLOR  7
+#define NEXTPAGECOLOR      16
+#define NORMALCOLOR        21
+#define DIMMEDCOLOR        24
+#define ACTIVECOLOR        241
+#define HIGHLIGHTCOLOR     1
+
+#define MouseInt 0x33
+#define GAMESVD      "There's already a game\n" \
+                     "saved at this position.\n"\
+                     "Overwrite?"
+#define COLOR        235
+
+#define CUSTOMX      76
+
+#define NUMSAVEGAMES 14
+
+#define PWORDX 58
+#define PWORDY 46
+//#define PBOXX  68
+#define PBOXX  ( ( 288 - PBOXW ) / 2 )
+#define PBOXY  71
+#define PBOXW  115
+#define PSTRW  110
+#define PBOXH  12
+
+
+#define QUICKSAVEBACKUP ("rottgamf.rot")
+//******************************************************************************
+//
+// ENUMS
+//
+//******************************************************************************
+
+typedef struct
+{
+   int allowed[4];
+} CustomCtrls;
+
+// FOR INPUT TYPES
+enum {MOUSE, JOYSTICK, KEYBOARDBTNS, KEYBOARDMOVE, SPECIAL1, SPECIAL2};
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+static byte *ScanNames[] =    // Scan code names with single chars
+{
+   "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
+   "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
+   "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
+   "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
+   "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
+   "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+   "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+   "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
+};
+
+
+static byte ExtScanCodes[] = // Scan codes with >1 char names
+{
+   1,    0xe,  0xf,  0x1d, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+   0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0x46, 0x1c, 0x36,
+   0x37, 0x38, 0x47, 0x49, 0x4f, 0x51, 0x52, 0x53, 0x45, 0x48,
+   0x50, 0x4b, 0x4d, 0x00
+};
+
+static byte *ExtScanNames[] = // Names corresponding to ExtScanCodes
+{
+   "Esc","BkSp","Tab","Ctrl","Space","CapLk","F1","F2","F3","F4",
+   "F5","F6","F7","F8","F9","F10","F11","F12","SclLk","Enter","Shift",
+   "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
+   "Down","Left","Right",""
+};
+
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void MouseSensitivity (void);
+void DoThreshold (void);
+byte * IN_GetScanName (ScanCode scan);
+void DisplayInfo (int which);
+
+void PrintLSEntry (int w);
+
+void DrawHalfStep (int x, int y);
+
+void DrawCtlScreen (void);
+void DrawCtlButtons (void);
+void DrawSoundMenu (void);
+void DrawCustomScreen (void);
+void DrawLoadSaveScreen (int loadsave);
+void DrawLoadSaveScreenAlt (int loadsave);
+void DrawMusicMenu (void);
+void DrawNewGame (void);
+void DrawNewGameDiff (int w);
+void DrawNewPlayerDiff (int w);
+void DrawFXMenu (void);
+void DrawFXButtons (void);
+void DrawCustomJoystick (void);
+void DrawCustomMouse (void);
+void DrawCustomSpecial (void);
+void DrawCustomMenu (void);
+void DrawPlayerMenu (void);
+
+void DoMainMenu (void);
+
+boolean CP_DisplayMsg (char *s, int number);
+void CP_EndGame (void);
+int CP_SaveGame (void);
+void CP_Control (void);
+void CP_Sound (void);
+void CP_ChangeView (void);
+void CP_DoubleClickSpeed( void );
+void CP_ErrorMsg( char *title, char *error, int font );
+void CP_Quit (int which);
+void CP_NewGame (void);
+void CP_Music (void);
+void CP_FX (void);
+void CP_MCports (void);
+void CP_FXMenu (void);
+void CP_Custom (void);
+void CP_Keyboard (void);
+void CP_Mouse (void);
+void CP_Joystick (void);
+void CP_Special (void);
+void CP_OrderInfo( void );
+
+void DefineMouseBtns1 (void);
+void DefineMouseBtns2 (void);
+void DefineKeyBtns1 (void);
+void DefineKeyBtns2 (void);
+void DefineKeyMove1 (void);
+void DefineKeyMove2 (void);
+void DefineJoyBtns1 (void);
+void DefineJoyBtns2 (void);
+void DefineSpecialBtns1 (void);
+void DefineSpecialBtns2 (void);
+
+void DrawSTMenuBuf (int x, int y, int w, int h, boolean up);
+
+void MusicVolume (void);
+void FXVolume (void);
+
+void DefineKey( void );
+void DefineJoyBtn( void );
+void DefineMouseBtn( void );
+
+void DrawControlMenu (void);
+void CP_ControlMenu (void);
+void DrawOptionsMenu (void);
+void DrawExtOptionsMenu (void);
+void CP_ExtOptionsMenu (void);
+void CP_OptionsMenu (void);
+void DrawOptionsButtons (void);
+void DrawExtOptionsButtons (void);
+void MenuFlipSpeed (void);
+void DrawDetailMenu (void);
+void CP_DetailMenu (void);
+void DrawBattleMenu (void);
+void CP_BattleMenu (void);
+void MCERROR (void);
+
+void DrawKeyboardMenu (void);
+void CP_KeyboardMenu (void);
+boolean SliderMenu( int *number, int upperbound, int lowerbound, int erasex,
+   int erasey, int erasew, int numadjust, char *blockname,
+   void (*routine) (int w), char *title, char *left, char *right );
+
+void DrawF1Help (void);
+void CP_F1Help (void);
+void CP_ScreenSize( void );
+
+void CP_ViolenceMenu (void);
+void DrawViolenceLevelMenu (void);
+void DrawViolenceLevelPWord (void);
+
+void DrawViolenceLevel (void);
+void CP_ViolenceLevel (void);
+
+void DrawPWMenu (void);
+void CP_PWMenu (void);
+
+void DrawBattleModes (void);
+void CP_BattleModes (void);
+
+void DrawBattleOptions (void);
+void CP_BattleOptions (void);
+
+void DrawGravityMenu (void);
+void CP_GravityOptions (void);
+void DrawSpeedMenu (void);
+void CP_SpeedOptions (void);
+void DrawAmmoPerWeaponMenu (void);
+void CP_AmmoPerWeaponOptions (void);
+void DrawHitPointsMenu (void);
+void CP_HitPointsOptions (void);
+void DrawSpawnControlMenu (void);
+void DrawSpawnControlButtons (void);
+void CP_SpawnControlOptions (void);
+void DrawLightLevelMenu (void);
+void CP_LightLevelOptions (void);
+void DrawPointGoalMenu (void);
+void CP_PointGoalOptions (void);
+void DrawDangerMenu (void);
+void CP_DangerOptions (void);
+void DrawTimeLimitMenu (void);
+void CP_TimeLimitOptions (void);
+void PrintBattleOption( boolean inmenu, int x, int y, char *text );
+
+void CP_OnePlayerWarningMessage( void );
+
+void DrawMultiPageCustomMenu( char *title, void ( *redrawfunc )( void ) );
+
+#endif

Added: tags/rott-1.1/rott/_rt_msg.h
===================================================================
--- tags/rott-1.1/rott/_rt_msg.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_msg.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,25 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_msg_private
+#define _rt_msg_private
+
+#define MESSAGETIME (35*6)
+
+#endif

Added: tags/rott-1.1/rott/_rt_net.h
===================================================================
--- tags/rott-1.1/rott/_rt_net.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_net.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,122 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_net_private
+#define _rt_net_private
+
+#define DEMOBUFFSIZE 50000
+
+#define FASTSPEED (0xB000)
+
+#define SETUPTIME     15
+
+#define PlayerCommand(player,command)    \
+        (PlayerCmds[(player)]->Commands[(command)])
+
+#define ClientCommand(player,command)    \
+        (ClientCmds[(player)]->Commands[(command)])
+
+#define LocalCommand(command)    \
+        (LocalCmds->Commands[(command)])
+
+#define ServerCommand(command)    \
+        (ServerCmds->Commands[(command)])
+
+#define CommandAddress(time)    \
+        (((time)-controlupdatestartedtime) & (MAXCMDS-1))
+
+#define NextLocalCommand()    \
+        (LocalCommand(CommandAddress(controlupdatetime)))
+
+#define NextServerCommand()    \
+        (ServerCommand(CommandAddress(serverupdatetime)))
+
+#define ClientTimeCommand(which,whichtime)    \
+        (ClientCmds[(which)]->Commands[(CommandAddress((whichtime)))])
+
+#define ServerCommandStatus(whichtime)    \
+        (CommandState[0]->CommandStates[(CommandAddress((whichtime)))])
+
+#define ServerCommandNumberStatus(command)    \
+        (CommandState[0]->CommandStates[(command)])
+
+#define ClientCommandStatus(which, whichtime)    \
+        (CommandState[(which+1)]->CommandStates[(CommandAddress((whichtime)))])
+
+#define ClientCommandNumberStatus(which, command)    \
+        (CommandState[(which+1)]->CommandStates[(command)])
+
+/*
+#define PacketAddress(time)    \
+        ((time) & (MAXCMDS-1))
+*/
+
+#define PacketAddress(time)    \
+        (time)
+
+
+#define NETWORKTIMEOUT  (VBLCOUNTER/3)
+#define MODEMTIMEOUT    (VBLCOUNTER/2)
+#define SERVERTIMEOUT    (VBLCOUNTER<<3)
+
+#define MAXPOLLTICS 3
+
+
+typedef enum {
+   scfp_nodata,
+   scfp_gameready,
+   scfp_data,
+   scfp_done
+} setupcheckforpacketstate;
+
+typedef enum {
+   cs_ready,
+   cs_notarrived,
+   cs_fixing
+} en_CommandStatus;
+
+typedef enum {
+   player_ingame,
+   player_quitgame,
+   player_leftgame
+} en_playerstatus;
+
+void PreparePacket (MoveType * pkt);
+int  GetPacketSize (void * pkt);
+void SendPacket (void * pkt, int dest);
+void GetRemotePacket (int from, int delay);
+void ResendLocalPackets  (int time, int dest, int numpackets);
+void ResendServerPackets (int time, int dest, int numpackets);
+void ResendPacket (void * pkt, int dest);
+void AddClientDelta (void * pkt, int src);
+void FixupPacket (void * pkt, int src);
+void ProcessPacket (void * pkt, int src);
+void AddServerPacket(void * pkt, int src);
+void AddClientPacket (void * pkt, int src);
+void AddPacket (void * pkt, int src);
+void RequestPacket (int time, int dest, int numpackets);
+boolean AllPlayersReady ( void );
+boolean AreClientsReady ( void );
+boolean IsServerCommandReady ( int time );
+void UpdatePlayerObj ( int player );
+void AddServerSubPacket(COM_ServerHeaderType * serverpkt);
+void AddSubPacket (void * pkt, int src);
+
+
+#endif

Added: tags/rott-1.1/rott/_rt_play.h
===================================================================
--- tags/rott-1.1/rott/_rt_play.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_play.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,125 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_playr_private
+#define _rt_playr_private
+
+#include "watcom.h"
+//double dTopYZANGLELIMIT; in winrott.c
+#define TopYZANGLELIMIT  (44*FINEANGLES/360)//bna added
+#define YZANGLELIMIT  (80*FINEANGLES/360)//bna--(30*FINEANGLES/360)
+/*
+//bna++ had to limit this or the sky would fuck up 
+#define TopYZANGLELIMIT  (6*FINEANGLES/360)//bna added
+#define YZANGLELIMIT  (40*FINEANGLES/360)//bna--(30*FINEANGLES/360)
+//partly fixed you can now se up but not down very much see rt_playr.c TopYZANGLELIMIT
+*/
+
+
+#define YZTILTSPEED   20*4//*2 = bna added
+#define SNAPBACKSPEED 10*15//*2 = bna added
+#define YZHORIZONSPEED 4*5//*2 = bna added
+#define HORIZONYZOFFSET (FINEANGLES/4)
+#define SetPlayerHorizon(ps,hlevel)    \
+    {                                  \
+    if ((hlevel)>YZANGLELIMIT)           \
+       (ps)->horizon=HORIZONYZOFFSET+YZANGLELIMIT;\
+    else if ((hlevel)<-YZANGLELIMIT)     \
+       (ps)->horizon=HORIZONYZOFFSET-YZANGLELIMIT;\
+    else                                  \
+       (ps)->horizon=HORIZONYZOFFSET+(hlevel);\
+	 }
+
+#define StartWeaponChange \
+{\
+ SD_PlaySoundRTP(SD_SELECTWPNSND,ob->x,ob->y);\
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;\
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )\
+	 DrawBarAmmo (false);            \
+}
+
+
+#define BULLETHOLEOFFSET 0x700
+
+#define M_DIST(x1,x2,y1,y2)   (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
+
+#define W_CHANGE(x)   ((x->weapondowntics) || (x->weaponuptics))
+#define NOMOM         ((!ob->momentumx) && (!ob->momentumy))
+#define DISTOK(p1,p2,d)    (abs((p1)-(p2)) <= d)
+#define Fix(a)        (a &= (FINEANGLES-1))
+#define REMOTEPKTSIZE    (sizeof(MoveType))
+#define BJRUNSPEED   2048
+#define BJJUMPSPEED  680
+#define PROJECTILESIZE 0xc000l
+
+#define MOVESCALE       150l
+#define BACKMOVESCALE   100l
+#define EXTRAPOINTS     40000
+#define JETPACKTHRUST (64)
+
+#define RUNMOVE      0xa00
+#define BASEMOVE     0x600
+#define ANGLEMOVE    0x100000
+
+#define SGN(x)                 (x>0 ? 1 : -1)
+#define NETMOM    (BASEMOVE+0x10000)
+
+#define DISTANCE(x1,x2,y1,y2)   (FixedMulShift((x1-x2),(x1-x2),16)+FixedMulShift((y1-y2),(y1-y2),16))
+
+#define TILTLIMIT     95
+#define PLAYERSTEPTIME 0xf000
+
+#define HITWALLSPEED  0x2800
+#define GODVIEWANGLE  FINEANGLES/150
+#define GODOFFSET     10
+#define DOGOFFSET     46
+#define KESTICS       70
+#define BBTIME        105
+
+#define KEYBOARDNORMALTURNAMOUNT (0x160000)
+//#define KEYBOARDPREAMBLETURNAMOUNT (0xe0000)
+#define KEYBOARDPREAMBLETURNAMOUNT (0xa0000)
+#define TURBOTURNTIME      (5)
+#define TURBOTURNAMOUNT    (0x1e000)
+#define TURNAROUNDSPEED   ((ANG180<<16)/15)
+
+#define VR_INPUT_SERVICE (0x30)
+#define VR_FEEDBACK_SERVICE (0x31)
+
+#define VR_RUNBUTTON         (0)
+#define VR_STRAFELEFTBUTTON  (1)
+#define VR_STRAFERIGHTBUTTON (2)
+#define VR_ATTACKBUTTON      (3)
+#define VR_LOOKUPBUTTON      (4)
+#define VR_LOOKDOWNBUTTON    (5)
+#define VR_SWAPWEAPONBUTTON  (6)
+#define VR_USEBUTTON         (7)
+#define VR_HORIZONUPBUTTON   (8)
+#define VR_HORIZONDOWNBUTTON (9)
+#define VR_MAPBUTTON         (10)
+#define VR_PISTOLBUTTON      (11)
+#define VR_DUALPISTOLBUTTON  (12)
+#define VR_MP40BUTTON        (13)
+#define VR_MISSILEWEAPONBUTTON (14)
+#define VR_RECORDBUTTON      (15)
+
+#define STEPADJUST 3
+void BatAttack(objtype*ob);
+void  T_DogLick (objtype *ob);
+#endif

Added: tags/rott-1.1/rott/_rt_rand.h
===================================================================
--- tags/rott-1.1/rott/_rt_rand.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_rand.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,291 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_rand_private
+#define _rt_rand_private
+
+//****************************************************************************
+//
+// Private header for RT_RAND.C
+//
+//****************************************************************************
+
+#define SIZE_OF_RANDOM_TABLE   2048
+
+static const unsigned char RandomTable[ SIZE_OF_RANDOM_TABLE ] =
+   {
+   107,   65,  179,   81,  212,    1,   34,  230,
+   167,  142,   82,   27,   62,   88,  140,  119,
+   222,  252,  254,  160,   26,   33,   30,  234,
+   162,  216,  126,   42,   20,  108,  245,  150,
+   167,  145,  215,  226,  153,  184,  251,  141,
+   116,  225,  201,  114,  111,   92,  223,  185,
+   199,  160,  244,  190,  113,   77,  217,  239,
+    15,  239,  129,  243,   21,  242,  202,  183,
+    49,  151,   38,   38,  147,  179,  234,  130,
+   138,  110,  228,  118,   93,   81,  253,   98,
+   246,   44,   75,  161,  189,   86,   85,  204,
+   169,   95,  199,  178,  186,  123,  200,  250,
+   118,  242,   86,   48,    7,  205,   71,  132,
+   185,  214,  192,   68,  191,  236,  175,  197,
+   199,  177,  163,   57,  220,  139,  133,  182,
+    91,  196,  246,   29,  177,   82,  184,  226,
+   209,  151,  206,  250,  195,  119,  193,  235,
+   144,  146,   58,   61,  245,   83,  204,  214,
+   249,  164,  212,  172,   90,  199,  242,  182,
+   228,  159,  127,   37,  209,  165,   89,  122,
+    87,  254,  222,   43,  148,  205,  155,  230,
+    74,  127,  238,  181,  154,  170,  232,   47,
+   105,   31,   96,  166,  208,    5,  201,   73,
+   244,   67,   55,  168,   84,  221,  251,   85,
+    44,  198,    8,   35,  229,  122,  229,   80,
+   137,   28,  202,  135,  211,   69,  100,  250,
+   224,  156,   75,  128,  176,   53,  207,  157,
+   241,  216,  210,  124,  163,  248,  223,  174,
+   241,  235,   97,  120,   25,    3,  218,  102,
+   143,  187,  202,  116,  209,  253,  227,  151,
+   203,  254,  223,   65,  146,  255,  231,  237,
+   162,  187,  194,   90,  198,   81,  219,   94,
+    70,  158,  106,  175,   81,  239,  181,   79,
+    62,  184,   21,   30,   98,  245,  233,    8,
+    57,   54,  133,   95,   43,  125,  161,  109,
+   167,  130,   32,   46,   72,    3,   42,   34,
+   147,  139,   19,  122,   49,   23,  253,  192,
+   231,  116,  165,    8,   15,   16,  223,  140,
+    29,  136,    2,  114,  248,  219,  214,  168,
+    36,  241,  210,   63,  230,   42,  197,  100,
+   134,  159,  179,  149,   17,   96,  152,   45,
+    93,  151,   26,  202,   35,   58,  189,  220,
+    74,  173,  250,   76,   57,   52,   55,   14,
+   205,   80,  213,  190,   14,  108,   60,   89,
+   236,   41,   53,   59,  249,  237,   88,  217,
+   129,  252,  169,  123,   87,   23,   91,   79,
+    36,  164,   89,   24,  102,  111,  104,  115,
+   116,  221,  212,   82,  166,   16,  244,   18,
+    68,   73,   64,  194,   82,  115,  121,  216,
+   133,   47,   85,  124,  242,  144,    1,   65,
+     0,   75,   91,   83,  137,  183,  132,   15,
+    66,  227,   67,   98,  186,  100,  208,  150,
+    74,   61,   69,  130,  120,   56,   39,   21,
+    44,  166,  180,  145,   97,  101,   68,   19,
+   243,  162,  222,  228,    9,  160,  185,   10,
+   168,   64,  109,  198,  113,   75,   48,   52,
+   119,  163,  176,  201,   12,  246,   20,   92,
+    31,  175,   33,    4,   70,  169,  218,   86,
+   240,  127,    7,   38,  102,   94,  112,   90,
+   114,   63,  139,  119,   45,    5,  183,  224,
+   155,   13,  141,   90,   93,  177,  118,   67,
+   211,  117,   58,  158,  135,   83,  236,  194,
+    72,   59,  131,   40,  196,  232,  247,  132,
+    18,   73,   37,  207,   50,  187,   32,  174,
+    13,   34,  135,   39,   46,  192,   51,  203,
+   216,    3,  188,   99,  245,  112,   61,  206,
+   127,  118,  136,  186,  153,  148,  140,  106,
+    55,  201,   19,    9,   27,   97,   84,   24,
+    48,  227,  108,  202,    5,  190,    6,  235,
+   160,  146,  123,  222,  212,  147,   27,   28,
+    50,  226,  200,  221,  180,  244,   34,  146,
+    41,  104,   37,  217,   10,  238,   52,  198,
+     4,   29,  126,   16,   45,  124,   64,   25,
+    40,   20,  138,  225,   71,  247,  128,   62,
+    62,  178,   31,  251,  197,  215,  226,  193,
+    28,   25,   82,   15,   21,   43,   30,   86,
+    50,   99,  199,  191,   80,  171,  250,    4,
+   149,   61,  163,  128,  143,   95,   76,   56,
+    14,  109,   54,   84,  137,   43,   77,  255,
+   204,  151,  129,    8,   20,   26,  193,   38,
+   205,  125,  203,   22,   78,   47,  101,   37,
+   121,  113,  141,   36,   33,   23,  131,   55,
+    78,   96,  123,  228,   69,  213,   51,  147,
+   195,  195,   85,   54,  225,   65,  143,   13,
+   152,   60,  110,   29,  146,  179,  164,   17,
+    96,   67,  156,    7,    3,   92,   26,  104,
+   157,  220,  211,  154,  103,    2,  174,  136,
+    83,  229,   18,  116,   66,   87,    0,   74,
+    98,   58,   75,  162,  254,  177,   89,  173,
+   169,  107,   12,   90,   71,  193,   53,  255,
+   138,    2,  233,  163,   11,  138,  183,  209,
+   119,  210,  249,  112,  113,   30,  185,  180,
+    11,  171,  164,   77,    5,   99,   35,  218,
+    11,  159,  221,  148,  170,  137,  129,  188,
+   231,  172,  191,  135,  176,   33,  189,   68,
+   190,  152,    7,  220,  246,  203,  181,   63,
+   199,   91,  251,  208,  217,   39,  170,  111,
+   182,  209,  216,  247,  240,  165,  153,  118,
+   238,  233,  204,   12,  126,  105,  168,  234,
+    38,  184,  132,  110,  145,  227,  165,   92,
+   241,   24,  251,  231,  213,  126,  240,  214,
+    31,   11,  223,   46,    0,   35,  218,  242,
+   211,  191,   48,  110,  253,   94,  161,  139,
+    42,  148,  198,  246,  239,  107,   57,    5,
+   117,  252,    9,   12,   73,   77,   58,  167,
+     6,  142,   32,   34,   72,   31,  243,  170,
+     0,   93,  182,   56,  254,  158,  250,   23,
+    77,   81,   45,   69,  142,  237,  225,   44,
+   232,  142,  209,  115,   61,   38,  224,   70,
+    53,   82,   10,  229,  214,  224,  101,   42,
+   100,  121,  133,   85,   67,  150,  116,   91,
+    79,   79,  235,   22,    1,  244,   16,  101,
+    88,   25,   43,  242,   53,  106,  128,   40,
+    18,    2,  196,   22,   47,   96,  130,  249,
+    49,  117,  178,  171,  132,  189,   95,   66,
+   153,  200,   71,   71,  215,  113,  102,  131,
+   172,  235,  192,  204,  107,  127,   60,   52,
+   254,   84,   20,   27,  107,   44,   72,  149,
+   230,   87,   64,  144,  140,  186,  154,   49,
+    76,  156,  162,  219,    9,  146,   41,   80,
+    59,  142,  147,  184,  115,  158,  103,  140,
+     8,  234,  157,   17,  112,   22,  163,  187,
+    47,  178,  207,   63,  125,  202,  156,   30,
+    97,  193,  171,  173,  204,   28,    4,  195,
+   109,  211,  105,  103,  179,  221,  203,  138,
+   139,  172,   14,   44,  119,  150,  185,  180,
+   205,  255,  152,   94,  205,  173,   40,  134,
+    13,   65,  194,  196,   68,  124,   26,  134,
+    85,  228,   50,  216,  159,  254,  237,  206,
+   103,   69,   90,  187,  182,  183,    2,  114,
+     3,  201,    1,  129,  212,  232,   81,   33,
+    56,  182,  133,  176,   19,    6,  144,   84,
+   145,   24,  243,  234,   35,   25,   89,  150,
+    54,  143,  207,  104,  248,  102,   41,  253,
+    46,   44,  197,  208,  200,   52,  219,  238,
+   223,  241,   60,  230,  196,   42,   88,   51,
+   170,   25,   40,  114,   39,   45,   57,   29,
+   186,   54,   36,  167,   51,  249,  194,  108,
+   250,  199,   67,  212,  123,  151,   92,   32,
+    46,   12,  248,  165,  223,   24,  143,  189,
+   120,   57,   38,  222,  169,   17,  188,   27,
+   209,  176,  215,  108,  177,   96,   50,  154,
+    41,   15,   32,  181,   99,  120,   73,  225,
+    49,  200,   43,  177,   72,  202,   97,   92,
+   240,  110,  252,   21,   28,  192,   70,  128,
+    85,   60,  127,   63,  235,  100,  155,   65,
+   241,  119,   34,   80,   75,  117,  148,  102,
+    15,   90,  121,  206,  104,  164,  132,   98,
+    36,  108,  214,    0,   84,   94,  107,  154,
+    14,   26,   23,   93,  195,  224,  162,  171,
+   245,   76,  125,  158,  120,   66,   80,  130,
+   183,  120,  179,  118,   31,  176,  106,  184,
+   164,  111,   59,  253,  118,   62,  114,  215,
+   156,  161,  127,  210,  112,  122,  204,   86,
+    29,   69,  187,  218,  233,   47,  188,   91,
+   105,  153,  236,  116,  135,   19,   83,  175,
+    88,  166,  156,  238,  245,  227,  248,  161,
+    10,  180,   22,  230,  157,  205,    6,   37,
+     3,  234,  155,   49,  239,  229,  122,  223,
+   234,  206,   82,  135,  190,   77,  130,  197,
+   144,  226,  123,  181,  143,  208,  169,    8,
+     1,  174,   97,  177,  232,  201,  210,  193,
+   192,   62,  211,   28,  252,   19,  189,  229,
+   191,  246,    7,  202,   35,   20,   28,   30,
+    70,  221,   55,  159,  237,   10,   15,  134,
+   124,  103,   73,  172,   26,  201,   13,  117,
+    35,  131,  136,   66,   33,  245,  159,  207,
+   225,  147,   18,  248,  126,  131,   33,  153,
+   101,   60,  186,  216,  250,   11,   30,   50,
+    57,   58,  151,  178,  181,  227,  128,  253,
+    10,    5,  224,   48,  160,   34,    7,  111,
+   124,   27,  160,   75,  137,   17,   53,   39,
+   243,  236,   39,   81,  217,  122,   79,   32,
+    13,  115,  191,  167,  137,   87,  228,   91,
+    86,   78,   18,   22,   40,   76,   94,  129,
+   119,   87,   63,  197,  203,   21,  218,  185,
+   166,   49,  161,  213,   38,  111,  209,  154,
+    43,  152,  134,  132,    4,  133,  108,   83,
+   145,   41,   97,   74,  251,  173,   42,  213,
+    46,  118,   73,   68,   21,  244,  106,  158,
+    11,   90,  252,  140,   44,  157,  194,   66,
+   229,   58,  215,  251,  144,  125,  146,  172,
+   165,  136,  105,  102,  173,   95,  150,  169,
+    78,  230,  111,  160,  196,  112,  120,  231,
+   168,  152,  149,  174,  128,  232,  194,  122,
+     3,   74,  231,  105,   12,  239,  180,  239,
+    89,  235,   95,  157,  149,  187,    6,  203,
+   188,   71,  110,    8,  126,  242,  188,  249,
+    71,  123,  162,   93,   59,   65,   16,  222,
+   192,   24,   27,  142,  168,  114,   89,  220,
+   226,  182,  207,   94,  195,  207,  174,  228,
+   142,  130,  115,  175,  154,  106,  206,   48,
+   185,  147,  155,  224,  239,   64,   88,   83,
+    54,  247,  113,  248,  137,   96,    5,  110,
+   240,   51,    1,  208,  166,  200,  233,  167,
+   230,   14,   20,  198,   36,   13,    0,  220,
+   165,  104,   85,  122,    1,  255,  212,  161,
+   190,   37,   86,  226,  195,  105,   78,  244,
+   236,  168,   48,  211,  121,  216,   25,  144,
+    16,  237,    7,   75,   12,   99,   56,  109,
+   218,   87,   35,  204,  155,   61,  191,   41,
+    61,   57,  121,  236,   62,   22,  187,   95,
+    92,   69,  210,  163,  205,  214,   34,   84,
+    73,  184,  109,  124,  231,  103,  217,  241,
+    77,  175,  183,  232,  198,  164,   14,  125,
+   103,  197,  249,  241,  176,   59,   48,   50,
+    25,  222,  134,  199,  252,  196,   23,   19,
+    78,    0,   59,  120,   91,  121,  117,  228,
+    52,   68,  113,  127,  141,   67,   65,  130,
+   132,  243,  160,  138,  138,  116,   10,   98,
+   170,   70,  246,  206,  219,   28,   94,  226,
+    29,   58,  255,   31,  141,   82,  134,  152,
+   251,   84,   52,   23,  154,  139,   74,   55,
+    47,  198,  167,  162,    4,   16,  220,   53,
+    37,  158,  135,  136,  190,   86,  151,  178,
+   238,  161,   88,  171,  148,  169,  137,  212,
+   181,  146,  189,   70,   49,   79,  142,  131,
+   195,  126,  149,  156,   93,   55,  164,  174,
+    87,  243,   66,   92,  207,    9,  126,  123,
+    40,   51,  133,  143,    9,   55,  193,  173,
+    56,   64,  210,  159,    6,  178,  145,  153,
+   115,  215,  185,  238,  101,  210,   98,  157,
+    95,  171,  235,  217,  240,  232,  107,   53,
+    54,  211,  111,  236,  100,   37,  147,   64,
+    60,  215,  174,  136,  128,   98,   79,  234,
+   145,   76,  197,  165,  191,  141,  114,  109,
+   148,  214,   93,   12,  163,  125,  222,   96,
+    71,  220,    8,  225,  200,   14,  139,  166,
+   155,    9,  237,    9,  172,    6,  229,  179,
+   247,   76,   24,  213,   26,  248,   56,  247,
+   106,  221,   63,   20,  206,  231,  168,  196,
+   208,   36,   31,  175,  178,  255,  124,  156,
+   129,  186,   45,  201,    7,  112,  189,   68,
+   225,   64,  150,   74,    2,  218,   62,  159,
+     4,   11,  213,   40,   23,   15,   67,   52,
+   182,  203,  246,  194,   72,   33,   89,  104,
+    16,  131,   60,  150,  243,   21,   59,  175,
+   219,  149,   56,  224,   32,  105,  153,   99,
+    80,  148,  107,   99,  108,   43,  106,   41,
+    32,  244,    4,  186,  253,   27,  233,  104,
+   245,    5,    2,  252,  170,    2,  101,   39,
+    17,  166,  221,   11,  227,  129,  103,   45,
+   144,   79,   17,  139,   70,  237,  176,    6,
+    76,  134,   54,   30,   69,   13,  100,  149,
+   141,  227,  255,   22,  179,   61,   88,   97,
+   121,   29,   24,   77,  170,  190,  242,  109,
+   152,   47,   81,  140,   45,   46,  249,   78,
+   180,  143,  102,   19,  208,  177,   72,   72,
+   247,   51,  115,    3,  141,  117,   39,  188,
+   180,  171,   83,    1,    0,   51,  100,  112,
+   172,   18,  219,  136,  155,  125,  200,  131,
+   157,  217,   78,   63,  213,  238,  193,  173,
+   145,   46,  101,  158,   42,  140,  110,   66,
+   183,  181,  233,  188,   10,  133,   36,  135,
+    17,  254,  138,  233,  117,  240,  184,   80,
+   113,   18,   99,  219,  240,   50,  192,  247
+   };
+
+#endif

Added: tags/rott-1.1/rott/_rt_scal.h
===================================================================
--- tags/rott-1.1/rott/_rt_scal.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_scal.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,25 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_scale_private
+#define _rt_scale_private
+
+#define PLAYERHEIGHT (260<<HEIGHTFRACTION)
+
+#endif

Added: tags/rott-1.1/rott/_rt_soun.h
===================================================================
--- tags/rott-1.1/rott/_rt_soun.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_soun.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,114 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_sound_private
+#define _rt_sound_private
+
+#define SOUNDTYPES 2
+
+typedef struct
+{
+   int     snds[SOUNDTYPES];
+   byte    flags;
+   byte    priority;
+   byte    count;
+   int     prevhandle;
+   int     prevdistance;
+} sound_t;
+
+#define SD_OVERWRITE  0x01
+#define SD_WRITE      0x02
+#define SD_LOOP       0x04
+#define SD_PITCHSHIFTOFF 0x08
+#define SD_PLAYONCE      0x10
+
+enum {
+   sd_prio0=17,
+   sd_prio1=16,
+   sd_prio2=15,
+   sd_prio3=14,
+   sd_prio4=13,
+   sd_prio5=12,
+   sd_prio6=11,
+   sd_prio7=10,
+   sd_prio8=9,
+   sd_prio9=8,
+   sd_prio10=7,
+   sd_prio11=6,
+   sd_prio12=5,
+   sd_prio13=4,
+   sd_prio14=3,
+   sd_prio15=2,
+   sd_prio16=1
+} ;
+
+#define SD_PRIOSECRET sd_prio1
+#define SD_PRIOREMOTE sd_prio1
+#define SD_PRIOPHURT  sd_prio1
+#define SD_PRIOGAME   sd_prio2
+#define SD_PRIOBOSS   sd_prio2
+#define SD_PRIOGODDOG sd_prio2
+#define SD_PRIOEXPL   sd_prio3
+#define SD_PRIOASNEAK sd_prio3
+#define SD_PRIOADEATH sd_prio3
+#define SD_PRIOPMISS  sd_prio4
+#define SD_PRIOPGUNS  sd_prio5
+#define SD_PRIOAFIRE  sd_prio6
+#define SD_PRIOPMP40  sd_prio7
+#define SD_PRIOAHURT  sd_prio8
+#define SD_PRIOGLASS  sd_prio9
+#define SD_PRIOPSNDS  sd_prio11
+#define SD_PRIOPCAUSD sd_prio12
+#define SD_PRIOAGREET sd_prio13
+#define SD_PRIOENVRON sd_prio14
+#define SD_PRIOQUIT   sd_prio15
+#define SD_PRIOMENU   sd_prio16
+
+#define SD_DISTANCESHIFT 12
+
+#define USEADLIB 255
+
+#define SD_RANDOMSHIFT 1
+
+#define PitchOffset()  ((RandomNumber("Pitch Offset",0)-128)>>SD_RANDOMSHIFT)
+
+#define SoundOffset(x) (sounds[x].snds[soundtype])
+
+#define GUSMIDIINIFILE ("gusmidi.ini")
+
+
+typedef enum {
+   loop_yes,
+   loop_no
+} looptypes;
+
+
+typedef struct
+{
+   byte    loopflag;
+   byte    songtype;
+   char    lumpname[9];
+   char    songname[40];
+} song_t;
+
+int SD_PlayIt ( int sndnum, int angle, int distance, int pitch );
+boolean SD_SoundOkay ( int sndnum );
+
+#endif
+

Added: tags/rott-1.1/rott/_rt_spba.h
===================================================================
--- tags/rott-1.1/rott/_rt_spba.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_spba.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,27 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_spba_private
+#define _rt_spba_private
+
+#define SGN(x)                 (x>0 ? 1 : -1)
+
+#define NUMSPACEBALLBUTTONS 6
+
+#endif

Added: tags/rott-1.1/rott/_rt_stat.h
===================================================================
--- tags/rott-1.1/rott/_rt_stat.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_stat.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_stat_private
+#define _rt_stat_private
+
+void        AddStatic(statobj_t*);
+void        AddAnimStatic(statobj_t*);
+void        PreCacheStaticSounds(int);
+
+#define SOLIDCOLORTICTIME   1
+#define SOLIDCOLORINCREMENT 1
+#define MAXFIRECOLOR      248
+#define INITIALFIRECOLOR  246
+#define IsLight(x,y)          ( (x>=0) && (x<=127) && (y>=0) && (y<=127) &&   \
+										  (sprites[x][y]) && (sprites[x][y]->flags & FL_LIGHT) )
+
+typedef struct
+{
+    int  tictime,
+         numanims;
+    char firstlump[9];
+} awallinfo_t;
+
+
+typedef struct sas
+{
+  int          x,y,z;
+  int          flags;
+  signed char  ticcount;
+  int          hitpoints;
+  short int    shapenum;
+  signed char  ammo;
+  signed char  count;
+  signed char  itemnumber;
+  short int    areanumber;
+  short int    whichstat;
+  byte         numanims;
+  int          linked_to;
+}saved_stat_type;
+
+#endif

Added: tags/rott-1.1/rott/_rt_str.h
===================================================================
--- tags/rott-1.1/rott/_rt_str.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_str.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,44 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+//******************************************************************************
+//
+// Private header for RT_STR.C
+//
+//******************************************************************************
+
+#ifndef _rt_str_private
+#define _rt_str_private
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void VWB_DrawPropString  (const char *string);
+void VW_MeasurePropString (const char *string, int *width, int *height );
+
+//void (*USL_MeasureString)(const char *, int *, int *, font_t *) = VW_MeasurePropString,
+//     (*USL_DrawString)(const char *) = VWB_DrawPropString;
+void (*USL_MeasureString)(const char *, int *, int *, font_t *) = (void (*)(const char *, int *, int *, font_t *))VW_MeasurePropString,
+     (*USL_DrawString)(const char *) = VWB_DrawPropString;
+
+
+#endif

Added: tags/rott-1.1/rott/_rt_swft.h
===================================================================
--- tags/rott-1.1/rott/_rt_swft.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_swft.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,109 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_swift_private
+#define _rt_swift_private
+
+#ifdef DOS
+//****************************************************************************
+//
+// Private header for RT_SWIFT.C.
+//
+//****************************************************************************
+
+
+
+//****************************************************************************
+//
+// DEFINES
+//
+//****************************************************************************
+
+#define DPMI_INT     0x31
+#define MOUSE_INT    0x33
+#define DOSMEMSIZE   64                // enough for any SWIFT structure
+
+//
+// device type codes, returned in deviceType field (SWIFT_StaticData)		
+//
+#define SWIFT_DEV_NONE		0
+#define SWIFT_DEV_CYBERMAN	1
+
+//
+// Dynamic device data
+//
+#define SDD_EXTERNAL_POWER_CONNECTED	1
+#define SDD_EXTERNAL_POWER_TOO_HIGH	   2
+
+#define AX(r) ((r).x.eax)
+#define BX(r) ((r).x.ebx)
+#define CX(r) ((r).x.ecx)
+#define DX(r) ((r).x.edx)
+#define SI(r) ((r).x.esi)
+#define DI(r) ((r).x.edi)
+
+
+//****************************************************************************
+//
+// TYPEDEFS
+//
+//****************************************************************************
+
+                                          // Active flag:
+static int fActive;                       //  TRUE after successful init
+                                          //  and before termination
+static int nAttached = SWIFT_DEV_NONE;    // type of SWIFT device
+
+union REGS regs;
+struct SREGS sregs;
+
+short selector;                           // selector of DOS memory block
+short segment;                            // segment of DOS memory block
+void far *pdosmem;                        // pointer to DOS memory block
+
+// DPMI real mode interrupt structure
+static struct rminfo
+{
+    long di;
+    long si;
+    long bp;
+    long reserved_by_system;
+    long bx;
+    long dx;
+    long cx;
+    long ax;
+    short flags;
+    short es, ds, fs, gs, ip, cs, sp, ss;
+} RMI;
+
+
+//****************************************************************************
+//
+// PROTOTYPES
+//
+//****************************************************************************
+
+void MouseInt (struct rminfo *prmi);
+static void far *allocDOS (unsigned nbytes, short *pseg, short *psel);
+static void freeDOS (short sel);
+
+#endif
+
+#endif
+

Added: tags/rott-1.1/rott/_rt_ted.h
===================================================================
--- tags/rott-1.1/rott/_rt_ted.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_ted.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,103 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_ted_private
+#define _rt_ted_private
+
+#define  MAXPRECACHE    3500
+
+#include "rt_actor.h"
+#include "develop.h"
+
+#define SHAREWARE_TAG     0x4d4b
+#define REGISTERED_TAG    0x4344
+#define RTL_VERSION       ( 0x0101 )
+#define COMMBAT_SIGNATURE ( "RTC" )
+#define NORMAL_SIGNATURE  ( "RTL" )
+#define RTL_HEADER_OFFSET 8
+
+typedef struct
+{
+	int  lump;
+	int  cachelevel;
+	int  type; // To make precaching possible on big endian machines
+} cachetype;
+
+//========================================
+
+typedef struct
+{
+        short   RLEWtag;
+        int             headeroffsets[100];
+        byte            tileinfo[1];
+} mapfiletype;
+
+
+typedef struct
+{
+        int   planestart[3];
+        word  planelength[3];
+        word  width,height;
+        char            name[16];
+} maptype;
+
+#define ActorIsPushWall(xx,yy)   ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->which==PWALL) )
+#define ActorIsWall(xx,yy)   ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->which==WALL) )
+#define ActorIsSpring(xx,yy)   ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->obclass==springobj) )
+#define StaticUndefined(xx,yy)   ((sprites[xx][yy])&&(((statobj_t *)sprites[xx][yy])->z<-64) )
+
+#define  PRECACHEASTRINGX 141
+#define  PRECACHEASTRINGY 8
+
+#define  PRECACHEESTRINGX 16
+#define  PRECACHEESTRINGY 8
+
+#define  PRECACHESTRINGX 16
+#define  PRECACHESTRINGY 144
+
+#define  PRECACHEBARX 28
+#define  PRECACHEBARY 178
+
+#define  PRECACHELED1X 9
+#define  PRECACHELED1Y 8
+
+#define  PRECACHELED2X 9
+#define  PRECACHELED2Y 12
+
+#define  MAXLEDS 57
+
+#define  MAXSILLYSTRINGS 32
+
+#if (SHAREWARE==0)
+   #define  STANDARDGAMELEVELS   (DATADIR "DARKWAR.RTL")
+   #if (SUPERROTT==1)
+       #define  STANDARDBATTLELEVELS (DATADIR "ROTTCD.RTC")
+   #elif (SITELICENSE==1)
+       #define  STANDARDBATTLELEVELS (DATADIR "ROTTSITE.RTC")
+   #else
+       #define  STANDARDBATTLELEVELS (DATADIR "DARKWAR.RTC")
+   #endif
+#else
+   #define  STANDARDGAMELEVELS   (DATADIR "HUNTBGIN.RTL")
+   #define  STANDARDBATTLELEVELS (DATADIR "HUNTBGIN.RTC")
+#endif
+
+
+
+#endif

Added: tags/rott-1.1/rott/_rt_util.h
===================================================================
--- tags/rott-1.1/rott/_rt_util.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_util.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,47 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_util_private
+#define _rt_util_private
+
+#ifdef DOS
+#define PEL_WRITE_ADR   0x3c8
+#define PEL_READ_ADR    0x3c7
+#define PEL_DATA        0x3c9
+#define PEL_MASK        0x3c6
+#endif
+
+#define ERRORROW        2
+#define ERRORCOL        11
+
+#define ERRORFILE       ("rotterr.txt")
+#define SOFTERRORFILE   ("error.txt")
+#define DEBUGFILE       ("rott.dbg")
+#define MAPDEBUGFILE    ("mapinfo.txt")
+
+#define SGN(x)          ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
+
+#define SLASHES         ('\\')
+#define MAXCHARS        8
+
+#define WeightR  3
+#define WeightG  5
+#define WeightB  2
+
+#endif

Added: tags/rott-1.1/rott/_rt_vid.h
===================================================================
--- tags/rott-1.1/rott/_rt_vid.h	                        (rev 0)
+++ tags/rott-1.1/rott/_rt_vid.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _rt_vid_private
+#define _rt_vid_private
+
+//******************************************************************************
+//
+// Private header for RT_VID.C
+//
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// DEFINES
+//
+//******************************************************************************
+
+#define PIXTOBLOCK         4
+
+#define VW_Hlin(x,z,y,c)   VL_Hlin(x,y,(z)-(x)+1,c)
+#define VW_Vlin(y,z,x,c)   VL_Vlin(x,y,(z)-(y)+1,c)
+
+#define VW_THlin(x,z,y,up)    VL_THlin(x,y,(z)-(x)+1, up)
+#define VW_TVlin(y,z,x,up)    VL_TVlin(x,y,(z)-(y)+1, up)
+
+
+#endif

Added: tags/rott-1.1/rott/_w_wad.h
===================================================================
--- tags/rott-1.1/rott/_w_wad.h	                        (rev 0)
+++ tags/rott-1.1/rott/_w_wad.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,76 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _w_wad_private
+#define _w_wad_private
+
+#include "develop.h"
+
+#define CHECKPERIOD 20
+
+
+#if ( SHAREWARE == 1 )
+
+#if ( DELUXE == 1)
+#define WADCHECKSUM (54748)
+#elif ( LOWCOST == 1)
+#define WADCHECKSUM (12185)
+#else
+#ifdef DOS
+#define WADCHECKSUM (45677)
+#else
+#define WADCHECKSUM (20567)
+#endif
+#endif
+
+#else
+
+#define WADCHECKSUM (24222)
+
+#endif
+
+//===============
+//   TYPES
+//===============
+
+
+typedef struct
+{
+        char            name[8];
+        int             handle,position,size;
+        int             byteswapped;
+} lumpinfo_t;
+
+
+typedef struct
+{
+        char            identification[4];              // should be IWAD
+        int             numlumps;
+        int             infotableofs;
+} wadinfo_t;
+
+
+typedef struct
+{
+        int             filepos;
+        int             size;
+        char            name[8];
+} filelump_t;
+
+#endif

Added: tags/rott-1.1/rott/_z_zone.h
===================================================================
--- tags/rott-1.1/rott/_z_zone.h	                        (rev 0)
+++ tags/rott-1.1/rott/_z_zone.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,57 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef _z_zone_private
+#define _z_zone_private
+
+#include "develop.h"
+
+#define MINFRAGMENT     64
+#define DPMI_INT  0x31
+#define MAXMEMORYSIZE   9000000
+
+#define LEVELZONESIZE   250000
+
+// memory storage data types
+
+#define MEMORYPRETAG   (0x1a2b3c4d)
+#define MEMORYPOSTTAG  (0x9f8e7d6b)
+
+typedef struct memblock_s
+{
+#if (MEMORYCORRUPTIONTEST==1)
+         int     pretag;
+#endif
+         int     size;   // including the header and possibly tiny fragments
+         void    **user; // NULL if a free block
+			int     tag;    // purgelevel
+         struct memblock_s   *next, *prev;
+#if (MEMORYCORRUPTIONTEST==1)
+         int     posttag;
+#endif
+} memblock_t;
+
+typedef struct
+{
+         int     size;          // total bytes malloced, including header
+         memblock_t  blocklist; // start / end cap for linked list
+         memblock_t  *rover;
+} memzone_t;
+
+#endif

Added: tags/rott-1.1/rott/audiolib/Makefile
===================================================================
--- tags/rott-1.1/rott/audiolib/Makefile	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/Makefile	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,22 @@
+CC=gcc
+AR=ar
+RANLIB=ranlib
+CFLAGS=-g -O2
+LDLIBS=
+
+CFLAGS += $(shell sdl-config --cflags)
+LDLIBS += $(shell sdl-config --libs)
+
+OBJ=fx_man.o dsl.o ll_man.o multivoc.o mv_mix.o mvreverb.o nodpmi.o \
+	pitch.o user.o usrhooks.o
+
+audiolib.a: $(OBJ)
+	rm -rf $@
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:
+	rm -rf audiolib.a *.o
+
+distclean: clean
+	rm -rf *~

Added: tags/rott-1.1/rott/audiolib/_al_midi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_al_midi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_al_midi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,174 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef ___AL_MIDI_H
+#define ___AL_MIDI_H
+
+#define NO_ADLIB_DETECTION    "NOAL"
+
+#define STEREO_DETUNE 5
+
+#define lobyte( num )   ( ( unsigned )*( ( char * )&( num ) ) )
+#define hibyte( num )   ( ( unsigned )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define AL_VoiceNotFound -1
+
+#define  alFreqH     0xb0
+#define  alEffects   0xbd
+
+/* Number of slots for the voices on the chip */
+#define NumChipSlots 18
+
+#define NUM_VOICES      9
+#define NUM_CHANNELS    16
+
+#define NOTE_ON         0x2000  /* Used to turn note on or toggle note */
+#define NOTE_OFF        0x0000
+
+#define MAX_VELOCITY   0x7f
+#define MAX_OCTAVE     7
+#define MAX_NOTE       ( MAX_OCTAVE * 12 + 11 )
+#define FINETUNE_MAX   31
+#define FINETUNE_RANGE ( FINETUNE_MAX + 1 )
+
+#define PITCHBEND_CENTER 1638400
+
+#define note_off             0x80
+#define note_on              0x90
+#define poly_aftertouch      0xa0
+#define control_change       0xb0
+#define program_chng         0xc0
+#define channel_aftertouch   0xd0
+#define pitch_wheel          0xe0
+
+#define MIDI_VOLUME          7
+#define MIDI_PAN             10
+#define MIDI_DETUNE          94
+#define MIDI_ALL_NOTES_OFF   0x7B
+#define MIDI_RESET_ALL_CONTROLLERS 0x79
+#define MIDI_RPN_MSB               100
+#define MIDI_RPN_LSB               101
+#define MIDI_DATAENTRY_MSB         6
+#define MIDI_DATAENTRY_LSB         38
+#define MIDI_PITCHBEND_RPN         0
+
+enum cromatic_scale
+   {
+   C       = 0x157,
+   C_SHARP = 0x16B,
+   D_FLAT  = 0x16B,
+   D       = 0x181,
+   D_SHARP = 0x198,
+   E_FLAT  = 0x198,
+   E       = 0x1B0,
+   F_FLAT  = 0x1B0,
+   E_SHARP = 0x1CA,
+   F       = 0x1CA,
+   F_SHARP = 0x1E5,
+   G_FLAT  = 0x1E5,
+   G       = 0x202,
+   G_SHARP = 0x220,
+   A_FLAT  = 0x220,
+   A       = 0x241,
+   A_SHARP = 0x263,
+   B_FLAT  = 0x263,
+   B       = 0x287,
+   C_FLAT  = 0x287,
+   B_SHARP = 0x2AE,
+   };
+
+/* Definition of octave information to be ORed onto F-Number */
+
+enum octaves
+   {
+   OCTAVE_0 = 0x0000,
+   OCTAVE_1 = 0x0400,
+   OCTAVE_2 = 0x0800,
+   OCTAVE_3 = 0x0C00,
+   OCTAVE_4 = 0x1000,
+   OCTAVE_5 = 0x1400,
+   OCTAVE_6 = 0x1800,
+   OCTAVE_7 = 0x1C00
+   };
+
+typedef struct VOICE
+   {
+   struct VOICE *next;
+   struct VOICE *prev;
+
+   unsigned num;
+   unsigned key;
+   unsigned velocity;
+   unsigned channel;
+   unsigned pitchleft;
+   unsigned pitchright;
+   int      timbre;
+   int      port;
+   unsigned status;
+   } VOICE;
+
+typedef struct
+   {
+   VOICE *start;
+   VOICE *end;
+   } VOICELIST;
+
+typedef struct
+   {
+   VOICELIST Voices;
+   int       Timbre;
+   int       Pitchbend;
+   int       KeyOffset;
+   unsigned  KeyDetune;
+   unsigned  Volume;
+   unsigned  EffectiveVolume;
+   int       Pan;
+   int       Detune;
+   unsigned  RPN;
+   short     PitchBendRange;
+   short     PitchBendSemiTones;
+   short     PitchBendHundreds;
+   } CHANNEL;
+
+typedef struct
+   {
+   unsigned char SAVEK[ 2 ];
+   unsigned char Level[ 2 ];
+   unsigned char Env1[ 2 ];
+   unsigned char Env2[ 2 ];
+   unsigned char Wave[ 2 ];
+   unsigned char Feedback;
+   signed   char Transpose;
+   signed   char Velocity;
+   } TIMBRE;
+
+extern TIMBRE ADLIB_TimbreBank[ 256 ];
+
+static void AL_ResetVoices( void );
+static void AL_CalcPitchInfo( void );
+static void AL_SetVoiceTimbre( int voice );
+static void AL_SetVoiceVolume( int voice );
+static int  AL_AllocVoice( void );
+static int  AL_GetVoice( int channel, int key );
+static void AL_SetVoicePitch( int voice );
+static void AL_SetChannelVolume( int channel, int volume );
+static void AL_SetChannelPan( int channel, int pan );
+static void AL_SetChannelDetune( int channel, int detune );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_blaster.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_blaster.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_blaster.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,133 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: _BLASTER.H
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Private header for for BLASTER.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___BLASTER_H
+#define ___BLASTER_H
+
+#define VALID   ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define YES ( 1 == 1 )
+#define NO  ( !YES )
+
+#define lobyte( num )   ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num )   ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define BLASTER_MixerAddressPort  0x04
+#define BLASTER_MixerDataPort     0x05
+#define BLASTER_ResetPort         0x06
+#define BLASTER_ReadPort          0x0A
+#define BLASTER_WritePort         0x0C
+#define BLASTER_DataAvailablePort 0x0E
+#define BLASTER_Ready             0xAA
+#define BLASTER_16BitDMAAck       0x0F
+
+#define MIXER_DSP4xxISR_Ack       0x82
+#define MIXER_DSP4xxISR_Enable    0x83
+#define MIXER_MPU401_INT          0x4
+#define MIXER_16BITDMA_INT        0x2
+#define MIXER_8BITDMA_INT         0x1
+#define MIXER_DisableMPU401Interrupts 0xB
+#define MIXER_SBProOutputSetting  0x0E
+#define MIXER_SBProStereoFlag     0x02
+#define MIXER_SBProVoice          0x04
+#define MIXER_SBProMidi           0x26
+#define MIXER_SB16VoiceLeft       0x32
+#define MIXER_SB16VoiceRight      0x33
+#define MIXER_SB16MidiLeft        0x34
+#define MIXER_SB16MidiRight       0x35
+
+#define DSP_Version1xx            0x0100
+#define DSP_Version2xx            0x0200
+#define DSP_Version201            0x0201
+#define DSP_Version3xx            0x0300
+#define DSP_Version4xx            0x0400
+#define DSP_SB16Version           DSP_Version4xx
+
+#define DSP_MaxNormalRate         22000
+#define DSP_MaxHighSpeedRate      44000
+
+#define DSP_8BitAutoInitRecord        0x2c
+#define DSP_8BitHighSpeedAutoInitRecord 0x98
+#define DSP_Old8BitADC                0x24
+#define DSP_8BitAutoInitMode          0x1c
+#define DSP_8BitHighSpeedAutoInitMode 0x90
+#define DSP_SetBlockLength            0x48
+#define DSP_Old8BitDAC                0x14
+#define DSP_16BitDAC                  0xB6
+#define DSP_8BitDAC                   0xC6
+#define DSP_8BitADC                   0xCe
+#define DSP_SetTimeConstant           0x40
+#define DSP_Set_DA_Rate               0x41
+#define DSP_Set_AD_Rate               0x42
+#define DSP_Halt8bitTransfer          0xd0
+#define DSP_Continue8bitTransfer      0xd4
+#define DSP_Halt16bitTransfer         0xd5
+#define DSP_Continue16bitTransfer     0xd6
+#define DSP_SpeakerOn                 0xd1
+#define DSP_SpeakerOff                0xd3
+#define DSP_GetVersion                0xE1
+#define DSP_Reset                     0xFFFF
+
+#define DSP_SignedBit                 0x10
+#define DSP_StereoBit                 0x20
+
+#define DSP_UnsignedMonoData      0x00
+#define DSP_SignedMonoData        ( DSP_SignedBit )
+#define DSP_UnsignedStereoData    ( DSP_StereoBit )
+#define DSP_SignedStereoData      ( DSP_SignedBit | DSP_StereoBit )
+
+#define BlasterEnv_Address    'A'
+#define BlasterEnv_Interrupt  'I'
+#define BlasterEnv_8bitDma    'D'
+#define BlasterEnv_16bitDma   'H'
+#define BlasterEnv_Type       'T'
+#define BlasterEnv_Midi       'P'
+#define BlasterEnv_EmuAddress 'E'
+
+#define CalcTimeConstant( rate, samplesize ) \
+   ( ( 65536L - ( 256000000L / ( ( samplesize ) * ( rate ) ) ) ) >> 8 )
+
+#define CalcSamplingRate( tc ) \
+   ( 256000000L / ( 65536L - ( tc << 8 ) ) )
+
+typedef struct
+   {
+   int IsSupported;
+   int HasMixer;
+   int MaxMixMode;
+   int MinSamplingRate;
+   int MaxSamplingRate;
+   } CARD_CAPABILITY;
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_guswave.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_guswave.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_guswave.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,164 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   _GUSWAVE.H
+
+   author: James R. Dose
+   date:   March 23, 1994
+
+   Private header for GUSWAVE.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___GUSWAVE_H
+#define ___GUSWAVE_H
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define LOADDS _loadds
+
+#define VOC_8BIT            0x0
+#define VOC_CT4_ADPCM       0x1
+#define VOC_CT3_ADPCM       0x2
+#define VOC_CT2_ADPCM       0x3
+#define VOC_16BIT           0x4
+#define VOC_ALAW            0x6
+#define VOC_MULAW           0x7
+#define VOC_CREATIVE_ADPCM  0x200
+
+#define MAX_BLOCK_LENGTH 0x8000
+
+#define GF1BSIZE   896L   /* size of buffer per wav on GUS */
+//#define GF1BSIZE   512L   /* size of buffer per wav on GUS */
+
+//#define VOICES     8      /* maximum amount of concurrent wav files */
+#define VOICES     2      /* maximum amount of concurrent wav files */
+#define MAX_VOICES 32     /* This should always be 32 */
+#define MAX_VOLUME 4095
+#define BUFFER     2048U  /* size of DMA buffer for patch loading */
+
+typedef enum
+   {
+   Raw,
+   VOC,
+   DemandFeed,
+   WAV
+   } wavedata;
+
+typedef enum
+   {
+   NoMoreData,
+   KeepPlaying,
+   SoundDone
+   } playbackstatus;
+
+
+typedef volatile struct VoiceNode
+   {
+   struct VoiceNode *next;
+   struct VoiceNode *prev;
+
+   wavedata      wavetype;
+   int           bits;
+   playbackstatus ( *GetSound )( struct VoiceNode *voice );
+
+   int num;
+
+   unsigned long  mem;           /* location in ultrasound memory */
+   int            Active;        /* this instance in use */
+   int            GF1voice;      /* handle to active voice */
+
+   char          *NextBlock;
+   char          *LoopStart;
+   char          *LoopEnd;
+   unsigned       LoopCount;
+   unsigned long  LoopSize;
+   unsigned long  BlockLength;
+
+   unsigned long  PitchScale;
+
+   unsigned char *sound;
+   unsigned long  length;
+   unsigned long  SamplingRate;
+   unsigned long  RateScale;
+   int            Playing;
+
+   int    handle;
+   int    priority;
+
+   void          ( *DemandFeed )( char **ptr, unsigned long *length );
+
+   unsigned long callbackval;
+
+   int    Volume;
+   int    Pan;
+   }
+VoiceNode;
+
+typedef struct
+   {
+   VoiceNode *start;
+   VoiceNode *end;
+   }
+voicelist;
+
+typedef volatile struct voicestatus
+   {
+   VoiceNode *Voice;
+   int playing;
+   }
+voicestatus;
+
+typedef struct
+   {
+   char          RIFF[ 4 ];
+   unsigned long file_size;
+   char          WAVE[ 4 ];
+   char          fmt[ 4 ];
+   unsigned long format_size;
+   } riff_header;
+
+typedef struct
+   {
+   unsigned short wFormatTag;
+   unsigned short nChannels;
+   unsigned long  nSamplesPerSec;
+   unsigned long  nAvgBytesPerSec;
+   unsigned short nBlockAlign;
+   unsigned short nBitsPerSample;
+   } format_header;
+
+typedef struct
+   {
+   unsigned char DATA[ 4 ];
+   unsigned long size;
+   } data_header;
+
+playbackstatus GUSWAVE_GetNextVOCBlock( VoiceNode *voice );
+VoiceNode *GUSWAVE_GetVoice( int handle );
+
+int GUSWAVE_Play( VoiceNode *voice, int angle, int volume, int channels );
+
+VoiceNode *GUSWAVE_AllocVoice( int priority );
+static int GUSWAVE_InitVoices( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_midi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_midi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_midi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: _MIDI.H
+
+   author: James R. Dose
+   date:   May 25, 1994
+
+   Private header for MIDI.C.  Midi song file playback routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___MIDI_H
+#define ___MIDI_H
+
+#define RELATIVE_BEAT( measure, beat, tick ) \
+   ( ( tick ) + ( ( beat ) << 9 ) + ( ( measure ) << 16 ) )
+
+//Bobby Prince thinks this may be 100
+//#define GENMIDI_DefaultVolume 100
+#define GENMIDI_DefaultVolume 90
+
+#define MAX_FORMAT            1
+
+#define NUM_MIDI_CHANNELS     16
+
+#define TIME_PRECISION        16
+
+#define MIDI_HEADER_SIGNATURE 0x6468544d    // "MThd"
+#define MIDI_TRACK_SIGNATURE  0x6b72544d    // "MTrk"
+
+#define MIDI_VOLUME                7
+#define MIDI_PAN                   10
+#define MIDI_DETUNE                94
+#define MIDI_RHYTHM_CHANNEL        9
+#define MIDI_RPN_MSB               100
+#define MIDI_RPN_LSB               101
+#define MIDI_DATAENTRY_MSB         6
+#define MIDI_DATAENTRY_LSB         38
+#define MIDI_PITCHBEND_MSB         0
+#define MIDI_PITCHBEND_LSB         0
+#define MIDI_RUNNING_STATUS        0x80
+#define MIDI_NOTE_OFF              0x8
+#define MIDI_NOTE_ON               0x9
+#define MIDI_POLY_AFTER_TCH        0xA
+#define MIDI_CONTROL_CHANGE        0xB
+#define MIDI_PROGRAM_CHANGE        0xC
+#define MIDI_AFTER_TOUCH           0xD
+#define MIDI_PITCH_BEND            0xE
+#define MIDI_SPECIAL               0xF
+#define MIDI_SYSEX                 0xF0
+#define MIDI_SYSEX_CONTINUE        0xF7
+#define MIDI_META_EVENT            0xFF
+#define MIDI_END_OF_TRACK          0x2F
+#define MIDI_TEMPO_CHANGE          0x51
+#define MIDI_TIME_SIGNATURE        0x58
+#define MIDI_RESET_ALL_CONTROLLERS 0x79
+#define MIDI_ALL_NOTES_OFF         0x7b
+#define MIDI_MONO_MODE_ON          0x7E
+#define MIDI_SYSTEM_RESET          0xFF
+
+#define GET_NEXT_EVENT( track, data ) \
+   ( data ) = *( track )->pos; \
+   ( track )->pos += 1
+
+#define GET_MIDI_CHANNEL( event )       ( ( event ) & 0xf )
+#define GET_MIDI_COMMAND( event )       ( ( event ) >> 4 )
+
+#define EMIDI_INFINITE          -1
+#define EMIDI_END_LOOP_VALUE    127
+#define EMIDI_ALL_CARDS         127
+#define EMIDI_INCLUDE_TRACK     110
+#define EMIDI_EXCLUDE_TRACK     111
+#define EMIDI_PROGRAM_CHANGE    112
+#define EMIDI_VOLUME_CHANGE     113
+#define EMIDI_CONTEXT_START     114
+#define EMIDI_CONTEXT_END       115
+#define EMIDI_LOOP_START        116
+#define EMIDI_LOOP_END          117
+#define EMIDI_SONG_LOOP_START   118
+#define EMIDI_SONG_LOOP_END     119
+
+#define EMIDI_GeneralMIDI       0
+#define EMIDI_SoundCanvas       1
+#define EMIDI_AWE32             2
+#define EMIDI_WaveBlaster       3
+#define EMIDI_SoundBlaster      4
+#define EMIDI_ProAudio          5
+#define EMIDI_SoundMan16        6
+#define EMIDI_Adlib             7
+#define EMIDI_Soundscape        8
+#define EMIDI_Ultrasound        9
+
+#define EMIDI_AffectsCurrentCard( c, type ) \
+   ( ( ( c ) == EMIDI_ALL_CARDS ) || ( ( c ) == ( type ) ) )
+
+
+#define EMIDI_NUM_CONTEXTS      7
+typedef struct
+   {
+   unsigned char *pos;
+   unsigned char *loopstart;
+   short          loopcount;
+   short          RunningStatus;
+   unsigned       time;
+   long           FPSecondsPerTick;
+   short          tick;
+   short          beat;
+   short          measure;
+   short          BeatsPerMeasure;
+   short          TicksPerBeat;
+   short          TimeBase;
+   long           delay;
+   short          active;
+   } songcontext;
+
+typedef struct
+   {
+   unsigned char *start;
+   unsigned char *pos;
+
+   long           delay;
+   short          active;
+   short          RunningStatus;
+
+   short          currentcontext;
+   songcontext    context[ EMIDI_NUM_CONTEXTS ];
+
+   char           EMIDI_IncludeTrack;
+   char           EMIDI_ProgramChange;
+   char           EMIDI_VolumeChange;
+   } track;
+
+static long _MIDI_ReadNumber( void *from, size_t size );
+static long _MIDI_ReadDelta( track *ptr );
+static void _MIDI_ResetTracks( void );
+static void _MIDI_AdvanceTick( void );
+static void _MIDI_MetaEvent( track *Track );
+static void _MIDI_SysEx( track *Track );
+static int  _MIDI_InterpretControllerInfo( track *Track, int TimeSet,
+   int channel, int c1, int c2 );
+//static
+   void _MIDI_ServiceRoutine( task *Task );
+static int  _MIDI_SendControlChange( int channel, int c1, int c2 );
+static void _MIDI_SetChannelVolume( int channel, int volume );
+static void _MIDI_SendChannelVolumes( void );
+static int  _MIDI_ProcessNextTick( void );
+static void _MIDI_InitEMIDI( void );
+
+/*
+               if ( c1 == EMIDI_LOOP_START )
+                  {
+                  if ( c2 == 0 )
+                     {
+                     Track->context[ 0 ].loopcount = EMIDI_INFINITE;
+                     }
+                  else
+                     {
+                     Track->context[ 0 ].loopcount = c2;
+                     }
+
+                  Track->context[ 0 ].pos              = Track->pos;
+                  Track->context[ 0 ].loopstart        = Track->pos;
+                  Track->context[ 0 ].RunningStatus    = Track->RunningStatus;
+                  Track->context[ 0 ].time             = _MIDI_Time;
+                  Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+                  Track->context[ 0 ].tick             = _MIDI_Tick;
+                  Track->context[ 0 ].beat             = _MIDI_Beat;
+                  Track->context[ 0 ].measure          = _MIDI_Measure;
+                  Track->context[ 0 ].BeatsPerMeasure  = _MIDI_BeatsPerMeasure;
+                  Track->context[ 0 ].TicksPerBeat     = _MIDI_TicksPerBeat;
+                  Track->context[ 0 ].TimeBase         = _MIDI_TimeBase;
+                  break;
+                  }
+
+               if ( ( c1 == EMIDI_LOOP_END ) &&
+                  ( c2 == EMIDI_END_LOOP_VALUE ) )
+                  {
+                  if ( ( Track->context[ 0 ].loopstart != NULL ) &&
+                     ( Track->context[ 0 ].loopcount != 0 ) )
+                     {
+                     if ( Track->context[ 0 ].loopcount != EMIDI_INFINITE )
+                        {
+                        Track->context[ 0 ].loopcount--;
+                        }
+
+                     Track->pos           = Track->context[ 0 ].loopstart;
+                     Track->RunningStatus = Track->context[ 0 ].RunningStatus;
+
+                     if ( !TimeSet )
+                        {
+                        _MIDI_Time             = Track->context[ 0 ].time;
+                        _MIDI_FPSecondsPerTick = Track->context[ 0 ].FPSecondsPerTick;
+                        _MIDI_Tick             = Track->context[ 0 ].tick;
+                        _MIDI_Beat             = Track->context[ 0 ].beat;
+                        _MIDI_Measure          = Track->context[ 0 ].measure;
+                        _MIDI_BeatsPerMeasure  = Track->context[ 0 ].BeatsPerMeasure;
+                        _MIDI_TicksPerBeat     = Track->context[ 0 ].TicksPerBeat;
+                        _MIDI_TimeBase         = Track->context[ 0 ].TimeBase;
+                        TimeSet = TRUE;
+                        }
+                     }
+                  break;
+                  }
+
+               if ( c1 == MIDI_MONO_MODE_ON )
+                  {
+                  Track->pos++;
+                  }
+
+               if ( ( c1 == MIDI_VOLUME ) && ( !Track->EMIDI_VolumeChange ) )
+                  {
+                  _MIDI_SetChannelVolume( channel, c2 );
+                  break;
+                  }
+               else if ( ( c1 == EMIDI_VOLUME_CHANGE ) &&
+                  ( Track->EMIDI_VolumeChange ) )
+                  {
+                  _MIDI_SetChannelVolume( channel, c2 );
+                  break;
+                  }
+
+               if ( ( c1 == EMIDI_PROGRAM_CHANGE ) &&
+                  ( Track->EMIDI_ProgramChange ) )
+                  {
+                  _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
+                  break;
+                  }
+
+               if ( c1 == EMIDI_CONTEXT_START )
+                  {
+                  break;
+                  }
+
+               if ( c1 == EMIDI_CONTEXT_END )
+                  {
+                  if ( ( Track->currentcontext != _MIDI_Context ) ||
+                     ( Track->context[ _MIDI_Context ].pos == NULL )
+                     {
+                     break;
+                     }
+
+                  Track->currentcontext = _MIDI_Context;
+                  Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
+                  Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
+                  Track->pos           = Track->context[ _MIDI_Context ].pos;
+                  Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
+
+                  if ( TimeSet )
+                     {
+                     break;
+                     }
+
+                  _MIDI_Time             = Track->context[ _MIDI_Context ].time;
+                  _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
+                  _MIDI_Tick             = Track->context[ _MIDI_Context ].tick;
+                  _MIDI_Beat             = Track->context[ _MIDI_Context ].beat;
+                  _MIDI_Measure          = Track->context[ _MIDI_Context ].measure;
+                  _MIDI_BeatsPerMeasure  = Track->context[ _MIDI_Context ].BeatsPerMeasure;
+                  _MIDI_TicksPerBeat     = Track->context[ _MIDI_Context ].TicksPerBeat;
+                  _MIDI_TimeBase         = Track->context[ _MIDI_Context ].TimeBase;
+                  TimeSet = TRUE;
+                  break;
+                  }
+
+               if ( _MIDI_Funcs->ControlChange )
+                  {
+                  _MIDI_Funcs->ControlChange( channel, c1, c2 );
+                  }
+ */
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_multivc.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_multivc.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_multivc.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,286 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   _MULTIVC.H
+
+   author: James R. Dose
+   date:   December 20, 1993
+
+   Private header for MULTIVOC.C
+
+   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___MULTIVC_H
+#define ___MULTIVC_H
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define VOC_8BIT            0x0
+#define VOC_CT4_ADPCM       0x1
+#define VOC_CT3_ADPCM       0x2
+#define VOC_CT2_ADPCM       0x3
+#define VOC_16BIT           0x4
+#define VOC_ALAW            0x6
+#define VOC_MULAW           0x7
+#define VOC_CREATIVE_ADPCM  0x200
+
+#define T_SIXTEENBIT_STEREO 0
+#define T_8BITS       1
+#define T_MONO        2
+#define T_16BITSOURCE 4
+#define T_LEFTQUIET   8
+#define T_RIGHTQUIET  16
+#define T_DEFAULT     T_SIXTEENBIT_STEREO
+
+#define MV_MaxPanPosition  31
+#define MV_NumPanPositions ( MV_MaxPanPosition + 1 )
+#define MV_MaxTotalVolume  255
+//#define MV_MaxVolume       63
+#define MV_NumVoices       8
+
+#define MIX_VOLUME( volume ) \
+   ( ( max( 0, min( ( volume ), 255 ) ) * ( MV_MaxVolume + 1 ) ) >> 8 )
+//   ( ( max( 0, min( ( volume ), 255 ) ) ) >> 2 )
+
+//#define SILENCE_16BIT     0x80008000
+#define SILENCE_16BIT     0
+#define SILENCE_8BIT      0x80808080
+//#define SILENCE_16BIT_PAS 0
+
+#define MixBufferSize     256
+
+#define NumberOfBuffers   16
+#define TotalBufferSize   ( MixBufferSize * NumberOfBuffers )
+
+#define PI                3.1415926536
+
+typedef enum
+   {
+   Raw,
+   VOC,
+   DemandFeed,
+   WAV
+   } wavedata;
+
+typedef enum
+   {
+   NoMoreData,
+   KeepPlaying
+   } playbackstatus;
+
+
+typedef struct VoiceNode
+   {
+   struct VoiceNode *next;
+   struct VoiceNode *prev;
+
+   wavedata      wavetype;
+   char          bits;
+
+   playbackstatus ( *GetSound )( struct VoiceNode *voice );
+
+   void ( *mix )( unsigned long position, unsigned long rate,
+      const char *start, unsigned long length );
+
+   char         *NextBlock;
+   char         *LoopStart;
+   char         *LoopEnd;
+   unsigned      LoopCount;
+   unsigned long LoopSize;
+   unsigned long BlockLength;
+
+   unsigned long PitchScale;
+   unsigned long FixedPointBufferSize;
+
+   char         *sound;
+   unsigned long length;
+   unsigned long SamplingRate;
+   unsigned long RateScale;
+   unsigned long position;
+   int           Playing;
+
+   int           handle;
+   int           priority;
+
+   void          ( *DemandFeed )( char **ptr, unsigned long *length );
+
+   short        *LeftVolume;
+   short        *RightVolume;
+
+   unsigned long callbackval;
+
+   } VoiceNode;
+
+typedef struct
+   {
+   VoiceNode *start;
+   VoiceNode *end;
+   } VList;
+
+typedef struct
+   {
+   unsigned char left;
+   unsigned char right;
+   } Pan;
+
+typedef signed short MONO16;
+typedef signed char  MONO8;
+
+typedef struct
+   {
+   MONO16 left;
+   MONO16 right;
+//   unsigned short left;
+//   unsigned short right;
+   } STEREO16;
+
+typedef struct
+   {
+   MONO16 left;
+   MONO16 right;
+   } SIGNEDSTEREO16;
+
+typedef struct
+   {
+//   MONO8 left;
+//   MONO8 right;
+   char left;
+   char right;
+   } STEREO8;
+
+typedef struct
+   {
+   char          RIFF[ 4 ];
+   unsigned long file_size;
+   char          WAVE[ 4 ];
+   char          fmt[ 4 ];
+   unsigned long format_size;
+   } riff_header;
+
+typedef struct
+   {
+   unsigned short wFormatTag;
+   unsigned short nChannels;
+   unsigned long  nSamplesPerSec;
+   unsigned long  nAvgBytesPerSec;
+   unsigned short nBlockAlign;
+   unsigned short nBitsPerSample;
+   } format_header;
+
+typedef struct
+   {
+   unsigned char DATA[ 4 ];
+   unsigned long size;
+   } data_header;
+
+typedef MONO8  VOLUME8[ 256 ];
+typedef MONO16 VOLUME16[ 256 ];
+
+typedef char HARSH_CLIP_TABLE_8[ MV_NumVoices * 256 ];
+
+static void MV_Mix( VoiceNode *voice, int buffer );
+static void MV_PlayVoice( VoiceNode *voice );
+static void MV_StopVoice( VoiceNode *voice );
+static void MV_ServiceVoc( void );
+
+static playbackstatus MV_GetNextVOCBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextDemandFeedBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextRawBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextWAVBlock( VoiceNode *voice );
+
+static void       MV_ServiceRecord( void );
+static VoiceNode *MV_GetVoice( int handle );
+static VoiceNode *MV_AllocVoice( int priority );
+
+static short     *MV_GetVolumeTable( int vol );
+
+static void       MV_SetVoiceMixMode( VoiceNode *voice );
+
+static void       MV_SetVoicePitch( VoiceNode *voice, unsigned long rate, int pitchoffset );
+static void       MV_CalcVolume( int MaxLevel );
+static void       MV_CalcPanTable( void );
+
+#ifdef PLAT_DOS
+#define ATR_INDEX               0x3c0
+#define STATUS_REGISTER_1       0x3da
+
+#define SetBorderColor(color) \
+   { \
+   inp  (STATUS_REGISTER_1); \
+   outp (ATR_INDEX,0x31);    \
+   outp (ATR_INDEX,color);   \
+   }
+#endif
+
+void ClearBuffer_DW( void *ptr, unsigned data, int length );
+
+#ifdef PLAT_DOS
+#pragma aux ClearBuffer_DW = \
+   "cld",                    \
+   "push   es",              \
+   "push   ds",              \
+   "pop    es",              \
+   "rep    stosd",           \
+   "pop    es",              \
+parm [ edi ] [ eax ] [ ecx ] modify exact [ ecx edi ];
+#endif
+
+void MV_Mix8BitMono( unsigned long position, unsigned long rate,
+   const char *start, unsigned long length );
+
+void MV_Mix8BitStereo( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitMono( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitStereo( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitMono16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix8BitMono16( unsigned long position, unsigned long rate,
+   const char *start, unsigned long length );
+
+void MV_Mix8BitStereo16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitStereo16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length );
+
+void MV_16BitReverb( const char *src, char *dest, const VOLUME16 *volume, int count );
+
+void MV_8BitReverb( const signed char *src, signed char *dest, const VOLUME16 *volume, int count );
+
+void MV_16BitReverbFast( const char *src, char *dest, int count, int shift );
+
+void MV_8BitReverbFast( const signed char *src, signed char *dest, int count, int shift );
+
+#ifdef PLAT_DOS
+#pragma aux MV_16BitReverb parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_8BitReverb parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_16BitReverbFast parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_8BitReverbFast parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#endif
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_pas16.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_pas16.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_pas16.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,250 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: _PAS16.H
+
+   author: James R. Dose
+   date:   March 27, 1994
+
+   Private header for for PAS16.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___PAS16_H
+#define ___PAS16_H
+
+#define TRUE    ( 1 == 1 )
+#define FALSE   ( !TRUE )
+
+#define VALID   ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define lobyte( num )   ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num )   ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define STEREO      1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT    0
+#define STEREO_8BIT  ( STEREO )
+#define MONO_16BIT   ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define PAS_MaxMixMode        STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE    1
+#define MONO_16BIT_SAMPLE_SIZE   2
+#define STEREO_8BIT_SAMPLE_SIZE  ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define PAS_RevisionBits        0xe0
+
+#define AudioFilterControl      0xb8a
+#define InterruptControl        0xb8b
+#define InterruptStatus         0xb89
+#define PCMDataRegister         0xf88
+#define CrossChannelControl     0xf8a
+#define SampleRateTimer         0x1388
+#define SampleBufferCount       0x1389
+#define LocalSpeakerTimerCount  0x138a
+#define LocalTimerControl       0x138b
+#define SampleSizeConfiguration 0x8389
+
+#define AudioMuteFlag             0x20
+#define SampleRateTimerGateFlag   0x40
+#define SampleBufferCountGateFlag 0x80
+
+#define SampleRateInterruptFlag   0x04
+#define SampleBufferInterruptFlag 0x08
+
+#define PAS_SampleSizeMask     0xf3
+#define PAS_SignedSampleMask   0xe3
+#define PAS_16BitSampleFlag    0x04
+#define PAS_UnsignedSampleFlag 0x10
+//bSC2msbinv   equ   00010000b   ;; invert MSB from standard method
+
+#define PAS_OverSamplingMask 0xfc
+
+#define PAS_1xOverSampling  0x00
+#define PAS_2xOverSampling  0x01
+#define PAS_4xOverSampling  0x03
+
+#define PAS_StereoFlag      0x20
+
+#define PAS_AudioMuteFlag  0x20
+
+#define DEFAULT_BASE ( 0x0388 ^ 0x388 ) /* default base I/O address */
+#define ALT_BASE_1   ( 0x0384 ^ 0x388 ) /* first alternate address  */
+#define ALT_BASE_2   ( 0x038C ^ 0x388 ) /* second alternate address */
+#define ALT_BASE_3   ( 0x0288 ^ 0x388 ) /* third alternate address  */
+
+#define PAS_DMAEnable          0x80
+#define PAS_ChannelConnectMask 0x0f
+#define PAS_PCMStartDAC        0xD0
+#define PAS_PCMStartADC        0xC0
+#define PAS_PCMStopMask        0x3f
+
+#define RECORD   0
+#define PLAYBACK 1
+
+#define SelectSampleRateTimer   0x36   // 00110110b
+#define SelectSampleBufferCount 0x74   // 01110100b
+
+#define CalcTimeInterval( rate ) \
+   ( 1193180UL / ( rate ) )
+
+#define CalcSamplingRate( interval ) \
+   ( 1193180UL / ( interval ) )
+
+#define MV_Signature                 0x4d56
+#define MV_SoundInt                  0x2f
+#define MV_CheckForDriver            0xbc00
+#define MV_GetVersion                0xbc01
+#define MV_GetPointerToStateTable    0xbc02
+#define MV_GetPointerToFunctionTable 0xbc03
+#define MV_GetDmaIrqInt              0xbc04
+#define MV_SendCommandStructure      0xbc05
+#define MV_GetDriverMessage          0xbc06
+#define MV_SetHotkeyScanCodes        0xbc0a
+#define MV_GetPathToDriver           0xbc0b
+
+#define OUTPUTMIXER     0x00         /* output mixer H/W select */
+#define INPUTMIXER      0x40         /* input mixer select      */
+#define DEFMIXER        -1           /* use last mixer selected   */
+
+/* left channel values */
+
+#define L_FM            0x01
+#define L_IMIXER        0x02
+#define L_EXT           0x03
+#define L_INT           0x04
+#define L_MIC           0x05
+#define L_PCM           0x06
+#define L_SPEAKER       0x07
+#define L_FREE          0x00
+#define L_SBDAC         0x00
+
+/* right channel values */
+
+#define R_FM            0x08
+#define R_IMIXER        0x09
+#define R_EXT           0x0A
+#define R_INT           0x0B
+#define R_MIC           0x0C
+#define R_PCM           0x0D
+#define R_SPEAKER       0x0E
+#define R_FREE          0x0F
+#define R_SBDAC         0x0F
+
+typedef struct
+   {
+   unsigned char  sysspkrtmr;   /*   42 System Speaker Timer Address */
+   unsigned char  systmrctlr;   /*   43 System Timer Control         */
+   unsigned char  sysspkrreg;   /*   61 System Speaker Register      */
+   unsigned char  joystick;     /*  201 Joystick Register            */
+   unsigned char  lfmaddr;      /*  388 Left  FM Synth Address       */
+   unsigned char  lfmdata;      /*  389 Left  FM Synth Data          */
+   unsigned char  rfmaddr;      /*  38A Right FM Synth Address       */
+   unsigned char  rfmdata;      /*  38B Right FM Synth Data          */
+   unsigned char  dfmaddr;      /*  788 Dual  FM Synth Address       */
+   unsigned char  dfmdata;      /*  789 Dual  FM Synth Data          */
+   unsigned char  RESRVD1[1];   /*      reserved                     */
+   unsigned char  paudiomixr;   /*  78B Paralllel Audio Mixer Control*/
+   unsigned char  audiomixr;    /*  B88 Audio Mixer Control          */
+   unsigned char  intrctlrst;   /*  B89 Interrupt Status             */
+   unsigned char  audiofilt;    /*  B8A Audio Filter Control         */
+   unsigned char  intrctlr;     /*  B8B Interrupt Control            */
+   unsigned char  pcmdata;      /*  F88 PCM Data I/O Register        */
+   unsigned char  RESRVD2;      /*      reserved                     */
+   unsigned char  crosschannel; /*  F8A Cross Channel                */
+   unsigned char  RESRVD3;      /*      reserved                     */
+   unsigned short samplerate;   /* 1388 Sample Rate Timer            */
+   unsigned short samplecnt;    /* 1389 Sample Count Register        */
+   unsigned short spkrtmr;      /* 138A Shadow Speaker Timer Count   */
+   unsigned char  tmrctlr;      /* 138B Shadow Speaker Timer Control */
+   unsigned char  mdirqvect;    /* 1788 MIDI IRQ Vector Register     */
+   unsigned char  mdsysctlr;    /* 1789 MIDI System Control Register */
+   unsigned char  mdsysstat;    /* 178A MIDI IRQ Status Register     */
+   unsigned char  mdirqclr;     /* 178B MIDI IRQ Clear Register      */
+   unsigned char  mdgroup1;     /* 1B88 MIDI Group #1 Register       */
+   unsigned char  mdgroup2;     /* 1B89 MIDI Group #2 Register       */
+   unsigned char  mdgroup3;     /* 1B8A MIDI Group #3 Register       */
+   unsigned char  mdgroup4;     /* 1B8B MIDI Group #4 Register       */
+   } MVState;
+
+typedef struct
+   {
+   unsigned long SetMixer;
+   unsigned long SetVolume;
+   unsigned long SetFilter;
+   unsigned long SetCrossChannel;
+   unsigned long GetMixer;
+   unsigned long GetVolume;
+   unsigned long GetFilter;
+   unsigned long GetCrossChannel;
+   unsigned long ReadSound;
+   unsigned long FMSplit;
+   } MVFunc;
+
+int     PAS_CheckForDriver( void );
+MVState *PAS_GetStateTable( void );
+MVFunc  *PAS_GetFunctionTable( void );
+int     PAS_GetCardSettings( void );
+void    PAS_EnableInterrupt( void );
+void    PAS_DisableInterrupt( void );
+void    interrupt far PAS_ServiceInterrupt( void );
+//void    interrupt PAS_ServiceInterrupt( void );
+void    PAS_Write( int Register, int Data );
+int     PAS_Read( int Register );
+void    PAS_SetSampleRateTimer( void );
+void    PAS_SetSampleBufferCount( void );
+int     PAS_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+int     PAS_GetFilterSetting( int rate );
+void    PAS_BeginTransfer( int mode );
+int     PAS_TestAddress( int address );
+int     PAS_FindCard( void );
+int     PAS_CallMVFunction( unsigned long function, int ebx, int ecx, int edx );
+void    PAS_SaveState( void );
+void    PAS_RestoreState( void );
+
+
+#pragma aux PAS_TestAddress = \
+   "mov   dx, 0b8bh", \
+   "xor    dx, ax", \
+   "in    al, dx", \
+   "cmp   al, 0ffh", \
+   "je    TestExit", \
+   "mov   ah, al", \
+   "xor   al, 0e0h", \
+   "out   dx, al", \
+   "jmp   TestDelay1", \
+   "TestDelay1:", \
+   "jmp   TestDelay2", \
+   "TestDelay2:", \
+   "in    al, dx", \
+   "xchg  al, ah", \
+   "out   dx, al", \
+   "sub   al, ah", \
+   "TestExit:", \
+   "and   eax, 0ffh" \
+   parm [ eax ] modify exact [ eax dx ];
+
+#endif

Added: tags/rott-1.1/rott/audiolib/_sndscap.h
===================================================================
--- tags/rott-1.1/rott/audiolib/_sndscap.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/_sndscap.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,136 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: _SNDSCAP.H
+
+   author: James R. Dose
+   date:   October 26, 1994
+
+   Private header for SNDSCAPE.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___SNDSCAP_H
+#define ___SNDSCAP_H
+
+#define VALID   ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define lobyte( num )   ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num )   ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define STEREO      1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT    0
+#define STEREO_8BIT  ( STEREO )
+#define MONO_16BIT   ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define SOUNDSCAPE_MaxMixMode        STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE    1
+#define MONO_16BIT_SAMPLE_SIZE   2
+#define STEREO_8BIT_SAMPLE_SIZE  ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define SOUNDSCAPE_DefaultSampleRate 11000
+#define SOUNDSCAPE_DefaultMixMode    MONO_8BIT
+#define SOUNDSCAPE_MaxIrq            15
+
+/* Ensoniq gate-array chip defines ... */
+#define ODIE            0       /* ODIE gate array */
+#define OPUS            1       /* OPUS gate array */
+#define MMIC            2       /* MiMIC gate array */
+
+/* relevant direct register defines - offsets from base address */
+#define GA_HOSTCSTAT    2       /* host port ctrl/stat reg */
+#define GA_HOSTDATA     3       /* host port data reg */
+#define GA_REGADDR      4       /* indirect address reg */
+#define GA_REGDATA      5       /* indirect data reg */
+#define SB_IACK      0x22e /* SoundBlaster IACK register */
+
+/* relevant indirect register defines */
+#define GA_DMACHB       3       /* DMA chan B assign reg */
+#define GA_INTCFG       4       /* interrupt configuration reg */
+#define GA_DMACFG       5       /* DMA config reg */
+#define GA_CDCFG        6       /* CD-ROM (AD-1848) config reg */
+#define GA_HMCTL  9  /* host master control reg */
+#define GA_CHIPSEL      10      /* programmable external chip select */
+
+/* AD-1848 chip defines ... */
+/* relevant direct register defines */
+#define AD_REGADDR      0       /* indirect address reg */
+#define AD_REGDATA      1       /* indirect data reg */
+#define AD_STATUS       2       /* status register */
+#define AD_OFFSET       8       /* for some boards, a fixed BasePort offset */
+
+/* relevant indirect register defines */
+#define AD_LEFTOUT      6       /* left DAC output control reg */
+#define AD_RIGHTOUT     7       /* right DAC output control reg */
+#define AD_FORMAT       8       /* clock and data format reg */
+#define AD_CONFIG       9       /* interface config register */
+#define AD_PINCTRL      10      /* external pin control reg */
+#define AD_UCOUNT       14      /* upper count reg */
+#define AD_LCOUNT       15      /* lower count reg */
+
+/* some firmware command and communication defines */
+#define SET_CTL      0x88  /* set a control value */
+#define GET_CTL      0x89  /* get a control value */
+#define SET_REV      0xb0  /* set synth reverb */
+#define SYNTH_VOL 0x04  /* Synth Vol control number */
+#define RXRDY     0x01  /* Receive-Ready bit mask */
+#define TXRDY     0x02  /* Transmit-Ready bit mask */
+
+/* some miscellaneous defines ... soundscape reg values, sytem int regs, ... */
+#define INTCONT1        0x20    /* Interrupt Controller 1 control register */
+#define INTCONT2        0xa0    /* Interrupt Controller 2 control register */
+#define INTMASK1        0x21    /* Interrupt Controller 1 mask register */
+#define INTMASK2        0xa1    /* Interrupt Controller 2 mask register */
+#define VECTBASE1       0x08    /* vector base for XT interrupts */
+#define VECTBASE2       0x70    /* vector base for AT extended interrupts */
+#define EOI             0x20    /* End Of Interrupt command */
+#define AUTO_OUT        0x58    /* DMA controller mode */
+
+static void SOUNDSCAPE_EnableInterrupt( void );
+static void SOUNDSCAPE_DisableInterrupt( void );
+static void __interrupt __far SOUNDSCAPE_ServiceInterrupt( void );
+static int  ga_read( int rnum );
+static void ga_write( int rnum, int value );
+static int  ad_read( int rnum );
+static void ad_write( int rnum, int value );
+static void tdelay( void );
+static void pcm_format( void );
+static int  SOUNDSCAPE_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+static int  SOUNDSCAPE_BeginPlayback( int length );
+static void SOUNDSCAPE_LockEnd( void );
+static void SOUNDSCAPE_UnlockMemory( void );
+static int  SOUNDSCAPE_LockMemory( void );
+static unsigned short allocateTimerStack( unsigned short size );
+static void deallocateTimerStack( unsigned short selector );
+static int  parse( char *val, char *str, FILE *p1 );
+static int  SOUNDSCAPE_FindCard( void );
+static int  SOUNDSCAPE_Setup( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/adlibfx.c
===================================================================
--- tags/rott-1.1/rott/audiolib/adlibfx.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/adlibfx.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,552 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: ADLIBFX.C
+
+   author: James R. Dose
+   date:   April 1, 1994
+
+   Low level routines to support Adlib sound effects created by Muse.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <stdlib.h>
+#include <conio.h>
+#include "dpmi.h"
+#include "task_man.h"
+#include "interrup.h"
+#include "al_midi.h"
+#include "adlibfx.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static void ADLIBFX_SendOutput( int reg, int data );
+static void ADLIBFX_Service( task *Task );
+
+static long     ADLIBFX_LengthLeft;
+static int      ADLIBFX_Block;
+static ALSound *ADLIBFX_Sound = NULL;
+static char    *ADLIBFX_SoundPtr = NULL;
+static int      ADLIBFX_Priority;
+static unsigned long ADLIBFX_CallBackVal;
+static void     ( *ADLIBFX_CallBackFunc )( unsigned long ) = NULL;
+static int      ADLIBFX_SoundVolume;
+static int      ADLIBFX_TotalVolume = ADLIBFX_MaxVolume;
+static task    *ADLIBFX_ServiceTask = NULL;
+static int      ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
+
+int ADLIBFX_Installed = FALSE;
+
+int ADLIBFX_ErrorCode = ADLIBFX_Ok;
+
+#define ADLIBFX_SetErrorCode( status ) \
+   ADLIBFX_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *ADLIBFX_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case ADLIBFX_Warning :
+      case ADLIBFX_Error :
+         ErrorString = ADLIBFX_ErrorString( ADLIBFX_ErrorCode );
+         break;
+
+      case ADLIBFX_Ok :
+         ErrorString = "Adlib FX ok.";
+         break;
+
+      case ADLIBFX_NoVoices :
+         ErrorString = "No free voices available in Adlib FX.";
+         break;
+
+      case ADLIBFX_VoiceNotFound :
+         ErrorString = "No voice with matching handle found.";
+         break;
+
+      case ADLIBFX_DPMI_Error :
+         ErrorString = "DPMI Error in AdlibFX.";
+         break;
+
+      default :
+         ErrorString = "Unknown Adlib FX error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define ADLIBFX_LockStart ADLIBFX_SendOutput
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_SendOutput
+
+   Writes a byte of data to the specified register on the Adlib card.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_SendOutput
+   (
+   int reg,
+   int data
+   )
+
+   {
+   int i;
+   int adlib_port = 0x388;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   outp( adlib_port, reg );
+
+   for( i = 6; i ; i-- )
+      {
+      inp( adlib_port );
+      }
+
+   outp( adlib_port + 1, data );
+
+   for( i = 35; i ; i-- )
+      {
+      inp( adlib_port );
+      }
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_Stop
+
+   Halts playback of the currently playing sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Stop
+   (
+   int handle
+   )
+
+   {
+   unsigned flags;
+
+   if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
+      {
+      ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
+      return( ADLIBFX_Warning );
+      }
+
+   flags = DisableInterrupts();
+
+   ADLIBFX_SendOutput( 0xb0, 0 );
+
+   ADLIBFX_Sound      = NULL;
+   ADLIBFX_SoundPtr   = NULL;
+   ADLIBFX_LengthLeft = 0;
+   ADLIBFX_Priority   = 0;
+
+   RestoreInterrupts( flags );
+
+   if ( ADLIBFX_CallBackFunc )
+      {
+      ADLIBFX_CallBackFunc( ADLIBFX_CallBackVal );
+      }
+
+   return( ADLIBFX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_Service
+
+   Task Manager routine to perform the playback of a sound effect.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_Service
+   (
+   task *Task
+   )
+
+   {
+   int value;
+
+   if ( ADLIBFX_SoundPtr )
+      {
+      value = *ADLIBFX_SoundPtr++;
+      if ( value != 0 )
+         {
+         ADLIBFX_SendOutput( 0xa0, value );
+         ADLIBFX_SendOutput( 0xb0, ADLIBFX_Block );
+         }
+      else
+         {
+         ADLIBFX_SendOutput( 0xb0, 0 );
+         }
+
+      ADLIBFX_LengthLeft--;
+      if ( ADLIBFX_LengthLeft <= 0 )
+         {
+         ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_SetVolume
+
+   Sets the volume of the currently playing sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SetVolume
+   (
+   int handle,
+   int volume
+   )
+
+   {
+   unsigned flags;
+   int      carrierlevel;
+
+   flags = DisableInterrupts();
+   if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
+      {
+      RestoreInterrupts( flags );
+      ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
+      return( ADLIBFX_Warning );
+      }
+
+   volume  = min( volume, ADLIBFX_MaxVolume );
+   volume  = max( volume, 0 );
+   ADLIBFX_SoundVolume = volume;
+
+   volume *= ADLIBFX_TotalVolume;
+   volume /= ADLIBFX_MaxVolume;
+
+   carrierlevel  = ADLIBFX_Sound->cScale & 0x3f;
+   carrierlevel ^= 0x3f;
+   carrierlevel *= ( volume / 2 ) + 0x80;
+   carrierlevel /= ADLIBFX_MaxVolume;
+   carrierlevel ^= 0x3f;
+   carrierlevel |= ADLIBFX_Sound->cScale & 0xc0;
+
+   ADLIBFX_SendOutput( 0x43, carrierlevel );
+
+   RestoreInterrupts( flags );
+   return( ADLIBFX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_SetTotalVolume
+
+   Sets the total volume of the sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SetTotalVolume
+   (
+   int volume
+   )
+
+   {
+   volume = max( volume, 0 );
+   volume = min( volume, ADLIBFX_MaxVolume );
+
+   ADLIBFX_TotalVolume = volume;
+   ADLIBFX_SetVolume( ADLIBFX_VoiceHandle, ADLIBFX_SoundVolume );
+
+   return( ADLIBFX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_GetTotalVolume
+
+   Returns the total volume of the sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_GetTotalVolume
+   (
+   void
+   )
+
+   {
+   return( ADLIBFX_TotalVolume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_VoiceAvailable
+
+   Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_VoiceAvailable
+   (
+   int priority
+   )
+
+   {
+   if ( priority < ADLIBFX_Priority )
+      {
+      return( FALSE );
+      }
+
+   return( TRUE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_Play
+
+   Starts playback of a Muse sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Play
+   (
+   ALSound *sound,
+   int volume,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   unsigned flags;
+   int      carrierlevel;
+
+   if ( priority < ADLIBFX_Priority )
+      {
+      ADLIBFX_SetErrorCode( ADLIBFX_NoVoices );
+      return( ADLIBFX_Warning );
+      }
+
+   ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+
+   ADLIBFX_VoiceHandle++;
+   if ( ADLIBFX_VoiceHandle < ADLIBFX_MinVoiceHandle )
+      {
+      ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
+      }
+
+   flags = DisableInterrupts();
+
+   ADLIBFX_LengthLeft  = sound->length;
+   ADLIBFX_Priority    = priority;
+   ADLIBFX_Sound       = sound;
+   ADLIBFX_SoundPtr    = &sound->data;
+   ADLIBFX_CallBackVal = callbackval;
+
+   ADLIBFX_Block = ( ( sound->block & 7 ) << 2 ) | 0x20;
+
+   volume = min( volume, ADLIBFX_MaxVolume );
+   volume = max( volume, 0 );
+   ADLIBFX_SoundVolume = volume;
+
+   volume *= ADLIBFX_TotalVolume;
+   volume /= ADLIBFX_MaxVolume;
+
+   carrierlevel  = sound->cScale & 0x3f;
+   carrierlevel ^= 0x3f;
+   carrierlevel *= ( volume / 2 ) + 0x80;
+   carrierlevel /= ADLIBFX_MaxVolume;
+   carrierlevel ^= 0x3f;
+   carrierlevel |= sound->cScale & 0xc0;
+
+   ADLIBFX_SendOutput( 0x20, sound->mChar );
+   ADLIBFX_SendOutput( 0x40, sound->mScale );
+   ADLIBFX_SendOutput( 0x60, sound->mAttack );
+   ADLIBFX_SendOutput( 0x80, sound->mSus );
+   ADLIBFX_SendOutput( 0xe0, sound->mWave );
+
+   ADLIBFX_SendOutput( 0x23, sound->cChar );
+   ADLIBFX_SendOutput( 0x43, carrierlevel );
+   ADLIBFX_SendOutput( 0x63, sound->cAttack );
+   ADLIBFX_SendOutput( 0x83, sound->cSus );
+   ADLIBFX_SendOutput( 0xe3, sound->cWave );
+
+   ADLIBFX_SendOutput( 0xc0, 0 );
+
+   RestoreInterrupts( flags );
+
+   return( ADLIBFX_VoiceHandle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_SoundPlaying
+
+   Checks if a sound effect is currently playing.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SoundPlaying
+   (
+   int handle
+   )
+
+   {
+   int status;
+
+   status = FALSE;
+   if ( ( handle == ADLIBFX_VoiceHandle ) && ( ADLIBFX_LengthLeft > 0 ) )
+      {
+      status = TRUE;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_SetCallBack
+
+   Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void ADLIBFX_SetCallBack
+   (
+   void ( *function )( unsigned long )
+   )
+
+   {
+   ADLIBFX_CallBackFunc = function;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_Init
+
+   Initializes the sound effect engine.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Init
+   (
+   void
+   )
+
+   {
+   int status;
+
+   if ( ADLIBFX_Installed )
+      {
+      ADLIBFX_Shutdown();
+      }
+
+   status  = DPMI_LockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
+   status |= DPMI_Lock( ADLIBFX_VoiceHandle );
+   status |= DPMI_Lock( ADLIBFX_Sound );
+   status |= DPMI_Lock( ADLIBFX_ErrorCode );
+   status |= DPMI_Lock( ADLIBFX_SoundPtr );
+   status |= DPMI_Lock( ADLIBFX_LengthLeft );
+   status |= DPMI_Lock( ADLIBFX_Priority );
+   status |= DPMI_Lock( ADLIBFX_CallBackFunc );
+   status |= DPMI_Lock( ADLIBFX_Block );
+
+   if ( status != DPMI_Ok )
+      {
+      ADLIBFX_SetErrorCode( ADLIBFX_DPMI_Error );
+      return( ADLIBFX_Error );
+      }
+
+//JIM
+//   AL_ReserveVoice( 0 );
+   ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+   ADLIBFX_ServiceTask = TS_ScheduleTask( &ADLIBFX_Service, 140, 2, NULL );
+   TS_Dispatch();
+   ADLIBFX_Installed = TRUE;
+   ADLIBFX_CallBackFunc = NULL;
+
+   ADLIBFX_SetErrorCode( ADLIBFX_Ok );
+   return( ADLIBFX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ADLIBFX_Shutdown
+
+   Ends the use of the sound effect engine.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Shutdown
+   (
+   void
+   )
+
+   {
+   if ( ADLIBFX_Installed )
+      {
+      ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+      TS_Terminate( ADLIBFX_ServiceTask );
+      ADLIBFX_ServiceTask = NULL;
+//JIM
+//      AL_ReleaseVoice( 0 );
+      ADLIBFX_Installed = FALSE;
+
+      DPMI_UnlockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
+      DPMI_Unlock( ADLIBFX_VoiceHandle );
+      DPMI_Unlock( ADLIBFX_Sound );
+      DPMI_Unlock( ADLIBFX_ErrorCode );
+      DPMI_Unlock( ADLIBFX_SoundPtr );
+      DPMI_Unlock( ADLIBFX_LengthLeft );
+      DPMI_Unlock( ADLIBFX_Priority );
+      DPMI_Unlock( ADLIBFX_CallBackFunc );
+      DPMI_Unlock( ADLIBFX_Block );
+      }
+
+   ADLIBFX_SetErrorCode( ADLIBFX_Ok );
+   return( ADLIBFX_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/adlibfx.h
===================================================================
--- tags/rott-1.1/rott/audiolib/adlibfx.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/adlibfx.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,80 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: ADLIBFX.H
+
+   author: James R. Dose
+   date:   April 1, 1994
+
+   Public header for ADLIBFX.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __ADLIBFX_H
+#define __ADLIBFX_H
+
+enum ADLIBFX_Errors
+   {
+   ADLIBFX_Warning = -2,
+   ADLIBFX_Error   = -1,
+   ADLIBFX_Ok      = 0,
+   ADLIBFX_NoVoices,
+   ADLIBFX_VoiceNotFound,
+   ADLIBFX_DPMI_Error
+   };
+
+typedef	struct
+   {
+   unsigned long  length;
+   short int      priority;
+   char           mChar, cChar;
+   char           mScale, cScale;
+   char           mAttack, cAttack;
+   char           mSus, cSus;
+   char           mWave, cWave;
+   char           nConn;
+   char           voice;
+   char           mode;
+   char           unused[ 3 ];
+   char           block;
+   char           data[];
+   } ALSound;
+
+#define ADLIBFX_MaxVolume      255
+#define ADLIBFX_MinVoiceHandle 1
+
+char *ADLIBFX_ErrorString( int ErrorNumber );
+int   ADLIBFX_Stop( int handle );
+int   ADLIBFX_SetVolume( int handle, int volume );
+int   ADLIBFX_SetTotalVolume( int volume );
+int   ADLIBFX_GetTotalVolume( void );
+int   ADLIBFX_VoiceAvailable( int priority );
+int   ADLIBFX_Play( ALSound *sound, int volume, int priority, unsigned long callbackval );
+int   ADLIBFX_SoundPlaying( int handle );
+void  ADLIBFX_SetCallBack( void ( *function )( unsigned long ) );
+int   ADLIBFX_Init( void );
+int   ADLIBFX_Shutdown( void );
+   #pragma aux ADLIBFX_Shutdown frame;
+void  PCFX_UnlockMemory( void );
+   #pragma aux ADLIBFX_UnlockMemory frame;
+int   PCFX_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/al_midi.c
===================================================================
--- tags/rott-1.1/rott/audiolib/al_midi.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/al_midi.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1510 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: AL_MIDI.C
+
+   author: James R. Dose
+   date:   April 1, 1994
+
+   Low level routines to support General MIDI music on Adlib compatible
+   cards.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stddef.h>
+#include <stdlib.h>
+//#include <math.h>
+#include "dpmi.h"
+#include "interrup.h"
+#include "sndcards.h"
+#include "blaster.h"
+#include "user.h"
+#include "al_midi.h"
+#include "_al_midi.h"
+#include "ll_man.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static unsigned OctavePitch[ MAX_OCTAVE + 1 ] =
+   {
+   OCTAVE_0, OCTAVE_1, OCTAVE_2, OCTAVE_3,
+   OCTAVE_4, OCTAVE_5, OCTAVE_6, OCTAVE_7,
+   };
+
+static unsigned NoteMod12[ MAX_NOTE + 1 ];
+static unsigned NoteDiv12[ MAX_NOTE + 1 ];
+
+// Pitch table
+
+//static unsigned NotePitch[ FINETUNE_MAX + 1 ][ 12 ] =
+//   {
+//      { C, C_SHARP, D, D_SHARP, E, F, F_SHARP, G, G_SHARP, A, A_SHARP, B },
+//   };
+
+static unsigned NotePitch[ FINETUNE_MAX + 1 ][ 12 ] =
+   {
+      { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287 },
+      { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x242, 0x264, 0x288 },
+      { 0x158, 0x16c, 0x182, 0x199, 0x1b1, 0x1cb, 0x1e6, 0x203, 0x221, 0x243, 0x265, 0x289 },
+      { 0x158, 0x16c, 0x183, 0x19a, 0x1b2, 0x1cc, 0x1e7, 0x204, 0x222, 0x244, 0x266, 0x28a },
+      { 0x159, 0x16d, 0x183, 0x19a, 0x1b3, 0x1cd, 0x1e8, 0x205, 0x223, 0x245, 0x267, 0x28b },
+      { 0x15a, 0x16e, 0x184, 0x19b, 0x1b3, 0x1ce, 0x1e9, 0x206, 0x224, 0x246, 0x268, 0x28c },
+      { 0x15a, 0x16e, 0x185, 0x19c, 0x1b4, 0x1ce, 0x1ea, 0x207, 0x225, 0x247, 0x269, 0x28e },
+      { 0x15b, 0x16f, 0x185, 0x19d, 0x1b5, 0x1cf, 0x1eb, 0x208, 0x226, 0x248, 0x26a, 0x28f },
+      { 0x15b, 0x170, 0x186, 0x19d, 0x1b6, 0x1d0, 0x1ec, 0x209, 0x227, 0x249, 0x26b, 0x290 },
+      { 0x15c, 0x170, 0x187, 0x19e, 0x1b7, 0x1d1, 0x1ec, 0x20a, 0x228, 0x24a, 0x26d, 0x291 },
+      { 0x15d, 0x171, 0x188, 0x19f, 0x1b7, 0x1d2, 0x1ed, 0x20b, 0x229, 0x24b, 0x26e, 0x292 },
+      { 0x15d, 0x172, 0x188, 0x1a0, 0x1b8, 0x1d3, 0x1ee, 0x20c, 0x22a, 0x24c, 0x26f, 0x293 },
+      { 0x15e, 0x172, 0x189, 0x1a0, 0x1b9, 0x1d4, 0x1ef, 0x20d, 0x22b, 0x24d, 0x270, 0x295 },
+      { 0x15f, 0x173, 0x18a, 0x1a1, 0x1ba, 0x1d4, 0x1f0, 0x20e, 0x22c, 0x24e, 0x271, 0x296 },
+      { 0x15f, 0x174, 0x18a, 0x1a2, 0x1bb, 0x1d5, 0x1f1, 0x20f, 0x22d, 0x24f, 0x272, 0x297 },
+      { 0x160, 0x174, 0x18b, 0x1a3, 0x1bb, 0x1d6, 0x1f2, 0x210, 0x22e, 0x250, 0x273, 0x298 },
+      { 0x161, 0x175, 0x18c, 0x1a3, 0x1bc, 0x1d7, 0x1f3, 0x211, 0x22f, 0x251, 0x274, 0x299 },
+      { 0x161, 0x176, 0x18c, 0x1a4, 0x1bd, 0x1d8, 0x1f4, 0x212, 0x230, 0x252, 0x276, 0x29b },
+      { 0x162, 0x176, 0x18d, 0x1a5, 0x1be, 0x1d9, 0x1f5, 0x212, 0x231, 0x254, 0x277, 0x29c },
+      { 0x162, 0x177, 0x18e, 0x1a6, 0x1bf, 0x1d9, 0x1f5, 0x213, 0x232, 0x255, 0x278, 0x29d },
+      { 0x163, 0x178, 0x18f, 0x1a6, 0x1bf, 0x1da, 0x1f6, 0x214, 0x233, 0x256, 0x279, 0x29e },
+      { 0x164, 0x179, 0x18f, 0x1a7, 0x1c0, 0x1db, 0x1f7, 0x215, 0x235, 0x257, 0x27a, 0x29f },
+      { 0x164, 0x179, 0x190, 0x1a8, 0x1c1, 0x1dc, 0x1f8, 0x216, 0x236, 0x258, 0x27b, 0x2a1 },
+      { 0x165, 0x17a, 0x191, 0x1a9, 0x1c2, 0x1dd, 0x1f9, 0x217, 0x237, 0x259, 0x27c, 0x2a2 },
+      { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1de, 0x1fa, 0x218, 0x238, 0x25a, 0x27e, 0x2a3 },
+      { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1df, 0x1fb, 0x219, 0x239, 0x25b, 0x27f, 0x2a4 },
+      { 0x167, 0x17c, 0x193, 0x1ab, 0x1c4, 0x1e0, 0x1fc, 0x21a, 0x23a, 0x25c, 0x280, 0x2a6 },
+      { 0x168, 0x17d, 0x194, 0x1ac, 0x1c5, 0x1e0, 0x1fd, 0x21b, 0x23b, 0x25d, 0x281, 0x2a7 },
+      { 0x168, 0x17d, 0x194, 0x1ad, 0x1c6, 0x1e1, 0x1fe, 0x21c, 0x23c, 0x25e, 0x282, 0x2a8 },
+      { 0x169, 0x17e, 0x195, 0x1ad, 0x1c7, 0x1e2, 0x1ff, 0x21d, 0x23d, 0x260, 0x283, 0x2a9 },
+      { 0x16a, 0x17f, 0x196, 0x1ae, 0x1c8, 0x1e3, 0x1ff, 0x21e, 0x23e, 0x261, 0x284, 0x2ab },
+      { 0x16a, 0x17f, 0x197, 0x1af, 0x1c8, 0x1e4, 0x200, 0x21f, 0x23f, 0x262, 0x286, 0x2ac }
+   };
+
+// Slot numbers as a function of the voice and the operator.
+// ( melodic only)
+
+static int slotVoice[ NUM_VOICES ][ 2 ] =
+   {
+      { 0, 3 },    // voice 0
+      { 1, 4 },    // 1
+      { 2, 5 },    // 2
+      { 6, 9 },    // 3
+      { 7, 10 },   // 4
+      { 8, 11 },   // 5
+      { 12, 15 },  // 6
+      { 13, 16 },  // 7
+      { 14, 17 },  // 8
+   };
+
+static int VoiceLevel[ NumChipSlots ][ 2 ];
+static int VoiceKsl[ NumChipSlots ][ 2 ];
+
+// This table gives the offset of each slot within the chip.
+// offset = fn( slot)
+
+static char offsetSlot[ NumChipSlots ] =
+   {
+    0,  1,  2,  3,  4,  5,
+    8,  9, 10, 11, 12, 13,
+   16, 17, 18, 19, 20, 21
+   };
+
+static int VoiceReserved[ NUM_VOICES * 2 ] =
+   {
+   FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+   FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
+   };
+
+static VOICE     Voice[ NUM_VOICES * 2 ];
+static VOICELIST Voice_Pool;
+
+static CHANNEL   Channel[ NUM_CHANNELS ];
+
+static int AL_LeftPort   = 0x388;
+static int AL_RightPort  = 0x388;
+static int AL_Stereo     = FALSE;
+static int AL_SendStereo = FALSE;
+static int AL_OPL3       = FALSE;
+static int AL_MaxMidiChannel = 16;
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define AL_LockStart AL_SendOutputToPort
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SendOutputToPort
+
+   Sends data to the Adlib using a specified port.
+---------------------------------------------------------------------*/
+
+void AL_SendOutputToPort
+   (
+   int  port,
+   int  reg,
+   int  data
+   )
+
+   {
+   int delay;
+
+   outp( port, reg );
+
+   for( delay = 6; delay > 0 ; delay-- )
+//   for( delay = 2; delay > 0 ; delay-- )
+      {
+      inp( port );
+      }
+
+   outp( port + 1, data );
+
+//   for( delay = 35; delay > 0 ; delay-- )
+   for( delay = 27; delay > 0 ; delay-- )
+//   for( delay = 2; delay > 0 ; delay-- )
+      {
+      inp( port );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SendOutput
+
+   Sends data to the Adlib.
+---------------------------------------------------------------------*/
+
+void AL_SendOutput
+   (
+   int  voice,
+   int  reg,
+   int  data
+   )
+
+   {
+   int port;
+
+   if ( AL_SendStereo )
+      {
+      AL_SendOutputToPort( AL_LeftPort, reg, data );
+      AL_SendOutputToPort( AL_RightPort, reg, data );
+      }
+   else
+      {
+      port = ( voice == 0 ) ? AL_RightPort : AL_LeftPort;
+      AL_SendOutputToPort( port, reg, data );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetVoiceTimbre
+
+   Programs the specified voice's timbre.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoiceTimbre
+   (
+   int voice
+   )
+
+   {
+   int    off;
+   int    slot;
+   int    port;
+   int    voc;
+   int    patch;
+   int    channel;
+   TIMBRE *timbre;
+
+   channel = Voice[ voice ].channel;
+
+   if ( channel == 9 )
+      {
+      patch = Voice[ voice ].key + 128;
+      }
+   else
+      {
+      patch = Channel[ channel ].Timbre;
+      }
+
+   if ( Voice[ voice ].timbre == patch )
+      {
+      return;
+      }
+
+   Voice[ voice ].timbre = patch;
+   timbre = &ADLIB_TimbreBank[ patch ];
+
+   port = Voice[ voice ].port;
+   voc  = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+   slot = slotVoice[ voc ][ 0 ];
+   off  = offsetSlot[ slot ];
+
+   VoiceLevel[ slot ][ port ] = 63 - ( timbre->Level[ 0 ] & 0x3f );
+   VoiceKsl[ slot ][ port ]   = timbre->Level[ 0 ] & 0xc0;
+
+   AL_SendOutput( port, 0xA0 + voc, 0 );
+   AL_SendOutput( port, 0xB0 + voc, 0 );
+
+   // Let voice clear the release
+   AL_SendOutput( port, 0x80 + off, 0xff );
+
+   AL_SendOutput( port, 0x60 + off, timbre->Env1[ 0 ] );
+   AL_SendOutput( port, 0x80 + off, timbre->Env2[ 0 ] );
+   AL_SendOutput( port, 0x20 + off, timbre->SAVEK[ 0 ] );
+   AL_SendOutput( port, 0xE0 + off, timbre->Wave[ 0 ] );
+
+   AL_SendOutput( port, 0x40 + off, timbre->Level[ 0 ] );
+   slot = slotVoice[ voc ][ 1 ];
+
+   if ( AL_SendStereo )
+      {
+      AL_SendOutputToPort( AL_LeftPort, 0xC0 + voice,
+         ( timbre->Feedback & 0x0f ) | 0x20 );
+      AL_SendOutputToPort( AL_RightPort, 0xC0 + voice,
+         ( timbre->Feedback & 0x0f ) | 0x10 );
+      }
+   else
+      {
+      if ( AL_OPL3 )
+         {
+         AL_SendOutput( port, 0xC0 + voc, ( timbre->Feedback & 0x0f ) |
+            0x30 );
+         }
+      else
+         {
+         AL_SendOutputToPort( ADLIB_PORT, 0xC0 + voice, timbre->Feedback );
+         }
+      }
+
+   off = offsetSlot[ slot ];
+
+   VoiceLevel[ slot ][ port ] = 63 - ( timbre->Level[ 1 ] & 0x3f );
+   VoiceKsl[ slot ][ port ]   = timbre->Level[ 1 ] & 0xc0;
+   AL_SendOutput( port, 0x40 + off, 63 );
+
+   // Let voice clear the release
+   AL_SendOutput( port, 0x80 + off, 0xff );
+
+   AL_SendOutput( port, 0x60 + off, timbre->Env1[ 1 ] );
+   AL_SendOutput( port, 0x80 + off, timbre->Env2[ 1 ] );
+   AL_SendOutput( port, 0x20 + off, timbre->SAVEK[ 1 ] );
+   AL_SendOutput( port, 0xE0 + off, timbre->Wave[ 1 ] );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetVoiceVolume
+
+   Sets the volume of the specified voice.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoiceVolume
+   (
+   int voice
+   )
+
+   {
+   int channel;
+   int velocity;
+   int slot;
+   int port;
+   int voc;
+   unsigned long t1;
+   unsigned long t2;
+   unsigned long volume;
+   TIMBRE *timbre;
+
+   channel = Voice[ voice ].channel;
+
+   timbre = &ADLIB_TimbreBank[ Voice[ voice ].timbre ];
+
+   velocity = Voice[ voice ].velocity + timbre->Velocity;
+   velocity = min( velocity, MAX_VELOCITY );
+
+   voc  = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+   slot = slotVoice[ voc ][ 1 ];
+   port = Voice[ voice ].port;
+
+   // amplitude
+   t1  = ( unsigned )VoiceLevel[ slot ][ port ];
+   t1 *= ( velocity + 0x80 );
+   t1  = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+   if ( !AL_SendStereo )
+      {
+      volume  = t1 ^ 63;
+      volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+      AL_SendOutput( port, 0x40 + offsetSlot[ slot ], volume );
+
+      // Check if this timbre is Additive
+      if ( timbre->Feedback & 0x01 )
+         {
+         slot = slotVoice[ voc ][ 0 ];
+
+         // amplitude
+         t2  = ( unsigned )VoiceLevel[ slot ][ port ];
+         t2 *= ( velocity + 0x80 );
+         t2  = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+         volume  = t2 ^ 63;
+         volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+         AL_SendOutput( port, 0x40 + offsetSlot[ slot ], volume );
+         }
+      }
+   else
+      {
+      // Set left channel volume
+      volume = t1;
+      if ( Channel[ channel ].Pan < 64 )
+         {
+         volume *= Channel[ channel ].Pan;
+         volume >>= 6;
+         }
+
+      volume ^= 63;
+      volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+      AL_SendOutputToPort( AL_LeftPort, 0x40 + offsetSlot[ slot ], volume );
+
+      // Set right channel volume
+      volume = t1;
+      if ( Channel[ channel ].Pan > 64 )
+         {
+         volume *= 127 - Channel[ channel ].Pan;
+         volume >>= 6;
+         }
+
+      volume ^= 63;
+      volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+      AL_SendOutputToPort( AL_RightPort, 0x40 + offsetSlot[ slot ], volume );
+
+      // Check if this timbre is Additive
+      if ( timbre->Feedback & 0x01 )
+         {
+         // amplitude
+         t2  = ( unsigned )VoiceLevel[ slot ][ port ];
+         t2 *= ( velocity + 0x80 );
+         t2  = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+         slot = slotVoice[ voc ][ 0 ];
+
+         // Set left channel volume
+         volume = t2;
+         if ( Channel[ channel ].Pan < 64 )
+            {
+            volume *= Channel[ channel ].Pan;
+            volume >>= 6;
+            }
+
+         volume ^= 63;
+         volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+         AL_SendOutputToPort( AL_LeftPort, 0x40 + offsetSlot[ slot ], volume );
+
+         // Set right channel volume
+         volume = t2;
+         if ( Channel[ channel ].Pan > 64 )
+            {
+            volume *= 127 - Channel[ channel ].Pan;
+            volume >>= 6;
+            }
+
+         volume ^= 63;
+         volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+         AL_SendOutputToPort( AL_RightPort, 0x40 + offsetSlot[ slot ], volume );
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_AllocVoice
+
+   Retrieves a free voice from the voice pool.
+---------------------------------------------------------------------*/
+
+static int AL_AllocVoice
+   (
+   void
+   )
+
+   {
+   int voice;
+
+   if ( Voice_Pool.start )
+      {
+      voice = Voice_Pool.start->num;
+      LL_Remove( VOICE, &Voice_Pool, &Voice[ voice ] );
+      return( voice );
+      }
+
+   return( AL_VoiceNotFound );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_GetVoice
+
+   Determines which voice is associated with a specified note and
+   MIDI channel.
+---------------------------------------------------------------------*/
+
+static int AL_GetVoice
+   (
+   int channel,
+   int key
+   )
+
+   {
+   VOICE *voice;
+
+   voice = Channel[ channel ].Voices.start;
+
+   while( voice != NULL )
+      {
+      if ( voice->key == key )
+         {
+         return( voice->num );
+         }
+      voice = voice->next;
+      }
+
+   return( AL_VoiceNotFound );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetVoicePitch
+
+   Programs the pitch of the specified voice.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoicePitch
+   (
+   int voice
+   )
+
+   {
+   int note;
+   int channel;
+   int patch;
+   int detune;
+   int ScaleNote;
+   int Octave;
+   int pitch;
+   int port;
+   int voc;
+
+   port = Voice[ voice ].port;
+   voc  = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+   channel = Voice[ voice ].channel;
+
+   if ( channel == 9 )
+      {
+      patch = Voice[ voice ].key + 128;
+      note  = ADLIB_TimbreBank[ patch ].Transpose;
+      }
+   else
+      {
+      patch = Channel[ channel ].Timbre;
+      note  = Voice[ voice ].key + ADLIB_TimbreBank[ patch ].Transpose;
+      }
+
+   note += Channel[ channel ].KeyOffset - 12;
+   if ( note > MAX_NOTE )
+      {
+      note = MAX_NOTE;
+      }
+   if ( note < 0 )
+      {
+      note = 0;
+      }
+
+   detune = Channel[ channel ].KeyDetune;
+
+   ScaleNote = NoteMod12[ note ];
+   Octave    = NoteDiv12[ note ];
+
+   pitch = OctavePitch[ Octave ] | NotePitch[ detune ][ ScaleNote ];
+
+   Voice[ voice ].pitchleft = pitch;
+
+   pitch |= Voice[ voice ].status;
+
+   if ( !AL_SendStereo )
+      {
+      AL_SendOutput( port, 0xA0 + voc, pitch );
+      AL_SendOutput( port, 0xB0 + voc, pitch >> 8 );
+      }
+   else
+      {
+      AL_SendOutputToPort( AL_LeftPort, 0xA0 + voice, pitch );
+      AL_SendOutputToPort( AL_LeftPort, 0xB0 + voice, pitch >> 8 );
+
+      if ( channel != 9 )
+         {
+         detune += STEREO_DETUNE;
+         }
+
+      if ( detune > FINETUNE_MAX )
+         {
+         detune -= FINETUNE_RANGE;
+         if ( note < MAX_NOTE )
+            {
+            note++;
+            ScaleNote = NoteMod12[ note ];
+            Octave    = NoteDiv12[ note ];
+            }
+         }
+
+      pitch = OctavePitch[ Octave ] | NotePitch[ detune ][ ScaleNote ];
+
+      Voice[ voice ].pitchright = pitch;
+
+      pitch |= Voice[ voice ].status;
+
+      AL_SendOutputToPort( AL_RightPort, 0xA0 + voice, pitch );
+      AL_SendOutputToPort( AL_RightPort, 0xB0 + voice, pitch >> 8 );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetChannelVolume
+
+   Sets the volume of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelVolume
+   (
+   int channel,
+   int volume
+   )
+
+   {
+   VOICE *voice;
+
+   volume = max( 0, volume );
+   volume = min( volume, AL_MaxVolume );
+   Channel[ channel ].Volume = volume;
+
+   voice = Channel[ channel ].Voices.start;
+   while( voice != NULL )
+      {
+      AL_SetVoiceVolume( voice->num );
+      voice = voice->next;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetChannelPan
+
+   Sets the pan position of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelPan
+   (
+   int channel,
+   int pan
+   )
+
+   {
+   // Don't pan drum sounds
+   if ( channel != 9 )
+      {
+      Channel[ channel ].Pan = pan;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetChannelDetune
+
+   Sets the stereo voice detune of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelDetune
+   (
+   int channel,
+   int detune
+   )
+
+   {
+   Channel[ channel ].Detune = detune;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_ResetVoices
+
+   Sets all voice info to the default state.
+---------------------------------------------------------------------*/
+
+static void AL_ResetVoices
+   (
+   void
+   )
+
+   {
+   int index;
+   int numvoices;
+
+   Voice_Pool.start = NULL;
+   Voice_Pool.end = NULL;
+
+   numvoices = NUM_VOICES;
+   if ( ( AL_OPL3 ) && ( !AL_Stereo ) )
+      {
+      numvoices = NUM_VOICES * 2;
+      }
+   for( index = 0; index < numvoices; index++ )
+      {
+      if ( VoiceReserved[ index ] == FALSE )
+         {
+         Voice[ index ].num = index;
+         Voice[ index ].key = 0;
+         Voice[ index ].velocity = 0;
+         Voice[ index ].channel = -1;
+         Voice[ index ].timbre = -1;
+         Voice[ index ].port = ( index < NUM_VOICES ) ? 0 : 1;
+         Voice[ index ].status = NOTE_OFF;
+         LL_AddToTail( VOICE, &Voice_Pool, &Voice[ index ] );
+         }
+      }
+
+   for( index = 0; index < NUM_CHANNELS; index++ )
+      {
+      Channel[ index ].Voices.start    = NULL;
+      Channel[ index ].Voices.end      = NULL;
+      Channel[ index ].Timbre          = 0;
+      Channel[ index ].Pitchbend       = 0;
+      Channel[ index ].KeyOffset       = 0;
+      Channel[ index ].KeyDetune       = 0;
+      Channel[ index ].Volume          = AL_DefaultChannelVolume;
+      Channel[ index ].Pan             = 64;
+      Channel[ index ].RPN             = 0;
+      Channel[ index ].PitchBendRange     = AL_DefaultPitchBendRange;
+      Channel[ index ].PitchBendSemiTones = AL_DefaultPitchBendRange / 100;
+      Channel[ index ].PitchBendHundreds  = AL_DefaultPitchBendRange % 100;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_CalcPitchInfo
+
+   Calculates the pitch table.
+---------------------------------------------------------------------*/
+
+static void AL_CalcPitchInfo
+   (
+   void
+   )
+
+   {
+   int    note;
+//   int    finetune;
+//   double detune;
+
+   for( note = 0; note <= MAX_NOTE; note++ )
+      {
+      NoteMod12[ note ] = note % 12;
+      NoteDiv12[ note ] = note / 12;
+      }
+
+//   for( finetune = 1; finetune <= FINETUNE_MAX; finetune++ )
+//      {
+//      detune = pow( 2, ( double )finetune / ( 12.0 * FINETUNE_RANGE ) );
+//      for( note = 0; note < 12; note++ )
+//         {
+//         NotePitch[ finetune ][ note ] = ( ( double )NotePitch[ 0 ][ note ] * detune );
+//         }
+//      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_FlushCard
+
+   Sets all voices to a known (quiet) state.
+---------------------------------------------------------------------*/
+
+void AL_FlushCard
+   (
+   int port
+   )
+
+   {
+   int i;
+   unsigned slot1;
+   unsigned slot2;
+
+   for( i = 0 ; i < NUM_VOICES; i++ )
+      {
+      if ( VoiceReserved[ i ] == FALSE )
+         {
+         slot1 = offsetSlot[ slotVoice[ i ][ 0 ] ];
+         slot2 = offsetSlot[ slotVoice[ i ][ 1 ] ];
+
+         AL_SendOutputToPort( port, 0xA0 + i, 0 );
+         AL_SendOutputToPort( port, 0xB0 + i, 0 );
+
+         AL_SendOutputToPort( port, 0xE0 + slot1, 0 );
+         AL_SendOutputToPort( port, 0xE0 + slot2, 0 );
+
+         // Set the envelope to be fast and quiet
+         AL_SendOutputToPort( port, 0x60 + slot1, 0xff );
+         AL_SendOutputToPort( port, 0x60 + slot2, 0xff );
+         AL_SendOutputToPort( port, 0x80 + slot1, 0xff );
+         AL_SendOutputToPort( port, 0x80 + slot2, 0xff );
+
+         // Maximum attenuation
+         AL_SendOutputToPort( port, 0x40 + slot1, 0xff );
+         AL_SendOutputToPort( port, 0x40 + slot2, 0xff );
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_StereoOn
+
+   Sets the card send info in stereo.
+---------------------------------------------------------------------*/
+
+void AL_StereoOn
+   (
+   void
+   )
+
+   {
+   if ( ( AL_Stereo ) && ( !AL_SendStereo ) )
+      {
+      AL_SendStereo = TRUE;
+      if ( AL_OPL3 )
+         {
+         // Set card to OPL3 operation
+         AL_SendOutputToPort( AL_RightPort, 0x5, 1 );
+         }
+      }
+   else if ( AL_OPL3 )
+      {
+      // Set card to OPL3 operation
+      AL_SendOutputToPort( AL_RightPort, 0x5, 1 );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_StereoOff
+
+   Sets the card send info in mono.
+---------------------------------------------------------------------*/
+
+void AL_StereoOff
+   (
+   void
+   )
+
+   {
+   if ( ( AL_Stereo ) && ( AL_SendStereo ) )
+      {
+      AL_SendStereo = FALSE;
+      if ( AL_OPL3 )
+         {
+         // Set card back to OPL2 operation
+         AL_SendOutputToPort( AL_RightPort, 0x5, 0 );
+         }
+      }
+   else if ( AL_OPL3 )
+      {
+      // Set card back to OPL2 operation
+      AL_SendOutputToPort( AL_RightPort, 0x5, 0 );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_Reset
+
+   Sets the card to a known (quiet) state.
+---------------------------------------------------------------------*/
+
+void AL_Reset
+   (
+   void
+   )
+
+   {
+   AL_SendOutputToPort( ADLIB_PORT, 1, 0x20 );
+   AL_SendOutputToPort( ADLIB_PORT, 0x08, 0 );
+
+   // Set the values: AM Depth, VIB depth & Rhythm
+   AL_SendOutputToPort( ADLIB_PORT, 0xBD, 0 );
+
+   AL_StereoOn();
+
+   if ( ( AL_SendStereo ) || ( AL_OPL3 ) )
+      {
+      AL_FlushCard( AL_LeftPort );
+      AL_FlushCard( AL_RightPort );
+      }
+   else
+      {
+      AL_FlushCard( ADLIB_PORT );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_ReserveVoice
+
+   Marks a voice as being not available for use.  This allows the
+   driver to use the rest of the card while another driver uses the
+   reserved voice.
+---------------------------------------------------------------------*/
+
+int AL_ReserveVoice
+   (
+   int voice
+   )
+
+   {
+   unsigned flags;
+
+   if ( ( voice < 0 ) || ( voice >= NUM_VOICES ) )
+      {
+      return( AL_Error );
+      }
+
+   if ( VoiceReserved[ voice ] )
+      {
+      return( AL_Warning );
+      }
+
+   flags = DisableInterrupts();
+
+   if ( Voice[ voice ].status == NOTE_ON )
+      {
+      AL_NoteOff( Voice[ voice ].channel, Voice[ voice ].key, 0 );
+      }
+
+   VoiceReserved[ voice ] = TRUE;
+   LL_Remove( VOICE, &Voice_Pool, &Voice[ voice ] );
+
+   RestoreInterrupts( flags );
+   return( AL_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_ReleaseVoice
+
+   Marks a previously reserved voice as being free to use.
+---------------------------------------------------------------------*/
+
+int AL_ReleaseVoice
+   (
+   int voice
+   )
+
+   {
+   unsigned flags;
+
+   if ( ( voice < 0 ) || ( voice >= NUM_VOICES ) )
+      {
+      return( AL_Error );
+      }
+
+   if ( !VoiceReserved[ voice ] )
+      {
+      return( AL_Warning );
+      }
+
+   flags = DisableInterrupts();
+
+   VoiceReserved[ voice ] = FALSE;
+   LL_AddToTail( VOICE, &Voice_Pool, &Voice[ voice ] );
+
+   RestoreInterrupts( flags );
+   return( AL_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_NoteOff
+
+   Turns off a note on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_NoteOff
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   int voice;
+   int port;
+   int voc;
+
+   // We only play channels 1 through 10
+   if ( channel > AL_MaxMidiChannel )
+      {
+      return;
+      }
+
+   voice = AL_GetVoice( channel, key );
+
+   if ( voice == AL_VoiceNotFound )
+      {
+      return;
+      }
+
+   Voice[ voice ].status = NOTE_OFF;
+
+   port = Voice[ voice ].port;
+   voc  = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+
+   if ( AL_SendStereo )
+      {
+      AL_SendOutputToPort( AL_LeftPort, 0xB0 + voice,
+         hibyte( Voice[ voice ].pitchleft ) );
+      AL_SendOutputToPort( AL_RightPort, 0xB0 + voice,
+         hibyte( Voice[ voice ].pitchright ) );
+      }
+   else
+      {
+      AL_SendOutput( port, 0xB0 + voc, hibyte( Voice[ voice ].pitchleft ) );
+      }
+
+   LL_Remove( VOICE, &Channel[ channel ].Voices, &Voice[ voice ] );
+   LL_AddToTail( VOICE, &Voice_Pool, &Voice[ voice ] );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_NoteOn
+
+   Plays a note on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_NoteOn
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   int voice;
+
+   // We only play channels 1 through 10
+   if ( channel > AL_MaxMidiChannel )
+      {
+      return;
+      }
+
+   if ( velocity == 0 )
+      {
+      AL_NoteOff( channel, key, velocity );
+      return;
+      }
+
+   voice = AL_AllocVoice();
+
+   if ( voice == AL_VoiceNotFound )
+      {
+      if ( Channel[ 9 ].Voices.start )
+         {
+         AL_NoteOff( 9, Channel[ 9 ].Voices.start->key, 0 );
+         voice = AL_AllocVoice();
+         }
+      if ( voice == AL_VoiceNotFound )
+         {
+         return;
+         }
+      }
+
+   Voice[ voice ].key      = key;
+   Voice[ voice ].channel  = channel;
+   Voice[ voice ].velocity = velocity;
+   Voice[ voice ].status   = NOTE_ON;
+
+   LL_AddToTail( VOICE, &Channel[ channel ].Voices, &Voice[ voice ] );
+
+   AL_SetVoiceTimbre( voice );
+   AL_SetVoiceVolume( voice );
+   AL_SetVoicePitch( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_AllNotesOff
+
+   Turns off all currently playing voices.
+---------------------------------------------------------------------*/
+
+void AL_AllNotesOff
+   (
+   int channel
+   )
+
+   {
+   while( Channel[ channel ].Voices.start != NULL )
+      {
+      AL_NoteOff( channel, Channel[ channel ].Voices.start->key, 0 );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_ControlChange
+
+   Sets the value of a controller on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_ControlChange
+   (
+   int channel,
+   int type,
+   int data
+   )
+
+   {
+   // We only play channels 1 through 10
+   if ( channel > AL_MaxMidiChannel )
+      {
+      return;
+      }
+
+   switch( type )
+      {
+      case MIDI_VOLUME :
+         AL_SetChannelVolume( channel, data );
+         break;
+
+      case MIDI_PAN :
+         AL_SetChannelPan( channel, data );
+         break;
+
+      case MIDI_DETUNE :
+         AL_SetChannelDetune( channel, data );
+         break;
+
+      case MIDI_ALL_NOTES_OFF :
+         AL_AllNotesOff( channel );
+         break;
+
+      case MIDI_RESET_ALL_CONTROLLERS :
+         AL_ResetVoices();
+         AL_SetChannelVolume( channel, AL_DefaultChannelVolume );
+         AL_SetChannelPan( channel, 64 );
+         AL_SetChannelDetune( channel, 0 );
+         break;
+
+      case MIDI_RPN_MSB :
+         Channel[ channel ].RPN &= 0x00FF;
+         Channel[ channel ].RPN |= ( data & 0xFF ) << 8;
+         break;
+
+      case MIDI_RPN_LSB :
+         Channel[ channel ].RPN &= 0xFF00;
+         Channel[ channel ].RPN |= data & 0xFF;
+         break;
+
+      case MIDI_DATAENTRY_MSB :
+         if ( Channel[ channel ].RPN == MIDI_PITCHBEND_RPN )
+            {
+            Channel[ channel ].PitchBendSemiTones = data;
+            Channel[ channel ].PitchBendRange     =
+               Channel[ channel ].PitchBendSemiTones * 100 +
+               Channel[ channel ].PitchBendHundreds;
+            }
+         break;
+
+      case MIDI_DATAENTRY_LSB :
+         if ( Channel[ channel ].RPN == MIDI_PITCHBEND_RPN )
+            {
+            Channel[ channel ].PitchBendHundreds = data;
+            Channel[ channel ].PitchBendRange    =
+               Channel[ channel ].PitchBendSemiTones * 100 +
+               Channel[ channel ].PitchBendHundreds;
+            }
+         break;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_ProgramChange
+
+   Selects the instrument to use on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_ProgramChange
+   (
+   int channel,
+   int patch
+   )
+
+   {
+   // We only play channels 1 through 10
+   if ( channel > AL_MaxMidiChannel )
+      {
+      return;
+      }
+
+   Channel[ channel ].Timbre  = patch;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetPitchBend
+
+   Sets the pitch bend amount on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_SetPitchBend
+   (
+   int channel,
+   int lsb,
+   int msb
+   )
+
+   {
+   int            pitchbend;
+   unsigned long  TotalBend;
+   VOICE         *voice;
+
+   // We only play channels 1 through 10
+   if ( channel > AL_MaxMidiChannel )
+      {
+      return;
+      }
+
+   pitchbend = lsb + ( msb << 8 );
+   Channel[ channel ].Pitchbend = pitchbend;
+
+   TotalBend  = pitchbend * Channel[ channel ].PitchBendRange;
+   TotalBend /= ( PITCHBEND_CENTER / FINETUNE_RANGE );
+
+   Channel[ channel ].KeyOffset  = ( int )( TotalBend / FINETUNE_RANGE );
+   Channel[ channel ].KeyOffset -= Channel[ channel ].PitchBendSemiTones;
+
+   Channel[ channel ].KeyDetune = ( unsigned )( TotalBend % FINETUNE_RANGE );
+
+   voice = Channel[ channel ].Voices.start;
+   while( voice != NULL )
+      {
+      AL_SetVoicePitch( voice->num );
+      voice = voice->next;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_DetectFM
+
+   Determines if an Adlib compatible card is installed in the machine.
+---------------------------------------------------------------------*/
+
+int AL_DetectFM
+   (
+   void
+   )
+
+   {
+   int status1;
+   int status2;
+   int i;
+
+   if ( USER_CheckParameter( NO_ADLIB_DETECTION ) )
+      {
+      return( FALSE );
+      }
+
+   AL_SendOutputToPort( ADLIB_PORT, 4, 0x60 );   // Reset T1 & T2
+   AL_SendOutputToPort( ADLIB_PORT, 4, 0x80 );   // Reset IRQ
+
+   status1 = inp( ADLIB_PORT );
+
+   AL_SendOutputToPort( ADLIB_PORT, 2, 0xff );   // Set timer 1
+   AL_SendOutputToPort( ADLIB_PORT, 4, 0x21 );   // Start timer 1
+
+   for( i = 100; i > 0; i-- )
+      {
+      inp( ADLIB_PORT );
+      }
+
+   status2 = inp( ADLIB_PORT );
+
+   AL_SendOutputToPort( ADLIB_PORT, 4, 0x60 );
+   AL_SendOutputToPort( ADLIB_PORT, 4, 0x80 );
+
+   return( ( ( status1 & 0xe0 ) == 0x00 ) && ( ( status2 & 0xe0 ) == 0xc0 ) );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void AL_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_Shutdown
+
+   Ends use of the sound card and resets it to a quiet state.
+---------------------------------------------------------------------*/
+
+void AL_Shutdown
+   (
+   void
+   )
+
+   {
+   AL_StereoOff();
+
+   AL_OPL3 = FALSE;
+   AL_ResetVoices();
+   AL_Reset();
+
+   DPMI_UnlockMemoryRegion( AL_LockStart, AL_LockEnd );
+   DPMI_Unlock( slotVoice );
+   DPMI_Unlock( VoiceLevel );
+   DPMI_Unlock( VoiceKsl );
+   DPMI_Unlock( offsetSlot );
+   DPMI_Unlock( NotePitch );
+   DPMI_Unlock( OctavePitch );
+   DPMI_Unlock( NoteMod12 );
+   DPMI_Unlock( NoteDiv12 );
+   DPMI_Unlock( VoiceReserved );
+   DPMI_Unlock( Voice );
+   DPMI_Unlock( Voice_Pool );
+   DPMI_Unlock( Channel );
+   DPMI_Unlock( AL_LeftPort );
+   DPMI_Unlock( AL_RightPort );
+   DPMI_Unlock( AL_Stereo );
+   DPMI_Unlock( AL_SendStereo );
+   DPMI_Unlock( AL_OPL3 );
+   DPMI_Unlock( AL_MaxMidiChannel );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_SetMaxMidiChannel
+
+   Sets the maximum MIDI channel that FM cards respond to.
+---------------------------------------------------------------------*/
+
+void AL_SetMaxMidiChannel
+   (
+   int channel
+   )
+
+   {
+   AL_MaxMidiChannel = channel - 1;
+   }
+
+/*---------------------------------------------------------------------
+   Function: AL_Init
+
+   Begins use of the sound card.
+---------------------------------------------------------------------*/
+
+int AL_Init
+   (
+   int soundcard
+   )
+
+   {
+   BLASTER_CONFIG Blaster;
+   int status;
+
+   status  = DPMI_LockMemoryRegion( AL_LockStart, AL_LockEnd );
+   status |= DPMI_Lock( slotVoice );
+   status |= DPMI_Lock( VoiceLevel );
+   status |= DPMI_Lock( VoiceKsl );
+   status |= DPMI_Lock( offsetSlot );
+   status |= DPMI_Lock( NotePitch );
+   status |= DPMI_Lock( OctavePitch );
+   status |= DPMI_Lock( NoteMod12 );
+   status |= DPMI_Lock( NoteDiv12 );
+   status |= DPMI_Lock( VoiceReserved );
+   status |= DPMI_Lock( Voice );
+   status |= DPMI_Lock( Voice_Pool );
+   status |= DPMI_Lock( Channel );
+   status |= DPMI_Lock( AL_LeftPort );
+   status |= DPMI_Lock( AL_RightPort );
+   status |= DPMI_Lock( AL_Stereo );
+   status |= DPMI_Lock( AL_SendStereo );
+   status |= DPMI_Lock( AL_OPL3 );
+   status |= DPMI_Lock( AL_MaxMidiChannel );
+
+   if ( status != DPMI_Ok )
+      {
+      return( AL_Error );
+      }
+
+   AL_Stereo = FALSE;
+   AL_OPL3   = FALSE;
+   AL_LeftPort = 0x388;
+   AL_RightPort = 0x388;
+
+   switch( soundcard )
+      {
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         AL_OPL3 = TRUE;
+         AL_LeftPort = 0x388;
+         AL_RightPort = 0x38A;
+         break;
+
+      case SoundBlaster :
+         status = BLASTER_GetCardSettings( &Blaster );
+         if ( status != BLASTER_Ok )
+            {
+            status = BLASTER_GetEnv( &Blaster );
+            if ( status != BLASTER_Ok )
+               {
+               break;
+               }
+            }
+
+         switch( Blaster.Type )
+            {
+            case SBPro2 :
+            case SB16 :
+               AL_OPL3 = TRUE;
+               AL_LeftPort  = Blaster.Address;
+               AL_RightPort = Blaster.Address + 2;
+               break;
+            }
+         break;
+      }
+// Temporarally commented out for ROTT.
+// Stereo FM seems to take too long on some computers and
+// causes the mouse driver to miss interrupts.
+
+/*
+   switch( soundcard )
+      {
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         AL_OPL3 = TRUE;
+         AL_Stereo = TRUE;
+         AL_LeftPort  = 0x388;
+         AL_RightPort = 0x38A;
+         break;
+
+      case SoundBlaster :
+         status = BLASTER_GetCardSettings( &Blaster );
+         if ( status != BLASTER_Ok )
+            {
+            status = BLASTER_GetEnv( &Blaster );
+            if ( status != BLASTER_Ok )
+               {
+               break;
+               }
+            }
+
+         switch( Blaster.Type )
+            {
+            case SBPro2 :
+            case SB16 :
+               AL_OPL3 = TRUE;
+               AL_Stereo = TRUE;
+               AL_LeftPort  = Blaster.Address;
+               AL_RightPort = Blaster.Address + 2;
+               break;
+
+            case SBPro :
+               AL_Stereo = TRUE;
+               AL_LeftPort  = Blaster.Address;
+               AL_RightPort = Blaster.Address + 2;
+               break;
+            }
+         break;
+      }
+*/
+
+   AL_CalcPitchInfo();
+   AL_Reset();
+   AL_ResetVoices();
+
+   return( AL_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AL_RegisterTimbreBank
+
+   Copies user supplied timbres over the default timbre bank.
+---------------------------------------------------------------------*/
+
+void AL_RegisterTimbreBank
+   (
+   unsigned char *timbres
+   )
+
+   {
+   int i;
+
+   for( i = 0; i < 256; i++ )
+      {
+      ADLIB_TimbreBank[ i ].SAVEK[ 0 ] = *( timbres++ );
+      ADLIB_TimbreBank[ i ].SAVEK[ 1 ] = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Level[ 0 ] = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Level[ 1 ] = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Env1[ 0 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Env1[ 1 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Env2[ 0 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Env2[ 1 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Wave[ 0 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Wave[ 1 ]  = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Feedback   = *( timbres++ );
+      ADLIB_TimbreBank[ i ].Transpose  = *( signed char * )( timbres++ );
+      ADLIB_TimbreBank[ i ].Velocity   = *( signed char * )( timbres++ );
+      }
+   }

Added: tags/rott-1.1/rott/audiolib/al_midi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/al_midi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/al_midi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __AL_MIDI_H
+#define __AL_MIDI_H
+
+enum AL_Errors
+   {
+   AL_Warning  = -2,
+   AL_Error    = -1,
+   AL_Ok       = 0,
+   };
+
+#define AL_MaxVolume             127
+#define AL_DefaultChannelVolume  90
+//#define AL_DefaultPitchBendRange 2
+#define AL_DefaultPitchBendRange 200
+
+#define ADLIB_PORT 0x388
+
+void AL_SendOutputToPort( int port, int reg, int data );
+void AL_SendOutput( int  voice, int reg, int data );
+void AL_StereoOn( void );
+void AL_StereoOff( void );
+int  AL_ReserveVoice( int voice );
+int  AL_ReleaseVoice( int voice );
+void AL_Shutdown( void );
+int  AL_Init( int soundcard );
+void AL_SetMaxMidiChannel( int channel );
+void AL_Reset( void );
+void AL_NoteOff( int channel, int key, int velocity );
+void AL_NoteOn( int channel, int key, int vel );
+//Turned off to test if it works with Watcom 10a
+//   #pragma aux AL_NoteOn frame;
+void AL_AllNotesOff( int channel );
+void AL_ControlChange( int channel, int type, int data );
+void AL_ProgramChange( int channel, int patch );
+void AL_SetPitchBend( int channel, int lsb, int msb );
+int  AL_DetectFM( void );
+void AL_RegisterTimbreBank( unsigned char *timbres );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/assert.h
===================================================================
--- tags/rott-1.1/rott/audiolib/assert.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/assert.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef    __ASSERT_H
+
+    #define    __ASSERT_H
+
+    #ifdef NDEBUG
+
+        #define ASSERT(f)
+
+    #else
+
+        #pragma aux _Assert aborts;          /* _Assert will not return */
+        extern void _Assert( char *strFile, unsigned  uLine ); /*prototype */
+
+        #define ASSERT(f)          \
+            if (f)                 \
+                ;                  \
+            else                   \
+                _Assert( __FILE__, __LINE__ )
+
+    #endif
+
+#else
+
+    #error Multiple definition of ASSERT()
+
+#endif

Added: tags/rott-1.1/rott/audiolib/awe32.c
===================================================================
--- tags/rott-1.1/rott/audiolib/awe32.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/awe32.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,540 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: AWE32.C
+
+   author: James R. Dose
+   date:   August 23, 1994
+
+   Cover functions for calling the AWE32 low-level library.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <string.h>
+#include "dpmi.h"
+#include "blaster.h"
+#include "ctaweapi.h"
+#include "awe32.h"
+
+#define _inp    inp
+#define _outp   outp
+
+/*  DSP defines  */
+#define MPU_ACK_OK          0xfe
+#define MPU_RESET_CMD       0xff
+#define MPU_ENTER_UART      0x3f
+
+static WORD wSBCBaseAddx;            /* Sound Blaster base address */
+static WORD wEMUBaseAddx;            /* EMU8000 subsystem base address */
+static WORD wMpuBaseAddx;            /* MPU401 base address */
+
+static unsigned short NoteFlags[ 128 ];
+
+/*  macros  */
+#define SBCPort( x )  ( ( x ) + wSBCBaseAddx )
+#define MPUPort( x )  ( ( x ) + wMpuBaseAddx )
+
+static SOUND_PACKET spSound =
+   {
+   0
+   };
+
+static LONG lBankSizes[ MAXBANKS ] =
+   {
+   0
+   };
+
+unsigned SetES( void );
+#pragma aux SetES = \
+        "xor eax, eax" \
+        "mov ax, es" \
+        "mov bx, ds" \
+        "mov es, bx" \
+        modify [ eax ebx ];
+
+void RestoreES( unsigned num );
+#pragma aux RestoreES = \
+        "mov  es, ax" \
+        parm [ eax ];
+
+int AWE32_ErrorCode = AWE32_Ok;
+
+#define AWE32_SetErrorCode( status ) \
+   AWE32_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: AWE32_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *AWE32_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case AWE32_Warning :
+      case AWE32_Error :
+         ErrorString = AWE32_ErrorString( AWE32_ErrorCode );
+         break;
+
+      case AWE32_Ok :
+         ErrorString = "AWE32 ok.";
+         break;
+
+      case AWE32_SoundBlasterError :
+         ErrorString = BLASTER_ErrorString( BLASTER_Error );
+         break;
+
+      case AWE32_NotDetected :
+         ErrorString = "Could not detect AWE32.";
+         break;
+
+      case AWE32_UnableToInitialize :
+         ErrorString = "Unable to initialize AWE32.";
+
+      case AWE32_MPU401Error :
+         ErrorString = "MPU-401 initialization failed in AWE32.";
+         break;
+
+      case AWE32_DPMI_Error :
+         ErrorString = "DPMI Error in AWE32.";
+         break;
+
+      default :
+         ErrorString = "Unknown AWE32 error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define AWE32_LockStart AWE32_NoteOff
+
+
+void AWE32_NoteOff
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32NoteOff( channel, key, velocity );
+   RestoreES( temp );
+   NoteFlags[ key ] ^= ( 1 << channel );
+   }
+
+void AWE32_NoteOn
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32NoteOn( channel, key, velocity );
+   RestoreES( temp );
+   NoteFlags[ key ] |= ( 1 << channel );
+   }
+
+void AWE32_PolyAftertouch
+   (
+   int channel,
+   int key,
+   int pressure
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32PolyKeyPressure( channel, key, pressure );
+   RestoreES( temp );
+   }
+
+void AWE32_ChannelAftertouch
+   (
+   int channel,
+   int pressure
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32ChannelPressure( channel, pressure );
+   RestoreES( temp );
+   }
+
+void AWE32_ControlChange
+   (
+   int channel,
+   int number,
+   int value
+   )
+
+   {
+   unsigned temp;
+   int i;
+   unsigned channelmask;
+
+   temp = SetES();
+
+   if ( number == 0x7b )
+      {
+      channelmask = 1 << channel;
+      for( i = 0; i < 128; i++ )
+         {
+         if ( NoteFlags[ i ] & channelmask )
+            {
+            awe32NoteOff( channel, i, 0 );
+            NoteFlags[ i ] ^= channelmask;
+            }
+         }
+      }
+   else
+      {
+      awe32Controller( channel, number, value );
+      }
+   RestoreES( temp );
+   }
+
+void AWE32_ProgramChange
+   (
+   int channel,
+   int program
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32ProgramChange( channel, program );
+   RestoreES( temp );
+   }
+
+void AWE32_PitchBend
+   (
+   int channel,
+   int lsb,
+   int msb
+   )
+
+   {
+   unsigned temp;
+
+   temp = SetES();
+   awe32PitchBend( channel, lsb, msb );
+   RestoreES( temp );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: AWE32_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void AWE32_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*
+static int InitMPU
+   (
+   void
+   )
+
+   {
+   volatile DWORD dwCount;
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+   _outp(MPUPort(1), MPU_RESET_CMD);
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+   _inp(MPUPort(0));
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+   _outp(MPUPort(1), MPU_RESET_CMD);
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+   _inp(MPUPort(0));
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+   _outp(MPUPort(1), MPU_ENTER_UART);
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+   if (!dwCount) return TRUE;
+   if (_inp(MPUPort(0)) != MPU_ACK_OK) return TRUE;
+
+   // mask MPU-401 interrupt
+   _outp(SBCPort(0x4), 0x83);
+   _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04);
+
+   return FALSE;
+   }
+*/
+
+/*ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸*/
+/*³ ShutdownMPU                                                    ³*/
+/*³ Cleans up Sound Blaster to normal state.                               ³*/
+/*ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;*/
+
+static void ShutdownMPU
+   (
+   void
+   )
+
+   {
+   volatile DWORD dwCount;
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+   _outp(MPUPort(1), MPU_RESET_CMD);
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   _inp(MPUPort(0));
+
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   dwCount = 0x2000;
+   while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+   _outp(MPUPort(1), MPU_RESET_CMD);
+   for (dwCount=0; dwCount<0x2000; dwCount++) ;
+   _inp(MPUPort(0));
+   }
+
+
+/*ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸*/
+/*³ LoadSBK                                                                ³*/
+/*ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;*/
+
+static void LoadSBK
+   (
+   void
+   )
+
+   {
+   /* use embeded preset objects */
+   spSound.bank_no = 0;            /* load as Bank 0 */
+   spSound.total_banks = 1;        /* use 1 bank first */
+   lBankSizes[ 0 ] = 0;            /* ram is not needed */
+
+   spSound.banksizes = lBankSizes;
+   awe32DefineBankSizes( &spSound );
+   awe32SoundPad.SPad1 = awe32SPad1Obj;
+   awe32SoundPad.SPad2 = awe32SPad2Obj;
+   awe32SoundPad.SPad3 = awe32SPad3Obj;
+   awe32SoundPad.SPad4 = awe32SPad4Obj;
+   awe32SoundPad.SPad5 = awe32SPad5Obj;
+   awe32SoundPad.SPad6 = awe32SPad6Obj;
+   awe32SoundPad.SPad7 = awe32SPad7Obj;
+   }
+
+
+int AWE32_Init
+   (
+   void
+   )
+
+   {
+   int status;
+   BLASTER_CONFIG Blaster;
+
+   wSBCBaseAddx = 0x220;
+   wEMUBaseAddx = 0x620;
+   wMpuBaseAddx = 0x330;
+
+   status = BLASTER_GetCardSettings( &Blaster );
+   if ( status != BLASTER_Ok )
+      {
+      status = BLASTER_GetEnv( &Blaster );
+      if ( status != BLASTER_Ok )
+         {
+         AWE32_SetErrorCode( AWE32_SoundBlasterError );
+         return( AWE32_Error );
+         }
+      }
+
+   wSBCBaseAddx = Blaster.Address;
+   if ( wSBCBaseAddx == UNDEFINED )
+      {
+      wSBCBaseAddx = 0x220;
+      }
+
+   wMpuBaseAddx = Blaster.Midi;
+   if ( wMpuBaseAddx == UNDEFINED )
+      {
+      wMpuBaseAddx = 0x330;
+      }
+
+   wEMUBaseAddx = Blaster.Emu;
+   if ( wEMUBaseAddx <= 0 )
+      {
+      wEMUBaseAddx = wSBCBaseAddx + 0x400;
+      }
+
+   status = awe32Detect( wEMUBaseAddx );
+   if ( status )
+      {
+      AWE32_SetErrorCode( AWE32_NotDetected );
+      return( AWE32_Error );
+      }
+
+   status = awe32InitHardware();
+   if ( status )
+      {
+      AWE32_SetErrorCode( AWE32_UnableToInitialize );
+      return( AWE32_Error );
+      }
+
+
+   status = awe32InitMIDI();
+   if ( status )
+      {
+      AWE32_Shutdown();
+      AWE32_SetErrorCode( AWE32_MPU401Error )
+      return( AWE32_Error );
+      }
+
+/*
+    status = InitMPU();
+   if ( status )
+      {
+      ShutdownMPU();
+      status = InitMPU();
+      if ( status )
+         {
+         ShutdownMPU();
+         status = InitMPU();
+         if ( status )
+            {
+            AWE32_Shutdown();
+            AWE32_SetErrorCode( AWE32_MPU401Error )
+            return( AWE32_Error );
+            }
+         }
+      }
+*/
+   status  = DPMI_LockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
+   status |= DPMI_Lock( wSBCBaseAddx );
+   status |= DPMI_Lock( wEMUBaseAddx );
+   status |= DPMI_Lock( wMpuBaseAddx );
+   status |= DPMI_Lock( spSound );
+   status |= DPMI_Lock( lBankSizes );
+   status |= DPMI_LockMemory( NoteFlags, sizeof( NoteFlags ) );
+
+   // Lock awe32 library
+   status  = DPMI_LockMemoryRegion( __midieng_code, __midieng_ecode );
+   status  = DPMI_LockMemoryRegion( __midieng_code(), __midieng_ecode() );
+   status  = DPMI_LockMemoryRegion( __nrpn_code, __nrpn_ecode );
+   status  = DPMI_LockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
+   status  = DPMI_LockMemoryRegion( &__midivar_data, &__midivar_edata );
+   status  = DPMI_LockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
+   status  = DPMI_LockMemoryRegion( &__embed_data, &__embed_edata );
+
+   if ( status != DPMI_Ok )
+      {
+      ShutdownMPU();
+      awe32Terminate();
+      AWE32_SetErrorCode( AWE32_DPMI_Error );
+      return( AWE32_Error );
+      }
+
+   // Set the number of voices to use to 32
+   awe32NumG = 32;
+
+   awe32TotalPatchRam(&spSound);
+
+   LoadSBK();
+   awe32InitMIDI();
+   awe32InitNRPN();
+
+   memset( NoteFlags, 0, sizeof( NoteFlags ) );
+
+   return( AWE32_Ok );
+   }
+
+void AWE32_Shutdown
+   (
+   void
+   )
+
+   {
+   ShutdownMPU();
+   awe32Terminate();
+
+   DPMI_UnlockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
+   DPMI_Unlock( wSBCBaseAddx );
+   DPMI_Unlock( wEMUBaseAddx );
+   DPMI_Unlock( wMpuBaseAddx );
+   DPMI_Unlock( spSound );
+   DPMI_Unlock( lBankSizes );
+   DPMI_UnlockMemory( NoteFlags, sizeof( NoteFlags ) );
+
+   // Unlock awe32 library
+   DPMI_UnlockMemoryRegion( __midieng_code, __midieng_ecode );
+   DPMI_UnlockMemoryRegion( __midieng_code(), __midieng_ecode() );
+   DPMI_UnlockMemoryRegion( __nrpn_code, __nrpn_ecode );
+   DPMI_UnlockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
+   DPMI_UnlockMemoryRegion( &__midivar_data, &__midivar_edata );
+   DPMI_UnlockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
+   DPMI_UnlockMemoryRegion( &__embed_data, &__embed_edata );
+   }

Added: tags/rott-1.1/rott/audiolib/awe32.h
===================================================================
--- tags/rott-1.1/rott/audiolib/awe32.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/awe32.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: AWE32.H
+
+   author: James R. Dose
+   date:   August 23, 1994
+
+   Public header for AWE32.C  Cover functions for calling the
+   AWE32 low-level library.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __AWE32_H
+#define __AWE32_H
+
+enum AWE32_ERRORS
+   {
+   AWE32_Warning = -2,
+   AWE32_Error = -1,
+   AWE32_Ok = 0,
+   AWE32_SoundBlasterError,
+   AWE32_NotDetected,
+   AWE32_UnableToInitialize,
+   AWE32_MPU401Error,
+   AWE32_DPMI_Error
+   };
+
+char *AWE32_ErrorString( int ErrorNumber );
+int  AWE32_Init( void );
+void AWE32_Shutdown( void );
+void AWE32_NoteOff( int channel, int key, int velocity );
+void AWE32_NoteOn( int channel, int key, int velocity );
+void AWE32_PolyAftertouch( int channel, int key, int pressure );
+void AWE32_ChannelAftertouch( int channel, int pressure );
+void AWE32_ControlChange( int channel, int number, int value );
+void AWE32_ProgramChange( int channel, int program );
+void AWE32_PitchBend( int channel, int lsb, int msb );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/blaster.c
===================================================================
--- tags/rott-1.1/rott/audiolib/blaster.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/blaster.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,2330 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: BLASTER.C
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Low level routines to support Sound Blaster, Sound Blaster Pro,
+   Sound Blaster 16, and compatible sound cards.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "dpmi.h"
+#include "dma.h"
+#include "irq.h"
+#include "blaster.h"
+#include "_blaster.h"
+
+#define USESTACK
+
+const int BLASTER_Interrupts[ BLASTER_MaxIrq + 1 ]  =
+   {
+   INVALID, INVALID,     0xa,     0xb,
+   INVALID,     0xd, INVALID,     0xf,
+   INVALID, INVALID,    0x72,    0x73,
+      0x74, INVALID, INVALID,    0x77
+   };
+
+const int BLASTER_SampleSize[ BLASTER_MaxMixMode + 1 ] =
+   {
+   MONO_8BIT_SAMPLE_SIZE,  STEREO_8BIT_SAMPLE_SIZE,
+   MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
+   };
+
+const CARD_CAPABILITY BLASTER_CardConfig[ BLASTER_MaxCardType + 1 ] =
+   {
+      { FALSE, INVALID,      INVALID, INVALID, INVALID }, // Unsupported
+      {  TRUE,      NO,    MONO_8BIT,    4000,   23000 }, // SB 1.0
+      {  TRUE,     YES,  STEREO_8BIT,    4000,   44100 }, // SBPro
+      {  TRUE,      NO,    MONO_8BIT,    4000,   23000 }, // SB 2.xx
+      {  TRUE,     YES,  STEREO_8BIT,    4000,   44100 }, // SBPro 2
+      { FALSE, INVALID,      INVALID, INVALID, INVALID }, // Unsupported
+      {  TRUE,     YES, STEREO_16BIT,    5000,   44100 }, // SB16
+   };
+
+CARD_CAPABILITY BLASTER_Card;
+
+static void    ( __interrupt __far *BLASTER_OldInt )( void );
+
+BLASTER_CONFIG BLASTER_Config =
+   {
+   UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED
+   };
+
+static int BLASTER_Installed = FALSE;
+
+int BLASTER_Version;
+
+static char   *BLASTER_DMABuffer;
+static char   *BLASTER_DMABufferEnd;
+static char   *BLASTER_CurrentDMABuffer;
+static int     BLASTER_TotalDMABufferSize;
+
+static int      BLASTER_TransferLength   = 0;
+static int      BLASTER_MixMode          = BLASTER_DefaultMixMode;
+static int      BLASTER_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
+static unsigned BLASTER_SampleRate       = BLASTER_DefaultSampleRate;
+
+static unsigned BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+volatile int   BLASTER_SoundPlaying;
+volatile int   BLASTER_SoundRecording;
+
+void ( *BLASTER_CallBack )( void );
+
+static int  BLASTER_IntController1Mask;
+static int  BLASTER_IntController2Mask;
+
+static int BLASTER_MixerAddress = UNDEFINED;
+static int BLASTER_MixerType    = 0;
+static int BLASTER_OriginalMidiVolumeLeft   = 255;
+static int BLASTER_OriginalMidiVolumeRight  = 255;
+static int BLASTER_OriginalVoiceVolumeLeft  = 255;
+static int BLASTER_OriginalVoiceVolumeRight = 255;
+
+static int BLASTER_WaveBlasterState = 0x0F;
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long  StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long  oldStackPointer;
+
+// This is defined because we can't create local variables in a
+// function that switches stacks.
+static int GlobalStatus;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack =  \
+   "mov  [edi],esp"     \
+   "mov  ax,ss"         \
+   "mov  [esi],ax"      \
+   parm [esi] [edi]     \
+   modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack =  \
+   "mov  ss,ax"         \
+   "mov  esp,edx"       \
+   parm [ax] [edx]      \
+   modify [eax edx];
+
+int BLASTER_DMAChannel;
+
+int BLASTER_ErrorCode = BLASTER_Ok;
+
+#define BLASTER_SetErrorCode( status ) \
+   BLASTER_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *BLASTER_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case BLASTER_Warning :
+      case BLASTER_Error :
+         ErrorString = BLASTER_ErrorString( BLASTER_ErrorCode );
+         break;
+
+      case BLASTER_Ok :
+         ErrorString = "Sound Blaster ok.";
+         break;
+
+      case BLASTER_EnvNotFound :
+         ErrorString = "BLASTER environment variable not set.";
+         break;
+
+      case BLASTER_AddrNotSet :
+         ErrorString = "Sound Blaster address not set.";
+         break;
+
+      case BLASTER_DMANotSet :
+         ErrorString = "Sound Blaster 8-bit DMA channel not set.";
+         break;
+
+      case BLASTER_DMA16NotSet :
+         ErrorString = "Sound Blaster 16-bit DMA channel not set.";
+         break;
+
+      case BLASTER_InvalidParameter :
+         ErrorString = "Invalid parameter in BLASTER environment variable.";
+         break;
+
+      case BLASTER_CardNotReady :
+         ErrorString = "Sound Blaster not responding on selected port.";
+         break;
+
+      case BLASTER_NoSoundPlaying :
+         ErrorString = "No sound playing on Sound Blaster.";
+         break;
+
+      case BLASTER_InvalidIrq :
+         ErrorString = "Invalid Sound Blaster Irq.";
+         break;
+
+      case BLASTER_UnableToSetIrq :
+         ErrorString = "Unable to set Sound Blaster IRQ.  Try selecting an IRQ of 7 or below.";
+         break;
+
+      case BLASTER_DmaError :
+         ErrorString = DMA_ErrorString( DMA_Error );
+         break;
+
+      case BLASTER_NoMixer :
+         ErrorString = "Mixer not available on selected Sound Blaster card.";
+         break;
+
+      case BLASTER_DPMI_Error :
+         ErrorString = "DPMI Error in Blaster.";
+         break;
+
+      case BLASTER_OutOfMemory :
+         ErrorString = "Out of conventional memory in Blaster.";
+         break;
+
+      default :
+         ErrorString = "Unknown Sound Blaster error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define BLASTER_LockStart BLASTER_EnableInterrupt
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_EnableInterrupt
+
+   Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void BLASTER_EnableInterrupt
+   (
+   void
+   )
+
+   {
+   int Irq;
+   int mask;
+
+   // Unmask system interrupt
+   Irq  = BLASTER_Config.Interrupt;
+   if ( Irq < 8 )
+      {
+      mask = inp( 0x21 ) & ~( 1 << Irq );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
+      outp( 0xA1, mask  );
+
+      mask = inp( 0x21 ) & ~( 1 << 2 );
+      outp( 0x21, mask  );
+      }
+
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DisableInterrupt
+
+   Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void BLASTER_DisableInterrupt
+   (
+   void
+   )
+
+   {
+   int Irq;
+   int mask;
+
+   // Restore interrupt mask
+   Irq  = BLASTER_Config.Interrupt;
+   if ( Irq < 8 )
+      {
+      mask  = inp( 0x21 ) & ~( 1 << Irq );
+      mask |= BLASTER_IntController1Mask & ( 1 << Irq );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask  = inp( 0x21 ) & ~( 1 << 2 );
+      mask |= BLASTER_IntController1Mask & ( 1 << 2 );
+      outp( 0x21, mask  );
+
+      mask  = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
+      mask |= BLASTER_IntController2Mask & ( 1 << ( Irq - 8 ) );
+      outp( 0xA1, mask  );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ServiceInterrupt
+
+   Handles interrupt generated by sound card at the end of a voice
+   transfer.  Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+void __interrupt __far BLASTER_ServiceInterrupt
+   (
+   void
+   )
+
+   {
+   #ifdef USESTACK
+   // save stack
+   GetStack( &oldStackSelector, &oldStackPointer );
+
+   // set our stack
+   SetStack( StackSelector, StackPointer );
+   #endif
+
+   // Acknowledge interrupt
+   // Check if this is this an SB16 or newer
+   if ( BLASTER_Version >= DSP_Version4xx )
+      {
+      outp( BLASTER_Config.Address + BLASTER_MixerAddressPort,
+         MIXER_DSP4xxISR_Ack );
+
+      GlobalStatus = inp( BLASTER_Config.Address + BLASTER_MixerDataPort );
+
+      // Check if a 16-bit DMA interrupt occurred
+      if ( GlobalStatus & MIXER_16BITDMA_INT )
+         {
+         // Acknowledge 16-bit transfer interrupt
+         inp( BLASTER_Config.Address + BLASTER_16BitDMAAck );
+         }
+      else if ( GlobalStatus & MIXER_8BITDMA_INT )
+         {
+         inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
+         }
+      else
+         {
+         #ifdef USESTACK
+         // restore stack
+         SetStack( oldStackSelector, oldStackPointer );
+         #endif
+
+         // Wasn't our interrupt.  Call the old one.
+         _chain_intr( BLASTER_OldInt );
+         }
+      }
+   else
+      {
+      // Older card - can't detect if an interrupt occurred.
+      inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
+      }
+
+   // Keep track of current buffer
+   BLASTER_CurrentDMABuffer += BLASTER_TransferLength;
+
+   if ( BLASTER_CurrentDMABuffer >= BLASTER_DMABufferEnd )
+      {
+      BLASTER_CurrentDMABuffer = BLASTER_DMABuffer;
+      }
+
+   // Continue playback on cards without autoinit mode
+   if ( BLASTER_Version < DSP_Version2xx )
+      {
+      if ( BLASTER_SoundPlaying )
+         {
+         BLASTER_DSP1xx_BeginPlayback( BLASTER_TransferLength );
+         }
+
+      if ( BLASTER_SoundRecording )
+         {
+         BLASTER_DSP1xx_BeginRecord( BLASTER_TransferLength );
+         }
+      }
+
+   // Call the caller's callback function
+   if ( BLASTER_CallBack != NULL )
+      {
+      BLASTER_CallBack();
+      }
+
+   #ifdef USESTACK
+   // restore stack
+   SetStack( oldStackSelector, oldStackPointer );
+   #endif
+
+   // send EOI to Interrupt Controller
+   if ( BLASTER_Config.Interrupt > 7 )
+      {
+      outp( 0xA0, 0x20 );
+      }
+
+   outp( 0x20, 0x20 );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_WriteDSP
+
+   Writes a byte of data to the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_WriteDSP
+   (
+   unsigned data
+   )
+
+   {
+   int      port;
+   unsigned count;
+   int      status;
+
+   port = BLASTER_Config.Address + BLASTER_WritePort;
+
+   status = BLASTER_Error;
+
+   count = 0xFFFF;
+
+   do
+      {
+      if ( ( inp( port ) & 0x80 ) == 0 )
+         {
+         outp( port, data );
+         status = BLASTER_Ok;
+         break;
+         }
+
+      count--;
+      }
+   while( count > 0 );
+
+   if ( status != BLASTER_Ok )
+      {
+      BLASTER_SetErrorCode( BLASTER_CardNotReady );
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ReadDSP
+
+   Reads a byte of data from the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_ReadDSP
+   (
+   void
+   )
+
+   {
+   int      port;
+   unsigned count;
+   int      status;
+
+   port = BLASTER_Config.Address + BLASTER_DataAvailablePort;
+
+   status = BLASTER_Error;
+
+   count = 0xFFFF;
+
+   do
+      {
+      if ( inp( port ) & 0x80 )
+         {
+         status = inp( BLASTER_Config.Address + BLASTER_ReadPort );
+         break;
+         }
+
+      count--;
+      }
+   while( count > 0 );
+
+   if ( status == BLASTER_Error )
+      {
+      BLASTER_SetErrorCode( BLASTER_CardNotReady );
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ResetDSP
+
+   Sends a reset command to the sound card's Digital Signal Processor
+   (DSP), causing it to perform an initialization.
+---------------------------------------------------------------------*/
+
+int BLASTER_ResetDSP
+   (
+   void
+   )
+
+   {
+   volatile int count;
+   int port;
+   int status;
+
+   port = BLASTER_Config.Address + BLASTER_ResetPort;
+
+   status = BLASTER_CardNotReady;
+
+   outp( port, 1 );
+
+/* What the hell am I doing here?
+   count = 100;
+
+   do
+      {
+      if ( inp( port ) == 255 )
+         {
+         break;
+         }
+
+      count--;
+      }
+   while( count > 0 );
+*/
+
+   count = 0x100;
+   do
+      {
+      count--;
+      }
+   while( count > 0 );
+
+   outp( port, 0 );
+
+   count = 100;
+
+   do
+      {
+      if ( BLASTER_ReadDSP() == BLASTER_Ready )
+         {
+         status = BLASTER_Ok;
+         break;
+         }
+
+      count--;
+      }
+   while( count > 0 );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetDSPVersion
+
+   Returns the version number of the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetDSPVersion
+   (
+   void
+   )
+
+   {
+   int MajorVersion;
+   int MinorVersion;
+   int version;
+
+   BLASTER_WriteDSP( DSP_GetVersion );
+
+   MajorVersion   = BLASTER_ReadDSP();
+   MinorVersion   = BLASTER_ReadDSP();
+
+   if ( ( MajorVersion == BLASTER_Error ) ||
+      ( MinorVersion == BLASTER_Error ) )
+      {
+      BLASTER_SetErrorCode( BLASTER_CardNotReady );
+      return( BLASTER_Error );
+      }
+
+   version = ( MajorVersion << 8 ) + MinorVersion;
+
+   if ( version >= DSP_Version4xx )
+      {
+      BLASTER_Card.IsSupported     = TRUE;
+      BLASTER_Card.HasMixer        = YES;
+      BLASTER_Card.MaxMixMode      = STEREO_16BIT;
+      BLASTER_Card.MinSamplingRate = 5000;
+      BLASTER_Card.MaxSamplingRate = 44100;
+      BLASTER_MixerType = SB16;
+      }
+   else if ( version >= DSP_Version3xx )
+      {
+      BLASTER_Card.IsSupported     = TRUE;
+      BLASTER_Card.HasMixer        = YES;
+      BLASTER_Card.MaxMixMode      = STEREO_8BIT;
+      BLASTER_Card.MinSamplingRate = 4000;
+      BLASTER_Card.MaxSamplingRate = 44100;
+      BLASTER_MixerType = SBPro;
+      }
+   else if ( version >= DSP_Version2xx )
+      {
+      BLASTER_Card.IsSupported     = TRUE;
+      BLASTER_Card.HasMixer        = NO;
+      BLASTER_Card.MaxMixMode      = MONO_8BIT;
+      BLASTER_Card.MinSamplingRate = 4000;
+      BLASTER_Card.MaxSamplingRate = 23000;
+      BLASTER_MixerType = 0;
+      }
+   else
+      {
+      // DSP_Version1xx
+      BLASTER_Card.IsSupported     = TRUE;
+      BLASTER_Card.HasMixer        = NO;
+      BLASTER_Card.MaxMixMode      = MONO_8BIT;
+      BLASTER_Card.MinSamplingRate = 4000;
+      BLASTER_Card.MaxSamplingRate = 23000;
+      BLASTER_MixerType = 0;
+      }
+
+   return( version );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SpeakerOn
+
+   Enables output from the DAC.
+---------------------------------------------------------------------*/
+
+void BLASTER_SpeakerOn
+   (
+   void
+   )
+
+   {
+   BLASTER_WriteDSP( DSP_SpeakerOn );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SpeakerOff
+
+   Disables output from the DAC.
+---------------------------------------------------------------------*/
+
+void BLASTER_SpeakerOff
+   (
+   void
+   )
+
+   {
+   BLASTER_WriteDSP( DSP_SpeakerOff );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetPlaybackRate
+
+   Sets the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetPlaybackRate
+   (
+   unsigned rate
+   )
+
+   {
+   int LoByte;
+   int HiByte;
+
+   if ( BLASTER_Version < DSP_Version4xx )
+      {
+      int  timeconstant;
+      long ActualRate;
+
+      // Send sampling rate as time constant for older Sound
+      // Blaster compatible cards.
+
+      ActualRate = rate * BLASTER_SamplePacketSize;
+      if ( ActualRate < BLASTER_Card.MinSamplingRate )
+         {
+         rate = BLASTER_Card.MinSamplingRate / BLASTER_SamplePacketSize;
+         }
+
+      if ( ActualRate > BLASTER_Card.MaxSamplingRate )
+         {
+         rate = BLASTER_Card.MaxSamplingRate / BLASTER_SamplePacketSize;
+         }
+
+      timeconstant = ( int )CalcTimeConstant( rate, BLASTER_SamplePacketSize );
+
+      // Keep track of what the actual rate is
+      BLASTER_SampleRate  = ( unsigned )CalcSamplingRate( timeconstant );
+      BLASTER_SampleRate /= BLASTER_SamplePacketSize;
+
+      BLASTER_WriteDSP( DSP_SetTimeConstant );
+      BLASTER_WriteDSP( timeconstant );
+      }
+   else
+      {
+      // Send literal sampling rate for cards with DSP version
+      // 4.xx (Sound Blaster 16)
+
+      BLASTER_SampleRate = rate;
+
+      if ( BLASTER_SampleRate < BLASTER_Card.MinSamplingRate )
+         {
+         BLASTER_SampleRate = BLASTER_Card.MinSamplingRate;
+         }
+
+      if ( BLASTER_SampleRate > BLASTER_Card.MaxSamplingRate )
+         {
+         BLASTER_SampleRate = BLASTER_Card.MaxSamplingRate;
+         }
+
+      HiByte = hibyte( BLASTER_SampleRate );
+      LoByte = lobyte( BLASTER_SampleRate );
+
+      // Set playback rate
+      BLASTER_WriteDSP( DSP_Set_DA_Rate );
+      BLASTER_WriteDSP( HiByte );
+      BLASTER_WriteDSP( LoByte );
+
+      // Set recording rate
+      BLASTER_WriteDSP( DSP_Set_AD_Rate );
+      BLASTER_WriteDSP( HiByte );
+      BLASTER_WriteDSP( LoByte );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetPlaybackRate
+
+   Returns the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+unsigned BLASTER_GetPlaybackRate
+   (
+   void
+   )
+
+   {
+   return( BLASTER_SampleRate );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetMixMode
+
+   Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetMixMode
+   (
+   int mode
+   )
+
+   {
+   int   port;
+   int   data;
+   int   CardType;
+
+   CardType = BLASTER_Config.Type;
+
+   mode &= BLASTER_MaxMixMode;
+
+   if ( !( BLASTER_Card.MaxMixMode & STEREO ) )
+      {
+      mode &= ~STEREO;
+      }
+
+   if ( !( BLASTER_Card.MaxMixMode & SIXTEEN_BIT ) )
+      {
+      mode &= ~SIXTEEN_BIT;
+      }
+
+   BLASTER_MixMode = mode;
+   BLASTER_SamplePacketSize = BLASTER_SampleSize[ mode ];
+
+   // For the Sound Blaster Pro, we have to set the mixer chip
+   // to play mono or stereo samples.
+
+   if ( ( CardType == SBPro ) || ( CardType == SBPro2 ) )
+      {
+      port = BLASTER_Config.Address + BLASTER_MixerAddressPort;
+      outp( port, MIXER_SBProOutputSetting );
+
+      port = BLASTER_Config.Address + BLASTER_MixerDataPort;
+
+      // Get current mode
+      data = inp( port );
+
+      // set stereo mode bit
+      if ( mode & STEREO )
+         {
+         data |= MIXER_SBProStereoFlag;
+         }
+      else
+         {
+         data &= ~MIXER_SBProStereoFlag;
+         }
+
+      // set the mode
+      outp( port, data );
+
+      BLASTER_SetPlaybackRate( BLASTER_SampleRate );
+      }
+
+   return( mode );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_StopPlayback
+
+   Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void BLASTER_StopPlayback
+   (
+   void
+   )
+
+   {
+   int DmaChannel;
+
+   // Don't allow anymore interrupts
+   BLASTER_DisableInterrupt();
+
+   if ( BLASTER_HaltTransferCommand == DSP_Reset )
+      {
+      BLASTER_ResetDSP();
+      }
+   else
+      {
+      BLASTER_WriteDSP( BLASTER_HaltTransferCommand );
+      }
+
+   // Disable the DMA channel
+   if ( BLASTER_MixMode & SIXTEEN_BIT )
+      {
+      DmaChannel = BLASTER_Config.Dma16;
+      }
+   else
+      {
+      DmaChannel = BLASTER_Config.Dma8;
+      }
+   DMA_EndTransfer( DmaChannel );
+
+   // Turn off speaker
+   BLASTER_SpeakerOff();
+
+   BLASTER_SoundPlaying = FALSE;
+   BLASTER_SoundRecording = FALSE;
+
+   BLASTER_DMABuffer = NULL;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetupDMABuffer
+
+   Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetupDMABuffer
+   (
+   char *BufferPtr,
+   int   BufferSize,
+   int   mode
+   )
+
+   {
+   int DmaChannel;
+   int DmaStatus;
+   int errorcode;
+
+   if ( BLASTER_MixMode & SIXTEEN_BIT )
+      {
+      DmaChannel = BLASTER_Config.Dma16;
+      errorcode  = BLASTER_DMA16NotSet;
+      }
+   else
+      {
+      DmaChannel = BLASTER_Config.Dma8;
+      errorcode  = BLASTER_DMANotSet;
+      }
+
+   if ( DmaChannel == UNDEFINED )
+      {
+      BLASTER_SetErrorCode( errorcode );
+      return( BLASTER_Error );
+      }
+
+   DmaStatus = DMA_SetupTransfer( DmaChannel, BufferPtr, BufferSize, mode );
+   if ( DmaStatus == DMA_Error )
+      {
+      BLASTER_SetErrorCode( BLASTER_DmaError );
+      return( BLASTER_Error );
+      }
+
+   BLASTER_DMAChannel = DmaChannel;
+
+   BLASTER_DMABuffer          = BufferPtr;
+   BLASTER_CurrentDMABuffer   = BufferPtr;
+   BLASTER_TotalDMABufferSize = BufferSize;
+   BLASTER_DMABufferEnd       = BufferPtr + BufferSize;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetCurrentPos
+
+   Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCurrentPos
+   (
+   void
+   )
+
+   {
+   char *CurrentAddr;
+   int   DmaChannel;
+   int   offset;
+
+   if ( !BLASTER_SoundPlaying )
+      {
+      BLASTER_SetErrorCode( BLASTER_NoSoundPlaying );
+      return( BLASTER_Error );
+      }
+
+   if ( BLASTER_MixMode & SIXTEEN_BIT )
+      {
+      DmaChannel = BLASTER_Config.Dma16;
+      }
+   else
+      {
+      DmaChannel = BLASTER_Config.Dma8;
+      }
+
+   if ( DmaChannel == UNDEFINED )
+      {
+      BLASTER_SetErrorCode( BLASTER_DMANotSet );
+      return( BLASTER_Error );
+      }
+
+   CurrentAddr = DMA_GetCurrentPos( DmaChannel );
+
+   offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+      ( ( unsigned long )BLASTER_CurrentDMABuffer ) );
+
+   if ( BLASTER_MixMode & SIXTEEN_BIT )
+      {
+      offset >>= 1;
+      }
+
+   if ( BLASTER_MixMode & STEREO )
+      {
+      offset >>= 1;
+      }
+
+   return( offset );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP1xx_BeginPlayback
+
+   Starts playback of digitized sound on cards compatible with DSP
+   version 1.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP1xx_BeginPlayback
+   (
+   int length
+   )
+
+   {
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   SampleLength = length - 1;
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   // Program DSP to play sound
+   BLASTER_WriteDSP( DSP_Old8BitDAC );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+   BLASTER_SoundPlaying = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP2xx_BeginPlayback
+
+   Starts playback of digitized sound on cards compatible with DSP
+   version 2.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP2xx_BeginPlayback
+   (
+   int length
+   )
+
+   {
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   SampleLength = length - 1;
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   BLASTER_WriteDSP( DSP_SetBlockLength );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
+      ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
+      {
+      BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitMode );
+      BLASTER_HaltTransferCommand = DSP_Reset;
+      }
+   else
+      {
+      BLASTER_WriteDSP( DSP_8BitAutoInitMode );
+      BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+      }
+
+   BLASTER_SoundPlaying = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP4xx_BeginPlayback
+
+   Starts playback of digitized sound on cards compatible with DSP
+   version 4.xx, such as the Sound Blaster 16.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP4xx_BeginPlayback
+   (
+   int length
+   )
+
+   {
+   int TransferCommand;
+   int TransferMode;
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   if ( BLASTER_MixMode & SIXTEEN_BIT )
+      {
+      TransferCommand = DSP_16BitDAC;
+      SampleLength = ( length / 2 ) - 1;
+      BLASTER_HaltTransferCommand = DSP_Halt16bitTransfer;
+      if ( BLASTER_MixMode & STEREO )
+         {
+         TransferMode = DSP_SignedStereoData;
+         }
+      else
+         {
+         TransferMode = DSP_SignedMonoData;
+         }
+      }
+   else
+      {
+      TransferCommand = DSP_8BitDAC;
+      SampleLength = length - 1;
+      BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+      if ( BLASTER_MixMode & STEREO )
+         {
+         TransferMode = DSP_UnsignedStereoData;
+         }
+      else
+         {
+         TransferMode = DSP_UnsignedMonoData;
+         }
+      }
+
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   // Program DSP to play sound
+   BLASTER_WriteDSP( TransferCommand );
+   BLASTER_WriteDSP( TransferMode );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   BLASTER_SoundPlaying = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_BeginBufferedPlayback
+
+   Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int BLASTER_BeginBufferedPlayback
+   (
+   char    *BufferStart,
+   int      BufferSize,
+   int      NumDivisions,
+   unsigned SampleRate,
+   int      MixMode,
+   void  ( *CallBackFunc )( void )
+   )
+
+   {
+   int DmaStatus;
+   int TransferLength;
+
+//JIM
+//   if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
+      {
+      BLASTER_StopPlayback();
+      }
+
+   BLASTER_SetMixMode( MixMode );
+
+   DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitRead );
+   if ( DmaStatus == BLASTER_Error )
+      {
+      return( BLASTER_Error );
+      }
+
+   BLASTER_SetPlaybackRate( SampleRate );
+
+   BLASTER_SetCallBack( CallBackFunc );
+
+   BLASTER_EnableInterrupt();
+
+   // Turn on speaker
+   BLASTER_SpeakerOn();
+
+   TransferLength = BufferSize / NumDivisions;
+   BLASTER_TransferLength = TransferLength;
+
+   //  Program the sound card to start the transfer.
+   if ( BLASTER_Version < DSP_Version2xx )
+      {
+      BLASTER_DSP1xx_BeginPlayback( TransferLength );
+      }
+   else if ( BLASTER_Version < DSP_Version4xx )
+      {
+      BLASTER_DSP2xx_BeginPlayback( TransferLength );
+      }
+   else
+      {
+      BLASTER_DSP4xx_BeginPlayback( TransferLength );
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP4xx_BeginRecord
+
+   Starts recording of digitized sound on cards compatible with DSP
+   version 4.xx, such as the Sound Blaster 16.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP4xx_BeginRecord
+   (
+   int length
+   )
+
+   {
+   int TransferCommand;
+   int TransferMode;
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   TransferCommand = DSP_8BitADC;
+   SampleLength = length - 1;
+   BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+   TransferMode = DSP_UnsignedMonoData;
+
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   // Program DSP to play sound
+   BLASTER_WriteDSP( TransferCommand );
+   BLASTER_WriteDSP( TransferMode );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   BLASTER_SoundRecording = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP2xx_BeginRecord
+
+   Starts recording of digitized sound on cards compatible with DSP
+   version 2.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP2xx_BeginRecord
+   (
+   int length
+   )
+
+   {
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   SampleLength = length - 1;
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   BLASTER_WriteDSP( DSP_SetBlockLength );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
+      ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
+      {
+      BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitRecord );
+      BLASTER_HaltTransferCommand = DSP_Reset;
+      }
+   else
+      {
+      BLASTER_WriteDSP( DSP_8BitAutoInitRecord );
+      BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+      }
+
+   BLASTER_SoundRecording = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_DSP1xx_BeginRecord
+
+   Starts recording of digitized sound on cards compatible with DSP
+   version 1.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP1xx_BeginRecord
+   (
+   int length
+   )
+
+   {
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   SampleLength = length - 1;
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+
+   // Program DSP to play sound
+   BLASTER_WriteDSP( DSP_Old8BitADC );
+   BLASTER_WriteDSP( LoByte );
+   BLASTER_WriteDSP( HiByte );
+
+   BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+   BLASTER_SoundRecording = TRUE;
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_BeginBufferedRecord
+
+   Begins multibuffered recording of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int BLASTER_BeginBufferedRecord
+   (
+   char    *BufferStart,
+   int      BufferSize,
+   int      NumDivisions,
+   unsigned SampleRate,
+   int      MixMode,
+   void  ( *CallBackFunc )( void )
+   )
+
+   {
+   int DmaStatus;
+   int TransferLength;
+
+//JIM
+//   if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
+      {
+      BLASTER_StopPlayback();
+      }
+
+   BLASTER_SetMixMode( MixMode );
+
+   DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitWrite );
+   if ( DmaStatus == BLASTER_Error )
+      {
+      return( BLASTER_Error );
+      }
+
+   BLASTER_SetPlaybackRate( SampleRate );
+
+   BLASTER_SetCallBack( CallBackFunc );
+
+   BLASTER_EnableInterrupt();
+
+   // Turn off speaker
+   BLASTER_SpeakerOff();
+
+   TransferLength = BufferSize / NumDivisions;
+   BLASTER_TransferLength = TransferLength;
+
+   //  Program the sound card to start the transfer.
+   if ( BLASTER_Version < DSP_Version2xx )
+      {
+      BLASTER_DSP1xx_BeginRecord( TransferLength );
+      }
+   else if ( BLASTER_Version < DSP_Version4xx )
+      {
+      BLASTER_DSP2xx_BeginRecord( TransferLength );
+      }
+   else
+      {
+      BLASTER_DSP4xx_BeginRecord( TransferLength );
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_WriteMixer
+
+   Writes a byte of data to the Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+void BLASTER_WriteMixer
+   (
+   int reg,
+   int data
+   )
+
+   {
+   outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
+   outp( BLASTER_MixerAddress + BLASTER_MixerDataPort, data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ReadMixer
+
+   Reads a byte of data from the Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_ReadMixer
+   (
+   int reg
+   )
+
+   {
+   int data;
+
+   outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
+   data = inp( BLASTER_MixerAddress + BLASTER_MixerDataPort );
+   return( data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetVoiceVolume
+
+   Reads the average volume of the digitized sound channel from the
+   Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetVoiceVolume
+   (
+   void
+   )
+
+   {
+   int volume;
+   int left;
+   int right;
+
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         left   = BLASTER_ReadMixer( MIXER_SBProVoice );
+         right  = ( left & 0x0f ) << 4;
+         left  &= 0xf0;
+         volume = ( left + right ) / 2;
+         break;
+
+      case SB16 :
+         left  = BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
+         right = BLASTER_ReadMixer( MIXER_SB16VoiceRight );
+         volume = ( left + right ) / 2;
+         break;
+
+      default :
+         BLASTER_SetErrorCode( BLASTER_NoMixer );
+         volume = BLASTER_Error;
+      }
+
+   return( volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetVoiceVolume
+
+   Sets the volume of the digitized sound channel on the Sound
+   Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetVoiceVolume
+   (
+   int volume
+   )
+
+   {
+   int data;
+   int status;
+
+   volume = min( 255, volume );
+   volume = max( 0, volume );
+
+   status = BLASTER_Ok;
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         data = ( volume & 0xf0 ) + ( volume >> 4 );
+         BLASTER_WriteMixer( MIXER_SBProVoice, data );
+         break;
+
+      case SB16 :
+         BLASTER_WriteMixer( MIXER_SB16VoiceLeft, volume & 0xf8 );
+         BLASTER_WriteMixer( MIXER_SB16VoiceRight, volume & 0xf8 );
+         break;
+
+      default :
+         BLASTER_SetErrorCode( BLASTER_NoMixer );
+         status = BLASTER_Error;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetMidiVolume
+
+   Reads the average volume of the Midi sound channel from the
+   Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetMidiVolume
+   (
+   void
+   )
+
+   {
+   int volume;
+   int left;
+   int right;
+
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         left   = BLASTER_ReadMixer( MIXER_SBProMidi );
+         right  = ( left & 0x0f ) << 4;
+         left  &= 0xf0;
+         volume = ( left + right ) / 2;
+         break;
+
+      case SB16 :
+         left  = BLASTER_ReadMixer( MIXER_SB16MidiLeft );
+         right = BLASTER_ReadMixer( MIXER_SB16MidiRight );
+         volume = ( left + right ) / 2;
+         break;
+
+      default :
+         BLASTER_SetErrorCode( BLASTER_NoMixer );
+         volume = BLASTER_Error;
+      }
+
+   return( volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetMidiVolume
+
+   Sets the volume of the Midi sound channel on the Sound
+   Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetMidiVolume
+   (
+   int volume
+   )
+
+   {
+   int data;
+   int status;
+
+   volume = min( 255, volume );
+   volume = max( 0, volume );
+
+   status = BLASTER_Ok;
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         data = ( volume & 0xf0 ) + ( volume >> 4 );
+         BLASTER_WriteMixer( MIXER_SBProMidi, data );
+         break;
+
+      case SB16 :
+         BLASTER_WriteMixer( MIXER_SB16MidiLeft, volume & 0xf8 );
+         BLASTER_WriteMixer( MIXER_SB16MidiRight, volume & 0xf8 );
+         break;
+
+      default :
+         BLASTER_SetErrorCode( BLASTER_NoMixer );
+         status = BLASTER_Error;
+      }
+
+   return( status );
+   }
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_CardHasMixer
+
+   Checks if the selected Sound Blaster card has a mixer.
+---------------------------------------------------------------------*/
+
+int BLASTER_CardHasMixer
+   (
+   void
+   )
+
+   {
+   return( BLASTER_Card.HasMixer );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SaveVoiceVolume
+
+   Saves the user's voice mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_SaveVoiceVolume
+   (
+   void
+   )
+
+   {
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         BLASTER_OriginalVoiceVolumeLeft =
+            BLASTER_ReadMixer( MIXER_SBProVoice );
+         break;
+
+      case SB16 :
+         BLASTER_OriginalVoiceVolumeLeft =
+            BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
+         BLASTER_OriginalVoiceVolumeRight =
+            BLASTER_ReadMixer( MIXER_SB16VoiceRight );
+         break;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_RestoreVoiceVolume
+
+   Restores the user's voice mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_RestoreVoiceVolume
+   (
+   void
+   )
+
+   {
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         BLASTER_WriteMixer( MIXER_SBProVoice,
+            BLASTER_OriginalVoiceVolumeLeft );
+         break;
+
+      case SB16 :
+         BLASTER_WriteMixer( MIXER_SB16VoiceLeft,
+            BLASTER_OriginalVoiceVolumeLeft );
+         BLASTER_WriteMixer( MIXER_SB16VoiceRight,
+            BLASTER_OriginalVoiceVolumeRight );
+         break;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SaveMidiVolume
+
+   Saves the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_SaveMidiVolume
+   (
+   void
+   )
+
+   {
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         BLASTER_OriginalMidiVolumeLeft =
+            BLASTER_ReadMixer( MIXER_SBProMidi );
+         break;
+
+      case SB16 :
+         BLASTER_OriginalMidiVolumeLeft =
+            BLASTER_ReadMixer( MIXER_SB16MidiLeft );
+         BLASTER_OriginalMidiVolumeRight =
+            BLASTER_ReadMixer( MIXER_SB16MidiRight );
+         break;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_RestoreMidiVolume
+
+   Restores the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_RestoreMidiVolume
+   (
+   void
+   )
+
+   {
+   switch( BLASTER_MixerType )
+      {
+      case SBPro :
+      case SBPro2 :
+         BLASTER_WriteMixer( MIXER_SBProMidi,
+            BLASTER_OriginalMidiVolumeLeft );
+         break;
+
+      case SB16 :
+         BLASTER_WriteMixer( MIXER_SB16MidiLeft,
+            BLASTER_OriginalMidiVolumeLeft );
+         BLASTER_WriteMixer( MIXER_SB16MidiRight,
+            BLASTER_OriginalMidiVolumeRight );
+         break;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetEnv
+
+   Retrieves the BLASTER environment settings and returns them to
+   the caller.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetEnv
+   (
+   BLASTER_CONFIG *Config
+   )
+
+   {
+   char *Blaster;
+   char parameter;
+
+   Config->Address   = UNDEFINED;
+   Config->Type      = UNDEFINED;
+   Config->Interrupt = UNDEFINED;
+   Config->Dma8      = UNDEFINED;
+   Config->Dma16     = UNDEFINED;
+   Config->Midi      = UNDEFINED;
+   Config->Emu       = UNDEFINED;
+
+   Blaster = getenv( "BLASTER" );
+   if ( Blaster == NULL )
+      {
+      BLASTER_SetErrorCode( BLASTER_EnvNotFound );
+      return( BLASTER_Error );
+      }
+
+   while( *Blaster != 0 )
+      {
+      if ( *Blaster == ' ' )
+         {
+         Blaster++;
+         continue;
+         }
+
+      parameter = toupper( *Blaster );
+      Blaster++;
+
+      if ( !isxdigit( *Blaster ) )
+         {
+         BLASTER_SetErrorCode( BLASTER_InvalidParameter );
+         return( BLASTER_Error );
+         }
+
+      switch( parameter )
+         {
+         case BlasterEnv_Address :
+            sscanf( Blaster, "%x", &Config->Address );
+            break;
+         case BlasterEnv_Interrupt :
+            sscanf( Blaster, "%d", &Config->Interrupt );
+            break;
+         case BlasterEnv_8bitDma :
+            sscanf( Blaster, "%d", &Config->Dma8 );
+            break;
+         case BlasterEnv_Type :
+            sscanf( Blaster, "%d", &Config->Type );
+            break;
+         case BlasterEnv_16bitDma :
+            sscanf( Blaster, "%d", &Config->Dma16 );
+            break;
+         case BlasterEnv_Midi :
+            sscanf( Blaster, "%x", &Config->Midi );
+            break;
+         case BlasterEnv_EmuAddress :
+            sscanf( Blaster, "%x", &Config->Emu );
+            break;
+         default  :
+            // Skip the offending data
+            // sscanf( Blaster, "%*s" );
+            break;
+         }
+
+      while( isxdigit( *Blaster ) )
+         {
+         Blaster++;
+         }
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetCardSettings
+
+   Sets up the sound card's parameters.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetCardSettings
+   (
+   BLASTER_CONFIG Config
+   )
+
+   {
+   if ( BLASTER_Installed )
+      {
+      BLASTER_Shutdown();
+      }
+
+   BLASTER_Config.Address   = Config.Address;
+   BLASTER_Config.Type      = Config.Type;
+   BLASTER_Config.Interrupt = Config.Interrupt;
+   BLASTER_Config.Dma8      = Config.Dma8;
+   BLASTER_Config.Dma16     = Config.Dma16;
+   BLASTER_Config.Midi      = Config.Midi;
+   BLASTER_Config.Emu       = Config.Emu;
+   BLASTER_MixerAddress     = Config.Address;
+   BLASTER_MixerType        = Config.Type;
+
+   if ( BLASTER_Config.Emu == UNDEFINED )
+      {
+      BLASTER_Config.Emu = BLASTER_Config.Address + 0x400;
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetCardSettings
+
+   Sets up the sound card's parameters.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCardSettings
+   (
+   BLASTER_CONFIG *Config
+   )
+
+   {
+   if ( BLASTER_Config.Address == UNDEFINED )
+      {
+      return( BLASTER_Warning );
+      }
+   else
+      {
+      Config->Address   = BLASTER_Config.Address;
+      Config->Type      = BLASTER_Config.Type;
+      Config->Interrupt = BLASTER_Config.Interrupt;
+      Config->Dma8      = BLASTER_Config.Dma8;
+      Config->Dma16     = BLASTER_Config.Dma16;
+      Config->Midi      = BLASTER_Config.Midi;
+      Config->Emu       = BLASTER_Config.Emu;
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_GetCardInfo
+
+   Returns the maximum number of bits that can represent a sample
+   (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCardInfo
+   (
+   int *MaxSampleBits,
+   int *MaxChannels
+   )
+
+   {
+   if ( BLASTER_Card.MaxMixMode & STEREO )
+      {
+      *MaxChannels = 2;
+      }
+   else
+      {
+      *MaxChannels = 1;
+      }
+
+   if ( BLASTER_Card.MaxMixMode & SIXTEEN_BIT )
+      {
+      *MaxSampleBits = 16;
+      }
+   else
+      {
+      *MaxSampleBits = 8;
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetCallBack
+
+   Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetCallBack
+   (
+   void ( *func )( void )
+   )
+
+   {
+   BLASTER_CallBack = func;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void BLASTER_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void BLASTER_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
+   DPMI_UnlockMemory( ( void * )&BLASTER_Interrupts[ 0 ],
+      sizeof( BLASTER_Interrupts ) );
+   DPMI_UnlockMemory( ( void * )&BLASTER_SampleSize[ 0 ],
+      sizeof( BLASTER_SampleSize ) );
+   DPMI_Unlock( BLASTER_Card );
+   DPMI_Unlock( BLASTER_OldInt );
+   DPMI_Unlock( BLASTER_Config );
+   DPMI_Unlock( BLASTER_Installed );
+   DPMI_Unlock( BLASTER_Version );
+   DPMI_Unlock( BLASTER_DMABuffer );
+   DPMI_Unlock( BLASTER_DMABufferEnd );
+   DPMI_Unlock( BLASTER_CurrentDMABuffer );
+   DPMI_Unlock( BLASTER_TotalDMABufferSize );
+   DPMI_Unlock( BLASTER_TransferLength );
+   DPMI_Unlock( BLASTER_MixMode );
+   DPMI_Unlock( BLASTER_SamplePacketSize );
+   DPMI_Unlock( BLASTER_SampleRate );
+   DPMI_Unlock( BLASTER_HaltTransferCommand );
+   DPMI_Unlock( ( int )BLASTER_SoundPlaying );
+   DPMI_Unlock( ( int )BLASTER_SoundRecording );
+   DPMI_Unlock( BLASTER_CallBack );
+   DPMI_Unlock( BLASTER_IntController1Mask );
+   DPMI_Unlock( BLASTER_IntController2Mask );
+   DPMI_Unlock( BLASTER_MixerAddress );
+   DPMI_Unlock( BLASTER_MixerType );
+   DPMI_Unlock( BLASTER_OriginalMidiVolumeLeft );
+   DPMI_Unlock( BLASTER_OriginalMidiVolumeRight );
+   DPMI_Unlock( BLASTER_OriginalVoiceVolumeLeft );
+   DPMI_Unlock( BLASTER_OriginalVoiceVolumeRight );
+   DPMI_Unlock( GlobalStatus );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int BLASTER_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
+   status |= DPMI_LockMemory( ( void * )&BLASTER_Interrupts[ 0 ],
+      sizeof( BLASTER_Interrupts ) );
+   status |= DPMI_LockMemory( ( void * )&BLASTER_SampleSize[ 0 ],
+      sizeof( BLASTER_SampleSize ) );
+   status |= DPMI_Lock( BLASTER_Card );
+   status |= DPMI_Lock( BLASTER_OldInt );
+   status |= DPMI_Lock( BLASTER_Config );
+   status |= DPMI_Lock( BLASTER_Installed );
+   status |= DPMI_Lock( BLASTER_Version );
+   status |= DPMI_Lock( BLASTER_DMABuffer );
+   status |= DPMI_Lock( BLASTER_DMABufferEnd );
+   status |= DPMI_Lock( BLASTER_CurrentDMABuffer );
+   status |= DPMI_Lock( BLASTER_TotalDMABufferSize );
+   status |= DPMI_Lock( BLASTER_TransferLength );
+   status |= DPMI_Lock( BLASTER_MixMode );
+   status |= DPMI_Lock( BLASTER_SamplePacketSize );
+   status |= DPMI_Lock( BLASTER_SampleRate );
+   status |= DPMI_Lock( BLASTER_HaltTransferCommand );
+   status |= DPMI_Lock( ( ( int )BLASTER_SoundPlaying ) );
+   status |= DPMI_Lock( ( ( int )BLASTER_SoundRecording ) );
+   status |= DPMI_Lock( BLASTER_CallBack );
+   status |= DPMI_Lock( BLASTER_IntController1Mask );
+   status |= DPMI_Lock( BLASTER_IntController2Mask );
+   status |= DPMI_Lock( BLASTER_MixerAddress );
+   status |= DPMI_Lock( BLASTER_MixerType );
+   status |= DPMI_Lock( BLASTER_OriginalMidiVolumeLeft );
+   status |= DPMI_Lock( BLASTER_OriginalMidiVolumeRight );
+   status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeLeft );
+   status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeRight );
+   status |= DPMI_Lock( GlobalStatus );
+
+   if ( status != DPMI_Ok )
+      {
+      BLASTER_UnlockMemory();
+      BLASTER_SetErrorCode( BLASTER_DPMI_Error );
+      return( BLASTER_Error );
+      }
+
+   return( BLASTER_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: allocateTimerStack
+
+   Allocate a block of memory from conventional (low) memory and return
+   the selector (which can go directly into a segment register) of the
+   memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+   (
+   unsigned short size
+   )
+
+   {
+   union REGS regs;
+
+   // clear all registers
+   memset( &regs, 0, sizeof( regs ) );
+
+   // DPMI allocate conventional memory
+   regs.w.ax = 0x100;
+
+   // size in paragraphs
+   regs.w.bx = ( size + 15 ) / 16;
+
+   int386( 0x31, &regs, &regs );
+   if (!regs.w.cflag)
+      {
+      // DPMI call returns selector in dx
+      // (ax contains real mode segment
+      // which is ignored here)
+
+      return( regs.w.dx );
+      }
+
+   // Couldn't allocate memory.
+   return( NULL );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: deallocateTimerStack
+
+   Deallocate a block of conventional (low) memory given a selector to
+   it.  Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+   (
+   unsigned short selector
+   )
+
+   {
+   union REGS regs;
+
+   if ( selector != NULL )
+      {
+      // clear all registers
+      memset( &regs, 0, sizeof( regs ) );
+
+      regs.w.ax = 0x101;
+      regs.w.dx = selector;
+      int386( 0x31, &regs, &regs );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_SetupWaveBlaster
+
+   Allows the WaveBlaster to play music while the Sound Blaster 16
+   plays digital sound.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetupWaveBlaster
+   (
+   void
+   )
+
+   {
+
+   if ( BLASTER_MixerType == SB16 )
+      {
+      // Disable MPU401 interrupts.  If they are not disabled,
+      // the SB16 will not produce sound or music.
+      BLASTER_WaveBlasterState = BLASTER_ReadMixer( MIXER_DSP4xxISR_Enable );
+      BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, MIXER_DisableMPU401Interrupts );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_ShutdownWaveBlaster
+
+   Restores WaveBlaster mixer to original state.
+---------------------------------------------------------------------*/
+
+void BLASTER_ShutdownWaveBlaster
+   (
+   void
+   )
+
+   {
+   if ( BLASTER_MixerType == SB16 )
+      {
+      // Restore the state of MPU401 interrupts.  If they are not disabled,
+      // the SB16 will not produce sound or music.
+      BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, BLASTER_WaveBlasterState );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_Init
+
+   Initializes the sound card and prepares the module to play
+   digitized sounds.
+---------------------------------------------------------------------*/
+
+int BLASTER_Init
+   (
+   void
+   )
+
+   {
+   int Irq;
+   int Interrupt;
+   int status;
+
+   if ( BLASTER_Installed )
+      {
+      BLASTER_Shutdown();
+      }
+
+   if ( BLASTER_Config.Address == UNDEFINED )
+      {
+      BLASTER_SetErrorCode( BLASTER_AddrNotSet );
+      return( BLASTER_Error );
+      }
+
+   // Save the interrupt masks
+   BLASTER_IntController1Mask = inp( 0x21 );
+   BLASTER_IntController2Mask = inp( 0xA1 );
+
+   status = BLASTER_ResetDSP();
+   if ( status == BLASTER_Ok )
+      {
+      BLASTER_SaveVoiceVolume();
+
+      BLASTER_SoundPlaying = FALSE;
+
+      BLASTER_SetCallBack( NULL );
+
+      BLASTER_DMABuffer = NULL;
+
+      BLASTER_Version = BLASTER_GetDSPVersion();
+
+      BLASTER_SetPlaybackRate( BLASTER_DefaultSampleRate );
+      BLASTER_SetMixMode( BLASTER_DefaultMixMode );
+
+      if ( BLASTER_Config.Dma16 != UNDEFINED )
+         {
+         status = DMA_VerifyChannel( BLASTER_Config.Dma16 );
+         if ( status == DMA_Error )
+            {
+            BLASTER_SetErrorCode( BLASTER_DmaError );
+            return( BLASTER_Error );
+            }
+         }
+
+      if ( BLASTER_Config.Dma8 != UNDEFINED )
+         {
+         status = DMA_VerifyChannel( BLASTER_Config.Dma8 );
+         if ( status == DMA_Error )
+            {
+            BLASTER_SetErrorCode( BLASTER_DmaError );
+            return( BLASTER_Error );
+            }
+         }
+
+      // Install our interrupt handler
+      Irq = BLASTER_Config.Interrupt;
+      if ( !VALID_IRQ( Irq ) )
+         {
+         BLASTER_SetErrorCode( BLASTER_InvalidIrq );
+         return( BLASTER_Error );
+         }
+
+      Interrupt = BLASTER_Interrupts[ Irq ];
+      if ( Interrupt == INVALID )
+         {
+         BLASTER_SetErrorCode( BLASTER_InvalidIrq );
+         return( BLASTER_Error );
+         }
+
+      status = BLASTER_LockMemory();
+      if ( status != BLASTER_Ok )
+         {
+         BLASTER_UnlockMemory();
+         return( status );
+         }
+
+      StackSelector = allocateTimerStack( kStackSize );
+      if ( StackSelector == NULL )
+         {
+         BLASTER_UnlockMemory();
+         BLASTER_SetErrorCode( BLASTER_OutOfMemory );
+         return( BLASTER_Error );
+         }
+
+      // Leave a little room at top of stack just for the hell of it...
+      StackPointer = kStackSize - sizeof( long );
+
+      BLASTER_OldInt = _dos_getvect( Interrupt );
+      if ( Irq < 8 )
+         {
+         _dos_setvect( Interrupt, BLASTER_ServiceInterrupt );
+         }
+      else
+         {
+         status = IRQ_SetVector( Interrupt, BLASTER_ServiceInterrupt );
+         if ( status != IRQ_Ok )
+            {
+            BLASTER_UnlockMemory();
+            deallocateTimerStack( StackSelector );
+            StackSelector = NULL;
+            BLASTER_SetErrorCode( BLASTER_UnableToSetIrq );
+            return( BLASTER_Error );
+            }
+         }
+
+      BLASTER_Installed = TRUE;
+      status = BLASTER_Ok;
+      }
+
+   BLASTER_SetErrorCode( status );
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: BLASTER_Shutdown
+
+   Ends transfer of sound data to the sound card and restores the
+   system resources used by the card.
+---------------------------------------------------------------------*/
+
+void BLASTER_Shutdown
+   (
+   void
+   )
+
+   {
+   int Irq;
+   int Interrupt;
+
+   // Halt the DMA transfer
+   BLASTER_StopPlayback();
+
+   BLASTER_RestoreVoiceVolume();
+
+   // Reset the DSP
+   BLASTER_ResetDSP();
+
+   // Restore the original interrupt
+   Irq = BLASTER_Config.Interrupt;
+   Interrupt = BLASTER_Interrupts[ Irq ];
+   if ( Irq >= 8 )
+      {
+      IRQ_RestoreVector( Interrupt );
+      }
+   _dos_setvect( Interrupt, BLASTER_OldInt );
+
+   BLASTER_SoundPlaying = FALSE;
+
+   BLASTER_DMABuffer = NULL;
+
+   BLASTER_SetCallBack( NULL );
+
+   BLASTER_UnlockMemory();
+
+   deallocateTimerStack( StackSelector );
+   StackSelector = NULL;
+
+   BLASTER_Installed = FALSE;
+   }

Added: tags/rott-1.1/rott/audiolib/blaster.h
===================================================================
--- tags/rott-1.1/rott/audiolib/blaster.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/blaster.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,148 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: BLASTER.H
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Public header for BLASTER.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __BLASTER_H
+#define __BLASTER_H
+
+typedef struct
+   {
+   unsigned Address;
+   unsigned Type;
+   unsigned Interrupt;
+   unsigned Dma8;
+   unsigned Dma16;
+   unsigned Midi;
+   unsigned Emu;
+   } BLASTER_CONFIG;
+
+extern BLASTER_CONFIG BLASTER_Config;
+extern int BLASTER_DMAChannel;
+
+#define UNDEFINED -1
+
+enum BLASTER_ERRORS
+   {
+   BLASTER_Warning = -2,
+   BLASTER_Error = -1,
+   BLASTER_Ok = 0,
+   BLASTER_EnvNotFound,
+   BLASTER_AddrNotSet,
+   BLASTER_DMANotSet,
+   BLASTER_DMA16NotSet,
+   BLASTER_InvalidParameter,
+   BLASTER_CardNotReady,
+   BLASTER_NoSoundPlaying,
+   BLASTER_InvalidIrq,
+   BLASTER_UnableToSetIrq,
+   BLASTER_DmaError,
+   BLASTER_NoMixer,
+   BLASTER_DPMI_Error,
+   BLASTER_OutOfMemory
+   };
+
+enum BLASTER_Types
+   {
+   SB     = 1,
+   SBPro  = 2,
+   SB20   = 3,
+   SBPro2 = 4,
+   SB16   = 6
+   };
+
+#define BLASTER_MinCardType    SB
+#define BLASTER_MaxCardType    SB16
+
+#define STEREO      1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT    0
+#define STEREO_8BIT  ( STEREO )
+#define MONO_16BIT   ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define BLASTER_MaxMixMode        STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE    1
+#define MONO_16BIT_SAMPLE_SIZE   2
+#define STEREO_8BIT_SAMPLE_SIZE  ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define BLASTER_DefaultSampleRate 11000
+#define BLASTER_DefaultMixMode    MONO_8BIT
+#define BLASTER_MaxIrq            15
+
+char *BLASTER_ErrorString( int ErrorNumber );
+void  BLASTER_EnableInterrupt( void );
+void  BLASTER_DisableInterrupt( void );
+int   BLASTER_WriteDSP( unsigned data );
+int   BLASTER_ReadDSP( void );
+int   BLASTER_ResetDSP( void );
+int   BLASTER_GetDSPVersion( void );
+void  BLASTER_SpeakerOn( void );
+void  BLASTER_SpeakerOff( void );
+void  BLASTER_SetPlaybackRate( unsigned rate );
+unsigned BLASTER_GetPlaybackRate( void );
+int   BLASTER_SetMixMode( int mode );
+void  BLASTER_StopPlayback( void );
+int   BLASTER_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+int   BLASTER_GetCurrentPos( void );
+int   BLASTER_DSP1xx_BeginPlayback( int length );
+int   BLASTER_DSP2xx_BeginPlayback( int length );
+int   BLASTER_DSP4xx_BeginPlayback( int length );
+int   BLASTER_BeginBufferedRecord( char *BufferStart, int BufferSize,
+          int NumDivisions, unsigned SampleRate, int MixMode,
+          void ( *CallBackFunc )( void ) );
+int   BLASTER_BeginBufferedPlayback( char *BufferStart,
+         int BufferSize, int NumDivisions, unsigned SampleRate,
+         int MixMode, void ( *CallBackFunc )( void ) );
+void  BLASTER_WriteMixer( int reg, int data );
+int   BLASTER_ReadMixer( int reg );
+int   BLASTER_GetVoiceVolume( void );
+int   BLASTER_SetVoiceVolume( int volume );
+int   BLASTER_GetMidiVolume( void );
+int   BLASTER_SetMidiVolume( int volume );
+int   BLASTER_CardHasMixer( void );
+void  BLASTER_SaveVoiceVolume( void );
+void  BLASTER_RestoreVoiceVolume( void );
+void  BLASTER_SaveMidiVolume( void );
+void  BLASTER_RestoreMidiVolume( void );
+int   BLASTER_GetEnv( BLASTER_CONFIG *Config );
+int   BLASTER_SetCardSettings( BLASTER_CONFIG Config );
+int   BLASTER_GetCardSettings( BLASTER_CONFIG *Config );
+int   BLASTER_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void  BLASTER_SetCallBack( void ( *func )( void ) );
+void  BLASTER_SetupWaveBlaster( void );
+void  BLASTER_ShutdownWaveBlaster( void );
+int   BLASTER_Init( void );
+void  BLASTER_Shutdown( void );
+void  BLASTER_UnlockMemory( void );
+int   BLASTER_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/ctaweapi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/ctaweapi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/ctaweapi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,352 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/****************************************************************************\
+*                                                                            *
+* CTAWEAPI.H SB AWE32 DOS API header                                         *
+*                                                                            *
+* (C) Copyright Creative Technology Ltd. 1992-94. All rights reserved        *
+* worldwide.                                                                 *
+*                                                                            *
+* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      *
+* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE        *
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR      *
+* PURPOSE.                                                                   *
+*                                                                            *
+* You have a royalty-free right to use, modify, reproduce and                *
+* distribute the Sample Files (and/or any modified version) in               *
+* any way you find useful, provided that you agree to                        *
+* the Creative's Software Licensing Aggreement and you also agree that       *
+* Creative has no warranty obligations or liability for any Sample Files.    *
+*                                                                            *
+\****************************************************************************/
+
+/****************************************************************************\
+*      File name       : CTAWEAPI.H                                          *
+*                                                                            *
+*      Programmer      : Creative SB AWE32 Team                              *
+*                        Creative Technology Ltd, 1994. All rights reserved. *
+*                                                                            *
+*      Version         : 2.0b                                                *
+*                                                                            *
+\****************************************************************************/
+
+#ifndef _CTAWEAPI
+#define _CTAWEAPI
+
+
+#define MAXBANKS            64      /* maximum number of banks */
+#define MAXNRPN             32      /* maximum number of NRPN */
+
+
+#if defined(__FLAT__) || defined(__HIGHC__) || defined(DOS386)
+#define PACKETSIZE      8192        /* packet size for 32bit libraries */
+#else
+#define PACKETSIZE      512         /* packet size for real mode libraries */
+#endif
+
+
+#if defined(__FLAT__)
+    #define NEAR
+    #define FAR
+#endif
+
+
+#if defined(__SC__)
+    #pragma pack(1)
+    #if defined(DOS386)
+        #define NEAR
+        #define FAR
+    #endif
+#endif
+
+
+#if defined(__WATCOMC__)
+    #pragma pack(1)
+#endif
+
+
+#if defined(__HIGHC__)
+    #define NEAR
+    #define FAR
+    #define PASCAL  _DCC((_DEFAULT_CALLING_CONVENTION|_CALLEE_POPS_STACK) & \
+                         ~ (_REVERSE_PARMS|_OVERLOADED))
+    #pragma Push_align_members(1)
+    #pragma Global_aliasing_convention("_%r")
+#endif
+
+
+typedef int                     BOOL;
+#define FALSE                   0
+#define TRUE                    1
+
+typedef unsigned char		BYTE;
+typedef unsigned short		WORD;
+typedef unsigned long		DWORD;
+
+typedef short int               SHORT;
+typedef unsigned int		UINT;
+typedef signed long 		LONG;
+
+#ifndef FAR
+#define FAR                     __far
+#endif
+
+#ifndef HUGE
+#define HUGE                    __huge
+#endif
+
+#ifndef PASCAL
+#define PASCAL                  __pascal
+#endif
+
+typedef void FAR*               LPVOID;
+typedef BYTE FAR*               LPBYTE;
+typedef WORD FAR*               LPWORD;
+typedef DWORD FAR*              LPDWORD;
+
+#define LOBYTE(w)               ((BYTE)(w))
+#define HIBYTE(w)               ((BYTE)(((UINT)(w) >> 8) & 0xFF))
+
+#define LOWORD(l)               ((WORD)(DWORD)(l))
+#define HIWORD(l)               ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Start of modules */
+extern int* __midieng_code(void);
+extern int* __hardware_code(void);
+extern int* __sbkload_code(void);
+extern int* __nrpn_code(void);
+extern int __midivar_data;
+extern int __nrpnvar_data;
+extern int __embed_data;
+
+
+typedef char SCRATCH[702];
+typedef char SOUNDFONT[124];
+typedef char GCHANNEL[20];
+typedef char MIDICHANNEL[32];
+typedef char NRPNCHANNEL[96];
+
+typedef struct {
+    SHORT bank_no;          /* Slot number being used */
+    SHORT total_banks;      /* Total number of banks */
+    LONG FAR* banksizes;    /* Pointer to a list of bank sizes */
+    LONG file_size;         /* exact size of the sound font file */
+    char FAR* data;         /* Address of buffer of size >= PACKETSIZE */
+    char FAR* presets;      /* Allocated memory for preset data */
+
+    LONG total_patch_ram;   /* Total patch ram available */
+    SHORT no_sample_packets;/* Number of packets of sound sample to stream */
+    LONG sample_seek;       /* Start file location of sound sample */
+    LONG preset_seek;       /* Address of preset_seek location */
+    LONG preset_read_size;  /* Number of bytes from preset_seek to allocate and read */
+    LONG preset_size;       /* Preset actual size */
+} SOUND_PACKET;
+
+typedef struct {
+    SHORT tag;              /* Must be 0x100 or 0x101 */
+    SHORT preset_size;      /* Preset table of this size is required */
+    SHORT no_wave_packets;  /* Number of packets of Wave sample to stream. */
+    LONG reserved;
+
+    SHORT bank_no;          /* bank number */
+    char FAR* data;         /* Address of packet of size PACKETSIZE */
+    char FAR* presets;      /* Allocated memory for preset data */
+    LONG sample_size;       /* Sample size, i.e. number of samples */
+    LONG samples_per_sec;   /* Samples per second */
+    SHORT bits_per_sample;  /* Bits per sample, 8 or 16 */
+    SHORT no_channels;      /* Number of channels, 1=mono, 2=stereo */
+    SHORT looping;          /* Looping? 0=no, 1=yes */
+    LONG startloop;         /* if looping, then these are the addresses */
+    LONG endloop;
+    SHORT release;          /* release time, 0=24ms, 8191=23.78s */
+} WAVE_PACKET;
+
+typedef struct {
+    LPBYTE SPad1;
+    LPBYTE SPad2;
+    LPBYTE SPad3;
+    LPBYTE SPad4;
+    LPBYTE SPad5;
+    LPBYTE SPad6;
+    LPBYTE SPad7;
+} SOUNDPAD;
+
+/* AWE32 variables */
+extern WORD         awe32NumG;
+extern WORD         awe32BaseAddx;
+extern DWORD        awe32DramSize;
+
+/* MIDI variables */
+extern SCRATCH      awe32Scratch;
+extern SOUNDFONT    awe32SFont[4];
+extern GCHANNEL     awe32GChannel[32];
+extern MIDICHANNEL  awe32MIDIChannel[16];
+extern SOUNDPAD     awe32SoundPad;
+
+/* NRPN variables */
+extern NRPNCHANNEL  awe32NRPNChannel[16];
+
+/* SoundFont objects */
+extern BYTE awe32SPad1Obj[];
+extern BYTE awe32SPad2Obj[];
+extern BYTE awe32SPad3Obj[];
+extern BYTE awe32SPad4Obj[];
+extern BYTE awe32SPad5Obj[];
+extern BYTE awe32SPad6Obj[];
+extern BYTE awe32SPad7Obj[];
+
+/* AWE register functions */
+extern void PASCAL awe32RegW(WORD, WORD);
+extern WORD PASCAL awe32RegRW(WORD);
+extern void PASCAL awe32RegDW(WORD, DWORD);
+extern DWORD PASCAL awe32RegRDW(WORD);
+
+/* MIDI support functions */
+extern WORD PASCAL awe32InitMIDI(void);
+extern WORD PASCAL awe32NoteOn(WORD, WORD, WORD);
+extern WORD PASCAL awe32NoteOff(WORD, WORD, WORD);
+extern WORD PASCAL awe32ProgramChange(WORD, WORD);
+extern WORD PASCAL awe32Controller(WORD, WORD, WORD);
+extern WORD PASCAL awe32PolyKeyPressure(WORD, WORD, WORD);
+extern WORD PASCAL awe32ChannelPressure(WORD, WORD);
+extern WORD PASCAL awe32PitchBend(WORD, WORD, WORD);
+extern WORD PASCAL awe32Sysex(WORD, LPBYTE, WORD);
+extern WORD PASCAL __awe32NoteOff(WORD, WORD, WORD, WORD);
+extern WORD PASCAL __awe32IsPlaying(WORD, WORD, WORD, WORD);
+
+/* NRPN support functions */
+extern WORD PASCAL awe32InitNRPN(void);
+
+/* Hardware support functions */
+extern WORD PASCAL awe32Detect(WORD);
+extern WORD PASCAL awe32InitHardware(void);
+extern WORD PASCAL awe32Terminate(void);
+
+/* SoundFont support functions */
+extern WORD PASCAL awe32TotalPatchRam(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32DefineBankSizes(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32SFontLoadRequest(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32StreamSample(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32SetPresets(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32ReleaseBank(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32ReleaseAllBanks(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32WPLoadRequest(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPLoadWave(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPStreamWave(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPBuildSFont(WAVE_PACKET FAR*);
+
+/* End of modules */
+extern int* __midieng_ecode(void);
+extern int* __hardware_ecode(void);
+extern int* __sbkload_ecode(void);
+extern int* __nrpn_ecode(void);
+extern int __midivar_edata;
+extern int __nrpnvar_edata;
+extern int __embed_edata;
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#if defined(__SC__)
+    #pragma pack()
+#endif
+
+
+#if defined(__HIGHC__)
+    #pragma Pop_align_members
+    #pragma Global_aliasing_convention()
+    #pragma Alias(awe32RegW,"AWE32REGW")
+    #pragma Alias(awe32RegRW,"AWE32REGRW")
+    #pragma Alias(awe32RegDW,"AWE32REGDW")
+    #pragma Alias(awe32RegRDW,"AWE32REGRDW")
+    #pragma Alias(awe32InitMIDI,"AWE32INITMIDI")
+    #pragma Alias(awe32NoteOn,"AWE32NOTEON")
+    #pragma Alias(awe32NoteOff,"AWE32NOTEOFF")
+    #pragma Alias(awe32ProgramChange,"AWE32PROGRAMCHANGE")
+    #pragma Alias(awe32Controller,"AWE32CONTROLLER")
+    #pragma Alias(awe32PolyKeyPressure,"AWE32POLYKEYPRESSURE")
+    #pragma Alias(awe32ChannelPressure,"AWE32CHANNELPRESSURE")
+    #pragma Alias(awe32PitchBend,"AWE32PITCHBEND")
+    #pragma Alias(awe32Sysex,"AWE32SYSEX")
+    #pragma Alias(__awe32NoteOff,"__AWE32NOTEOFF")
+    #pragma Alias(__awe32IsPlaying,"__AWE32ISPLAYING")
+    #pragma Alias(awe32InitNRPN,"AWE32INITNRPN")
+    #pragma Alias(awe32Detect,"AWE32DETECT")
+    #pragma Alias(awe32InitHardware,"AWE32INITHARDWARE")
+    #pragma Alias(awe32Terminate,"AWE32TERMINATE")
+    #pragma Alias(awe32TotalPatchRam,"AWE32TOTALPATCHRAM")
+    #pragma Alias(awe32DefineBankSizes,"AWE32DEFINEBANKSIZES")
+    #pragma Alias(awe32SFontLoadRequest,"AWE32SFONTLOADREQUEST")
+    #pragma Alias(awe32StreamSample,"AWE32STREAMSAMPLE")
+    #pragma Alias(awe32SetPresets,"AWE32SETPRESETS")
+    #pragma Alias(awe32ReleaseBank,"AWE32RELEASEBANK")
+    #pragma Alias(awe32ReleaseAllBanks,"AWE32RELEASEALLBANKS")
+    #pragma Alias(awe32WPLoadRequest,"AWE32WPLOADREQUEST")
+    #pragma Alias(awe32WPLoadWave,"AWE32WPLOADWAVE")
+    #pragma Alias(awe32WPStreamWave,"AWE32WPSTREAMWAVE")
+    #pragma Alias(awe32WPBuildSFont,"AWE32WPBUILDSFONT")
+#endif
+
+
+#if defined(__WATCOMC__)
+    #pragma pack()
+    #pragma aux awe32NumG "_*"
+    #pragma aux awe32BaseAddx "_*"
+    #pragma aux awe32DramSize "_*"
+    #pragma aux awe32Scratch "_*"
+    #pragma aux awe32SFont "_*"
+    #pragma aux awe32GChannel "_*"
+    #pragma aux awe32MIDIChannel "_*"
+    #pragma aux awe32SoundPad "_*"
+    #pragma aux awe32NRPNChannel "_*"
+    #pragma aux awe32SPad1Obj "_*"
+    #pragma aux awe32SPad2Obj "_*"
+    #pragma aux awe32SPad3Obj "_*"
+    #pragma aux awe32SPad4Obj "_*"
+    #pragma aux awe32SPad5Obj "_*"
+    #pragma aux awe32SPad6Obj "_*"
+    #pragma aux awe32SPad7Obj "_*"
+    #pragma aux __midieng_code "_*"
+    #pragma aux __midieng_ecode "_*"
+    #pragma aux __hardware_code "_*"
+    #pragma aux __hardware_ecode "_*"
+    #pragma aux __sbkload_code "_*"
+    #pragma aux __sbkload_ecode "_*"
+    #pragma aux __nrpn_code "_*"
+    #pragma aux __nrpn_ecode "_*"
+    #pragma aux __midivar_data "_*"
+    #pragma aux __midivar_edata "_*"
+    #pragma aux __nrpnvar_data "_*"
+    #pragma aux __nrpnvar_edata "_*"
+    #pragma aux __embed_data "_*"
+    #pragma aux __embed_edata "_*"
+#endif
+
+
+#endif      /* _CTAWEAPI */

Added: tags/rott-1.1/rott/audiolib/debugio.c
===================================================================
--- tags/rott-1.1/rott/audiolib/debugio.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/debugio.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,251 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "debugio.h"
+
+static unsigned short disp_offset = 160 * 24;
+static void myutoa( unsigned num, char *string, int radix );
+static void myitoa( int num, char *string, int radix );
+
+void DB_SetXY
+   (
+   int x,
+   int y
+   )
+
+   {
+   disp_offset = ( x * 2 ) + ( y * 160 );
+   }
+
+void DB_PutChar
+   (
+   char ch
+   )
+
+   {
+   int j;
+   char *disp_start = (char *)( 0xb0000 );
+
+   if ( disp_offset >= 160 * 24 )
+      {
+      for ( j = 160; j < 160 * 24; j += 2 )
+         {
+         *( disp_start + j - 160 ) = *( disp_start + j );
+         }
+
+      disp_offset = 160 * 23;
+
+      for ( j = disp_offset; j < ( 160 * 24 ); j += 2 )
+         {
+         *( disp_start + j ) = ' ';
+         }
+      }
+
+   if ( ch >= 32 )
+      {
+      *( disp_start + disp_offset ) = ch;
+      disp_offset = disp_offset + 2;
+      }
+
+   if ( ch == '\r' )
+      {
+      disp_offset = disp_offset / 160;
+      disp_offset = disp_offset * 160;
+      }
+
+   if ( ch == '\n' )
+      {
+      disp_offset = disp_offset + 160;
+      if ( disp_offset < 160 * 24 )
+         {
+         for ( j = disp_offset; j < ( ( ( disp_offset / 160 ) + 1 ) *
+            160 ); j += 2 )
+            {
+            *( disp_start + j ) = ' ';
+            }
+         }
+      }
+   }
+
+int DB_PrintString
+   (
+   char *string
+   )
+
+   {
+   int count;
+   char *ptr;
+
+   ptr = string;
+   count = 0;
+
+   while ( *ptr )
+      {
+      DB_PutChar( *ptr );
+      count++;
+      ptr++;
+      }
+
+   return( count );
+   }
+
+static void myutoa
+   (
+   unsigned num,
+   char *string,
+   int radix
+   )
+
+   {
+   int val;
+   int length;
+   int pos;
+   char temp[ 100 ];
+
+   length = 0;
+   do
+      {
+      val = num % radix;
+      if ( val < 10 )
+         {
+         temp[ length ] = '0' + val;
+         }
+      else
+         {
+         temp[ length ] = 'A' + val - 10;
+         }
+      num /= radix;
+      length++;
+      }
+   while( num > 0 );
+
+   pos = 0;
+   while( length > 0 )
+      {
+      length--;
+      string[ length ] = temp[ pos ];
+      pos++;
+      }
+   string[ pos ] = 0;
+   }
+
+static void myitoa
+   (
+   int num,
+   char *string,
+   int radix
+   )
+
+   {
+   if ( num < 0 )
+      {
+      *string++ = '-';
+      num = -num;
+      }
+
+   myutoa( num, string, radix );
+   }
+
+int DB_PrintNum
+   (
+   int number
+   )
+
+   {
+   char string[ 100 ];
+   int  count;
+
+   myitoa( number, &string[ 0 ], 10 );
+   count = DB_PrintString( &string[ 0 ] );
+
+   return( count );
+   }
+
+int DB_PrintUnsigned
+   (
+   unsigned long number,
+   int radix
+   )
+
+   {
+   char string[ 100 ];
+   int  count;
+
+   myutoa( number, &string[ 0 ], radix );
+   count = DB_PrintString( &string[ 0 ] );
+
+   return( count );
+   }
+
+int DB_printf
+   (
+   char *fmt,
+   ...
+   )
+
+   {
+   va_list argptr;
+   int     count;
+   char    *ptr;
+
+   va_start( argptr, fmt );
+   ptr = fmt;
+   count = 0;
+
+   while( *ptr != 0 )
+      {
+      if ( *ptr == '%' )
+         {
+         ptr++;
+         switch( *ptr )
+            {
+            case 0 :
+               return( EOF );
+               break;
+            case 'd' :
+               count += DB_PrintNum( va_arg( argptr, int ) );
+               break;
+            case 's' :
+               count += DB_PrintString( va_arg( argptr, char * ) );
+               break;
+            case 'u' :
+               count += DB_PrintUnsigned( va_arg( argptr, int ), 10 );
+               break;
+            case 'x' :
+            case 'X' :
+               count += DB_PrintUnsigned( va_arg( argptr, int ), 16 );
+               break;
+            }
+         ptr++;
+         }
+      else
+         {
+         DB_PutChar( *ptr );
+         count++;
+         ptr++;
+         }
+      }
+
+   va_end( argptr );
+
+   return( count );
+   }

Added: tags/rott-1.1/rott/audiolib/debugio.h
===================================================================
--- tags/rott-1.1/rott/audiolib/debugio.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/debugio.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,30 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __DEBUGIO_H
+#define __DEBUGIO_H
+
+void DB_SetXY( int x, int y );
+void DB_PutChar( char ch );
+int  DB_PrintString( char *string );
+int  DB_PrintNum( int number );
+int  DB_PrintUnsigned( unsigned long number, int radix );
+int  DB_printf( char *fmt, ... );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/dma.c
===================================================================
--- tags/rott-1.1/rott/audiolib/dma.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dma.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,379 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: DMA.C
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Low level routines to for programming the DMA controller for 8 bit
+   and 16 bit transfers.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include "dma.h"
+
+#define DMA_MaxChannel 7
+
+#define VALID   ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define BYTE 0
+#define WORD 1
+
+typedef struct
+   {
+   int Valid;
+   int Width;
+   int Mask;
+   int Mode;
+   int Clear;
+   int Page;
+   int Address;
+   int Length;
+   } DMA_PORT;
+
+static const DMA_PORT DMA_PortInfo[ DMA_MaxChannel + 1 ] =
+   {
+      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x87,  0x0,  0x1 },
+      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x83,  0x2,  0x3 },
+      { INVALID, BYTE,  0xA,  0xB,  0xC, 0x81,  0x4,  0x5 },
+      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x82,  0x6,  0x7 },
+      { INVALID, WORD, 0xD4, 0xD6, 0xD8, 0x8F, 0xC0, 0xC2 },
+      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8B, 0xC4, 0xC6 },
+      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x89, 0xC8, 0xCA },
+      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8A, 0xCC, 0xCE },
+   };
+
+int DMA_ErrorCode = DMA_Ok;
+
+#define DMA_SetErrorCode( status ) \
+   DMA_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *DMA_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case DMA_Error :
+         ErrorString = DMA_ErrorString( DMA_ErrorCode );
+         break;
+
+      case DMA_Ok :
+         ErrorString = "DMA channel ok.";
+         break;
+
+      case DMA_ChannelOutOfRange :
+         ErrorString = "DMA channel out of valid range.";
+         break;
+
+      case DMA_InvalidChannel :
+         ErrorString = "Unsupported DMA channel.";
+         break;
+
+      default :
+         ErrorString = "Unknown DMA error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_VerifyChannel
+
+   Verifies whether a DMA channel is available to transfer data.
+---------------------------------------------------------------------*/
+
+int DMA_VerifyChannel
+   (
+   int channel
+   )
+
+   {
+   int      status;
+   int      Error;
+
+   status = DMA_Ok;
+   Error  = DMA_Ok;
+
+   if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
+      {
+      Error = DMA_ChannelOutOfRange;
+      status = DMA_Error;
+      }
+   else if ( DMA_PortInfo[ channel ].Valid == INVALID )
+      {
+      Error = DMA_InvalidChannel;
+      status = DMA_Error;
+      }
+
+   DMA_SetErrorCode( Error );
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_SetupTransfer
+
+   Programs the specified DMA channel to transfer data.
+---------------------------------------------------------------------*/
+
+int DMA_SetupTransfer
+   (
+   int  channel,
+   char *address,
+   int  length,
+   int  mode
+   )
+
+   {
+   DMA_PORT *Port;
+   int      addr;
+   int      ChannelSelect;
+   int      Page;
+   int      HiByte;
+   int      LoByte;
+   int      TransferLength;
+   int      status;
+
+   status = DMA_VerifyChannel( channel );
+
+   if ( status == DMA_Ok )
+      {
+      Port = &DMA_PortInfo[ channel ];
+      ChannelSelect = channel & 0x3;
+
+      addr = ( int )address;
+
+      if ( Port->Width == WORD )
+         {
+         Page   = ( addr >> 16 ) & 255;
+         HiByte = ( addr >> 9 ) & 255;
+         LoByte = ( addr >> 1 ) & 255;
+
+         // Convert the length in bytes to the length in words
+         TransferLength = ( length + 1 ) >> 1;
+
+         // The length is always one less the number of bytes or words
+         // that we're going to send
+         TransferLength--;
+         }
+      else
+         {
+         Page   = ( addr >> 16 ) & 255;
+         HiByte = ( addr >> 8 ) & 255;
+         LoByte = addr & 255;
+
+         // The length is always one less the number of bytes or words
+         // that we're going to send
+         TransferLength = length - 1;
+         }
+
+      // Mask off DMA channel
+      outp( Port->Mask, 4 | ChannelSelect );
+
+      // Clear flip-flop to lower byte with any data
+      outp( Port->Clear, 0 );
+
+      // Set DMA mode
+      switch( mode )
+         {
+         case DMA_SingleShotRead :
+            outp( Port->Mode, 0x48 | ChannelSelect );
+            break;
+
+         case DMA_SingleShotWrite :
+            outp( Port->Mode, 0x44 | ChannelSelect );
+            break;
+
+         case DMA_AutoInitRead :
+            outp( Port->Mode, 0x58 | ChannelSelect );
+            break;
+
+         case DMA_AutoInitWrite :
+            outp( Port->Mode, 0x54 | ChannelSelect );
+            break;
+         }
+
+      // Send address
+      outp( Port->Address, LoByte );
+      outp( Port->Address, HiByte );
+
+      // Send page
+      outp( Port->Page, Page );
+
+      // Send length
+      outp( Port->Length, TransferLength );
+      outp( Port->Length, TransferLength >> 8 );
+
+      // enable DMA channel
+      outp( Port->Mask, ChannelSelect );
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_EndTransfer
+
+   Ends use of the specified DMA channel.
+---------------------------------------------------------------------*/
+
+int DMA_EndTransfer
+   (
+   int channel
+   )
+
+   {
+   DMA_PORT *Port;
+   int       ChannelSelect;
+   int       status;
+
+   status = DMA_VerifyChannel( channel );
+   if ( status == DMA_Ok )
+      {
+      Port = &DMA_PortInfo[ channel ];
+      ChannelSelect = channel & 0x3;
+
+      // Mask off DMA channel
+      outp( Port->Mask, 4 | ChannelSelect );
+
+      // Clear flip-flop to lower byte with any data
+      outp( Port->Clear, 0 );
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_GetCurrentPos
+
+   Returns the position of the specified DMA transfer.
+---------------------------------------------------------------------*/
+
+char *DMA_GetCurrentPos
+   (
+   int channel
+   )
+
+   {
+   DMA_PORT      *Port;
+   unsigned long addr;
+   int           status;
+
+   addr   = NULL;
+   status = DMA_VerifyChannel( channel );
+
+   if ( status == DMA_Ok )
+      {
+      Port = &DMA_PortInfo[ channel ];
+
+      if ( Port->Width == WORD )
+         {
+         // Get address
+         addr  = inp( Port->Address ) << 1;
+         addr |= inp( Port->Address ) << 9;
+
+         // Get page
+         addr |= inp( Port->Page ) << 16;
+         }
+      else
+         {
+         // Get address
+         addr = inp( Port->Address );
+         addr |= inp( Port->Address ) << 8;
+
+         // Get page
+         addr |= inp( Port->Page ) << 16;
+         }
+      }
+
+   return( ( char * )addr );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DMA_GetTransferCount
+
+   Returns how many bytes are left in the DMA's transfer.
+---------------------------------------------------------------------*/
+
+int DMA_GetTransferCount
+   (
+   int channel
+   )
+
+   {
+   DMA_PORT      *Port;
+   int           count;
+   int           status;
+
+   status = DMA_Ok;
+
+   count = 0;
+
+   if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
+      {
+      status = DMA_ChannelOutOfRange;
+      }
+   else if ( DMA_PortInfo[ channel ].Valid == INVALID )
+      {
+      status = DMA_InvalidChannel;
+      }
+
+   if ( status == DMA_Ok )
+      {
+      Port = &DMA_PortInfo[ channel ];
+
+      outp( Port->Clear, 0 );
+      count  = inp( Port->Length );
+      count += inp( Port->Length ) << 8;
+
+      if ( Port->Width == WORD )
+         {
+         count <<= 1;
+         }
+      }
+
+   DMA_SetErrorCode( status );
+
+   return( count );
+   }

Added: tags/rott-1.1/rott/audiolib/dma.h
===================================================================
--- tags/rott-1.1/rott/audiolib/dma.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dma.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,83 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   DMA.H
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Public header file for DMA.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __DMA_H
+#define __DMA_H
+
+enum DMA_ERRORS
+   {
+   DMA_Error = -1,
+   DMA_Ok    = 0,
+   DMA_ChannelOutOfRange,
+   DMA_InvalidChannel
+   };
+
+enum DMA_Modes
+   {
+   DMA_SingleShotRead,
+   DMA_SingleShotWrite,
+   DMA_AutoInitRead,
+   DMA_AutoInitWrite
+   };
+
+char *DMA_ErrorString
+   (
+   int ErrorNumber
+   );
+
+int DMA_VerifyChannel
+   (
+   int channel
+   );
+
+int DMA_SetupTransfer
+   (
+   int  channel,
+   char *address,
+   int  length,
+   int  mode
+   );
+
+int DMA_EndTransfer
+   (
+   int channel
+   );
+
+char *DMA_GetCurrentPos
+   (
+   int channel
+   );
+
+int DMA_GetTransferCount
+   (
+   int channel
+   );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/dpmi.c
===================================================================
--- tags/rott-1.1/rott/audiolib/dpmi.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dpmi.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,250 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: DPMI.C
+
+   author: James R. Dose
+   date:   April 8, 1994
+
+   Functions for performing DPMI calls.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <string.h>
+#include "dpmi.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static union  REGS  Regs;
+static struct SREGS SegRegs;
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_GetRealModeVector
+
+   Returns the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+unsigned long DPMI_GetRealModeVector
+   (
+   int num
+   )
+
+   {
+   unsigned long vector;
+
+   Regs.x.eax = 0x0200;
+   Regs.h.bl  = num;
+   int386( 0x31, &Regs, &Regs );
+
+   vector   = Regs.w.cx & 0xffff;
+   vector <<= 16;
+   vector  |= Regs.w.dx & 0xffff;
+
+   return( vector );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_SetRealModeVector
+
+   Sets the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+void DPMI_SetRealModeVector
+   (
+   int num,
+   unsigned long vector
+   )
+
+   {
+   Regs.x.eax = 0x0201;
+   Regs.h.bl  = num;
+   Regs.w.dx = vector & 0xffff;
+   Regs.w.cx = ( vector >> 16 ) & 0xffff;
+
+   int386( 0x31, &Regs, &Regs );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_CallRealModeFunction
+
+   Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int DPMI_CallRealModeFunction
+   (
+   dpmi_regs *callregs
+   )
+
+   {
+   // Setup our registers to call DPMI
+   Regs.w.ax = 0x0301;
+   Regs.h.bl = 0;
+   Regs.h.bh = 0;
+   Regs.w.cx = 0;
+
+   SegRegs.es = FP_SEG( callregs );
+   Regs.x.edi = FP_OFF( callregs );
+
+   // Call Real-mode procedure with Far Return Frame
+   int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+   if ( Regs.x.cflag )
+      {
+      return( DPMI_Error );
+      }
+
+   return( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_LockMemory
+
+   Locks a region of memory to keep the virtual memory manager from
+   paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemory
+   (
+   void *address,
+   unsigned length
+   )
+
+   {
+   unsigned linear;
+
+   // Thanks to DOS/4GW's zero-based flat memory model, converting
+   // a pointer of any type to a linear address is trivial.
+
+   linear = (unsigned) address;
+
+   // DPMI Lock Linear Region
+   Regs.w.ax = 0x600;
+
+   // Linear address in BX:CX
+   Regs.w.bx = (linear >> 16);
+   Regs.w.cx = (linear & 0xFFFF);
+
+   // Length in SI:DI
+   Regs.w.si = (length >> 16);
+   Regs.w.di = (length & 0xFFFF);
+
+   int386 (0x31, &Regs, &Regs);
+
+   // Return 0 if can't lock
+   if ( Regs.w.cflag )
+      {
+      return( DPMI_Error );
+      }
+
+   return ( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_LockMemoryRegion
+
+   Locks a region of memory to keep the virtual memory manager from
+   paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemoryRegion
+   (
+   void *start,
+   void *end
+   )
+
+   {
+   int status;
+
+   status = DPMI_LockMemory( start, ( char * )end - ( char * )start );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_UnlockMemory
+
+   Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemory
+   (
+   void *address,
+   unsigned length
+   )
+
+   {
+   unsigned linear;
+
+   // Thanks to DOS/4GW's zero-based flat memory model, converting
+   // a pointer of any type to a linear address is trivial.
+
+   linear = (unsigned) address;
+
+   // DPMI Unlock Linear Region
+   Regs.w.ax = 0x601;
+
+   // Linear address in BX:CX
+   Regs.w.bx = (linear >> 16);
+   Regs.w.cx = (linear & 0xFFFF);
+
+   // Length in SI:DI
+   Regs.w.si = (length >> 16);
+   Regs.w.di = (length & 0xFFFF);
+
+   int386 (0x31, &Regs, &Regs);
+
+   // Return 0 if can't unlock
+   if ( Regs.w.cflag )
+      {
+      return( DPMI_Error );
+      }
+
+   return ( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_UnlockMemoryRegion
+
+   Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemoryRegion
+   (
+   void *start,
+   void *end
+   )
+
+   {
+   int status;
+
+   status = DPMI_UnlockMemory( start, ( char * )end - ( char * )start );
+
+   return( status );
+   }

Added: tags/rott-1.1/rott/audiolib/dpmi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/dpmi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dpmi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,102 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: DPMI.H
+
+   author: James R. Dose
+   date:   March 31, 1994
+
+   Inline functions for performing DPMI calls.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __DPMI_H
+#define __DPMI_H
+
+enum DPMI_Errors
+   {
+   DPMI_Warning = -2,
+   DPMI_Error   = -1,
+   DPMI_Ok      = 0
+   };
+
+typedef struct
+   {
+   unsigned long  EDI;
+   unsigned long  ESI;
+   unsigned long  EBP;
+   unsigned long  Reserved;
+   unsigned long  EBX;
+   unsigned long  EDX;
+   unsigned long  ECX;
+   unsigned long  EAX;
+   unsigned short Flags;
+   unsigned short ES;
+   unsigned short DS;
+   unsigned short FS;
+   unsigned short GS;
+   unsigned short IP;
+   unsigned short CS;
+   unsigned short SP;
+   unsigned short SS;
+   } dpmi_regs;
+
+unsigned long DPMI_GetRealModeVector( int num );
+void DPMI_SetRealModeVector( int num, unsigned long vector );
+int  DPMI_CallRealModeFunction( dpmi_regs *callregs );
+int  DPMI_GetDOSMemory( void **ptr, long *descriptor, unsigned length );
+int  DPMI_FreeDOSMemory( long descriptor );
+int  DPMI_LockMemory( void *address, unsigned length );
+int  DPMI_LockMemoryRegion( void *start, void *end );
+int  DPMI_UnlockMemory( void *address, unsigned length );
+int  DPMI_UnlockMemoryRegion( void *start, void *end );
+
+#define DPMI_Lock( variable ) \
+   ( DPMI_LockMemory( (void *) &( variable ), sizeof( variable ) ) )
+
+#define DPMI_Unlock( variable ) \
+   ( DPMI_UnlockMemory( (void *) &( variable ), sizeof( variable ) ) )
+
+#ifdef PLAT_DOS
+#pragma aux DPMI_GetDOSMemory = \
+   "mov    eax, 0100h",         \
+   "add    ebx, 15",            \
+   "shr    ebx, 4",             \
+   "int    31h",                \
+   "jc     DPMI_Exit",          \
+   "movzx  eax, ax",            \
+   "shl    eax, 4",             \
+   "mov    [ esi ], eax",       \
+   "mov    [ edi ], edx",       \
+   "sub    eax, eax",           \
+   "DPMI_Exit:",                \
+   parm [ esi ] [ edi ] [ ebx ] modify exact [ eax ebx edx ];
+
+#pragma aux DPMI_FreeDOSMemory = \
+   "mov    eax, 0101h",          \
+   "int    31h",                 \
+   "jc     DPMI_Exit",           \
+   "sub    eax, eax",            \
+   "DPMI_Exit:",                 \
+   parm [ edx ] modify exact [ eax ];
+#endif
+
+#endif

Added: tags/rott-1.1/rott/audiolib/dsl.c
===================================================================
--- tags/rott-1.1/rott/audiolib/dsl.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dsl.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,235 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "dsl.h"
+#include "util.h"
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+extern volatile int MV_MixPage;
+
+static int DSL_ErrorCode = DSL_Ok;
+
+static int mixer_initialized;
+
+static void ( *_CallBackFunc )( void );
+static volatile char *_BufferStart;
+static int _BufferSize;
+static int _NumDivisions;
+static int _SampleRate;
+static int _remainder;
+
+static Mix_Chunk *blank;
+static unsigned char *blank_buf;
+
+/*
+possible todo ideas: cache sdl/sdl mixer error messages.
+*/
+
+char *DSL_ErrorString( int ErrorNumber )
+{
+	char *ErrorString;
+	
+	switch (ErrorNumber) {
+		case DSL_Warning:
+		case DSL_Error:
+			ErrorString = DSL_ErrorString(DSL_ErrorCode);
+			break;
+		
+		case DSL_Ok:
+			ErrorString = "SDL Driver ok.";
+			break;
+		
+		case DSL_SDLInitFailure:
+			ErrorString = "SDL Audio initialization failed.";
+			break;
+		
+		case DSL_MixerActive:
+			ErrorString = "SDL Mixer already initialized.";
+			break;	
+	
+		case DSL_MixerInitFailure:
+			ErrorString = "SDL Mixer initialization failed.";
+			break;
+			
+		default:
+			ErrorString = "Unknown SDL Driver error.";
+			break;
+	}
+	
+	return ErrorString;
+}
+
+static void DSL_SetErrorCode(int ErrorCode)
+{
+	DSL_ErrorCode = ErrorCode;
+}
+
+int DSL_Init( void )
+{
+	DSL_SetErrorCode(DSL_Ok);
+	
+	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
+		DSL_SetErrorCode(DSL_SDLInitFailure);
+		
+		return DSL_Error;
+	}
+	
+	return DSL_Ok;
+}
+
+void DSL_Shutdown( void )
+{
+	DSL_StopPlayback();
+}
+
+static void mixer_callback(int chan, void *stream, int len, void *udata)
+{
+	Uint8 *stptr;
+	Uint8 *fxptr;
+	int copysize;
+	
+	/* len should equal _BufferSize, else this is screwed up */
+
+	stptr = (Uint8 *)stream;
+	
+	if (_remainder > 0) {
+		copysize = min(len, _remainder);
+		
+		fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * 
+			_BufferSize]);
+		
+		memcpy(stptr, fxptr+(_BufferSize-_remainder), copysize);
+		
+		len -= copysize;
+		_remainder -= copysize;
+		
+		stptr += copysize;
+	}
+	
+	while (len > 0) {
+		/* new buffer */
+		
+		_CallBackFunc();
+		
+		fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * 
+			_BufferSize]);
+
+		copysize = min(len, _BufferSize);
+		
+		memcpy(stptr, fxptr, copysize);
+		
+		len -= copysize;
+		
+		stptr += copysize;
+	}
+	
+	_remainder = len;
+}
+
+int   DSL_BeginBufferedPlayback( char *BufferStart,
+      int BufferSize, int NumDivisions, unsigned SampleRate,
+      int MixMode, void ( *CallBackFunc )( void ) )
+{
+	Uint16 format;
+	Uint8 *tmp;
+	int channels;
+	int chunksize;
+		
+	if (mixer_initialized) {
+		DSL_SetErrorCode(DSL_MixerActive);
+		
+		return DSL_Error;
+	}
+	
+	_CallBackFunc = CallBackFunc;
+	_BufferStart = BufferStart;
+	_BufferSize = (BufferSize / NumDivisions);
+	_NumDivisions = NumDivisions;
+	_SampleRate = SampleRate;
+
+	_remainder = 0;
+	
+	format = (MixMode & SIXTEEN_BIT) ? AUDIO_S16SYS : AUDIO_U8;
+	channels = (MixMode & STEREO) ? 2 : 1;
+
+/*
+	23ms is typically ideal (11025,22050,44100)
+	46ms isn't bad
+*/
+	
+	chunksize = 512;
+	
+	if (SampleRate >= 16000) chunksize *= 2;
+	if (SampleRate >= 32000) chunksize *= 2;
+	
+/*	
+// SDL mixer does this already
+	if (MixMode & SIXTEEN_BIT) chunksize *= 2;
+	if (MixMode & STEREO) chunksize *= 2;
+*/
+	
+	if (Mix_OpenAudio(SampleRate, format, channels, chunksize) < 0) {
+		DSL_SetErrorCode(DSL_MixerInitFailure);
+		
+		return DSL_Error;
+	}
+
+/*
+	Mix_SetPostMix(mixer_callback, NULL);
+*/
+	/* have to use a channel because postmix will overwrite the music... */
+	Mix_RegisterEffect(0, mixer_callback, NULL, NULL);
+	
+	/* create a dummy sample just to allocate that channel */
+	blank_buf = (Uint8 *)malloc(4096);
+	memset(blank_buf, 0, 4096);
+	
+	blank = Mix_QuickLoad_RAW(blank_buf, 4096);
+		
+	Mix_PlayChannel(0, blank, -1);
+	
+	mixer_initialized = 1;
+	
+	return DSL_Ok;
+}
+
+void DSL_StopPlayback( void )
+{
+	if (mixer_initialized) {
+		Mix_HaltChannel(0);
+	}
+	
+	if (blank != NULL) {
+		Mix_FreeChunk(blank);
+	}
+	
+	blank = NULL;
+	
+	if (blank_buf  != NULL) {
+		free(blank_buf);
+	}
+	
+	blank_buf = NULL;
+	
+	if (mixer_initialized) {
+		Mix_CloseAudio();
+	}
+	
+	mixer_initialized = 0;
+}
+
+unsigned DSL_GetPlaybackRate( void )
+{
+	return _SampleRate;
+}
+
+unsigned long DisableInterrupts( void )
+{
+	return 0;
+}
+
+void RestoreInterrupts( unsigned long flags )
+{
+}

Added: tags/rott-1.1/rott/audiolib/dsl.h
===================================================================
--- tags/rott-1.1/rott/audiolib/dsl.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/dsl.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,28 @@
+#ifndef AUDIOLIB__DSL_H
+#define AUDIOLIB__DSL_H
+
+#define MONO_8BIT    0
+#define STEREO      1
+#define SIXTEEN_BIT 2
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+enum DSL_ERRORS
+   {
+   DSL_Warning = -2,
+   DSL_Error = -1,
+   DSL_Ok = 0,
+   DSL_SDLInitFailure,
+   DSL_MixerActive,
+   DSL_MixerInitFailure
+   };
+
+char *DSL_ErrorString( int ErrorNumber );
+int   DSL_Init( void );
+void  DSL_StopPlayback( void );
+unsigned DSL_GetPlaybackRate( void );
+int   DSL_BeginBufferedPlayback( char *BufferStart,
+      int BufferSize, int NumDivisions, unsigned SampleRate,
+      int MixMode, void ( *CallBackFunc )( void ) );
+void  DSL_Shutdown( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/fx_man.c
===================================================================
--- tags/rott-1.1/rott/audiolib/fx_man.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/fx_man.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1376 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: FX_MAN.C
+
+   author: James R. Dose
+   date:   March 17, 1994
+
+   Device independant sound effect routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "sndcards.h"
+#include "multivoc.h"
+
+#ifdef PLAT_DOS
+#include "blaster.h"
+#include "pas16.h"
+#include "sndscape.h"
+#include "guswave.h"
+#include "sndsrc.h"
+#else
+#include "dsl.h"
+#endif
+
+#include "ll_man.h"
+#include "user.h"
+#include "fx_man.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static unsigned FX_MixRate;
+
+int FX_SoundDevice = -1;
+int FX_ErrorCode = FX_Ok;
+int FX_Installed = FALSE;
+
+#define FX_SetErrorCode( status ) \
+   FX_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+   Function: FX_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *FX_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case FX_Warning :
+      case FX_Error :
+         ErrorString = FX_ErrorString( FX_ErrorCode );
+         break;
+
+      case FX_Ok :
+         ErrorString = "Fx ok.";
+         break;
+
+      case FX_ASSVersion :
+         ErrorString = "Apogee Sound System Version " ASS_VERSION_STRING "  "
+            "Programmed by Jim Dose\n"
+            "(c) Copyright 1995 James R. Dose.  All Rights Reserved.\n";
+         break;
+
+#ifdef PLAT_DOS
+      case FX_BlasterError :
+         ErrorString = BLASTER_ErrorString( BLASTER_Error );
+         break;
+#endif
+
+      case FX_SoundCardError :
+#ifdef PLAT_DOS
+         switch( FX_SoundDevice )
+         {
+            case SoundBlaster :
+            case Awe32 :
+               ErrorString = BLASTER_ErrorString( BLASTER_Error );
+               break;
+
+            case ProAudioSpectrum :
+            case SoundMan16 :
+               ErrorString = PAS_ErrorString( PAS_Error );
+               break;
+
+            case SoundScape :
+               ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+               break;
+
+            case UltraSound :
+               ErrorString = GUSWAVE_ErrorString( GUSWAVE_Error );
+               break;
+
+            case SoundSource :
+            case TandySoundSource :
+               ErrorString = SS_ErrorString( SS_Error );
+               break;
+            }
+#else
+         ErrorString = DSL_ErrorString( DSL_Error );
+#endif
+         break;
+
+      case FX_InvalidCard :
+         ErrorString = "Invalid Sound Fx device.";
+         break;
+
+      case FX_MultiVocError :
+         ErrorString = MV_ErrorString( MV_Error );
+         break;
+
+      case FX_DPMI_Error :
+         ErrorString = "DPMI Error in FX_MAN.";
+         break;
+
+      default :
+         ErrorString = "Unknown Fx error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetupCard
+
+   Sets the configuration of a sound device.
+---------------------------------------------------------------------*/
+
+int FX_SetupCard
+   (
+   int SoundCard,
+   fx_device *device
+   )
+
+   {
+   int status;
+   int DeviceStatus;
+
+   if ( USER_CheckParameter( "ASSVER" ) )
+      {
+      FX_SetErrorCode( FX_ASSVersion );
+      return( FX_Error );
+      }
+
+   FX_SoundDevice = SoundCard;
+
+   status = FX_Ok;
+   FX_SetErrorCode( FX_Ok );
+
+#ifdef PLAT_DOS
+   switch( SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         DeviceStatus = BLASTER_Init();
+         if ( DeviceStatus != BLASTER_Ok )
+            {
+            FX_SetErrorCode( FX_SoundCardError );
+            status = FX_Error;
+            break;
+            }
+
+         device->MaxVoices = 32;
+         BLASTER_GetCardInfo( &device->MaxSampleBits, &device->MaxChannels );
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         DeviceStatus = PAS_Init();
+         if ( DeviceStatus != PAS_Ok )
+            {
+            FX_SetErrorCode( FX_SoundCardError );
+            status = FX_Error;
+            break;
+            }
+
+         device->MaxVoices = 32;
+         PAS_GetCardInfo( &device->MaxSampleBits, &device->MaxChannels );
+         break;
+
+      case GenMidi :
+      case SoundCanvas :
+      case WaveBlaster :
+         device->MaxVoices     = 0;
+         device->MaxSampleBits = 0;
+         device->MaxChannels   = 0;
+         break;
+
+      case SoundScape :
+         device->MaxVoices = 32;
+         DeviceStatus = SOUNDSCAPE_GetCardInfo( &device->MaxSampleBits,
+            &device->MaxChannels );
+         if ( DeviceStatus != SOUNDSCAPE_Ok )
+            {
+            FX_SetErrorCode( FX_SoundCardError );
+            status = FX_Error;
+            }
+         break;
+
+      case UltraSound :
+         if ( GUSWAVE_Init( 8 ) != GUSWAVE_Ok )
+            {
+            FX_SetErrorCode( FX_SoundCardError );
+            status = FX_Error;
+            break;
+            }
+
+         device->MaxVoices     = 8;
+         device->MaxSampleBits = 0;
+         device->MaxChannels   = 0;
+         break;
+
+      case SoundSource :
+      case TandySoundSource :
+         DeviceStatus = SS_Init( SoundCard );
+         if ( DeviceStatus != SS_Ok )
+            {
+            FX_SetErrorCode( FX_SoundCardError );
+            status = FX_Error;
+            break;
+            }
+         SS_Shutdown();
+         device->MaxVoices     = 32;
+         device->MaxSampleBits = 8;
+         device->MaxChannels   = 1;
+         break;
+      default :
+         FX_SetErrorCode( FX_InvalidCard );
+         status = FX_Error;
+      }
+#else
+      DeviceStatus = DSL_Init();
+      if ( DeviceStatus != DSL_Ok )
+         {
+         FX_SetErrorCode( FX_SoundCardError );
+         status = FX_Error;
+         }
+         else
+         {
+         device->MaxVoices     = 32;
+         device->MaxSampleBits = 0;
+         device->MaxChannels   = 0;
+         }
+#endif
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_GetBlasterSettings
+
+   Returns the current BLASTER environment variable settings.
+---------------------------------------------------------------------*/
+
+int FX_GetBlasterSettings
+   (
+   fx_blaster_config *blaster
+   )
+
+   {
+#ifdef PLAT_DOS
+   int status;
+   BLASTER_CONFIG Blaster;
+
+   FX_SetErrorCode( FX_Ok );
+
+   status = BLASTER_GetEnv( &Blaster );
+   if ( status != BLASTER_Ok )
+      {
+      FX_SetErrorCode( FX_BlasterError );
+      return( FX_Error );
+      }
+
+   blaster->Type      = Blaster.Type;
+   blaster->Address   = Blaster.Address;
+   blaster->Interrupt = Blaster.Interrupt;
+   blaster->Dma8      = Blaster.Dma8;
+   blaster->Dma16     = Blaster.Dma16;
+   blaster->Midi      = Blaster.Midi;
+   blaster->Emu       = Blaster.Emu;
+#endif
+
+   return( FX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetupSoundBlaster
+
+   Handles manual setup of the Sound Blaster information.
+---------------------------------------------------------------------*/
+
+int FX_SetupSoundBlaster
+   (
+   fx_blaster_config blaster,
+   int *MaxVoices,
+   int *MaxSampleBits,
+   int *MaxChannels
+   )
+
+   {
+#ifdef PLAT_DOS
+   int DeviceStatus;
+   BLASTER_CONFIG Blaster;
+
+   FX_SetErrorCode( FX_Ok );
+
+   FX_SoundDevice = SoundBlaster;
+
+   Blaster.Type      = blaster.Type;
+   Blaster.Address   = blaster.Address;
+   Blaster.Interrupt = blaster.Interrupt;
+   Blaster.Dma8      = blaster.Dma8;
+   Blaster.Dma16     = blaster.Dma16;
+   Blaster.Midi      = blaster.Midi;
+   Blaster.Emu       = blaster.Emu;
+
+   BLASTER_SetCardSettings( Blaster );
+
+   DeviceStatus = BLASTER_Init();
+   if ( DeviceStatus != BLASTER_Ok )
+      {
+      FX_SetErrorCode( FX_SoundCardError );
+      return( FX_Error );
+      }
+
+   *MaxVoices = 8;
+   BLASTER_GetCardInfo( MaxSampleBits, MaxChannels );
+#endif
+
+   return( FX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_Init
+
+   Selects which sound device to use.
+---------------------------------------------------------------------*/
+
+int FX_Init
+   (
+   int SoundCard,
+   int numvoices,
+   int numchannels,
+   int samplebits,
+   unsigned mixrate
+   )
+
+   {
+   int status;
+   int devicestatus;
+
+   if ( FX_Installed )
+      {
+      FX_Shutdown();
+      }
+
+   if ( USER_CheckParameter( "ASSVER" ) )
+      {
+      FX_SetErrorCode( FX_ASSVersion );
+      return( FX_Error );
+      }
+
+   status = LL_LockMemory();
+   if ( status != LL_Ok )
+      {
+      FX_SetErrorCode( FX_DPMI_Error );
+      return( FX_Error );
+      }
+
+   FX_MixRate = mixrate;
+
+   status = FX_Ok;
+   FX_SoundDevice = SoundCard;
+   switch( SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+      case SoundScape :
+      case SoundSource :
+      case TandySoundSource :
+      case UltraSound :
+         devicestatus = MV_Init( SoundCard, FX_MixRate, numvoices,
+            numchannels, samplebits );
+         if ( devicestatus != MV_Ok )
+            {
+            FX_SetErrorCode( FX_MultiVocError );
+            status = FX_Error;
+            }
+         break;
+
+      default :
+         FX_SetErrorCode( FX_InvalidCard );
+         status = FX_Error;
+      }
+
+   if ( status != FX_Ok )
+      {
+      LL_UnlockMemory();
+      }
+   else
+      {
+      FX_Installed = TRUE;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_Shutdown
+
+   Terminates use of sound device.
+---------------------------------------------------------------------*/
+
+int FX_Shutdown
+   (
+   void
+   )
+
+   {
+   int status;
+
+   if ( !FX_Installed )
+      {
+      return( FX_Ok );
+      }
+
+   status = FX_Ok;
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+      case SoundScape :
+      case SoundSource :
+      case TandySoundSource :
+      case UltraSound :
+         status = MV_Shutdown();
+         if ( status != MV_Ok )
+            {
+            FX_SetErrorCode( FX_MultiVocError );
+            status = FX_Error;
+            }
+         break;
+
+      default :
+         FX_SetErrorCode( FX_InvalidCard );
+         status = FX_Error;
+      }
+
+   FX_Installed = FALSE;
+   LL_UnlockMemory();
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetCallback
+
+   Sets the function to call when a voice is done.
+---------------------------------------------------------------------*/
+
+int FX_SetCallBack
+   (
+   void ( *function )( unsigned long )
+   )
+
+   {
+   int status;
+
+   status = FX_Ok;
+
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+      case SoundScape :
+      case SoundSource :
+      case TandySoundSource :
+      case UltraSound :
+         MV_SetCallBack( function );
+         break;
+
+      default :
+         FX_SetErrorCode( FX_InvalidCard );
+         status = FX_Error;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetVolume
+
+   Sets the volume of the current sound device.
+---------------------------------------------------------------------*/
+
+void FX_SetVolume
+   (
+   int volume
+   )
+
+   {
+   int status;
+
+#ifdef PLAT_DOS
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         if ( BLASTER_CardHasMixer() )
+            {
+            BLASTER_SetVoiceVolume( volume );
+            }
+         else
+            {
+            MV_SetVolume( volume );
+            }
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = PAS_SetPCMVolume( volume );
+         if ( status != PAS_Ok )
+            {
+            MV_SetVolume( volume );
+            }
+         break;
+
+      case GenMidi :
+      case SoundCanvas :
+      case WaveBlaster :
+         break;
+
+      case SoundScape :
+         MV_SetVolume( volume );
+         break;
+
+      case UltraSound :
+         GUSWAVE_SetVolume( volume );
+         break;
+
+      case SoundSource :
+      case TandySoundSource :
+         MV_SetVolume( volume );
+         break;
+      }
+#else
+   MV_SetVolume( volume );
+#endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_GetVolume
+
+   Returns the volume of the current sound device.
+---------------------------------------------------------------------*/
+
+int FX_GetVolume
+   (
+   void
+   )
+
+   {
+   int volume;
+
+#ifdef PLAT_DOS
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         if ( BLASTER_CardHasMixer() )
+            {
+            volume = BLASTER_GetVoiceVolume();
+            }
+         else
+            {
+            volume = MV_GetVolume();
+            }
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         volume = PAS_GetPCMVolume();
+         if ( volume == PAS_Error )
+            {
+            volume = MV_GetVolume();
+            }
+         break;
+
+      case GenMidi :
+      case SoundCanvas :
+      case WaveBlaster :
+         volume = 255;
+         break;
+
+      case SoundScape :
+         volume = MV_GetVolume();
+         break;
+
+      case UltraSound :
+         volume = GUSWAVE_GetVolume();
+         break;
+
+      case SoundSource :
+      case TandySoundSource :
+         volume = MV_GetVolume();
+         break;
+
+      default :
+         volume = 0;
+      }
+#else
+   volume = MV_GetVolume();
+#endif
+
+   return( volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetReverseStereo
+
+   Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void FX_SetReverseStereo
+   (
+   int setting
+   )
+
+   {
+   MV_SetReverseStereo( setting );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_GetReverseStereo
+
+   Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int FX_GetReverseStereo
+   (
+   void
+   )
+
+   {
+   return MV_GetReverseStereo();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetReverb
+
+   Sets the reverb level.
+---------------------------------------------------------------------*/
+
+void FX_SetReverb
+   (
+   int reverb
+   )
+
+   {
+   MV_SetReverb( reverb );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetFastReverb
+
+   Sets the reverb level.
+---------------------------------------------------------------------*/
+
+void FX_SetFastReverb
+   (
+   int reverb
+   )
+
+   {
+   MV_SetFastReverb( reverb );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_GetMaxReverbDelay
+
+   Returns the maximum delay time for reverb.
+---------------------------------------------------------------------*/
+
+int FX_GetMaxReverbDelay
+   (
+   void
+   )
+
+   {
+   return MV_GetMaxReverbDelay();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_GetReverbDelay
+
+   Returns the current delay time for reverb.
+---------------------------------------------------------------------*/
+
+int FX_GetReverbDelay
+   (
+   void
+   )
+
+   {
+   return MV_GetReverbDelay();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetReverbDelay
+
+   Sets the delay level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void FX_SetReverbDelay
+   (
+   int delay
+   )
+
+   {
+   MV_SetReverbDelay( delay );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_VoiceAvailable
+
+   Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int FX_VoiceAvailable
+   (
+   int priority
+   )
+
+   {
+   return MV_VoiceAvailable( priority );
+   }
+
+/*---------------------------------------------------------------------
+   Function: FX_EndLooping
+
+   Stops the voice associated with the specified handle from looping
+   without stoping the sound.
+---------------------------------------------------------------------*/
+
+int FX_EndLooping
+   (
+   int handle
+   )
+
+   {
+   int status;
+
+   status = MV_EndLooping( handle );
+   if ( status == MV_Error )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      status = FX_Warning;
+      }
+
+   return( status );
+   }
+
+/*---------------------------------------------------------------------
+   Function: FX_SetPan
+
+   Sets the stereo and mono volume level of the voice associated
+   with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetPan
+   (
+   int handle,
+   int vol,
+   int left,
+   int right
+   )
+
+   {
+   int status;
+
+   status = MV_SetPan( handle, vol, left, right );
+   if ( status == MV_Error )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      status = FX_Warning;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetPitch
+
+   Sets the pitch of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetPitch
+   (
+   int handle,
+   int pitchoffset
+   )
+
+   {
+   int status;
+
+   status = MV_SetPitch( handle, pitchoffset );
+   if ( status == MV_Error )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      status = FX_Warning;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SetFrequency
+
+   Sets the frequency of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetFrequency
+   (
+   int handle,
+   int frequency
+   )
+
+   {
+   int status;
+
+   status = MV_SetFrequency( handle, frequency );
+   if ( status == MV_Error )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      status = FX_Warning;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayVOC
+
+   Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayVOC
+   (
+   char *ptr,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayVOC( ptr, pitchoffset, vol, left, right,
+      priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayLoopedVOC
+
+   Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedVOC
+   (
+   char *ptr,
+   long loopstart,
+   long loopend,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayLoopedVOC( ptr, loopstart, loopend, pitchoffset,
+      vol, left, right, priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayWAV
+
+   Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayWAV
+   (
+   char *ptr,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayWAV( ptr, pitchoffset, vol, left, right,
+      priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayWAV
+
+   Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedWAV
+   (
+   char *ptr,
+   long loopstart,
+   long loopend,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayLoopedWAV( ptr, loopstart, loopend,
+      pitchoffset, vol, left, right, priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayVOC3D
+
+   Begin playback of sound data at specified angle and distance
+   from listener.
+---------------------------------------------------------------------*/
+
+int FX_PlayVOC3D
+   (
+   char *ptr,
+   int pitchoffset,
+   int angle,
+   int distance,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayVOC3D( ptr, pitchoffset, angle, distance,
+      priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayWAV3D
+
+   Begin playback of sound data at specified angle and distance
+   from listener.
+---------------------------------------------------------------------*/
+
+int FX_PlayWAV3D
+   (
+   char *ptr,
+   int pitchoffset,
+   int angle,
+   int distance,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayWAV3D( ptr, pitchoffset, angle, distance,
+      priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayRaw
+
+   Begin playback of raw sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayRaw
+   (
+   char *ptr,
+   unsigned long length,
+   unsigned rate,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayRaw( ptr, length, rate, pitchoffset,
+      vol, left, right, priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_PlayLoopedRaw
+
+   Begin playback of raw sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedRaw
+   (
+   char *ptr,
+   unsigned long length,
+   char *loopstart,
+   char *loopend,
+   unsigned rate,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_PlayLoopedRaw( ptr, length, loopstart, loopend,
+      rate, pitchoffset, vol, left, right, priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_Pan3D
+
+   Set the angle and distance from the listener of the voice associated
+   with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_Pan3D
+   (
+   int handle,
+   int angle,
+   int distance
+   )
+
+   {
+   int status;
+
+   status = MV_Pan3D( handle, angle, distance );
+   if ( status != MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      status = FX_Warning;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SoundActive
+
+   Tests if the specified sound is currently playing.
+---------------------------------------------------------------------*/
+
+int FX_SoundActive
+   (
+   int handle
+   )
+
+   {
+   return( MV_VoicePlaying( handle ) );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_SoundsPlaying
+
+   Reports the number of voices playing.
+---------------------------------------------------------------------*/
+
+int FX_SoundsPlaying
+   (
+   void
+   )
+
+   {
+   return( MV_VoicesPlaying() );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_StopSound
+
+   Halts playback of a specific voice
+---------------------------------------------------------------------*/
+
+int FX_StopSound
+   (
+   int handle
+   )
+
+   {
+   int status;
+
+   status = MV_Kill( handle );
+   if ( status != MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      return( FX_Warning );
+      }
+
+   return( FX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_StopAllSounds
+
+   Halts playback of all sounds.
+---------------------------------------------------------------------*/
+
+int FX_StopAllSounds
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status = MV_KillAllVoices();
+   if ( status != MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      return( FX_Warning );
+      }
+
+   return( FX_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_StartDemandFeedPlayback
+
+   Plays a digitized sound from a user controlled buffering system.
+---------------------------------------------------------------------*/
+
+int FX_StartDemandFeedPlayback
+   (
+   void ( *function )( char **ptr, unsigned long *length ),
+   int rate,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+
+   handle = MV_StartDemandFeedPlayback( function, rate,
+      pitchoffset, vol, left, right, priority, callbackval );
+   if ( handle < MV_Ok )
+      {
+      FX_SetErrorCode( FX_MultiVocError );
+      handle = FX_Warning;
+      }
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_StartRecording
+
+   Starts the sound recording engine.
+---------------------------------------------------------------------*/
+
+int FX_StartRecording
+   (
+   int MixRate,
+   void ( *function )( char *ptr, int length )
+   )
+
+   {
+   int status;
+
+#ifdef PLAT_DOS
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = MV_StartRecording( MixRate, function );
+         if ( status != MV_Ok )
+            {
+            FX_SetErrorCode( FX_MultiVocError );
+            status = FX_Warning;
+            }
+         else
+            {
+            status = FX_Ok;
+            }
+         break;
+
+      default :
+         FX_SetErrorCode( FX_InvalidCard );
+         status = FX_Warning;
+         break;
+      }
+#else
+   FX_SetErrorCode( FX_InvalidCard );
+   status = FX_Warning;
+#endif
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: FX_StopRecord
+
+   Stops the sound record engine.
+---------------------------------------------------------------------*/
+
+void FX_StopRecord
+   (
+   void
+   )
+
+   {
+#ifdef PLAT_DOS
+   // Stop sound playback
+   switch( FX_SoundDevice )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         MV_StopRecord();
+         break;
+      }
+#endif
+   }

Added: tags/rott-1.1/rott/audiolib/fx_man.h
===================================================================
--- tags/rott-1.1/rott/audiolib/fx_man.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/fx_man.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,135 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: FX_MAN.H
+
+   author: James R. Dose
+   date:   March 17, 1994
+
+   Public header for FX_MAN.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __FX_MAN_H
+#define __FX_MAN_H
+
+#include "sndcards.h"
+
+typedef struct
+   {
+   int MaxVoices;
+   int MaxSampleBits;
+   int MaxChannels;
+   } fx_device;
+
+#define MonoFx   1
+#define StereoFx 2
+
+typedef struct
+   {
+   unsigned long Address;
+   unsigned long Type;
+   unsigned long Interrupt;
+   unsigned long Dma8;
+   unsigned long Dma16;
+   unsigned long Midi;
+   unsigned long Emu;
+   } fx_blaster_config;
+
+enum FX_ERRORS
+   {
+   FX_Warning = -2,
+   FX_Error = -1,
+   FX_Ok = 0,
+   FX_ASSVersion,
+   FX_BlasterError,
+   FX_SoundCardError,
+   FX_InvalidCard,
+   FX_MultiVocError,
+   FX_DPMI_Error
+   };
+
+enum fx_BLASTER_Types
+   {
+   fx_SB     = 1,
+   fx_SBPro  = 2,
+   fx_SB20   = 3,
+   fx_SBPro2 = 4,
+   fx_SB16   = 6
+   };
+
+
+char *FX_ErrorString( int ErrorNumber );
+int   FX_SetupCard( int SoundCard, fx_device *device );
+int   FX_GetBlasterSettings( fx_blaster_config *blaster );
+int   FX_SetupSoundBlaster( fx_blaster_config blaster, int *MaxVoices, int *MaxSampleBits, int *MaxChannels );
+int   FX_Init( int SoundCard, int numvoices, int numchannels, int samplebits, unsigned mixrate );
+int   FX_Shutdown( void );
+int   FX_SetCallBack( void ( *function )( unsigned long ) );
+void  FX_SetVolume( int volume );
+int   FX_GetVolume( void );
+
+void  FX_SetReverseStereo( int setting );
+int   FX_GetReverseStereo( void );
+void  FX_SetReverb( int reverb );
+void  FX_SetFastReverb( int reverb );
+int   FX_GetMaxReverbDelay( void );
+int   FX_GetReverbDelay( void );
+void  FX_SetReverbDelay( int delay );
+
+int FX_VoiceAvailable( int priority );
+int FX_EndLooping( int handle );
+int FX_SetPan( int handle, int vol, int left, int right );
+int FX_SetPitch( int handle, int pitchoffset );
+int FX_SetFrequency( int handle, int frequency );
+
+int FX_PlayVOC( char *ptr, int pitchoffset, int vol, int left, int right,
+       int priority, unsigned long callbackval );
+int FX_PlayLoopedVOC( char *ptr, long loopstart, long loopend,
+       int pitchoffset, int vol, int left, int right, int priority,
+       unsigned long callbackval );
+int FX_PlayWAV( char *ptr, int pitchoffset, int vol, int left, int right,
+       int priority, unsigned long callbackval );
+int FX_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+       int pitchoffset, int vol, int left, int right, int priority,
+       unsigned long callbackval );
+int FX_PlayVOC3D( char *ptr, int pitchoffset, int angle, int distance,
+       int priority, unsigned long callbackval );
+int FX_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+       int priority, unsigned long callbackval );
+int FX_PlayRaw( char *ptr, unsigned long length, unsigned rate,
+       int pitchoffset, int vol, int left, int right, int priority,
+       unsigned long callbackval );
+int FX_PlayLoopedRaw( char *ptr, unsigned long length, char *loopstart,
+       char *loopend, unsigned rate, int pitchoffset, int vol, int left,
+       int right, int priority, unsigned long callbackval );
+int FX_Pan3D( int handle, int angle, int distance );
+int FX_SoundActive( int handle );
+int FX_SoundsPlaying( void );
+int FX_StopSound( int handle );
+int FX_StopAllSounds( void );
+int FX_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+       int rate, int pitchoffset, int vol, int left, int right,
+       int priority, unsigned long callbackval );
+int  FX_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
+void FX_StopRecord( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/gmtimbre.c
===================================================================
--- tags/rott-1.1/rott/audiolib/gmtimbre.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/gmtimbre.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+typedef struct
+   {
+   unsigned char SAVEK[ 2 ];
+   unsigned char Level[ 2 ];
+   unsigned char Env1[ 2 ];
+   unsigned char Env2[ 2 ];
+   unsigned char Wave[ 2 ];
+   unsigned char Feedback;
+   signed   char Transpose;
+   signed   char Velocity;
+   } TIMBRE;
+
+TIMBRE ADLIB_TimbreBank[ 256 ] =
+   {
+      { { 33, 33 }, { 143, 6 }, { 242, 242 }, { 69, 118 }, { 0, 0 }, 8, 0 },
+      { { 49, 33 }, { 75, 0 }, { 242, 242 }, { 84, 86 }, { 0, 0 }, 8, 0 },
+      { { 49, 33 }, { 73, 0 }, { 242, 242 }, { 85, 118 }, { 0, 0 }, 8, 0 },
+      { { 177, 97 }, { 14, 0 }, { 242, 243 }, { 59, 11 }, { 0, 0 }, 6, 0 },
+      { { 1, 33 }, { 87, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0 },
+      { { 1, 33 }, { 147, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0 },
+      { { 33, 54 }, { 128, 14 }, { 162, 241 }, { 1, 213 }, { 0, 0 }, 8, 0 },
+      { { 1, 1 }, { 146, 0 }, { 194, 194 }, { 168, 88 }, { 0, 0 }, 10, 0 },
+      { { 12, 129 }, { 92, 0 }, { 246, 243 }, { 84, 181 }, { 0, 0 }, 0, 0 },
+      { { 7, 17 }, { 151, 128 }, { 246, 245 }, { 50, 17 }, { 0, 0 }, 2, 0 },
+      { { 23, 1 }, { 33, 0 }, { 86, 246 }, { 4, 4 }, { 0, 0 }, 2, 0 },
+      { { 24, 129 }, { 98, 0 }, { 243, 242 }, { 230, 246 }, { 0, 0 }, 0, 0 },
+      { { 24, 33 }, { 35, 0 }, { 247, 229 }, { 85, 216 }, { 0, 0 }, 0, 0 },
+      { { 21, 1 }, { 145, 0 }, { 246, 246 }, { 166, 230 }, { 0, 0 }, 4, 0 },
+      { { 69, 129 }, { 89, 128 }, { 211, 163 }, { 130, 227 }, { 0, 0 }, 12, 0 },
+      { { 3, 129 }, { 73, 128 }, { 116, 179 }, { 85, 5 }, { 1, 0 }, 4, 0 },
+      { { 113, 49 }, { 146, 0 }, { 246, 241 }, { 20, 7 }, { 0, 0 }, 2, 0 },
+      { { 114, 48 }, { 20, 0 }, { 199, 199 }, { 88, 8 }, { 0, 0 }, 2, 0 },
+      { { 112, 177 }, { 68, 0 }, { 170, 138 }, { 24, 8 }, { 0, 0 }, 4, 0 },
+      { { 35, 177 }, { 147, 0 }, { 151, 85 }, { 35, 20 }, { 1, 0 }, 4, 0 },
+      { { 97, 177 }, { 19, 128 }, { 151, 85 }, { 4, 4 }, { 1, 0 }, 0, 0 },
+      { { 36, 177 }, { 72, 0 }, { 152, 70 }, { 42, 26 }, { 1, 0 }, 12, 0 },
+      { { 97, 33 }, { 19, 0 }, { 145, 97 }, { 6, 7 }, { 1, 0 }, 10, 0 },
+      { { 33, 161 }, { 19, 137 }, { 113, 97 }, { 6, 7 }, { 0, 0 }, 6, 0 },
+      { { 2, 65 }, { 156, 128 }, { 243, 243 }, { 148, 200 }, { 1, 0 }, 12, 0 },
+      { { 3, 17 }, { 84, 0 }, { 243, 241 }, { 154, 231 }, { 1, 0 }, 12, 0 },
+      { { 35, 33 }, { 95, 0 }, { 241, 242 }, { 58, 248 }, { 0, 0 }, 0, 0 },
+      { { 3, 33 }, { 135, 128 }, { 246, 243 }, { 34, 243 }, { 1, 0 }, 6, 0 },
+      { { 3, 33 }, { 71, 0 }, { 249, 246 }, { 84, 58 }, { 0, 0 }, 0, 0 },
+      { { 35, 33 }, { 72, 0 }, { 149, 132 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+      { { 35, 33 }, { 74, 0 }, { 149, 148 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+      { { 9, 132 }, { 161, 128 }, { 32, 209 }, { 79, 248 }, { 0, 0 }, 8, 0 },
+      { { 33, 162 }, { 30, 0 }, { 148, 195 }, { 6, 166 }, { 0, 0 }, 2, 0 },
+      { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0 },
+      { { 49, 49 }, { 141, 0 }, { 241, 241 }, { 232, 120 }, { 0, 0 }, 10, 0 },
+      { { 49, 50 }, { 91, 0 }, { 81, 113 }, { 40, 72 }, { 0, 0 }, 12, 0 },
+      { { 1, 33 }, { 139, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0 },
+      { { 1, 33 }, { 137, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0 },
+      { { 49, 49 }, { 139, 0 }, { 244, 241 }, { 232, 120 }, { 0, 0 }, 10, 0 },
+      { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0 },
+      { { 49, 33 }, { 21, 0 }, { 221, 86 }, { 19, 38 }, { 1, 0 }, 8, 0 },
+      { { 49, 33 }, { 22, 0 }, { 221, 102 }, { 19, 6 }, { 1, 0 }, 8, 0 },
+      { { 113, 49 }, { 73, 0 }, { 209, 97 }, { 28, 12 }, { 1, 0 }, 8, 0 },
+      { { 33, 35 }, { 77, 128 }, { 113, 114 }, { 18, 6 }, { 1, 0 }, 2, 0 },
+      { { 241, 225 }, { 64, 0 }, { 241, 111 }, { 33, 22 }, { 1, 0 }, 2, 0 },
+      { { 2, 1 }, { 26, 128 }, { 245, 133 }, { 117, 53 }, { 1, 0 }, 0, 0 },
+      { { 2, 1 }, { 29, 128 }, { 245, 243 }, { 117, 244 }, { 1, 0 }, 0, 0 },
+      { { 16, 17 }, { 65, 0 }, { 245, 242 }, { 5, 195 }, { 1, 0 }, 2, 0 },
+      { { 33, 162 }, { 155, 1 }, { 177, 114 }, { 37, 8 }, { 1, 0 }, 14, 0 },
+      { { 161, 33 }, { 152, 0 }, { 127, 63 }, { 3, 7 }, { 1, 1 }, 0, 0 },
+      { { 161, 97 }, { 147, 0 }, { 193, 79 }, { 18, 5 }, { 0, 0 }, 10, 0 },
+      { { 33, 97 }, { 24, 0 }, { 193, 79 }, { 34, 5 }, { 0, 0 }, 12, 0 },
+      { { 49, 114 }, { 91, 131 }, { 244, 138 }, { 21, 5 }, { 0, 0 }, 0, 0 },
+      { { 161, 97 }, { 144, 0 }, { 116, 113 }, { 57, 103 }, { 0, 0 }, 0, 0 },
+      { { 113, 114 }, { 87, 0 }, { 84, 122 }, { 5, 5 }, { 0, 0 }, 12, 0 },
+      { { 144, 65 }, { 0, 0 }, { 84, 165 }, { 99, 69 }, { 0, 0 }, 8, 0 },
+      { { 33, 33 }, { 146, 1 }, { 133, 143 }, { 23, 9 }, { 0, 0 }, 12, 0 },
+      { { 33, 33 }, { 148, 5 }, { 117, 143 }, { 23, 9 }, { 0, 0 }, 12, 0 },
+      { { 33, 97 }, { 148, 0 }, { 118, 130 }, { 21, 55 }, { 0, 0 }, 12, 0 },
+      { { 49, 33 }, { 67, 0 }, { 158, 98 }, { 23, 44 }, { 1, 1 }, 2, 0 },
+      { { 33, 33 }, { 155, 0 }, { 97, 127 }, { 106, 10 }, { 0, 0 }, 2, 0 },
+      { { 97, 34 }, { 138, 6 }, { 117, 116 }, { 31, 15 }, { 0, 0 }, 8, 0 },
+      { { 161, 33 }, { 134, 13 }, { 114, 113 }, { 85, 24 }, { 1, 0 }, 0, 0 },
+      { { 33, 33 }, { 77, 0 }, { 84, 166 }, { 60, 28 }, { 0, 0 }, 8, 0 },
+      { { 49, 97 }, { 143, 0 }, { 147, 114 }, { 2, 11 }, { 1, 0 }, 8, 0 },
+      { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 3, 9 }, { 1, 0 }, 8, 0 },
+      { { 49, 97 }, { 145, 0 }, { 147, 130 }, { 3, 9 }, { 1, 0 }, 10, 0 },
+      { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 15, 15 }, { 1, 0 }, 10, 0 },
+      { { 33, 33 }, { 75, 0 }, { 170, 143 }, { 22, 10 }, { 1, 0 }, 8, 0 },
+      { { 49, 33 }, { 144, 0 }, { 126, 139 }, { 23, 12 }, { 1, 1 }, 6, 0 },
+      { { 49, 50 }, { 129, 0 }, { 117, 97 }, { 25, 25 }, { 1, 0 }, 0, 0 },
+      { { 50, 33 }, { 144, 0 }, { 155, 114 }, { 33, 23 }, { 0, 0 }, 4, 0 },
+      { { 225, 225 }, { 31, 0 }, { 133, 101 }, { 95, 26 }, { 0, 0 }, 0, 0 },
+      { { 225, 225 }, { 70, 0 }, { 136, 101 }, { 95, 26 }, { 0, 0 }, 0, 0 },
+      { { 161, 33 }, { 156, 0 }, { 117, 117 }, { 31, 10 }, { 0, 0 }, 2, 0 },
+      { { 49, 33 }, { 139, 0 }, { 132, 101 }, { 88, 26 }, { 0, 0 }, 0, 0 },
+      { { 225, 161 }, { 76, 0 }, { 102, 101 }, { 86, 38 }, { 0, 0 }, 0, 0 },
+      { { 98, 161 }, { 203, 0 }, { 118, 85 }, { 70, 54 }, { 0, 0 }, 0, 0 },
+      { { 98, 161 }, { 153, 0 }, { 87, 86 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+      { { 98, 161 }, { 147, 0 }, { 119, 118 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+      { { 34, 33 }, { 89, 0 }, { 255, 255 }, { 3, 15 }, { 2, 0 }, 0, 0 },
+      { { 33, 33 }, { 14, 0 }, { 255, 255 }, { 15, 15 }, { 1, 1 }, 0, 0 },
+      { { 34, 33 }, { 70, 128 }, { 134, 100 }, { 85, 24 }, { 0, 0 }, 0, 0 },
+      { { 33, 161 }, { 69, 0 }, { 102, 150 }, { 18, 10 }, { 0, 0 }, 0, 0 },
+      { { 33, 34 }, { 139, 0 }, { 146, 145 }, { 42, 42 }, { 1, 0 }, 0, 0 },
+      { { 162, 97 }, { 158, 64 }, { 223, 111 }, { 5, 7 }, { 0, 0 }, 2, 0 },
+      { { 32, 96 }, { 26, 0 }, { 239, 143 }, { 1, 6 }, { 0, 2 }, 0, 0 },
+      { { 33, 33 }, { 143, 128 }, { 241, 244 }, { 41, 9 }, { 0, 0 }, 10, 0 },
+      { { 119, 161 }, { 165, 0 }, { 83, 160 }, { 148, 5 }, { 0, 0 }, 2, 0 },
+      { { 97, 177 }, { 31, 128 }, { 168, 37 }, { 17, 3 }, { 0, 0 }, 10, 0 },
+      { { 97, 97 }, { 23, 0 }, { 145, 85 }, { 52, 22 }, { 0, 0 }, 12, 0 },
+      { { 113, 114 }, { 93, 0 }, { 84, 106 }, { 1, 3 }, { 0, 0 }, 0, 0 },
+      { { 33, 162 }, { 151, 0 }, { 33, 66 }, { 67, 53 }, { 0, 0 }, 8, 0 },
+      { { 161, 33 }, { 28, 0 }, { 161, 49 }, { 119, 71 }, { 1, 1 }, 0, 0 },
+      { { 33, 97 }, { 137, 3 }, { 17, 66 }, { 51, 37 }, { 0, 0 }, 10, 0 },
+      { { 161, 33 }, { 21, 0 }, { 17, 207 }, { 71, 7 }, { 1, 0 }, 0, 0 },
+      { { 58, 81 }, { 206, 0 }, { 248, 134 }, { 246, 2 }, { 0, 0 }, 2, 0 },
+      { { 33, 33 }, { 21, 0 }, { 33, 65 }, { 35, 19 }, { 1, 0 }, 0, 0 },
+      { { 6, 1 }, { 91, 0 }, { 116, 165 }, { 149, 114 }, { 0, 0 }, 0, 0 },
+      { { 34, 97 }, { 146, 131 }, { 177, 242 }, { 129, 38 }, { 0, 0 }, 12, 0 },
+      { { 65, 66 }, { 77, 0 }, { 241, 242 }, { 81, 245 }, { 1, 0 }, 0, 0 },
+      { { 97, 163 }, { 148, 128 }, { 17, 17 }, { 81, 19 }, { 1, 0 }, 6, 0 },
+      { { 97, 161 }, { 140, 128 }, { 17, 29 }, { 49, 3 }, { 0, 0 }, 6, 0 },
+      { { 164, 97 }, { 76, 0 }, { 243, 129 }, { 115, 35 }, { 1, 0 }, 4, 0 },
+      { { 2, 7 }, { 133, 3 }, { 210, 242 }, { 83, 246 }, { 0, 1 }, 0, 0 },
+      { { 17, 19 }, { 12, 128 }, { 163, 162 }, { 17, 229 }, { 1, 0 }, 0, 0 },
+      { { 17, 17 }, { 6, 0 }, { 246, 242 }, { 65, 230 }, { 1, 2 }, 4, 0 },
+      { { 147, 145 }, { 145, 0 }, { 212, 235 }, { 50, 17 }, { 0, 1 }, 8, 0 },
+      { { 4, 1 }, { 79, 0 }, { 250, 194 }, { 86, 5 }, { 0, 0 }, 12, 0 },
+      { { 33, 34 }, { 73, 0 }, { 124, 111 }, { 32, 12 }, { 0, 1 }, 6, 0 },
+      { { 49, 33 }, { 133, 0 }, { 221, 86 }, { 51, 22 }, { 1, 0 }, 10, 0 },
+      { { 32, 33 }, { 4, 129 }, { 218, 143 }, { 5, 11 }, { 2, 0 }, 6, 0 },
+      { { 5, 3 }, { 106, 128 }, { 241, 195 }, { 229, 229 }, { 0, 0 }, 6, 0 },
+      { { 7, 2 }, { 21, 0 }, { 236, 248 }, { 38, 22 }, { 0, 0 }, 10, 0 },
+      { { 5, 1 }, { 157, 0 }, { 103, 223 }, { 53, 5 }, { 0, 0 }, 8, 0 },
+      { { 24, 18 }, { 150, 0 }, { 250, 248 }, { 40, 229 }, { 0, 0 }, 10, 0 },
+      { { 16, 0 }, { 134, 3 }, { 168, 250 }, { 7, 3 }, { 0, 0 }, 6, 0 },
+      { { 17, 16 }, { 65, 3 }, { 248, 243 }, { 71, 3 }, { 2, 0 }, 4, 0 },
+      { { 1, 16 }, { 142, 0 }, { 241, 243 }, { 6, 2 }, { 2, 0 }, 14, 0 },
+      { { 14, 192 }, { 0, 0 }, { 31, 31 }, { 0, 255 }, { 0, 3 }, 14, 0 },
+      { { 6, 3 }, { 128, 136 }, { 248, 86 }, { 36, 132 }, { 0, 2 }, 14, 0 },
+      { { 14, 208 }, { 0, 5 }, { 248, 52 }, { 0, 4 }, { 0, 3 }, 14, 0 },
+      { { 14, 192 }, { 0, 0 }, { 246, 31 }, { 0, 2 }, { 0, 3 }, 14, 0 },
+      { { 213, 218 }, { 149, 64 }, { 55, 86 }, { 163, 55 }, { 0, 0 }, 0, 0 },
+      { { 53, 20 }, { 92, 8 }, { 178, 244 }, { 97, 21 }, { 2, 0 }, 10, 0 },
+      { { 14, 208 }, { 0, 0 }, { 246, 79 }, { 0, 245 }, { 0, 3 }, 14, 0 },
+      { { 38, 228 }, { 0, 0 }, { 255, 18 }, { 1, 22 }, { 0, 1 }, 14, 0 },
+      { { 0, 0 }, { 0, 0 }, { 243, 246 }, { 240, 201 }, { 0, 2 }, 14, 0 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 52 },
+      { { 0, 1 }, { 2, 0 }, { 255, 255 }, { 7, 8 }, { 0, 0 }, 0, 48 },
+      { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 58 },
+      { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 60 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 47 },
+      { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 49 },
+      { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 51 },
+      { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 54 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 57 },
+      { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 72 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 60 },
+      { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 76 },
+      { { 14, 7 }, { 10, 93 }, { 228, 245 }, { 228, 229 }, { 3, 1 }, 6, 84 },
+      { { 2, 5 }, { 3, 10 }, { 180, 151 }, { 4, 247 }, { 0, 0 }, 14, 36 },
+      { { 78, 158 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 76 },
+      { { 17, 16 }, { 69, 8 }, { 248, 243 }, { 55, 5 }, { 2, 0 }, 8, 84 },
+      { { 14, 208 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 83 },
+      { { 128, 16 }, { 0, 13 }, { 255, 255 }, { 3, 20 }, { 3, 0 }, 12, 84 },
+      { { 14, 7 }, { 8, 81 }, { 248, 244 }, { 66, 228 }, { 0, 3 }, 14, 24 },
+      { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 77 },
+      { { 1, 2 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 7, 60 },
+      { { 1, 1 }, { 81, 0 }, { 250, 250 }, { 135, 183 }, { 0, 0 }, 6, 65 },
+      { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 59 },
+      { { 1, 2 }, { 89, 0 }, { 250, 248 }, { 136, 182 }, { 0, 0 }, 6, 51 },
+      { { 1, 0 }, { 0, 0 }, { 249, 250 }, { 10, 6 }, { 3, 0 }, 14, 45 },
+      { { 0, 0 }, { 128, 0 }, { 249, 246 }, { 137, 108 }, { 3, 0 }, 14, 71 },
+      { { 3, 12 }, { 128, 8 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 60 },
+      { { 3, 12 }, { 133, 0 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 58 },
+      { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 53 },
+      { { 14, 3 }, { 64, 0 }, { 200, 155 }, { 73, 105 }, { 0, 2 }, 14, 64 },
+      { { 215, 199 }, { 220, 0 }, { 173, 141 }, { 5, 5 }, { 3, 0 }, 14, 71 },
+      { { 215, 199 }, { 220, 0 }, { 168, 136 }, { 4, 4 }, { 3, 0 }, 14, 61 },
+      { { 128, 17 }, { 0, 0 }, { 246, 103 }, { 6, 23 }, { 3, 3 }, 14, 61 },
+      { { 128, 17 }, { 0, 9 }, { 245, 70 }, { 5, 22 }, { 2, 3 }, 14, 48 },
+      { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 48 },
+      { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 3, 0 }, 0, 69 },
+      { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 68 },
+      { { 1, 2 }, { 88, 0 }, { 103, 117 }, { 231, 7 }, { 0, 0 }, 0, 63 },
+      { { 65, 66 }, { 69, 8 }, { 248, 117 }, { 72, 5 }, { 0, 0 }, 0, 74 },
+      { { 10, 30 }, { 64, 78 }, { 224, 255 }, { 240, 5 }, { 3, 0 }, 8, 60 },
+      { { 10, 30 }, { 124, 82 }, { 224, 255 }, { 240, 2 }, { 3, 0 }, 8, 80 },
+      { { 14, 0 }, { 64, 8 }, { 122, 123 }, { 74, 27 }, { 0, 2 }, 14, 64 },
+      { { 14, 7 }, { 10, 64 }, { 228, 85 }, { 228, 57 }, { 3, 1 }, 6, 69 },
+      { { 5, 4 }, { 5, 64 }, { 249, 214 }, { 50, 165 }, { 3, 0 }, 14, 73 },
+      { { 2, 21 }, { 63, 0 }, { 0, 247 }, { 243, 245 }, { 3, 0 }, 8, 75 },
+      { { 1, 2 }, { 79, 0 }, { 250, 248 }, { 141, 181 }, { 0, 0 }, 7, 68 },
+      { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 48 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 53 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 }
+   };

Added: tags/rott-1.1/rott/audiolib/gus.c
===================================================================
--- tags/rott-1.1/rott/audiolib/gus.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/gus.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,283 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   GUS.C
+
+   author: James R. Dose
+   date:   September 7, 1994
+
+   Gravis Ultrasound initialization routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "usrhooks.h"
+#include "interrup.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+#include "guswave.h"
+#include "_guswave.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+// size of DMA buffer for patch loading
+#define DMABUFFSIZE 2048U
+
+struct gf1_dma_buff GUS_HoldBuffer;
+static int          HoldBufferAllocated = FALSE;
+
+static int GUS_Installed = 0;
+
+extern VoiceNode   GUSWAVE_Voices[ VOICES ];
+extern int GUSWAVE_Installed;
+
+unsigned long GUS_TotalMemory;
+int           GUS_MemConfig;
+
+int GUS_AuxError  = 0;
+
+int GUS_ErrorCode = GUS_Ok;
+
+#define GUS_SetErrorCode( status ) \
+   GUS_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: GUS_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *GUS_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case GUS_Warning :
+      case GUS_Error :
+         ErrorString = GUS_ErrorString( GUS_ErrorCode );
+         break;
+
+      case GUS_Ok :
+         ErrorString = "Ultrasound music ok.";
+         break;
+
+      case GUS_OutOfMemory :
+         ErrorString = "Out of memory in GusMidi.";
+         break;
+
+      case GUS_OutOfDosMemory :
+         ErrorString = "Out of conventional (640K) memory in GusMidi.";
+         break;
+
+      case GUS_GF1Error :
+         ErrorString = gf1_error_str( GUS_AuxError );
+         break;
+
+      case GUS_InvalidIrq :
+         ErrorString = "Ultrasound IRQ must be 7 or less.";
+         break;
+
+      case GUS_ULTRADIRNotSet :
+         ErrorString = "ULTRADIR environment variable not set.";
+         break;
+
+      case GUS_MissingConfig :
+//         ErrorString = "Can't find GUSMIDI.INI file.";
+         ErrorString = "Can't find ULTRAMID.INI file.";
+         break;
+
+      case GUS_FileError :
+         ErrorString = strerror( GUS_AuxError );
+         break;
+
+      default :
+         ErrorString = "Unknown Ultrasound error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+
+/*---------------------------------------------------------------------
+   Function: D32DosMemAlloc
+
+   Allocate a block of Conventional memory.
+---------------------------------------------------------------------*/
+
+void *D32DosMemAlloc
+   (
+   unsigned size
+   )
+
+   {
+   union REGS r;
+
+   // DPMI allocate DOS memory
+   r.x.eax = 0x0100;
+
+   // Number of paragraphs requested
+   r.x.ebx = ( size + 15 ) >> 4;
+   int386( 0x31, &r, &r );
+   if ( r.x.cflag )
+      {
+      // Failed
+      return( NULL );
+      }
+
+   return( ( void * )( ( r.x.eax & 0xFFFF ) << 4 ) );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUS_Init
+
+   Initializes the Gravis Ultrasound for sound and music playback.
+---------------------------------------------------------------------*/
+
+int GUS_Init
+   (
+   void
+   )
+
+   {
+   struct load_os os;
+   int ret;
+
+   if ( GUS_Installed > 0 )
+      {
+      GUS_Installed++;
+      return( GUS_Ok );
+      }
+
+   GUS_SetErrorCode( GUS_Ok );
+
+   GUS_Installed = 0;
+
+   GetUltraCfg( &os );
+
+   if ( os.forced_gf1_irq > 7 )
+      {
+      GUS_SetErrorCode( GUS_InvalidIrq );
+      return( GUS_Error );
+      }
+
+   if ( !HoldBufferAllocated )
+      {
+      GUS_HoldBuffer.vptr = D32DosMemAlloc( DMABUFFSIZE );
+      if ( GUS_HoldBuffer.vptr == NULL )
+         {
+         GUS_SetErrorCode( GUS_OutOfDosMemory );
+         return( GUS_Error );
+         }
+      GUS_HoldBuffer.paddr = ( unsigned long )GUS_HoldBuffer.vptr;
+
+      HoldBufferAllocated = TRUE;
+      }
+
+   os.voices = 24;
+   ret = gf1_load_os( &os );
+   if ( ret )
+      {
+      GUS_AuxError = ret;
+      GUS_SetErrorCode( GUS_GF1Error );
+      return( GUS_Error );
+      }
+
+   GUS_TotalMemory = gf1_mem_avail();
+   GUS_MemConfig   = ( GUS_TotalMemory - 1 ) >> 18;
+
+   GUS_Installed = 1;
+   return( GUS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUS_Shutdown
+
+   Ends use of the Gravis Ultrasound.  Must be called the same number
+   of times as GUS_Init.
+---------------------------------------------------------------------*/
+
+void GUS_Shutdown
+   (
+   void
+   )
+
+   {
+   if ( GUS_Installed > 0 )
+      {
+      GUS_Installed--;
+      if ( GUS_Installed == 0 )
+         {
+         gf1_unload_os();
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_Shutdown
+
+   Terminates use of the Gravis Ultrasound for digitized sound playback.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_Shutdown
+   (
+   void
+   )
+
+   {
+   int i;
+
+   if ( GUSWAVE_Installed )
+      {
+      GUSWAVE_KillAllVoices();
+
+      // free memory
+      for ( i = 0; i < VOICES; i++ )
+         {
+         if ( GUSWAVE_Voices[ i ].mem != NULL )
+            {
+            gf1_free( GUSWAVE_Voices[ i ].mem );
+            GUSWAVE_Voices[ i ].mem = NULL;
+            }
+         }
+
+      GUS_Shutdown();
+      GUSWAVE_Installed = FALSE;
+      }
+   }

Added: tags/rott-1.1/rott/audiolib/gusmidi.c
===================================================================
--- tags/rott-1.1/rott/audiolib/gusmidi.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/gusmidi.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,561 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   GUSMIDI.C
+
+   author: James R. Dose
+   date:   March 23, 1994
+
+   General MIDI playback functions for the Gravis Ultrasound
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+// Module MUST be compiled with structure allignment set to a maximum
+// of 1 byte ( zp1 ).
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "usrhooks.h"
+#include "interrup.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+// size of DMA buffer for patch loading
+#define DMABUFFSIZE 2048U
+
+#define MAX_MEM_CONFIG   3
+
+// size of patch array (128 perc, 128 melodic)
+#define NUM_PATCHES 256
+
+// size of largest patch name
+#define BIGGEST_NAME 9
+
+#define UNUSED_PATCH -1
+
+static struct patch   Patch[ NUM_PATCHES ];
+static unsigned char *PatchWaves[ NUM_PATCHES ];
+
+static int   PatchMap[ NUM_PATCHES ][ MAX_MEM_CONFIG + 1 ];
+static char  ProgramName[ NUM_PATCHES ][ BIGGEST_NAME ];
+static char  PatchLoaded[ NUM_PATCHES ];
+
+static char  ConfigFileName[] = "ULTRAMID.INI";
+static char  ConfigDirectory[ 80 ] = { '\0' };
+
+// The name of the configuration directory
+static char  InstrumentDirectory[ 80 ];
+
+extern struct gf1_dma_buff GUS_HoldBuffer;
+
+extern unsigned long GUS_TotalMemory;
+extern int           GUS_MemConfig;
+
+static int GUSMIDI_Volume = 255;
+
+extern int GUS_AuxError;
+extern int GUS_ErrorCode;
+
+int GUSMIDI_Installed = FALSE;
+
+#define GUS_SetErrorCode( status ) \
+   GUS_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: GUS_GetPatchMap
+
+   Reads the patch map from disk.
+---------------------------------------------------------------------*/
+
+int GUS_GetPatchMap
+   (
+   char *name
+   )
+
+   {
+   char text[ 80 ];
+   char *ud;
+   int  index;
+   int  ignore;
+   FILE *fp;
+
+   for( index = 0; index < NUM_PATCHES; index++ )
+      {
+      PatchMap[ index ][ 0 ] = UNUSED_PATCH;
+      PatchMap[ index ][ 1 ] = UNUSED_PATCH;
+      PatchMap[ index ][ 2 ] = UNUSED_PATCH;
+      PatchMap[ index ][ 3 ] = UNUSED_PATCH;
+      ProgramName[ index ][ 0 ] = 0;
+      }
+
+   ud = getenv( "ULTRADIR" );
+   if ( ud == NULL )
+      {
+      GUS_SetErrorCode( GUS_ULTRADIRNotSet );
+      return( GUS_Error );
+      }
+
+   strcpy( InstrumentDirectory, ud );
+   strcat( InstrumentDirectory, "\\midi\\" );
+   strcpy( ConfigDirectory, ud );
+   strcat( ConfigDirectory, "\\midi\\" );
+   strcpy( text, name );
+
+   fp = fopen( text, "r" );
+   if ( fp == NULL )
+      {
+      strcpy( text, InstrumentDirectory );
+      strcat( text, name );
+
+      fp = fopen( text, "r" );
+      if ( fp == NULL )
+         {
+         GUS_SetErrorCode( GUS_MissingConfig );
+         return( GUS_Error );
+         }
+      }
+
+   while( 1 )
+      {
+      if ( fgets( text, 80, fp ) == NULL )
+         {
+         break;
+         }
+
+      if ( text[ 0 ] == '#' )
+         {
+         continue;
+         }
+
+      if ( sscanf( text, "%d", &index ) != 1 )
+         {
+         continue;
+         }
+
+      sscanf( text, "%d, %d, %d, %d, %d, %s\n", &ignore,
+         &PatchMap[ index ][ 0 ],
+         &PatchMap[ index ][ 1 ],
+         &PatchMap[ index ][ 2 ],
+         &PatchMap[ index ][ 3 ],
+         ProgramName[ index ] );
+      }
+
+   fclose( fp );
+
+   return( GUS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_UnloadPatch
+
+   Unloads a patch from the GUS's memory.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_UnloadPatch
+   (
+   int prognum
+   )
+
+   {
+   int      prog;
+   unsigned flags;
+
+   prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+   if ( PatchLoaded[ prog ] )
+      {
+      flags = DisableInterrupts();
+
+      gf1_unload_patch( &Patch[ prog ] );
+      if ( PatchWaves[ prog ] != NULL )
+         {
+         USRHOOKS_FreeMem( PatchWaves[ prog ] );
+         PatchWaves[ prog ] = NULL;
+         }
+
+      // just in case sequence is still playing
+      Patch[ prog ].nlayers = 0;
+      PatchLoaded[ prog ]   = FALSE;
+
+      RestoreInterrupts( flags );
+      }
+
+   return( GUS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_LoadPatch
+
+   Loads a patch into the GUS's memory.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_LoadPatch
+   (
+   int prognum
+   )
+
+   {
+   int  prog;
+   char text[ 80 ];
+   int  ret;
+   unsigned char *wave_buff;
+   struct patchinfo  patchi;
+   int  status;
+
+   prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+   if ( ( PatchLoaded[ prog ] ) || ( prog == UNUSED_PATCH ) )
+      {
+      return( GUS_Ok );
+      }
+
+   if ( !ProgramName[ prog ][ 0 ] )
+      {
+      return( GUS_Ok );
+      }
+
+   strcpy( text, InstrumentDirectory );
+   strcat( text, ProgramName[ prog ] );
+   strcat( text, ".pat" );
+
+   ret = gf1_get_patch_info( text, &patchi );
+   if ( ret != OK )
+      {
+      GUS_AuxError = ret;
+      GUS_SetErrorCode( GUS_GF1Error );
+      return( GUS_Error );
+      }
+
+   status = USRHOOKS_GetMem( &wave_buff, patchi.header.wave_forms *
+      sizeof( struct wave_struct ) );
+   if ( status != USRHOOKS_Ok )
+      {
+      GUS_SetErrorCode( GUS_OutOfMemory );
+      return( GUS_Error );
+      }
+
+   ret = gf1_load_patch( text, &patchi, &Patch[ prog ], &GUS_HoldBuffer,
+      DMABUFFSIZE, ( unsigned char * )wave_buff, PATCH_LOAD_8_BIT );
+
+   if ( ret != OK )
+      {
+      USRHOOKS_FreeMem( wave_buff );
+      GUS_AuxError = ret;
+      GUS_SetErrorCode( GUS_GF1Error );
+      return( GUS_Error );
+      }
+
+   PatchWaves[ prog ] = wave_buff;
+   PatchLoaded[ prog ] = TRUE;
+
+   return( GUS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_ProgramChange
+
+   Selects the instrument to use on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ProgramChange
+   (
+   int channel,
+   int prognum
+   )
+
+   {
+   int  prog;
+
+   prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+   if ( PatchLoaded[ prog ] )
+      {
+      gf1_midi_change_program( &Patch[ prog ], channel );
+      }
+   else
+      {
+      gf1_midi_change_program( NULL, channel );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_NoteOn
+
+   Plays a note on the specified channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_NoteOn
+   (
+   int chan,
+   int note,
+   int velocity
+   )
+
+   {
+   int prog;
+
+   if ( chan == 9 )
+      {
+      prog = PatchMap[ note + 128 ][ GUS_MemConfig ];
+
+      if ( PatchLoaded[ prog ] )
+         {
+         gf1_midi_note_on( &Patch[ note + 128 ], 1,
+            note, velocity, 9 );
+         }
+      }
+   else
+      {
+      gf1_midi_note_on( 0L, 1, note, velocity, chan );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_NoteOff
+
+   Turns off a note on the specified channel.
+---------------------------------------------------------------------*/
+#pragma warn -par
+void GUSMIDI_NoteOff
+   (
+   int chan,
+   int note,
+   int velocity
+   )
+
+   {
+   gf1_midi_note_off( note, chan );
+   }
+#pragma warn .par
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_ControlChange
+
+   Sets the value of a controller on the specified channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ControlChange
+   (
+   int channel,
+   int number,
+   int value
+   )
+
+   {
+   gf1_midi_parameter( channel, number, value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_PitchBend
+
+   Sets the pitch bend on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_PitchBend
+   (
+   int channel,
+   int lsb,
+   int msb
+   )
+
+   {
+   gf1_midi_pitch_bend( channel, lsb, msb );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_ReleasePatches
+
+   Removes all the instruments from the GUS's memory.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ReleasePatches
+   (
+   void
+   )
+
+   {
+   int i;
+
+   for( i = 0; i < 256; i++ )
+      {
+      GUSMIDI_UnloadPatch( i );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_SetVolume
+
+   Sets the total music volume.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_SetVolume
+   (
+   int volume
+   )
+
+   {
+   // Set the minimum to 2 because 0 has a tremolo problem
+   volume = max( 2, volume );
+   volume = min( volume, 255 );
+
+   GUSMIDI_Volume = volume;
+
+   // range = 0 to 127
+   gf1_midi_synth_volume( 0, volume >> 1 );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_GetVolume
+
+   Returns the total music volume.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_GetVolume
+   (
+   void
+   )
+
+   {
+   return( GUSMIDI_Volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_Init
+
+   Initializes the Gravis Ultrasound for music playback.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_Init
+   (
+   void
+   )
+
+   {
+   int ret;
+   int i;
+   int startmem;
+//   unsigned long mem;
+   extern int GUSWAVE_Installed;
+
+   if ( GUSMIDI_Installed )
+      {
+      GUSMIDI_Shutdown();
+      }
+
+   ret = GUS_Init();
+   if ( ret != GUS_Ok )
+      {
+      return( ret );
+      }
+
+   if ( GUS_MemConfig < 0 )
+      {
+      GUS_MemConfig = 0;
+      }
+
+   if ( GUS_MemConfig > MAX_MEM_CONFIG )
+      {
+      GUS_MemConfig = MAX_MEM_CONFIG;
+      }
+
+   for( i = 0; i < NUM_PATCHES; i++ )
+      {
+      ProgramName[ i ][ 0 ] = '\0';
+      PatchWaves[ i ]       = NULL;
+      PatchLoaded[ i ]      = FALSE;
+      }
+
+   GUSMIDI_SetVolume( 255 );
+
+   GUSMIDI_Installed = TRUE;
+
+   ret = GUS_GetPatchMap( ConfigFileName );
+   if ( ret != GUS_Ok )
+      {
+      GUSMIDI_Shutdown();
+      return( ret );
+      }
+
+//   if ( !GUSWAVE_Installed )
+//      {
+//      mem = gf1_malloc( 8192 );
+//      }
+
+   startmem = gf1_mem_avail();
+   for( i = 0; i < NUM_PATCHES; i++ )
+      {
+      ret = GUSMIDI_LoadPatch( i );
+      if ( ret != GUS_Ok )
+         {
+         }
+//      if ( ret != GUS_Ok )
+//         {
+//         return( ret );
+//         }
+      }
+
+//   if ( !GUSWAVE_Installed )
+//      {
+//      gf1_free( mem );
+//      }
+
+   GUSMIDI_Installed = TRUE;
+
+   return( GUS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSMIDI_Shutdown
+
+   Ends use of the Gravis Ultrasound for music playback.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_Shutdown
+   (
+   void
+   )
+
+   {
+   GUSMIDI_ReleasePatches();
+   GUS_Shutdown();
+   GUSMIDI_Installed = FALSE;
+   }

Added: tags/rott-1.1/rott/audiolib/gusmidi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/gusmidi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/gusmidi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,59 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __GUSMIDI_H
+#define __GUSMIDI_H
+
+extern struct gf1_dma_buff GUS_HoldBuffer;
+
+enum GUS_Errors
+   {
+   GUS_Warning        = -2,
+   GUS_Error          = -1,
+   GUS_Ok             = 0,
+   GUS_OutOfMemory,
+   GUS_OutOfDosMemory,
+   GUS_OutOfDRAM,
+   GUS_GF1Error,
+   GUS_InvalidIrq,
+   GUS_ULTRADIRNotSet,
+   GUS_MissingConfig,
+   GUS_FileError
+   };
+
+char *GUS_ErrorString( int ErrorNumber );
+int   GUS_GetPatchMap( char *name );
+int   GUSMIDI_UnloadPatch( int prog );
+int   GUSMIDI_LoadPatch( int prog );
+void  GUSMIDI_ProgramChange( int channel, int prog );
+void  GUSMIDI_NoteOn( int chan, int note, int velocity );
+void  GUSMIDI_NoteOff( int chan, int note, int velocity );
+void  GUSMIDI_ControlChange( int channel, int number, int value );
+void  GUSMIDI_PitchBend( int channel, int lsb, int msb );
+void  GUSMIDI_ReleasePatches( void );
+void  GUSMIDI_SetVolume( int volume );
+int   GUSMIDI_GetVolume( void );
+int   GUS_Init( void );
+void  GUS_Shutdown( void );
+#pragma aux GUS_Shutdown frame;
+int   GUSMIDI_Init( void );
+void  GUSMIDI_Shutdown( void );
+void *D32DosMemAlloc( unsigned size );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/guswave.c
===================================================================
--- tags/rott-1.1/rott/audiolib/guswave.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/guswave.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1773 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   GUSWAVE.C
+
+   author: James R. Dose
+   date:   March 23, 1994
+
+   Digitized sound playback routines for the Gravis Ultrasound.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include "debugio.h"
+#include "interrup.h"
+#include "ll_man.h"
+#include "pitch.h"
+#include "user.h"
+#include "multivoc.h"
+#include "_guswave.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+#include "guswave.h"
+
+#define ATR_INDEX               0x3c0
+#define STATUS_REGISTER_1       0x3da
+
+#define SetBorderColor(color) \
+   { \
+   inp  (STATUS_REGISTER_1); \
+   outp (ATR_INDEX,0x31);    \
+   outp (ATR_INDEX,color);   \
+   }
+
+static const int GUSWAVE_PanTable[ 32 ] =
+   {
+      8,  9, 10, 11, 11, 12, 13, 14,
+     15, 14, 13, 12, 11, 10,  9,  8,
+      7,  6,  5,  4,  4,  3,  2,  1,
+      0,  1,  2,  3,  4,  5,  6,  7
+   };
+
+static voicelist VoiceList;
+static voicelist VoicePool;
+
+static voicestatus VoiceStatus[ MAX_VOICES ];
+//static
+VoiceNode GUSWAVE_Voices[ VOICES ];
+
+static int GUSWAVE_VoiceHandle  = GUSWAVE_MinVoiceHandle;
+static int GUSWAVE_MaxVoices = VOICES;
+//static
+int GUSWAVE_Installed = FALSE;
+
+static void ( *GUSWAVE_CallBackFunc )( unsigned long ) = NULL;
+
+// current volume for dig audio - from 0 to 4095
+static int GUSWAVE_Volume = MAX_VOLUME;
+
+static int GUSWAVE_SwapLeftRight = FALSE;
+
+static int GUS_Debug = FALSE;
+
+extern int GUSMIDI_Installed;
+
+int GUSWAVE_ErrorCode = GUSWAVE_Ok;
+
+#define GUSWAVE_SetErrorCode( status ) \
+   GUSWAVE_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *GUSWAVE_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case GUSWAVE_Warning :
+      case GUSWAVE_Error :
+         ErrorString = GUSWAVE_ErrorString( GUSWAVE_ErrorCode );
+         break;
+
+      case GUSWAVE_Ok :
+         ErrorString = "GUSWAVE ok.";
+         break;
+
+      case GUSWAVE_GUSError :
+         ErrorString = GUS_ErrorString( GUS_Error );
+         break;
+
+      case GUSWAVE_NotInstalled :
+         ErrorString = "GUSWAVE not installed.";
+         break;
+
+      case GUSWAVE_NoVoices :
+         ErrorString = "No free voices available to GUSWAVE.";
+         break;
+
+      case GUSWAVE_UltraNoMem :
+         ErrorString = "Not enough Ultrasound memory available for GUSWAVE.";
+         break;
+
+      case GUSWAVE_UltraNoMemMIDI :
+         ErrorString = "Not enough Ultrasound memory available for GUSWAVE.  "
+            "Try initializing Sound FX before Music.";
+         break;
+
+      case GUSWAVE_VoiceNotFound :
+         ErrorString = "No voice with matching handle found.";
+         break;
+
+      case GUSWAVE_InvalidVOCFile :
+         ErrorString = "Invalid VOC file passed in to GUSWAVE.";
+         break;
+
+      case GUSWAVE_InvalidWAVFile :
+         ErrorString = "Invalid WAV file passed in to GUSWAVE.";
+         break;
+
+      default :
+         ErrorString = "Unknown GUSWAVE error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_CallBack
+
+   GF1 callback service routine.
+---------------------------------------------------------------------*/
+
+char GUS_Silence8[ 1024 ] = //256 ] =
+   {
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
+
+
+   };
+
+//unsigned short GUS_Silence16[ 128 ] =
+unsigned short GUS_Silence16[ 512 ] =
+   {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+
+
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+   };
+
+static int LOADDS GUSWAVE_CallBack
+   (
+   int reason,
+   int voice,
+   unsigned char **buf,
+   unsigned long *size
+   )
+
+   {
+   VoiceNode *Voice;
+   playbackstatus status;
+
+   // this function is called from an interrupt
+   // remember not to make any DOS or BIOS calls from here
+   // also don't call any C library functions unless you are sure that
+   // they are reentrant
+   // restore our DS register
+
+   if ( VoiceStatus[ voice ].playing == FALSE )
+      {
+      return( DIG_DONE );
+      }
+
+   if ( reason == DIG_MORE_DATA )
+      {
+//      SetBorderColor(16);
+      Voice = VoiceStatus[ voice ].Voice;
+
+      if ( ( Voice != NULL ) && ( Voice->Playing ) )
+/*
+         {
+         *buf = ( unsigned char * )GUS_Silence16;
+         *size = 1024;
+
+         SetBorderColor(0);
+         return( DIG_MORE_DATA );
+         }
+ */
+         {
+         status = Voice->GetSound( Voice );
+         if ( status != SoundDone )
+            {
+            if ( ( Voice->sound == NULL ) || ( status == NoMoreData ) )
+               {
+               if ( Voice->bits == 8 )
+                  {
+                  *buf = GUS_Silence8;
+                  }
+               else
+                  {
+                  *buf = ( unsigned char * )GUS_Silence16;
+                  }
+               *size = 256;
+               }
+            else
+               {
+               *buf  = Voice->sound;
+               *size = Voice->length;
+               }
+            return( DIG_MORE_DATA );
+            }
+         }
+//      SetBorderColor(16);
+      return( DIG_DONE );
+      }
+
+   if ( reason == DIG_DONE )
+      {
+      Voice = VoiceStatus[ voice ].Voice;
+      VoiceStatus[ voice ].playing = FALSE;
+
+      if ( Voice != NULL )
+         {
+         Voice->Active   = FALSE;
+         Voice->Playing  = FALSE;
+
+// I'm commenting this out because a -1 could cause a crash if it
+// is sent to the GF1 code.  This shouldn't be necessary since
+// Active should be false when GF1voice is -1, but this is just
+// a precaution.  Adjust the pan on the wrong voice is a lot
+// more pleasant than a crash!
+//         Voice->GF1voice = -1;
+
+         LL_Remove( VoiceNode, &VoiceList, Voice );
+         LL_AddToTail( VoiceNode, &VoicePool, Voice );
+         }
+
+      if ( GUSWAVE_CallBackFunc )
+         {
+         GUSWAVE_CallBackFunc( Voice->callbackval );
+         }
+      }
+
+   return( DIG_DONE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_DebugCallBack
+
+   GF1 callback service routine with debugging info.
+---------------------------------------------------------------------*/
+
+static int LOADDS GUSWAVE_DebugCallBack
+   (
+   int reason,
+   int voice,
+   unsigned char **buf,
+   unsigned long *size
+   )
+
+   {
+   VoiceNode *Voice;
+
+   // this function is called from an interrupt
+   // remember not to make any DOS or BIOS calls from here
+   // also don't call any C library functions unless you are sure that
+   // they are reentrant
+   // restore our DS register
+
+   if ( VoiceStatus[ voice ].playing == FALSE )
+      {
+//      DB_printf( "GUS Voice %d not playing.\n", voice );
+      DB_printf( "GUS Voice " );
+      DB_PrintNum( voice );
+      DB_printf( " not playing.\n" );
+      return( DIG_DONE );
+         }
+
+      if ( reason == DIG_MORE_DATA )
+         {
+         Voice = VoiceStatus[ voice ].Voice;
+
+//         DB_printf( "Voice %d : More data -- ", Voice );
+         DB_printf( "Voice " );
+         DB_PrintNum( voice );
+         DB_printf( " : More data -- " );
+         if ( Voice != NULL )
+            {
+            if ( Voice->Playing )
+               {
+               GUSWAVE_GetNextVOCBlock( Voice );
+               if ( Voice->Playing )
+                  {
+//                  DB_printf( "More data -- size = %u blocklength = %u\n",
+//                     Voice->length, Voice->BlockLength );
+                  DB_printf( "More data -- size = " );
+                  DB_PrintNum( Voice->length );
+                  DB_printf( " blocklength = " );
+                  DB_PrintNum( Voice->BlockLength );
+                  DB_printf( "\n" );
+                  *buf  = Voice->sound;
+                  *size = Voice->length;
+                  return( DIG_MORE_DATA );
+                  }
+               else
+                  {
+                  DB_printf( "Voice done.\n" );
+                  }
+               }
+            else
+               {
+               DB_printf( "Voice not active.\n" );
+               }
+            }
+         else
+            {
+            DB_printf( " NULL Voice\n" );
+            }
+
+         return( DIG_DONE );
+         }
+
+      if ( reason == DIG_DONE )
+         {
+         VoiceStatus[ voice ].playing = FALSE;
+         Voice = VoiceStatus[ voice ].Voice;
+//         DB_printf( "Voice %d : Done -- ", Voice );
+         DB_printf( "Voice " );
+         DB_PrintNum( voice );
+         DB_printf( " : Done -- " );
+
+         if ( Voice != NULL )
+            {
+            DB_printf( "Ok\n" );
+
+            Voice->Active   = FALSE;
+            Voice->Playing  = FALSE;
+
+// I'm commenting this out because a -1 could cause a crash if it
+// is sent to the GF1 code.  This shouldn't be necessary since
+// Active should be false when GF1voice is -1, but this is just
+// a precaution.  Adjust the pan on the wrong voice is a lot
+// more pleasant than a crash!
+//         Voice->GF1voice = -1;
+
+         LL_Remove( VoiceNode, &VoiceList, Voice );
+         LL_AddToTail( VoiceNode, &VoicePool, Voice );
+         }
+      else
+         {
+         DB_printf( "Null voice\n" );
+         }
+
+      if ( GUSWAVE_CallBackFunc )
+         {
+         GUSWAVE_CallBackFunc( Voice->callbackval );
+         }
+      }
+
+   return( DIG_DONE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetVoice
+
+   Locates the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+static VoiceNode *GUSWAVE_GetVoice
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   voice = VoiceList.start;
+
+   while( voice != NULL )
+      {
+      if ( handle == voice->handle )
+         {
+         break;
+         }
+
+      voice = voice->next;
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( voice == NULL )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+      }
+
+   return( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_VoicePlaying
+
+   Checks if the voice associated with the specified handle is
+   playing.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoicePlaying
+   (
+   int handle
+   )
+
+   {
+   VoiceNode   *voice;
+
+   voice = GUSWAVE_GetVoice( handle );
+   if ( voice != NULL )
+      {
+      return( voice->Active );
+      }
+
+   return( FALSE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_VoicesPlaying
+
+   Determines the number of currently active voices.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoicesPlaying
+   (
+   void
+   )
+
+   {
+   int         index;
+   int         NumVoices = 0;
+   unsigned    flags;
+
+   flags = DisableInterrupts();
+
+   for( index = 0; index < GUSWAVE_MaxVoices; index++ )
+      {
+      if ( GUSWAVE_Voices[ index ].Active )
+         {
+         NumVoices++;
+         }
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( GUS_Debug )
+      {
+      DB_printf( "Number of voices = %d.\n", NumVoices );
+      }
+
+   return( NumVoices );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_Kill
+
+   Stops output of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Kill
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   voice = GUSWAVE_GetVoice( handle );
+
+   if ( voice == NULL )
+      {
+      RestoreInterrupts( flags );
+      GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+
+      if ( GUS_Debug )
+         {
+         DB_printf( "Could not find voice to kill.\n" );
+         }
+
+      return( GUSWAVE_Warning );
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( !GUS_Debug )
+      {
+      if ( voice->Active )
+         {
+         gf1_stop_digital( voice->GF1voice );
+         }
+      }
+   else
+      {
+      DB_printf( "Kill - GUS Voice %d ", voice->GF1voice );
+      if ( voice->Active )
+         {
+         DB_printf( "active\n" );
+         gf1_stop_digital( voice->GF1voice );
+         }
+      else
+         {
+         DB_printf( "inactive\n" );
+         }
+      }
+
+//   RestoreInterrupts( flags );
+
+   return( GUSWAVE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_KillAllVoices
+
+   Stops output of all currently active voices.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_KillAllVoices
+   (
+   void
+   )
+
+   {
+   int i;
+   unsigned  flags;
+
+   if ( !GUSWAVE_Installed )
+      {
+      return( GUSWAVE_Ok );
+      }
+
+   if ( GUS_Debug )
+      {
+      DB_printf( "Kill All Voices\n" );
+      }
+
+   flags = DisableInterrupts();
+
+   // Remove all the voices from the list
+   for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+      {
+      if ( GUSWAVE_Voices[ i ].Active )
+         {
+//         GUSWAVE_Kill( GUSWAVE_Voices[ i ].handle );
+
+         gf1_stop_digital( GUSWAVE_Voices[ i ].GF1voice );
+         }
+      }
+
+   for( i = 0; i < MAX_VOICES; i++ )
+      {
+      VoiceStatus[ i ].playing = FALSE;
+      VoiceStatus[ i ].Voice   = NULL;
+      }
+
+   VoicePool.start = NULL;
+   VoicePool.end   = NULL;
+   VoiceList.start = NULL;
+   VoiceList.end   = NULL;
+
+   for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+      {
+      GUSWAVE_Voices[ i ].Active = FALSE;
+      if ( GUSWAVE_Voices[ i ].mem != NULL )
+         {
+         LL_AddToTail( VoiceNode, &VoicePool, &GUSWAVE_Voices[ i ] );
+         }
+      }
+
+   RestoreInterrupts( flags );
+
+   return( GUSWAVE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_SetPitch
+
+   Sets the pitch for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_SetPitch
+   (
+   int handle,
+   int pitchoffset
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   voice = GUSWAVE_GetVoice( handle );
+
+   if ( voice == NULL )
+      {
+      RestoreInterrupts( flags );
+
+      GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+      return( GUSWAVE_Warning );
+      }
+
+   if ( voice->Active )
+      {
+      voice->PitchScale  = PITCH_GetScale( pitchoffset );
+      voice->RateScale   = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+      gf1_dig_set_freq( voice->GF1voice, voice->RateScale );
+      }
+
+   RestoreInterrupts( flags );
+
+   return( GUSWAVE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_SetPan3D
+
+   Sets the pan position of the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_SetPan3D
+   (
+   int handle,
+   int angle,
+   int distance
+   )
+
+   {
+   VoiceNode *voice;
+   int        pan;
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   voice = GUSWAVE_GetVoice( handle );
+
+   if ( voice == NULL )
+      {
+      RestoreInterrupts( flags );
+
+      GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+      return( GUSWAVE_Warning );
+      }
+
+   if ( voice->Active )
+      {
+      angle &= 31;
+
+      pan = GUSWAVE_PanTable[ angle ];
+      if ( GUSWAVE_SwapLeftRight )
+         {
+         pan = 15 - pan;
+         }
+
+      distance = max( 0, distance );
+      distance = min( 255, distance );
+
+      voice->Volume = 255 - distance;
+      voice->Pan    = pan;
+
+      gf1_dig_set_pan( voice->GF1voice, pan );
+      gf1_dig_set_vol( voice->GF1voice, GUSWAVE_Volume - distance * 4 );
+      }
+
+   RestoreInterrupts( flags );
+
+   return( GUSWAVE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_SetVolume
+
+   Sets the total volume of the digitized sounds.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetVolume
+   (
+   int volume
+   )
+
+   {
+   int i;
+
+   volume = max( 0, volume );
+   volume = min( 255, volume );
+   GUSWAVE_Volume = MAX_VOLUME - ( 255 - volume ) * 4;
+
+   for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+      {
+      if ( GUSWAVE_Voices[ i ].Active )
+         {
+         gf1_dig_set_vol( GUSWAVE_Voices[ i ].GF1voice,
+            GUSWAVE_Volume - ( 255 - GUSWAVE_Voices[ i ].Volume ) * 4 );
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetVolume
+
+   Returns the total volume of the digitized sounds.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_GetVolume
+   (
+   void
+   )
+
+   {
+   return( 255 - ( ( MAX_VOLUME - GUSWAVE_Volume ) / 4 ) );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_AllocVoice
+
+   Retrieve an inactive or lower priority voice for output.
+---------------------------------------------------------------------*/
+
+static VoiceNode *GUSWAVE_AllocVoice
+   (
+   int priority
+   )
+
+   {
+   VoiceNode   *voice;
+   VoiceNode   *node;
+   unsigned    flags;
+
+   // If we don't have any free voices, check if we have a higher
+   // priority than one that is playing.
+   if ( GUSWAVE_VoicesPlaying() >= GUSWAVE_MaxVoices )
+      {
+      flags = DisableInterrupts();
+
+      node = VoiceList.start;
+      voice = node;
+      while( node != NULL )
+         {
+         if ( node->priority < voice->priority )
+            {
+            voice = node;
+            }
+
+         node = node->next;
+         }
+
+      RestoreInterrupts( flags );
+
+      if ( priority >= voice->priority )
+         {
+         GUSWAVE_Kill( voice->handle );
+         }
+      }
+
+   // Check if any voices are in the voice pool
+   flags = DisableInterrupts();
+
+   voice = VoicePool.start;
+   if ( voice != NULL )
+      {
+      LL_Remove( VoiceNode, &VoicePool, voice );
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( voice != NULL )
+      {
+      do
+         {
+         GUSWAVE_VoiceHandle++;
+         if ( GUSWAVE_VoiceHandle < GUSWAVE_MinVoiceHandle )
+            {
+            GUSWAVE_VoiceHandle = GUSWAVE_MinVoiceHandle;
+            }
+         }
+      while( GUSWAVE_VoicePlaying( GUSWAVE_VoiceHandle ) );
+
+      voice->handle = GUSWAVE_VoiceHandle;
+      }
+
+   return( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_VoiceAvailable
+
+   Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoiceAvailable
+   (
+   int priority
+   )
+
+   {
+   VoiceNode   *voice;
+   VoiceNode   *node;
+   unsigned    flags;
+
+   if ( GUSWAVE_VoicesPlaying() < GUSWAVE_MaxVoices )
+      {
+      return( TRUE );
+      }
+
+   flags = DisableInterrupts();
+
+   node = VoiceList.start;
+   voice = node;
+   while( node != NULL )
+      {
+      if ( node->priority < voice->priority )
+         {
+         voice = node;
+         }
+
+      node = node->next;
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( priority >= voice->priority )
+      {
+      return( TRUE );
+      }
+
+   return( FALSE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetNextVOCBlock
+
+   Interperate the information of a VOC format sound file.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextVOCBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   unsigned char *ptr;
+   int            blocktype;
+   int            lastblocktype;
+   unsigned long  blocklength;
+   unsigned long  samplespeed;
+   unsigned int   tc;
+   int            packtype;
+   int            voicemode;
+   int            done;
+   unsigned       BitsPerSample;
+   unsigned       Channels;
+   unsigned       Format;
+
+   if ( voice->BlockLength > 0 )
+      {
+      voice->sound       += MAX_BLOCK_LENGTH;
+      voice->length       = min( voice->BlockLength, MAX_BLOCK_LENGTH );
+      voice->BlockLength -= voice->length;
+      return( KeepPlaying );
+      }
+
+   ptr = ( unsigned char * )voice->NextBlock;
+
+   voice->Playing = TRUE;
+
+   voicemode = 0;
+   lastblocktype = 0;
+   packtype = 0;
+
+   done = FALSE;
+   while( !done )
+      {
+      // Stop playing if we get a NULL pointer
+      if ( ptr == NULL )
+         {
+         voice->Playing = FALSE;
+         done = TRUE;
+         break;
+         }
+
+      blocktype = ( int )*ptr;
+      blocklength = ( *( unsigned long * )( ptr + 1 ) ) & 0x00ffffff;
+      ptr += 4;
+
+      switch( blocktype )
+         {
+         case 0 :
+            // End of data
+            voice->Playing = FALSE;
+            done = TRUE;
+            break;
+
+         case 1 :
+            // Sound data block
+            voice->bits = 8;
+            if ( lastblocktype != 8 )
+               {
+               tc = ( unsigned int )*ptr << 8;
+               packtype = *( ptr + 1 );
+               }
+
+            ptr += 2;
+            blocklength -= 2;
+
+            samplespeed = 256000000L / ( 65536 - tc );
+
+            // Skip packed or stereo data
+            if ( ( packtype != 0 ) || ( voicemode != 0 ) )
+               {
+               ptr += blocklength;
+               }
+            else
+               {
+               done = TRUE;
+               }
+            voicemode = 0;
+            break;
+
+         case 2 :
+            // Sound continuation block
+            samplespeed = voice->SamplingRate;
+            done = TRUE;
+            break;
+
+         case 3 :
+            // Silence
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 4 :
+            // Marker
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 5 :
+            // ASCII string
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 6 :
+            // Repeat begin
+            voice->LoopCount = *( unsigned short * )ptr;
+            ptr += blocklength;
+            voice->LoopStart = ptr;
+            break;
+
+         case 7 :
+            // Repeat end
+            ptr += blocklength;
+            if ( lastblocktype == 6 )
+               {
+               voice->LoopCount = 0;
+               }
+            else
+               {
+               if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
+                  {
+                  ptr = voice->LoopStart;
+                  if ( voice->LoopCount < 0xffff )
+                     {
+                     voice->LoopCount--;
+                     if ( voice->LoopCount == 0 )
+                        {
+                        voice->LoopStart = NULL;
+                        }
+                     }
+                  }
+               }
+            break;
+
+         case 8 :
+            // Extended block
+            voice->bits = 8;
+            tc = *( unsigned short * )ptr;
+            packtype = *( ptr + 2 );
+            voicemode = *( ptr + 3 );
+            ptr += blocklength;
+            break;
+
+         case 9 :
+            // New sound data block
+            samplespeed = *( unsigned long * )ptr;
+            BitsPerSample = ( unsigned )*( ptr + 4 );
+            Channels = ( unsigned )*( ptr + 5 );
+            Format = ( unsigned )*( unsigned short * )( ptr + 6 );
+
+            if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
+               ( Format == VOC_8BIT ) )
+               {
+               ptr += 12;
+               blocklength -= 12;
+               voice->bits  = 8;
+               done = TRUE;
+               }
+            else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
+               ( Format == VOC_16BIT ) )
+               {
+               ptr         += 12;
+               blocklength -= 12;
+               voice->bits  = 16;
+               done         = TRUE;
+               }
+            else
+               {
+               ptr += blocklength;
+               }
+            break;
+
+         default :
+            // Unknown data.  Probably not a VOC file.
+            voice->Playing = FALSE;
+            done = TRUE;
+            break;
+         }
+
+      lastblocktype = blocktype;
+      }
+
+   if ( voice->Playing )
+      {
+      voice->NextBlock    = ptr + blocklength;
+      voice->sound        = ptr;
+
+      voice->SamplingRate = samplespeed;
+      voice->RateScale    = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+      voice->length       = min( blocklength, MAX_BLOCK_LENGTH );
+      voice->BlockLength  = blocklength - voice->length;
+
+      return( KeepPlaying );
+      }
+
+   return( SoundDone );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetNextWAVBlock
+
+   Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextWAVBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   if ( voice->BlockLength <= 0 )
+      {
+      if ( voice->LoopStart == NULL )
+         {
+         voice->Playing = FALSE;
+         return( SoundDone );
+         }
+
+      voice->BlockLength = voice->LoopSize;
+      voice->NextBlock   = voice->LoopStart;
+      voice->length      = 0;
+      }
+
+   voice->sound        = voice->NextBlock;
+   voice->length       = min( voice->BlockLength, 0x8000 );
+   voice->NextBlock   += voice->length;
+   voice->BlockLength -= voice->length;
+
+   return( KeepPlaying );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetNextDemandFeedBlock
+
+   Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextDemandFeedBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   if ( voice->BlockLength > 0 )
+      {
+      voice->sound       += voice->length;
+      voice->length       = min( voice->BlockLength, 0x8000 );
+      voice->BlockLength -= voice->length;
+
+      return( KeepPlaying );
+      }
+
+   if ( voice->DemandFeed == NULL )
+      {
+      return( SoundDone );
+      }
+
+   ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
+//   voice->sound = GUS_Silence16;
+//   voice->BlockLength = 256;
+
+   voice->length       = min( voice->BlockLength, 0x8000 );
+   voice->BlockLength -= voice->length;
+
+   if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
+      {
+      return( KeepPlaying );
+      }
+   return( NoMoreData );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_Play
+
+   Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Play
+   (
+   VoiceNode *voice,
+   int angle,
+   int volume,
+   int channels
+   )
+
+   {
+   int      VoiceNumber;
+   int      type;
+   int      pan;
+   unsigned flags;
+   int ( *servicefunction )( int reason, int voice, unsigned char **buf, unsigned long *size );
+
+   type = 0;
+   if ( channels != 1 )
+      {
+      type |= TYPE_STEREO;
+      }
+
+   if ( voice->bits == 8 )
+      {
+      type |= TYPE_8BIT;
+      type |= TYPE_INVERT_MSB;
+      }
+
+   voice->GF1voice  = -1;
+
+   angle &= 31;
+   pan = GUSWAVE_PanTable[ angle ];
+   if ( GUSWAVE_SwapLeftRight )
+      {
+      pan = 15 - pan;
+      }
+
+   voice->Pan = pan;
+
+   volume = max( 0, volume );
+   volume = min( 255, volume );
+   voice->Volume = volume;
+
+   if ( !GUS_Debug )
+      {
+      servicefunction = GUSWAVE_CallBack;
+      }
+   else
+      {
+      servicefunction = GUSWAVE_DebugCallBack;
+      }
+
+   VoiceNumber = gf1_play_digital( 0, voice->sound, voice->length,
+      voice->mem, GUSWAVE_Volume - ( 255 - volume ) * 4, pan,
+      voice->RateScale, type, &GUS_HoldBuffer, servicefunction );
+
+   if ( VoiceNumber == NO_MORE_VOICES )
+      {
+      if ( GUS_Debug )
+         {
+         DB_printf( "Out of voices.\n" );
+         }
+
+      flags = DisableInterrupts();
+      LL_AddToTail( VoiceNode, &VoicePool, voice );
+      RestoreInterrupts( flags );
+
+      GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+      return( GUSWAVE_Warning );
+      }
+
+   flags = DisableInterrupts();
+   voice->GF1voice = VoiceNumber;
+   voice->Active   = TRUE;
+   LL_AddToTail( VoiceNode, &VoiceList, voice );
+   VoiceStatus[ VoiceNumber ].playing = TRUE;
+   VoiceStatus[ VoiceNumber ].Voice   = voice;
+
+   if ( GUS_Debug )
+      {
+      DB_printf( "GUS voice %d playing\n", VoiceNumber );
+      }
+
+   RestoreInterrupts( flags );
+
+   return( voice->handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_PlayVOC
+
+   Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_PlayVOC
+   (
+   char *sample,
+   int   pitchoffset,
+   int   angle,
+   int   volume,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   int handle;
+   int status;
+   playbackstatus soundstatus;
+   VoiceNode *voice;
+   unsigned flags;
+
+   // Make sure it's a valid VOC file.
+   status = strncmp( sample, "Creative Voice File", 19 );
+   if ( status != 0 )
+      {
+      // Tell multivoc that we had a bad VOC file
+      MV_ErrorCode = MV_InvalidVOCFile;
+
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidVOCFile );
+      return( GUSWAVE_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = GUSWAVE_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      if ( GUS_Debug )
+         {
+         DB_printf( "No more voices.  Skipping sound.\n" );
+         }
+      GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+      return( GUSWAVE_Warning );
+      }
+
+   voice->NextBlock   = sample + *( unsigned short int * )( sample + 0x14 );
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->BlockLength = 0;
+   voice->PitchScale  = PITCH_GetScale( pitchoffset );
+   voice->wavetype    = VOC;
+   voice->bits        = 8;
+   voice->GetSound    = GUSWAVE_GetNextVOCBlock;
+   voice->length      = 0;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+
+   soundstatus = GUSWAVE_GetNextVOCBlock( voice );
+   if ( soundstatus == SoundDone )
+      {
+      flags = DisableInterrupts();
+      LL_AddToTail( VoiceNode, &VoicePool, voice );
+      RestoreInterrupts( flags );
+
+      if ( GUS_Debug )
+         {
+         DB_printf( "Voice ended before playback.\n" );
+         }
+
+      // Tell multivoc that we had a bad VOC file
+      MV_ErrorCode = MV_InvalidVOCFile;
+
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidVOCFile );
+      return( GUSWAVE_Error );
+      }
+
+   handle = GUSWAVE_Play( voice, angle, volume, 1 );
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_PlayWAV
+
+   Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_PlayWAV
+   (
+   char *sample,
+   int   pitchoffset,
+   int   angle,
+   int   volume,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   VoiceNode *voice;
+   int        handle;
+   int        channels;
+   int        bits;
+   int        length;
+   riff_header   *riff;
+   format_header *format;
+   data_header   *data;
+
+   riff = ( riff_header * )sample;
+
+   if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
+      ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
+      ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+      return( GUSWAVE_Error );
+      }
+
+   format = ( format_header * )( riff + 1 );
+   data   = ( data_header * )( ( ( char * )format ) + riff->format_size );
+
+   if ( format->wFormatTag != 1 )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+      return( GUSWAVE_Error );
+      }
+
+   channels = format->nChannels;
+   if ( ( channels != 1 ) && ( channels != 2 ) )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+      return( GUSWAVE_Error );
+      }
+
+   bits = format->nBitsPerSample;
+   if ( ( bits != 8 ) && ( bits != 16 ) )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+      return( GUSWAVE_Error );
+      }
+
+   if ( strncmp( data->DATA, "data", 4 ) != 0 )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+      return( GUSWAVE_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = GUSWAVE_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      if ( GUS_Debug )
+         {
+         DB_printf( "No more voices.  Skipping sound.\n" );
+         }
+      GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+      return( GUSWAVE_Warning );
+      }
+
+   voice->wavetype    = WAV;
+   voice->bits        = bits;
+   voice->GetSound    = GUSWAVE_GetNextWAVBlock;
+
+   length = data->size;
+
+   voice->Playing     = TRUE;
+   voice->DemandFeed  = NULL;
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->length      = min( length, 0x8000 );
+   voice->BlockLength = length - voice->length;//  min( loopend + 1, data->size );
+   voice->sound       = ( char * )( data + 1 );
+   voice->NextBlock   = voice->sound + voice->length;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+   voice->LoopStart   = NULL;// voice->NextBlock + loopstart;
+   voice->LoopEnd     = NULL;//voice->NextBlock + min( loopend, data->size - 1 );
+   voice->LoopSize    = 0;//( voice->LoopEnd - voice->LoopStart ) + 1;
+   voice->PitchScale  = PITCH_GetScale( pitchoffset );
+   voice->SamplingRate = format->nSamplesPerSec;
+   voice->RateScale   = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+   handle = GUSWAVE_Play( voice, angle, volume, channels );
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_StartDemandFeedPlayback
+
+   Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_StartDemandFeedPlayback
+   (
+   void ( *function )( char **ptr, unsigned long *length ),
+   int   channels,
+   int   bits,
+   int   rate,
+   int   pitchoffset,
+   int   angle,
+   int   volume,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   VoiceNode *voice;
+   int        handle;
+
+   // Request a voice from the voice pool
+   voice = GUSWAVE_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      if ( GUS_Debug )
+         {
+         DB_printf( "No more voices.  Skipping sound.\n" );
+         }
+      GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+      return( GUSWAVE_Warning );
+      }
+
+   voice->wavetype    = DemandFeed;
+   voice->bits        = bits;
+   voice->GetSound    = GUSWAVE_GetNextDemandFeedBlock;
+   voice->Playing     = TRUE;
+   voice->DemandFeed  = function;
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->BlockLength = 0;
+   voice->length      = 256;
+   voice->sound       = ( bits == 8 ) ? GUS_Silence8 : ( char * )GUS_Silence16;
+   voice->NextBlock   = NULL;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+   voice->PitchScale  = PITCH_GetScale( pitchoffset );
+   voice->SamplingRate = rate;
+   voice->RateScale   = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+   handle = GUSWAVE_Play( voice, angle, volume, channels );
+
+   return( handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_SetReverseStereo
+
+   Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetReverseStereo
+   (
+   int setting
+   )
+
+   {
+   GUSWAVE_SwapLeftRight = setting;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_GetReverseStereo
+
+   Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_GetReverseStereo
+   (
+   void
+   )
+
+   {
+   return( GUSWAVE_SwapLeftRight );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_InitVoices
+
+   Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+static int GUSWAVE_InitVoices
+   (
+   void
+   )
+
+   {
+   int i;
+
+   for( i = 0; i < MAX_VOICES; i++ )
+      {
+      VoiceStatus[ i ].playing = FALSE;
+      VoiceStatus[ i ].Voice   = NULL;
+      }
+
+   VoicePool.start = NULL;
+   VoicePool.end   = NULL;
+   VoiceList.start = NULL;
+   VoiceList.end   = NULL;
+
+   for( i = 0; i < VOICES; i++ )
+      {
+      GUSWAVE_Voices[ i ].num      = -1;
+      GUSWAVE_Voices[ i ].Active   = FALSE;
+      GUSWAVE_Voices[ i ].GF1voice = -1;
+      GUSWAVE_Voices[ i ].mem      = NULL;
+      }
+
+   for( i = 0; i < VOICES; i++ )
+      {
+      GUSWAVE_Voices[ i ].num      = i;
+      GUSWAVE_Voices[ i ].Active   = FALSE;
+      GUSWAVE_Voices[ i ].GF1voice = 0;
+
+      GUSWAVE_Voices[ i ].mem = gf1_malloc( GF1BSIZE );
+      if ( GUSWAVE_Voices[ i ].mem == NULL )
+         {
+         GUSWAVE_MaxVoices = i;
+         if ( i < 1 )
+            {
+            if ( GUSMIDI_Installed )
+               {
+               GUSWAVE_SetErrorCode( GUSWAVE_UltraNoMemMIDI );
+               }
+            else
+               {
+               GUSWAVE_SetErrorCode( GUSWAVE_UltraNoMem );
+               }
+            return( GUSWAVE_Error );
+            }
+
+         break;
+         }
+
+      LL_AddToTail( VoiceNode, &VoicePool, &GUSWAVE_Voices[ i ] );
+      }
+
+   return( GUSWAVE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_SetCallBack
+
+   Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetCallBack
+   (
+   void ( *function )( unsigned long )
+   )
+
+   {
+   GUSWAVE_CallBackFunc = function;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: GUSWAVE_Init
+
+   Initializes the Gravis Ultrasound for digitized sound playback.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Init
+   (
+   int numvoices
+   )
+
+   {
+   int status;
+
+   if ( GUSWAVE_Installed )
+      {
+      GUSWAVE_Shutdown();
+      }
+
+   GUSWAVE_SetErrorCode( GUSWAVE_Ok );
+
+   status = GUS_Init();
+   if ( status != GUS_Ok )
+      {
+      GUSWAVE_SetErrorCode( GUSWAVE_GUSError );
+      return( GUSWAVE_Error );
+      }
+
+   GUS_Debug = USER_CheckParameter( "DEBUGGUS" );
+
+   GUSWAVE_MaxVoices = min( numvoices, VOICES );
+   GUSWAVE_MaxVoices = max( GUSWAVE_MaxVoices, 0 );
+
+   status = GUSWAVE_InitVoices();
+   if ( status != GUSWAVE_Ok )
+      {
+      GUS_Shutdown();
+      return( status );
+      }
+
+   GUSWAVE_SetReverseStereo( FALSE );
+
+   GUSWAVE_CallBackFunc = NULL;
+   GUSWAVE_Installed = TRUE;
+
+   return( GUSWAVE_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/guswave.h
===================================================================
--- tags/rott-1.1/rott/audiolib/guswave.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/guswave.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,75 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: GUSWAVE.H
+
+   author: James R. Dose
+   date:   March 23, 1994
+
+   Public header for for GUSWAVE.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __GUSWAVE_H
+#define __GUSWAVE_H
+
+#define GUSWAVE_MinVoiceHandle 1
+
+enum GUSWAVE_Errors
+   {
+   GUSWAVE_Warning  = -2,
+   GUSWAVE_Error    = -1,
+   GUSWAVE_Ok       = 0,
+   GUSWAVE_GUSError,
+   GUSWAVE_NotInstalled,
+   GUSWAVE_NoVoices,
+   GUSWAVE_UltraNoMem,
+   GUSWAVE_UltraNoMemMIDI,
+   GUSWAVE_VoiceNotFound,
+   GUSWAVE_InvalidVOCFile,
+   GUSWAVE_InvalidWAVFile
+   };
+
+char *GUSWAVE_ErrorString( int ErrorNumber );
+int   GUSWAVE_VoicePlaying( int handle );
+int   GUSWAVE_VoicesPlaying( void );
+int   GUSWAVE_Kill( int handle );
+int   GUSWAVE_KillAllVoices( void );
+int   GUSWAVE_SetPitch( int handle, int pitchoffset );
+int   GUSWAVE_SetPan3D( int handle, int angle, int distance );
+void  GUSWAVE_SetVolume( int volume );
+int   GUSWAVE_GetVolume( void );
+int   GUSWAVE_VoiceAvailable( int priority );
+int   GUSWAVE_PlayVOC( char *sample, int pitchoffset, int angle, int volume,
+         int priority, unsigned long callbackval );
+int   GUSWAVE_PlayWAV( char *sample, int pitchoffset, int angle, int volume,
+         int priority, unsigned long callbackval );
+int   GUSWAVE_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+         int channels, int bits, int rate, int pitchoffset, int angle,
+         int volume, int priority, unsigned long callbackval );
+void  GUSWAVE_SetCallBack( void ( *function )( unsigned long ) );
+void  GUSWAVE_SetReverseStereo( int setting );
+int   GUSWAVE_GetReverseStereo( void );
+int   GUSWAVE_Init( int numvoices );
+void  GUSWAVE_Shutdown( void );
+#pragma aux GUSWAVE_Shutdown frame;
+
+#endif

Added: tags/rott-1.1/rott/audiolib/interrup.h
===================================================================
--- tags/rott-1.1/rott/audiolib/interrup.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/interrup.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,50 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: INTERRUP.H
+
+   author: James R. Dose
+   date:   March 31, 1994
+
+   Inline functions for disabling and restoring the interrupt flag.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __INTERRUPT_H
+#define __INTERRUPT_H
+
+unsigned long DisableInterrupts( void );
+void          RestoreInterrupts( unsigned long flags );
+
+#ifdef PLAT_DOS
+#pragma aux DisableInterrupts = \
+   "pushfd",                    \
+   "pop    eax",                \
+   "cli"                        \
+   modify [ eax ];
+
+#pragma aux RestoreInterrupts = \
+   "push   eax",                \
+   "popfd"                      \
+   parm [ eax ];
+#endif
+
+#endif

Added: tags/rott-1.1/rott/audiolib/irq.c
===================================================================
--- tags/rott-1.1/rott/audiolib/irq.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/irq.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,325 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: IRQ.C
+
+   author: James R. Dose
+   date:   August 26, 1994
+
+   Low level routines to set and restore IRQ's through DPMI.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <stdlib.h>
+#include "irq.h"
+
+#define D32RealSeg(P) ( ( ( ( unsigned long )( P ) ) >> 4 ) & 0xFFFF )
+#define D32RealOff(P) ( ( ( unsigned long )( P ) ) & 0xF )
+
+typedef struct
+   {
+   unsigned long  drdi;
+   unsigned long  drsi;
+   unsigned long  drbp;
+   unsigned long  drxx;
+   unsigned long  drbx;
+   unsigned long  drdx;
+   unsigned long  drcx;
+   unsigned long  drax;
+
+   unsigned short drflags;
+   unsigned short dres;
+   unsigned short drds;
+   unsigned short drfs;
+   unsigned short drgs;
+   unsigned short drip;
+   unsigned short drcs;
+   unsigned short drsp;
+   unsigned short drss;
+   } DPMI_REGS;
+
+static DPMI_REGS rmregs = { 0 };
+static void ( __interrupt __far *IRQ_Callback )( void ) = NULL;
+
+static char *IRQ_RealModeCode = NULL;
+
+static unsigned short IRQ_CallBackSegment;
+static unsigned short IRQ_CallBackOffset;
+static unsigned short IRQ_RealModeSegment;
+static unsigned short IRQ_RealModeOffset;
+static unsigned long  IRQ_ProtectedModeOffset;
+static unsigned short IRQ_ProtectedModeSelector;
+
+static union  REGS  Regs;
+static struct SREGS SegRegs;
+
+static void *D32DosMemAlloc
+   (
+   unsigned long size
+   )
+
+   {
+   // DPMI allocate DOS memory
+   Regs.x.eax = 0x0100;
+
+   // Number of paragraphs requested
+   Regs.x.ebx = ( size + 15 ) >> 4;
+
+   int386( 0x31, &Regs, &Regs );
+
+   if ( Regs.x.cflag != 0 )
+      {
+      // Failed
+      return ( ( unsigned long )0 );
+      }
+
+   return( ( void * )( ( Regs.x.eax & 0xFFFF ) << 4  ) );
+   }
+
+// Intermediary function: DPMI calls this, making it
+// easier to write in C
+// handle 16-bit incoming stack
+
+void fixebp
+   (
+   void
+   );
+
+#pragma aux fixebp = \
+        "mov   bx,  ss" \
+        "lar   ebx, ebx" \
+        "bt    ebx, 22" \
+        "jc    bigstk" \
+        "movzx esp, sp" \
+        "mov   ebp, esp" \
+        "bigstk:" \
+modify exact [ ebx ];
+
+#pragma aux rmcallback parm [];
+
+void rmcallback
+   (
+   unsigned short _far *stkp
+   )
+
+   {
+   // "Pop" the real mode return frame so we
+   // can resume where we left off
+   rmregs.drip = *stkp++;
+   rmregs.drcs = *stkp++;
+
+   rmregs.drsp = FP_OFF(stkp);
+
+   // Call protected-mode handler
+   IRQ_Callback();
+   }
+
+static void _interrupt _cdecl callback_x
+   (
+   // regs pushed in this order by prologue
+
+   int rgs,
+   int rfs,
+   int res,
+   int rds,
+   int rdi,
+   int rsi,
+   int rbp,
+   int rsp,
+   int rbx,
+   int rdx,
+   int rcx,
+   int rax
+   )
+
+   {
+//   unsigned short _far *stkp;
+//   return;
+
+   fixebp();
+   rmcallback (MK_FP(rds, rsi));
+   }
+
+/*
+static void _interrupt _cdecl callback_x
+   (
+   // regs pushed in this order by prologue
+
+   int rgs,
+   int rfs,
+   int res,
+   int rds,
+   int rdi,
+   int rsi,
+   int rbp,
+   int rsp,
+   int rbx,
+   int rdx,
+   int rcx,
+   int rax
+   )
+
+   {
+   unsigned short _far *stkp;
+
+   fixebp();
+   stkp = MK_FP(rds, rsi);
+
+   // "Pop" the real mode return frame so we
+   // can resume where we left off
+   rmregs.drip = *stkp++;
+   rmregs.drcs = *stkp++;
+
+   rmregs.drsp = FP_OFF(stkp);
+
+   // Call protected-mode handler
+   IRQ_Callback();
+   }
+*/
+
+
+int IRQ_SetVector
+   (
+   int vector,
+   void ( __interrupt __far *function )( void )
+   )
+
+   {
+   void far *fp;
+
+   IRQ_Callback = function;
+
+   // Save the starting real-mode and protected-mode handler addresses
+
+   // DPMI get protected mode vector */
+   Regs.w.ax = 0x0204;
+   Regs.w.bx = vector;
+   int386( 0x31, &Regs, &Regs );
+   IRQ_ProtectedModeSelector = Regs.w.cx;
+   IRQ_ProtectedModeOffset = Regs.x.edx;
+
+   // DPMI get real mode vector
+   Regs.w.ax = 0x0200;
+   Regs.w.bx = vector;
+   int386( 0x31, &Regs, &Regs );
+   IRQ_RealModeSegment = Regs.w.cx;
+   IRQ_RealModeOffset = Regs.w.dx;
+
+   // Set up callback
+   // DPMI allocate real mode callback
+   Regs.w.ax = 0x0303;
+   fp = ( void far * )callback_x;
+   SegRegs.ds   = FP_SEG( fp );
+   Regs.x.esi = FP_OFF( fp );
+   fp      = ( void _far * )&rmregs;
+   SegRegs.es   = FP_SEG( fp );
+   Regs.x.edi = FP_OFF( fp );
+   int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+   IRQ_CallBackSegment = Regs.w.cx;
+   IRQ_CallBackOffset = Regs.w.dx;
+
+   if ( Regs.x.cflag != 0 )
+      {
+      return( IRQ_Error );
+      }
+
+   if ( IRQ_RealModeCode == NULL )
+      {
+      // Allocate 6 bytes of low memory for real mode interrupt handler
+      IRQ_RealModeCode = D32DosMemAlloc( 6 );
+      if ( IRQ_RealModeCode == NULL )
+         {
+         // Free callback
+         Regs.w.ax = 0x304;
+         Regs.w.cx = IRQ_CallBackSegment;
+         Regs.w.dx = IRQ_CallBackOffset;
+         int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+         return( IRQ_Error );
+         }
+      }
+
+   // Poke code (to call callback) into real mode handler
+
+   // CALL FAR PTR (callback)
+   IRQ_RealModeCode[ 0 ] = '\x9A';
+   *( ( unsigned short * )&IRQ_RealModeCode[ 1 ] ) = IRQ_CallBackOffset;
+   *( ( unsigned short * )&IRQ_RealModeCode[ 3 ] ) = IRQ_CallBackSegment;
+
+   // IRET
+   IRQ_RealModeCode[ 5 ] = '\xCF';
+
+   // Install protected mode handler
+   // DPMI set protected mode vector
+   Regs.w.ax = 0x0205;
+   Regs.w.bx = vector;
+   fp = function;
+
+   Regs.w.cx  = FP_SEG( fp );
+   Regs.x.edx = FP_OFF( fp );
+   int386( 0x31, &Regs, &Regs );
+
+   // Install callback address as real mode handler
+   // DPMI set real mode vector
+   Regs.w.ax = 0x0201;
+   Regs.w.bx = vector;
+   Regs.w.cx = D32RealSeg( IRQ_RealModeCode );
+   Regs.w.dx = D32RealOff( IRQ_RealModeCode );
+   int386( 0x31, &Regs, &Regs );
+
+   return( IRQ_Ok );
+   }
+
+int IRQ_RestoreVector
+   (
+   int vector
+   )
+
+   {
+   // Restore original interrupt handlers
+   // DPMI set real mode vector
+   Regs.w.ax = 0x0201;
+   Regs.w.bx = vector;
+   Regs.w.cx = IRQ_RealModeSegment;
+   Regs.w.dx = IRQ_RealModeOffset;
+   int386( 0x31, &Regs, &Regs );
+
+   Regs.w.ax = 0x0205;
+   Regs.w.bx = vector;
+   Regs.w.cx = IRQ_ProtectedModeSelector;
+   Regs.x.edx = IRQ_ProtectedModeOffset;
+   int386( 0x31, &Regs, &Regs );
+
+   // Free callback
+   Regs.w.ax = 0x304;
+   Regs.w.cx = IRQ_CallBackSegment;
+   Regs.w.dx = IRQ_CallBackOffset;
+   int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+   if ( Regs.x.cflag )
+      {
+      return( IRQ_Error );
+      }
+
+   return( IRQ_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/irq.h
===================================================================
--- tags/rott-1.1/rott/audiolib/irq.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/irq.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,54 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: IRQ.H
+
+   author: James R. Dose
+   date:   August 8, 1994
+
+   Public header for IRQ.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+enum IRQ_ERRORS
+   {
+   IRQ_Warning = -2,
+   IRQ_Error = -1,
+   IRQ_Ok = 0,
+   };
+
+#define VALID_IRQ( irq )  ( ( ( irq ) >= 0 ) && ( ( irq ) <= 15 ) )
+
+int IRQ_SetVector
+   (
+   int vector,
+   void ( __interrupt *function )( void )
+   );
+int IRQ_RestoreVector
+   (
+   int vector
+   );
+
+
+#endif

Added: tags/rott-1.1/rott/audiolib/leetimbr.c
===================================================================
--- tags/rott-1.1/rott/audiolib/leetimbr.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/leetimbr.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+typedef struct
+   {
+   unsigned char SAVEK[ 2 ];
+   unsigned char Level[ 2 ];
+   unsigned char Env1[ 2 ];
+   unsigned char Env2[ 2 ];
+   unsigned char Wave[ 2 ];
+   unsigned char Feedback;
+   signed   char Transpose;
+   signed   char Velocity;
+   } TIMBRE;
+
+TIMBRE ADLIB_TimbreBank[ 256 ] =
+   {
+      { { 33, 49 }, { 79, 0 }, { 242, 210 }, { 82, 115 }, { 0, 0 }, 6, 0 },
+      { { 19, 17 }, { 198, 10 }, { 242, 241 }, { 245, 245 }, { 1, 0 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 3, 18 }, { 48, 16 }, { 246, 242 }, { 25, 244 }, { 0, 0 }, 15, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 24, 129 }, { 98, 0 }, { 243, 242 }, { 230, 246 }, { 0, 0 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 23, 2 }, { 79, 16 }, { 242, 242 }, { 96, 114 }, { 0, 0 }, 8, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 178, 176 }, { 192, 134 }, { 159, 148 }, { 6, 15 }, { 1, 1 }, 9, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 178, 176 }, { 192, 128 }, { 159, 148 }, { 6, 15 }, { 1, 1 }, 9, 0 },
+      { { 130, 128 }, { 192, 134 }, { 145, 145 }, { 246, 246 }, { 1, 1 }, 9, 0 },
+      { { 36, 49 }, { 79, 27 }, { 242, 82 }, { 11, 11 }, { 0, 0 }, 14, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 35, 33 }, { 72, 0 }, { 149, 132 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 19, 49 }, { 150, 128 }, { 254, 242 }, { 33, 148 }, { 0, 0 }, 10, 0 },
+      { { 1, 17 }, { 77, 0 }, { 242, 245 }, { 83, 116 }, { 1, 1 }, 8, 0 },
+      { { 33, 40 }, { 1, 9 }, { 148, 148 }, { 25, 9 }, { 0, 0 }, 6, 0 },
+      { { 33, 40 }, { 1, 19 }, { 148, 148 }, { 25, 9 }, { 0, 0 }, 6, 0 },
+      { { 36, 194 }, { 138, 3 }, { 250, 145 }, { 111, 248 }, { 0, 0 }, 8, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 33 }, { 26, 0 }, { 241, 246 }, { 207, 72 }, { 0, 0 }, 10, 0 },
+      { { 1, 34 }, { 29, 0 }, { 183, 196 }, { 34, 55 }, { 0, 0 }, 14, 0 },
+      { { 49, 34 }, { 30, 0 }, { 242, 241 }, { 239, 104 }, { 0, 0 }, 14, 0 },
+      { { 49, 34 }, { 30, 0 }, { 242, 245 }, { 239, 120 }, { 0, 0 }, 14, 0 },
+      { { 49, 34 }, { 30, 0 }, { 242, 245 }, { 239, 120 }, { 0, 0 }, 14, 0 },
+      { { 17, 49 }, { 5, 9 }, { 249, 241 }, { 37, 52 }, { 0, 0 }, 10, 0 },
+      { { 17, 49 }, { 5, 0 }, { 249, 241 }, { 37, 52 }, { 0, 0 }, 10, 0 },
+      { { 49, 114 }, { 138, 0 }, { 213, 97 }, { 25, 27 }, { 0, 0 }, 12, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 17, 17 }, { 150, 128 }, { 165, 245 }, { 85, 179 }, { 2, 1 }, 12, 0 },
+      { { 1, 17 }, { 156, 128 }, { 128, 240 }, { 5, 6 }, { 0, 0 }, 0, 0 },
+      { { 17, 17 }, { 150, 128 }, { 165, 245 }, { 85, 179 }, { 2, 1 }, 12, 0 },
+      { { 2, 1 }, { 153, 128 }, { 245, 246 }, { 85, 83 }, { 0, 0 }, 0, 0 },
+      { { 192, 0 }, { 13, 0 }, { 165, 212 }, { 67, 35 }, { 2, 1 }, 0, 0 },
+      { { 33, 32 }, { 88, 0 }, { 194, 97 }, { 227, 22 }, { 1, 3 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 34 }, { 22, 0 }, { 176, 179 }, { 129, 44 }, { 0, 1 }, 12, 0 },
+      { { 49, 114 }, { 91, 131 }, { 244, 138 }, { 21, 5 }, { 0, 0 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+      { { 49, 97 }, { 28, 128 }, { 65, 146 }, { 11, 59 }, { 0, 0 }, 14, 0 },
+      { { 49, 241 }, { 28, 0 }, { 65, 146 }, { 11, 27 }, { 0, 0 }, 10, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 33 }, { 155, 0 }, { 97, 127 }, { 106, 10 }, { 0, 0 }, 2, 0 },
+      { { 225, 226 }, { 21, 3 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+      { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+      { { 33, 33 }, { 77, 0 }, { 84, 166 }, { 60, 28 }, { 0, 0 }, 8, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 50 }, { 79, 0 }, { 113, 82 }, { 83, 76 }, { 0, 0 }, 10, 0 },
+      { { 33, 50 }, { 79, 0 }, { 113, 82 }, { 83, 76 }, { 0, 0 }, 10, 0 },
+      { { 32, 49 }, { 78, 0 }, { 113, 82 }, { 104, 94 }, { 0, 0 }, 10, 0 },
+      { { 33, 33 }, { 75, 0 }, { 170, 143 }, { 22, 10 }, { 1, 0 }, 8, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 50, 97 }, { 154, 130 }, { 81, 162 }, { 27, 59 }, { 0, 0 }, 12, 0 },
+      { { 50, 33 }, { 192, 0 }, { 155, 114 }, { 33, 7 }, { 0, 0 }, 4, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 162 }, { 131, 141 }, { 116, 101 }, { 23, 23 }, { 0, 0 }, 7, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 225, 98 }, { 236, 0 }, { 110, 101 }, { 143, 42 }, { 0, 0 }, 14, 0 },
+      { { 50, 33 }, { 144, 0 }, { 155, 114 }, { 33, 23 }, { 0, 0 }, 4, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 245, 242 }, { 154, 128 }, { 12, 96 }, { 199, 165 }, { 0, 0 }, 13, 0 },
+      { { 98, 161 }, { 147, 0 }, { 119, 118 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+      { { 34, 33 }, { 89, 8 }, { 255, 255 }, { 3, 15 }, { 2, 0 }, 0, 0 },
+      { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 14, 14 }, { 0, 0 }, 14, 0 },
+      { { 34, 33 }, { 70, 128 }, { 134, 100 }, { 85, 24 }, { 0, 0 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 113, 114 }, { 93, 0 }, { 84, 106 }, { 1, 3 }, { 0, 0 }, 0, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 0, 17 }, { 13, 128 }, { 241, 80 }, { 255, 255 }, { 0, 0 }, 6, 0 },
+      { { 33, 97 }, { 137, 3 }, { 17, 66 }, { 51, 37 }, { 0, 0 }, 10, 0 },
+      { { 0, 49 }, { 16, 128 }, { 17, 176 }, { 239, 15 }, { 0, 0 }, 10, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 164, 97 }, { 76, 16 }, { 243, 129 }, { 115, 35 }, { 1, 0 }, 4, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 1, 1 }, { 0, 0 }, { 255, 255 }, { 7, 7 }, { 0, 0 }, 7, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 1, 221 }, { 0, 0 }, { 246, 31 }, { 0, 6 }, { 2, 3 }, 12, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 36 },
+      { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 36 },
+      { { 3, 15 }, { 0, 0 }, { 251, 245 }, { 43, 11 }, { 2, 0 }, 15, 36 },
+      { { 33, 0 }, { 128, 0 }, { 255, 249 }, { 7, 7 }, { 0, 1 }, 14, 36 },
+      { { 240, 229 }, { 192, 0 }, { 255, 251 }, { 255, 240 }, { 3, 0 }, 14, 48 },
+      { { 33, 0 }, { 128, 0 }, { 255, 248 }, { 10, 25 }, { 0, 1 }, 14, 36 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 48 },
+      { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 69 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 52 },
+      { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 48 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 55 },
+      { { 2, 5 }, { 3, 10 }, { 180, 151 }, { 4, 247 }, { 0, 0 }, 14, 57 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 58 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 60 },
+      { { 1, 221 }, { 12, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 12, 62 },
+      { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 63 },
+      { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 67 }, { 0, 2 }, 10, 70 },
+      { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 19 }, { 0, 2 }, 10, 70 },
+      { { 14, 7 }, { 6, 68 }, { 248, 244 }, { 66, 228 }, { 3, 3 }, 14, 53 },
+      { { 14, 0 }, { 64, 8 }, { 150, 183 }, { 79, 24 }, { 0, 2 }, 14, 48 },
+      { { 1, 221 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 2, 3 }, 12, 84 },
+      { { 2, 9 }, { 27, 0 }, { 245, 246 }, { 118, 214 }, { 2, 0 }, 4, 43 },
+      { { 0, 223 }, { 9, 0 }, { 246, 147 }, { 0, 67 }, { 0, 2 }, 14, 56 },
+      { { 128, 144 }, { 13, 0 }, { 248, 159 }, { 0, 4 }, { 2, 3 }, 14, 24 },
+      { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 67 }, { 0, 2 }, 10, 65 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 48 },
+      { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 51 },
+      { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 54 },
+      { { 2, 4 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 11, 42 },
+      { { 2, 4 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 11, 39 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 64 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 128, 17 }, { 0, 0 }, { 255, 111 }, { 6, 22 }, { 3, 0 }, 14, 52 },
+      { { 128, 17 }, { 0, 0 }, { 255, 79 }, { 6, 22 }, { 3, 0 }, 14, 52 },
+      { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 60 },
+      { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 66 },
+      { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 59 },
+      { { 65, 66 }, { 69, 0 }, { 252, 105 }, { 69, 5 }, { 0, 0 }, 0, 91 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 23, 2 }, { 79, 16 }, { 242, 242 }, { 96, 114 }, { 0, 0 }, 8, 109 },
+      { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 64 },
+      { { 133, 132 }, { 5, 64 }, { 249, 214 }, { 50, 165 }, { 3, 0 }, 14, 79 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+      { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 }
+   };

Added: tags/rott-1.1/rott/audiolib/linklist.h
===================================================================
--- tags/rott-1.1/rott/audiolib/linklist.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/linklist.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,118 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __linklist_h
+#define __linklist_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NewNode(type)  ((type*)SafeMalloc(sizeof(type)))
+
+
+#define LL_CreateNewLinkedList(rootnode,type,next,prev) 			\
+   { 																				\
+   (rootnode) = NewNode(type);                            		\
+   (rootnode)->prev = (rootnode);                         		\
+   (rootnode)->next = (rootnode);                         		\
+   }
+
+
+
+#define LL_AddNode(rootnode, newnode, next, prev) 			\
+   {                                              			\
+   (newnode)->next = (rootnode);                  			\
+   (newnode)->prev = (rootnode)->prev;                	\
+   (rootnode)->prev->next = (newnode);                	\
+   (rootnode)->prev = (newnode);                      	\
+   }
+
+#define LL_TransferList(oldroot,newroot,next,prev)  \
+   {                                                \
+   if ((oldroot)->prev != (oldroot))                    \
+      {                                             \
+      (oldroot)->prev->next = (newroot);                \
+      (oldroot)->next->prev = (newroot)->prev;          \
+      (newroot)->prev->next = (oldroot)->next;          \
+      (newroot)->prev = (oldroot)->prev;                \
+      (oldroot)->next = (oldroot);                      \
+      (oldroot)->prev = (oldroot);                      \
+      }                                             \
+   }
+
+#define LL_ReverseList(root,type,next,prev)              \
+   {                                                     \
+   type *newend,*trav,*tprev;                            \
+                                                         \
+   newend = (root)->next;                                  \
+   for(trav = (root)->prev; trav != newend; trav = tprev)  \
+      {                                                  \
+      tprev = trav->prev;                                \
+      LL_MoveNode(trav,newend,next,prev);                \
+      }                                                  \
+   }
+
+
+#define LL_RemoveNode(node,next,prev) \
+   {                                  \
+   (node)->prev->next = (node)->next;     \
+   (node)->next->prev = (node)->prev;     \
+   (node)->next = (node);                 \
+   (node)->prev = (node);                 \
+   }
+
+
+#define LL_SortedInsertion(rootnode,insertnode,next,prev,type,sortparm) \
+   {                                                                    \
+   type *hoya;                                                          \
+                                                                        \
+   hoya = (rootnode)->next;                                               \
+   while((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \
+      {                                                                 \
+      hoya = hoya->next;                                                \
+      }                                                                 \
+   LL_AddNode(hoya,(insertnode),next,prev);                               \
+   }
+
+#define LL_MoveNode(node,newroot,next,prev) \
+   {                                        \
+   LL_RemoveNode((node),next,prev);           \
+   LL_AddNode((newroot),(node),next,prev);      \
+   }
+
+#define LL_ListEmpty(list,next,prev) \
+   (                                 \
+   ((list)->next == (list)) &&       \
+   ((list)->prev == (list))          \
+   )
+
+#define LL_Free(list)   SafeFree(list)
+#define LL_Reset(list,next,prev)    (list)->next = (list)->prev = (list)
+#define LL_New      LL_CreateNewLinkedList
+#define LL_Remove   LL_RemoveNode
+#define LL_Add      LL_AddNode
+#define LL_Empty    LL_ListEmpty
+#define LL_Move     LL_MoveNode
+
+
+#ifdef __cplusplus
+};
+#endif
+#endif

Added: tags/rott-1.1/rott/audiolib/ll_man.c
===================================================================
--- tags/rott-1.1/rott/audiolib/ll_man.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/ll_man.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,173 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: LL_MAN.C
+
+   author: James R. Dose
+   date:   January 1, 1994
+
+   Linked list management routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#define LOCKMEMORY
+
+#include <stddef.h>
+#include "ll_man.h"
+
+#ifdef LOCKMEMORY
+#include "dpmi.h"
+#endif
+
+#define OFFSET( structure, offset ) \
+   ( *( ( char ** )&( structure )[ offset ] ) )
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define LL_LockStart LL_AddNode
+
+
+void LL_AddNode
+   (
+   char *item,
+   char **head,
+   char **tail,
+   int next,
+   int prev
+   )
+
+   {
+   OFFSET( item, prev ) = NULL;
+   OFFSET( item, next ) = *head;
+
+   if ( *head )
+      {
+      OFFSET( *head, prev ) = item;
+      }
+   else
+      {
+      *tail = item;
+      }
+
+   *head = item;
+   }
+
+void LL_RemoveNode
+   (
+   char *item,
+   char **head,
+   char **tail,
+   int next,
+   int prev
+   )
+
+   {
+   if ( OFFSET( item, prev ) == NULL )
+      {
+      *head = OFFSET( item, next );
+      }
+   else
+      {
+      OFFSET( OFFSET( item, prev ), next ) = OFFSET( item, next );
+      }
+
+   if ( OFFSET( item, next ) == NULL )
+      {
+      *tail = OFFSET( item, prev );
+      }
+   else
+      {
+      OFFSET( OFFSET( item, next ), prev ) = OFFSET( item, prev );
+      }
+
+   OFFSET( item, next ) = NULL;
+   OFFSET( item, prev ) = NULL;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: LL_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void LL_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: LL_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void LL_UnlockMemory
+   (
+   void
+   )
+
+   {
+#ifdef LOCKMEMORY
+
+   DPMI_UnlockMemoryRegion( LL_LockStart, LL_LockEnd );
+
+#endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: LL_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int LL_LockMemory
+   (
+   void
+   )
+
+   {
+
+#ifdef LOCKMEMORY
+
+   int status;
+
+   status = DPMI_LockMemoryRegion( LL_LockStart, LL_LockEnd );
+   if ( status != DPMI_Ok )
+      {
+      return( LL_Error );
+      }
+
+#endif
+
+   return( LL_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/ll_man.h
===================================================================
--- tags/rott-1.1/rott/audiolib/ll_man.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/ll_man.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,76 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: LL_MAN.H
+
+   author: James R. Dose
+   date:   February 4, 1994
+
+   Public header for LL_MAN.C.  Linked list management routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __LL_MAN_H
+#define __LL_MAN_H
+
+enum LL_Errors
+   {
+   LL_Warning = -2,
+   LL_Error   = -1,
+   LL_Ok      = 0
+   };
+
+typedef struct list
+   {
+   void *start;
+   void *end;
+   } list;
+
+void LL_AddNode( char *node, char **head, char **tail, int next, int prev );
+void LL_RemoveNode( char *node, char **head, char **tail, int next, int prev );
+void LL_UnlockMemory( void );
+int  LL_LockMemory( void );
+
+#define LL_AddToHead( type, listhead, node )         \
+    LL_AddNode( ( char * )( node ),                  \
+                ( char ** )&( ( listhead )->start ), \
+                ( char ** )&( ( listhead )->end ),   \
+                ( int )&( ( type * ) 0 )->next,      \
+                ( int )&( ( type * ) 0 )->prev )
+
+#define LL_AddToTail( type, listhead, node )         \
+    LL_AddNode( ( char * )( node ),                  \
+                ( char ** )&( ( listhead )->end ),   \
+                ( char ** )&( ( listhead )->start ), \
+                ( int )&( ( type * ) 0 )->prev,      \
+                ( int )&( ( type * ) 0 )->next )
+
+#define LL_Remove( type, listhead, node )               \
+    LL_RemoveNode( ( char * )( node ),                  \
+                   ( char ** )&( ( listhead )->start ), \
+                   ( char ** )&( ( listhead )->end ),   \
+                   ( int )&( ( type * ) 0 )->next,      \
+                   ( int )&( ( type * ) 0 )->prev )
+
+#define LL_NextNode( node )     ( ( node )->next )
+#define LL_PreviousNode( node ) ( ( node )->prev )
+
+#endif

Added: tags/rott-1.1/rott/audiolib/midi.c
===================================================================
--- tags/rott-1.1/rott/audiolib/midi.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/midi.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,2265 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MIDI.C
+
+   author: James R. Dose
+   date:   May 25, 1994
+
+   Midi song file playback routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <time.h>
+#include <dos.h>
+#include <string.h>
+#include "sndcards.h"
+#include "interrup.h"
+#include "dpmi.h"
+#include "standard.h"
+#include "task_man.h"
+#include "ll_man.h"
+#include "usrhooks.h"
+#include "music.h"
+#include "_midi.h"
+#include "midi.h"
+#include "debugio.h"
+
+extern int MUSIC_SoundDevice;
+
+static const int _MIDI_CommandLengths[ NUM_MIDI_CHANNELS ] =
+   {
+   0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0
+   };
+
+static int cdecl ( *_MIDI_RerouteFunctions[ NUM_MIDI_CHANNELS ] )
+   (
+   int event,
+   int c1,
+   int c2
+   ) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+static track *_MIDI_TrackPtr = NULL;
+static int    _MIDI_TrackMemSize;
+static int    _MIDI_NumTracks;
+
+static int _MIDI_SongActive = FALSE;
+static int _MIDI_SongLoaded = FALSE;
+static int _MIDI_Loop = FALSE;
+
+static task *_MIDI_PlayRoutine = NULL;
+
+static int  _MIDI_Division;
+static int  _MIDI_Tick    = 0;
+static int  _MIDI_Beat    = 1;
+static int  _MIDI_Measure = 1;
+static unsigned _MIDI_Time;
+static int  _MIDI_BeatsPerMeasure;
+static int  _MIDI_TicksPerBeat;
+static int  _MIDI_TimeBase;
+static long _MIDI_FPSecondsPerTick;
+static unsigned _MIDI_TotalTime;
+static int  _MIDI_TotalTicks;
+static int  _MIDI_TotalBeats;
+static int  _MIDI_TotalMeasures;
+
+static unsigned long _MIDI_PositionInTicks;
+
+static int  _MIDI_Context;
+
+static int _MIDI_ActiveTracks;
+static int _MIDI_TotalVolume = MIDI_MaxVolume;
+
+static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ];
+static int _MIDI_UserChannelVolume[ NUM_MIDI_CHANNELS ] =
+   {
+   256, 256, 256, 256, 256, 256, 256, 256,
+   256, 256, 256, 256, 256, 256, 256, 256
+   };
+
+static midifuncs *_MIDI_Funcs = NULL;
+
+static int Reset = FALSE;
+
+int MIDI_Tempo = 120;
+
+char MIDI_PatchMap[ 128 ];
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define MIDI_LockStart _MIDI_ReadNumber
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_ReadNumber
+
+   Reads a variable length number from a MIDI track.
+---------------------------------------------------------------------*/
+
+static long _MIDI_ReadNumber
+   (
+   void *from,
+   size_t size
+   )
+
+   {
+   unsigned char *FromPtr;
+   long          value;
+
+   if ( size > 4 )
+      {
+      size = 4;
+      }
+
+   FromPtr = ( unsigned char * )from;
+
+   value = 0;
+   while( size-- )
+      {
+      value <<= 8;
+      value += *FromPtr++;
+      }
+
+   return( value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_ReadDelta
+
+   Reads a variable length encoded delta delay time from the MIDI data.
+---------------------------------------------------------------------*/
+
+static long _MIDI_ReadDelta
+   (
+   track *ptr
+   )
+
+   {
+   long          value;
+   unsigned char c;
+
+   GET_NEXT_EVENT( ptr, value );
+
+   if ( value & 0x80 )
+      {
+      value &= 0x7f;
+      do
+         {
+         GET_NEXT_EVENT( ptr, c );
+         value = ( value << 7 ) + ( c & 0x7f );
+         }
+      while ( c & 0x80 );
+      }
+
+   return( value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_ResetTracks
+
+   Sets the track pointers to the beginning of the song.
+---------------------------------------------------------------------*/
+
+static void _MIDI_ResetTracks
+   (
+   void
+   )
+
+   {
+   int    i;
+   track *ptr;
+
+   _MIDI_Tick = 0;
+   _MIDI_Beat = 1;
+   _MIDI_Measure = 1;
+   _MIDI_Time = 0;
+   _MIDI_BeatsPerMeasure = 4;
+   _MIDI_TicksPerBeat = _MIDI_Division;
+   _MIDI_TimeBase = 4;
+
+   _MIDI_PositionInTicks = 0;
+   _MIDI_ActiveTracks    = 0;
+   _MIDI_Context         = 0;
+
+   ptr = _MIDI_TrackPtr;
+   for( i = 0; i < _MIDI_NumTracks; i++ )
+      {
+      ptr->pos                    = ptr->start;
+      ptr->delay                  = _MIDI_ReadDelta( ptr );
+      ptr->active                 = ptr->EMIDI_IncludeTrack;
+      ptr->RunningStatus          = 0;
+      ptr->currentcontext         = 0;
+      ptr->context[ 0 ].loopstart = ptr->start;
+      ptr->context[ 0 ].loopcount = 0;
+
+      if ( ptr->active )
+         {
+         _MIDI_ActiveTracks++;
+         }
+
+      ptr++;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_AdvanceTick
+
+   Increment tick counters.
+---------------------------------------------------------------------*/
+
+static void _MIDI_AdvanceTick
+   (
+   void
+   )
+
+   {
+   _MIDI_PositionInTicks++;
+   _MIDI_Time += _MIDI_FPSecondsPerTick;
+
+   _MIDI_Tick++;
+   while( _MIDI_Tick > _MIDI_TicksPerBeat )
+      {
+      _MIDI_Tick -= _MIDI_TicksPerBeat;
+      _MIDI_Beat++;
+      }
+   while( _MIDI_Beat > _MIDI_BeatsPerMeasure )
+      {
+      _MIDI_Beat -= _MIDI_BeatsPerMeasure;
+      _MIDI_Measure++;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_SysEx
+
+   Interpret SysEx Event.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SysEx
+   (
+   track *Track
+   )
+
+   {
+   int length;
+
+   length = _MIDI_ReadDelta( Track );
+   Track->pos += length;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_MetaEvent
+
+   Interpret Meta Event.
+---------------------------------------------------------------------*/
+
+static void _MIDI_MetaEvent
+   (
+   track *Track
+   )
+
+   {
+   int   command;
+   int   length;
+   int   denominator;
+   long  tempo;
+
+   GET_NEXT_EVENT( Track, command );
+   GET_NEXT_EVENT( Track, length );
+
+   switch( command )
+      {
+      case MIDI_END_OF_TRACK :
+         Track->active = FALSE;
+
+         _MIDI_ActiveTracks--;
+         break;
+
+      case MIDI_TEMPO_CHANGE :
+         tempo = 60000000L / _MIDI_ReadNumber( Track->pos, 3 );
+         MIDI_SetTempo( tempo );
+         break;
+
+      case MIDI_TIME_SIGNATURE :
+         if ( ( _MIDI_Tick > 0 ) || ( _MIDI_Beat > 1 ) )
+            {
+            _MIDI_Measure++;
+            }
+
+         _MIDI_Tick = 0;
+         _MIDI_Beat = 1;
+
+         _MIDI_BeatsPerMeasure = (int)*Track->pos;
+         denominator = (int)*( Track->pos + 1 );
+         _MIDI_TimeBase = 1;
+         while( denominator > 0 )
+            {
+            _MIDI_TimeBase += _MIDI_TimeBase;
+            denominator--;
+            }
+         _MIDI_TicksPerBeat = ( _MIDI_Division * 4 ) / _MIDI_TimeBase;
+         break;
+      }
+
+   Track->pos += length;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_InterpretControllerInfo
+
+   Interprets the MIDI controller info.
+---------------------------------------------------------------------*/
+
+static int _MIDI_InterpretControllerInfo
+   (
+   track *Track,
+   int   TimeSet,
+   int   channel,
+   int   c1,
+   int   c2
+   )
+
+   {
+   track *trackptr;
+   int tracknum;
+   int loopcount;
+
+   switch( c1 )
+      {
+      case MIDI_MONO_MODE_ON :
+         Track->pos++;
+         break;
+
+      case MIDI_VOLUME :
+         if ( !Track->EMIDI_VolumeChange )
+            {
+            _MIDI_SetChannelVolume( channel, c2 );
+            }
+         break;
+
+      case EMIDI_INCLUDE_TRACK :
+      case EMIDI_EXCLUDE_TRACK :
+         break;
+
+      case EMIDI_PROGRAM_CHANGE :
+         if ( Track->EMIDI_ProgramChange )
+            {
+            _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
+            }
+         break;
+
+      case EMIDI_VOLUME_CHANGE :
+         if ( Track->EMIDI_VolumeChange )
+            {
+            _MIDI_SetChannelVolume( channel, c2 );
+            }
+         break;
+
+      case EMIDI_CONTEXT_START :
+         break;
+
+      case EMIDI_CONTEXT_END :
+         if ( ( Track->currentcontext == _MIDI_Context ) ||
+            ( _MIDI_Context < 0 ) ||
+            ( Track->context[ _MIDI_Context ].pos == NULL ) )
+            {
+            break;
+            }
+
+         Track->currentcontext = _MIDI_Context;
+         Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
+         Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
+         Track->pos           = Track->context[ _MIDI_Context ].pos;
+         Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
+
+         if ( TimeSet )
+            {
+            break;
+            }
+
+         _MIDI_Time             = Track->context[ _MIDI_Context ].time;
+         _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
+         _MIDI_Tick             = Track->context[ _MIDI_Context ].tick;
+         _MIDI_Beat             = Track->context[ _MIDI_Context ].beat;
+         _MIDI_Measure          = Track->context[ _MIDI_Context ].measure;
+         _MIDI_BeatsPerMeasure  = Track->context[ _MIDI_Context ].BeatsPerMeasure;
+         _MIDI_TicksPerBeat     = Track->context[ _MIDI_Context ].TicksPerBeat;
+         _MIDI_TimeBase         = Track->context[ _MIDI_Context ].TimeBase;
+         TimeSet = TRUE;
+         break;
+
+      case EMIDI_LOOP_START :
+      case EMIDI_SONG_LOOP_START :
+         if ( c2 == 0 )
+            {
+            loopcount = EMIDI_INFINITE;
+            }
+         else
+            {
+            loopcount = c2;
+            }
+
+         if ( c1 == EMIDI_SONG_LOOP_START )
+            {
+            trackptr = _MIDI_TrackPtr;
+            tracknum = _MIDI_NumTracks;
+            }
+         else
+            {
+            trackptr = Track;
+            tracknum = 1;
+            }
+
+         while( tracknum > 0 )
+            {
+            trackptr->context[ 0 ].loopcount        = loopcount;
+            trackptr->context[ 0 ].pos              = trackptr->pos;
+            trackptr->context[ 0 ].loopstart        = trackptr->pos;
+            trackptr->context[ 0 ].RunningStatus    = trackptr->RunningStatus;
+            trackptr->context[ 0 ].active           = trackptr->active;
+            trackptr->context[ 0 ].delay            = trackptr->delay;
+            trackptr->context[ 0 ].time             = _MIDI_Time;
+            trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+            trackptr->context[ 0 ].tick             = _MIDI_Tick;
+            trackptr->context[ 0 ].beat             = _MIDI_Beat;
+            trackptr->context[ 0 ].measure          = _MIDI_Measure;
+            trackptr->context[ 0 ].BeatsPerMeasure  = _MIDI_BeatsPerMeasure;
+            trackptr->context[ 0 ].TicksPerBeat     = _MIDI_TicksPerBeat;
+            trackptr->context[ 0 ].TimeBase         = _MIDI_TimeBase;
+            trackptr++;
+            tracknum--;
+            }
+         break;
+
+      case EMIDI_LOOP_END :
+      case EMIDI_SONG_LOOP_END :
+         if ( ( c2 != EMIDI_END_LOOP_VALUE ) ||
+            ( Track->context[ 0 ].loopstart == NULL ) ||
+            ( Track->context[ 0 ].loopcount == 0 ) )
+            {
+            break;
+            }
+
+         if ( c1 == EMIDI_SONG_LOOP_END )
+            {
+            trackptr = _MIDI_TrackPtr;
+            tracknum = _MIDI_NumTracks;
+            _MIDI_ActiveTracks = 0;
+            }
+         else
+            {
+            trackptr = Track;
+            tracknum = 1;
+            _MIDI_ActiveTracks--;
+            }
+
+         while( tracknum > 0 )
+            {
+            if ( trackptr->context[ 0 ].loopcount != EMIDI_INFINITE )
+               {
+               trackptr->context[ 0 ].loopcount--;
+               }
+
+            trackptr->pos           = trackptr->context[ 0 ].loopstart;
+            trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus;
+            trackptr->delay         = trackptr->context[ 0 ].delay;
+            trackptr->active        = trackptr->context[ 0 ].active;
+            if ( trackptr->active )
+               {
+               _MIDI_ActiveTracks++;
+               }
+
+            if ( !TimeSet )
+               {
+               _MIDI_Time             = trackptr->context[ 0 ].time;
+               _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick;
+               _MIDI_Tick             = trackptr->context[ 0 ].tick;
+               _MIDI_Beat             = trackptr->context[ 0 ].beat;
+               _MIDI_Measure          = trackptr->context[ 0 ].measure;
+               _MIDI_BeatsPerMeasure  = trackptr->context[ 0 ].BeatsPerMeasure;
+               _MIDI_TicksPerBeat     = trackptr->context[ 0 ].TicksPerBeat;
+               _MIDI_TimeBase         = trackptr->context[ 0 ].TimeBase;
+               TimeSet = TRUE;
+               }
+
+            trackptr++;
+            tracknum--;
+            }
+         break;
+
+      default :
+         if ( _MIDI_Funcs->ControlChange )
+            {
+            _MIDI_Funcs->ControlChange( channel, c1, c2 );
+            }
+      }
+
+   return TimeSet;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_ServiceRoutine
+
+   Task that interperates the MIDI data.
+---------------------------------------------------------------------*/
+// NOTE: We have to use a stack frame here because of a strange bug
+// that occurs with Watcom.  This means that we cannot access Task!
+//Turned off to test if it works with Watcom 10a
+//#pragma aux _MIDI_ServiceRoutine frame;
+/*
+static void test
+   (
+   task *Task
+   )
+   {
+   _MIDI_ServiceRoutine( Task );
+   _MIDI_ServiceRoutine( Task );
+   _MIDI_ServiceRoutine( Task );
+   _MIDI_ServiceRoutine( Task );
+   }
+*/
+static void _MIDI_ServiceRoutine
+   (
+   task *Task
+   )
+
+   {
+   int   event;
+   int   channel;
+   int   command;
+   track *Track;
+   int   tracknum;
+   int   status;
+   int   c1;
+   int   c2;
+   int   TimeSet = FALSE;
+
+   if ( !_MIDI_SongActive )
+      {
+      return;
+      }
+
+   Track = _MIDI_TrackPtr;
+   tracknum = 0;
+   while( tracknum < _MIDI_NumTracks )
+      {
+      while ( ( Track->active ) && ( Track->delay == 0 ) )
+         {
+         GET_NEXT_EVENT( Track, event );
+
+         if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+            {
+            switch( event )
+               {
+               case MIDI_SYSEX :
+               case MIDI_SYSEX_CONTINUE :
+                  _MIDI_SysEx( Track );
+                  break;
+
+               case MIDI_META_EVENT :
+                  _MIDI_MetaEvent( Track );
+                  break;
+               }
+
+            if ( Track->active )
+               {
+               Track->delay = _MIDI_ReadDelta( Track );
+               }
+
+            continue;
+            }
+
+         if ( event & MIDI_RUNNING_STATUS )
+            {
+            Track->RunningStatus = event;
+            }
+         else
+            {
+            event = Track->RunningStatus;
+            Track->pos--;
+            }
+
+         channel = GET_MIDI_CHANNEL( event );
+         command = GET_MIDI_COMMAND( event );
+
+         if ( _MIDI_CommandLengths[ command ] > 0 )
+            {
+            GET_NEXT_EVENT( Track, c1 );
+            if ( _MIDI_CommandLengths[ command ] > 1 )
+               {
+               GET_NEXT_EVENT( Track, c2 );
+               }
+            }
+
+         if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+            {
+            status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
+
+            if ( status == MIDI_DONT_PLAY )
+               {
+               Track->delay = _MIDI_ReadDelta( Track );
+               continue;
+               }
+            }
+
+         switch ( command )
+            {
+            case MIDI_NOTE_OFF :
+               if ( _MIDI_Funcs->NoteOff )
+                  {
+                  _MIDI_Funcs->NoteOff( channel, c1, c2 );
+                  }
+               break;
+
+            case MIDI_NOTE_ON :
+               if ( _MIDI_Funcs->NoteOn )
+                  {
+                  _MIDI_Funcs->NoteOn( channel, c1, c2 );
+                  }
+               break;
+
+            case MIDI_POLY_AFTER_TCH :
+               if ( _MIDI_Funcs->PolyAftertouch )
+                  {
+                  _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
+                  }
+               break;
+
+            case MIDI_CONTROL_CHANGE :
+               TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
+                  channel, c1, c2 );
+               break;
+
+            case MIDI_PROGRAM_CHANGE :
+               if ( ( _MIDI_Funcs->ProgramChange ) &&
+                  ( !Track->EMIDI_ProgramChange ) )
+                  {
+                  _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c1 & 0x7f ] );
+                  }
+               break;
+
+            case MIDI_AFTER_TOUCH :
+               if ( _MIDI_Funcs->ChannelAftertouch )
+                  {
+                  _MIDI_Funcs->ChannelAftertouch( channel, c1 );
+                  }
+               break;
+
+            case MIDI_PITCH_BEND :
+               if ( _MIDI_Funcs->PitchBend )
+                  {
+                  _MIDI_Funcs->PitchBend( channel, c1, c2 );
+                  }
+               break;
+
+            default :
+               break;
+            }
+
+         Track->delay = _MIDI_ReadDelta( Track );
+         }
+
+      Track->delay--;
+      Track++;
+      tracknum++;
+
+      if ( _MIDI_ActiveTracks == 0 )
+         {
+         _MIDI_ResetTracks();
+         if ( _MIDI_Loop )
+            {
+            tracknum = 0;
+            Track = _MIDI_TrackPtr;
+            }
+         else
+            {
+            _MIDI_SongActive = FALSE;
+            break;
+            }
+         }
+      }
+
+   _MIDI_AdvanceTick();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_SendControlChange
+
+   Sends a control change to the proper device
+---------------------------------------------------------------------*/
+
+static int _MIDI_SendControlChange
+   (
+   int channel,
+   int c1,
+   int c2
+   )
+
+   {
+   int status;
+
+   if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+      {
+      status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
+         c1, c2 );
+      if ( status == MIDI_DONT_PLAY )
+         {
+         return( MIDI_Ok );
+         }
+      }
+
+   if ( _MIDI_Funcs == NULL )
+      {
+      return( MIDI_Error );
+      }
+
+   if ( _MIDI_Funcs->ControlChange == NULL )
+      {
+      return( MIDI_Error );
+      }
+
+   _MIDI_Funcs->ControlChange( channel, c1, c2 );
+
+   return( MIDI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_RerouteMidiChannel
+
+   Sets callback function to reroute MIDI commands from specified
+   function.
+---------------------------------------------------------------------*/
+
+void MIDI_RerouteMidiChannel
+   (
+   int channel,
+   int cdecl ( *function )( int event, int c1, int c2 )
+   )
+
+   {
+   if ( ( channel >= 1 ) && ( channel <= 16 ) )
+      {
+      _MIDI_RerouteFunctions[ channel - 1 ] = function;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_AllNotesOff
+
+   Sends all notes off commands on all midi channels.
+---------------------------------------------------------------------*/
+
+int MIDI_AllNotesOff
+   (
+   void
+   )
+
+   {
+   int channel;
+
+   for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+      {
+      _MIDI_SendControlChange( channel, 0x40, 0 );
+      _MIDI_SendControlChange( channel, MIDI_ALL_NOTES_OFF, 0 );
+      _MIDI_SendControlChange( channel, 0x78, 0 );
+      }
+
+   return( MIDI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_SetChannelVolume
+
+   Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SetChannelVolume
+   (
+   int channel,
+   int volume
+   )
+
+   {
+   int status;
+   int remotevolume;
+
+   _MIDI_ChannelVolume[ channel ] = volume;
+
+   if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+      {
+      remotevolume = volume * _MIDI_TotalVolume;
+      remotevolume *= _MIDI_UserChannelVolume[ channel ];
+      remotevolume /= MIDI_MaxVolume;
+      remotevolume >>= 8;
+
+      status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
+         MIDI_VOLUME, remotevolume );
+      if ( status == MIDI_DONT_PLAY )
+         {
+         return;
+         }
+      }
+
+   if ( _MIDI_Funcs == NULL )
+      {
+      return;
+      }
+
+   if ( _MIDI_Funcs->ControlChange == NULL )
+      {
+      return;
+      }
+
+   // For user volume
+   volume *= _MIDI_UserChannelVolume[ channel ];
+
+   if ( _MIDI_Funcs->SetVolume == NULL )
+      {
+      volume *= _MIDI_TotalVolume;
+      volume /= MIDI_MaxVolume;
+      }
+
+   // For user volume
+   volume >>= 8;
+
+   _MIDI_Funcs->ControlChange( channel, MIDI_VOLUME, volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetUserChannelVolume
+
+   Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+void MIDI_SetUserChannelVolume
+   (
+   int channel,
+   int volume
+   )
+
+   {
+   // Convert channel from 1-16 to 0-15
+   channel--;
+
+   volume = max( 0, volume );
+   volume = min( volume, 256 );
+
+   if ( ( channel >= 0 ) && ( channel < NUM_MIDI_CHANNELS ) )
+      {
+      _MIDI_UserChannelVolume[ channel ] = volume;
+      _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_ResetUserChannelVolume
+
+   Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+void MIDI_ResetUserChannelVolume
+   (
+   void
+   )
+
+   {
+   int channel;
+
+   for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+      {
+      _MIDI_UserChannelVolume[ channel ] = 256;
+      }
+
+   _MIDI_SendChannelVolumes();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_SendChannelVolumes
+
+   Sets the volume on all the midi channels.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SendChannelVolumes
+   (
+   void
+   )
+
+   {
+   int channel;
+
+   for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+      {
+      _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_Reset
+
+   Resets the MIDI device to General Midi defaults.
+---------------------------------------------------------------------*/
+
+int MIDI_Reset
+   (
+   void
+   )
+
+   {
+   int channel;
+   long time;
+   unsigned flags;
+
+   MIDI_AllNotesOff();
+
+   flags = DisableInterrupts();
+   _enable();
+   time = clock() + CLOCKS_PER_SEC/24;
+   while(clock() < time)
+      ;
+
+   RestoreInterrupts( flags );
+
+   for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+      {
+      _MIDI_SendControlChange( channel, MIDI_RESET_ALL_CONTROLLERS, 0 );
+      _MIDI_SendControlChange( channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB );
+      _MIDI_SendControlChange( channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB );
+      _MIDI_SendControlChange( channel, MIDI_DATAENTRY_MSB, 2 ); /* Pitch Bend Sensitivity MSB */
+      _MIDI_SendControlChange( channel, MIDI_DATAENTRY_LSB, 0 ); /* Pitch Bend Sensitivity LSB */
+      _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume;
+      }
+
+   _MIDI_SendChannelVolumes();
+
+   Reset = TRUE;
+
+   return( MIDI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetVolume
+
+   Sets the total volume of the music.
+---------------------------------------------------------------------*/
+
+int MIDI_SetVolume
+   (
+   int volume
+   )
+
+   {
+   int i;
+
+   if ( _MIDI_Funcs == NULL )
+      {
+      return( MIDI_NullMidiModule );
+      }
+
+   volume = min( MIDI_MaxVolume, volume );
+   volume = max( 0, volume );
+
+   _MIDI_TotalVolume = volume;
+
+   if ( _MIDI_Funcs->SetVolume )
+      {
+      _MIDI_Funcs->SetVolume( volume );
+
+      for( i = 0; i < NUM_MIDI_CHANNELS; i++ )
+         {
+         if ( _MIDI_RerouteFunctions[ i ] != NULL )
+            {
+            _MIDI_SetChannelVolume( i, _MIDI_ChannelVolume[ i ] );
+            }
+         }
+      }
+   else
+      {
+      _MIDI_SendChannelVolumes();
+      }
+
+   return( MIDI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_GetVolume
+
+   Returns the total volume of the music.
+---------------------------------------------------------------------*/
+
+int MIDI_GetVolume
+   (
+   void
+   )
+
+   {
+   int volume;
+
+   if ( _MIDI_Funcs == NULL )
+      {
+      return( MIDI_NullMidiModule );
+      }
+
+   if ( _MIDI_Funcs->GetVolume )
+      {
+      volume = _MIDI_Funcs->GetVolume();
+      }
+   else
+      {
+      volume = _MIDI_TotalVolume;
+      }
+
+   return( volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetContext
+
+   Sets the song context.
+---------------------------------------------------------------------*/
+
+void MIDI_SetContext
+   (
+   int context
+   )
+
+   {
+   if ( ( context > 0 ) && ( context < EMIDI_NUM_CONTEXTS ) )
+      {
+      _MIDI_Context = context;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_GetContext
+
+   Returns the current song context.
+---------------------------------------------------------------------*/
+
+int MIDI_GetContext
+   (
+   void
+   )
+
+   {
+   return _MIDI_Context;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetLoopFlag
+
+   Sets whether the song should loop when finished or not.
+---------------------------------------------------------------------*/
+
+void MIDI_SetLoopFlag
+   (
+   int loopflag
+   )
+
+   {
+   _MIDI_Loop = loopflag;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_ContinueSong
+
+   Continues playback of a paused song.
+---------------------------------------------------------------------*/
+
+void MIDI_ContinueSong
+   (
+   void
+   )
+
+   {
+   if ( _MIDI_SongLoaded )
+      {
+      _MIDI_SongActive = TRUE;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_PauseSong
+
+   Pauses playback of the current song.
+---------------------------------------------------------------------*/
+
+void MIDI_PauseSong
+   (
+   void
+   )
+
+   {
+   if ( _MIDI_SongLoaded )
+      {
+      _MIDI_SongActive = FALSE;
+      MIDI_AllNotesOff();
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SongPlaying
+
+   Returns whether a song is playing or not.
+---------------------------------------------------------------------*/
+
+int MIDI_SongPlaying
+   (
+   void
+   )
+
+   {
+   return( _MIDI_SongActive );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetMidiFuncs
+
+   Selects the routines that send the MIDI data to the music device.
+---------------------------------------------------------------------*/
+
+void MIDI_SetMidiFuncs
+   (
+   midifuncs *funcs
+   )
+
+   {
+   _MIDI_Funcs = funcs;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_StopSong
+
+   Stops playback of the currently playing song.
+---------------------------------------------------------------------*/
+
+void MIDI_StopSong
+   (
+   void
+   )
+
+   {
+   if ( _MIDI_SongLoaded )
+      {
+      TS_Terminate( _MIDI_PlayRoutine );
+
+      _MIDI_PlayRoutine = NULL;
+      _MIDI_SongActive = FALSE;
+      _MIDI_SongLoaded = FALSE;
+
+      MIDI_Reset();
+      _MIDI_ResetTracks();
+
+      if ( _MIDI_Funcs->ReleasePatches )
+         {
+         _MIDI_Funcs->ReleasePatches();
+         }
+
+      DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+      USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+      _MIDI_TrackPtr     = NULL;
+      _MIDI_NumTracks    = 0;
+      _MIDI_TrackMemSize = 0;
+
+      _MIDI_TotalTime     = 0;
+      _MIDI_TotalTicks    = 0;
+      _MIDI_TotalBeats    = 0;
+      _MIDI_TotalMeasures = 0;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_PlaySong
+
+   Begins playback of a MIDI song.
+---------------------------------------------------------------------*/
+
+int MIDI_PlaySong
+   (
+   unsigned char *song,
+   int loopflag
+   )
+
+   {
+   int    numtracks;
+   int    format;
+   long   headersize;
+   long   tracklength;
+   track *CurrentTrack;
+   unsigned char *ptr;
+   int    status;
+
+   if ( _MIDI_SongLoaded )
+      {
+      MIDI_StopSong();
+      }
+
+   _MIDI_Loop = loopflag;
+
+   if ( _MIDI_Funcs == NULL )
+      {
+      return( MIDI_NullMidiModule );
+      }
+
+   if ( *( unsigned long * )song != MIDI_HEADER_SIGNATURE )
+      {
+      return( MIDI_InvalidMidiFile );
+      }
+
+   song += 4;
+
+   headersize      = _MIDI_ReadNumber( song, 4 );
+   song += 4;
+   format          = _MIDI_ReadNumber( song, 2 );
+   _MIDI_NumTracks = _MIDI_ReadNumber( song + 2, 2 );
+   _MIDI_Division  = _MIDI_ReadNumber( song + 4, 2 );
+   if ( _MIDI_Division < 0 )
+      {
+      // If a SMPTE time division is given, just set to 96 so no errors occur
+      _MIDI_Division = 96;
+      }
+
+   if ( format > MAX_FORMAT )
+      {
+      return( MIDI_UnknownMidiFormat );
+      }
+
+   ptr = song + headersize;
+
+   if ( _MIDI_NumTracks == 0 )
+      {
+      return( MIDI_NoTracks );
+      }
+
+   _MIDI_TrackMemSize = _MIDI_NumTracks  * sizeof( track );
+   status = USRHOOKS_GetMem( &_MIDI_TrackPtr, _MIDI_TrackMemSize );
+   if ( status != USRHOOKS_Ok )
+      {
+      return( MIDI_NoMemory );
+      }
+
+   status = DPMI_LockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+   if ( status != DPMI_Ok )
+      {
+      USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+      _MIDI_TrackPtr     = NULL;
+      _MIDI_TrackMemSize = 0;
+      _MIDI_NumTracks    = 0;
+//      MIDI_SetErrorCode( MIDI_DPMI_Error );
+      return( MIDI_Error );
+      }
+
+   CurrentTrack = _MIDI_TrackPtr;
+   numtracks    = _MIDI_NumTracks;
+   while( numtracks-- )
+      {
+      if ( *( unsigned long * )ptr != MIDI_TRACK_SIGNATURE )
+         {
+         DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+
+         USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+         _MIDI_TrackPtr = NULL;
+         _MIDI_TrackMemSize = 0;
+
+         return( MIDI_InvalidTrack );
+         }
+
+      tracklength = _MIDI_ReadNumber( ptr + 4, 4 );
+      ptr += 8;
+      CurrentTrack->start = ptr;
+      ptr += tracklength;
+      CurrentTrack++;
+      }
+
+   if ( _MIDI_Funcs->GetVolume != NULL )
+      {
+      _MIDI_TotalVolume = _MIDI_Funcs->GetVolume();
+      }
+
+   _MIDI_InitEMIDI();
+
+   if ( _MIDI_Funcs->LoadPatch )
+      {
+      MIDI_LoadTimbres();
+      }
+
+   _MIDI_ResetTracks();
+
+   if ( !Reset )
+      {
+      MIDI_Reset();
+      }
+
+   Reset = FALSE;
+
+   _MIDI_PlayRoutine = TS_ScheduleTask( _MIDI_ServiceRoutine, 100, 1, NULL );
+//   _MIDI_PlayRoutine = TS_ScheduleTask( test, 100, 1, NULL );
+   MIDI_SetTempo( 120 );
+   TS_Dispatch();
+
+   _MIDI_SongLoaded = TRUE;
+   _MIDI_SongActive = TRUE;
+
+   return( MIDI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetTempo
+
+   Sets the song tempo.
+---------------------------------------------------------------------*/
+
+void MIDI_SetTempo
+   (
+   int tempo
+   )
+
+   {
+   long tickspersecond;
+
+   MIDI_Tempo = tempo;
+   tickspersecond = ( tempo * _MIDI_Division ) / 60;
+   if ( _MIDI_PlayRoutine != NULL )
+      {
+      TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond );
+//      TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond / 4 );
+      }
+   _MIDI_FPSecondsPerTick = ( 1 << TIME_PRECISION ) / tickspersecond;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_GetTempo
+
+   Returns the song tempo.
+---------------------------------------------------------------------*/
+
+int MIDI_GetTempo
+   (
+   void
+   )
+
+   {
+   return( MIDI_Tempo );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: _MIDI_ProcessNextTick
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+static int _MIDI_ProcessNextTick
+   (
+   void
+   )
+
+   {
+   int   event;
+   int   channel;
+   int   command;
+   track *Track;
+   int   tracknum;
+   int   status;
+   int   c1;
+   int   c2;
+   int   TimeSet = FALSE;
+
+   Track = _MIDI_TrackPtr;
+   tracknum = 0;
+   while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+      {
+      while ( ( Track->active ) && ( Track->delay == 0 ) )
+         {
+         GET_NEXT_EVENT( Track, event );
+
+         if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+            {
+            switch( event )
+               {
+               case MIDI_SYSEX :
+               case MIDI_SYSEX_CONTINUE :
+                  _MIDI_SysEx( Track );
+                  break;
+
+               case MIDI_META_EVENT :
+                  _MIDI_MetaEvent( Track );
+                  break;
+               }
+
+            if ( Track->active )
+               {
+               Track->delay = _MIDI_ReadDelta( Track );
+               }
+
+            continue;
+            }
+
+         if ( event & MIDI_RUNNING_STATUS )
+            {
+            Track->RunningStatus = event;
+            }
+         else
+            {
+            event = Track->RunningStatus;
+            Track->pos--;
+            }
+
+         channel = GET_MIDI_CHANNEL( event );
+         command = GET_MIDI_COMMAND( event );
+
+         if ( _MIDI_CommandLengths[ command ] > 0 )
+            {
+            GET_NEXT_EVENT( Track, c1 );
+            if ( _MIDI_CommandLengths[ command ] > 1 )
+               {
+               GET_NEXT_EVENT( Track, c2 );
+               }
+            }
+
+         if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+            {
+            status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
+
+            if ( status == MIDI_DONT_PLAY )
+               {
+               Track->delay = _MIDI_ReadDelta( Track );
+               continue;
+               }
+            }
+
+         switch ( command )
+            {
+            case MIDI_NOTE_OFF :
+               break;
+
+            case MIDI_NOTE_ON :
+               break;
+
+            case MIDI_POLY_AFTER_TCH :
+               if ( _MIDI_Funcs->PolyAftertouch )
+                  {
+                  _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
+                  }
+               break;
+
+            case MIDI_CONTROL_CHANGE :
+               TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
+                  channel, c1, c2 );
+               break;
+
+            case MIDI_PROGRAM_CHANGE :
+               if ( ( _MIDI_Funcs->ProgramChange ) &&
+                  ( !Track->EMIDI_ProgramChange ) )
+                  {
+                  _MIDI_Funcs->ProgramChange( channel, c1 );
+                  }
+               break;
+
+            case MIDI_AFTER_TOUCH :
+               if ( _MIDI_Funcs->ChannelAftertouch )
+                  {
+                  _MIDI_Funcs->ChannelAftertouch( channel, c1 );
+                  }
+               break;
+
+            case MIDI_PITCH_BEND :
+               if ( _MIDI_Funcs->PitchBend )
+                  {
+                  _MIDI_Funcs->PitchBend( channel, c1, c2 );
+                  }
+               break;
+
+            default :
+               break;
+            }
+
+         Track->delay = _MIDI_ReadDelta( Track );
+         }
+
+      Track->delay--;
+      Track++;
+      tracknum++;
+
+      if ( _MIDI_ActiveTracks == 0 )
+         {
+         break;
+         }
+      }
+
+   _MIDI_AdvanceTick();
+
+   return( TimeSet );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetSongTick
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongTick
+   (
+   unsigned long PositionInTicks
+   )
+
+   {
+   if ( !_MIDI_SongLoaded )
+      {
+      return;
+      }
+
+   MIDI_PauseSong();
+
+   if ( PositionInTicks < _MIDI_PositionInTicks )
+      {
+      _MIDI_ResetTracks();
+      MIDI_Reset();
+      }
+
+   while( _MIDI_PositionInTicks < PositionInTicks )
+      {
+      if ( _MIDI_ProcessNextTick() )
+         {
+         break;
+         }
+      if ( _MIDI_ActiveTracks == 0 )
+         {
+         _MIDI_ResetTracks();
+         if ( !_MIDI_Loop )
+            {
+            return;
+            }
+         break;
+         }
+      }
+
+   MIDI_SetVolume( _MIDI_TotalVolume );
+   MIDI_ContinueSong();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetSongTime
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongTime
+   (
+   unsigned long milliseconds
+   )
+
+   {
+   unsigned long mil;
+   unsigned long sec;
+   unsigned long newtime;
+
+   if ( !_MIDI_SongLoaded )
+      {
+      return;
+      }
+
+   MIDI_PauseSong();
+
+   mil = ( ( milliseconds % 1000 ) << TIME_PRECISION ) / 1000;
+   sec = ( milliseconds / 1000 ) << TIME_PRECISION;
+   newtime = sec + mil;
+
+   if ( newtime < _MIDI_Time )
+      {
+      _MIDI_ResetTracks();
+      MIDI_Reset();
+      }
+
+   while( _MIDI_Time < newtime )
+      {
+      if ( _MIDI_ProcessNextTick() )
+         {
+         break;
+         }
+      if ( _MIDI_ActiveTracks == 0 )
+         {
+         _MIDI_ResetTracks();
+         if ( !_MIDI_Loop )
+            {
+            return;
+            }
+         break;
+         }
+      }
+
+   MIDI_SetVolume( _MIDI_TotalVolume );
+   MIDI_ContinueSong();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_SetSongPosition
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongPosition
+   (
+   int measure,
+   int beat,
+   int tick
+   )
+
+   {
+   unsigned long pos;
+
+   if ( !_MIDI_SongLoaded )
+      {
+      return;
+      }
+
+   MIDI_PauseSong();
+
+   pos = RELATIVE_BEAT( measure, beat, tick );
+
+   if ( pos < RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) )
+      {
+      _MIDI_ResetTracks();
+      MIDI_Reset();
+      }
+
+   while( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) < pos )
+      {
+      if ( _MIDI_ProcessNextTick() )
+         {
+         break;
+         }
+      if ( _MIDI_ActiveTracks == 0 )
+         {
+         _MIDI_ResetTracks();
+         if ( !_MIDI_Loop )
+            {
+            return;
+            }
+         break;
+         }
+      }
+
+   MIDI_SetVolume( _MIDI_TotalVolume );
+   MIDI_ContinueSong();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_GetSongPosition
+
+   Returns the position of the song pointer in Measures, beats, ticks.
+---------------------------------------------------------------------*/
+
+void MIDI_GetSongPosition
+   (
+   songposition *pos
+   )
+
+   {
+   unsigned long mil;
+   unsigned long sec;
+
+   mil = ( _MIDI_Time & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
+   sec = _MIDI_Time >> TIME_PRECISION;
+   pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
+   pos->tickposition = _MIDI_PositionInTicks;
+   pos->measure      = _MIDI_Measure;
+   pos->beat         = _MIDI_Beat;
+   pos->tick         = _MIDI_Tick;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_GetSongLength
+
+   Returns the length of the song.
+---------------------------------------------------------------------*/
+
+void MIDI_GetSongLength
+   (
+   songposition *pos
+   )
+
+   {
+   unsigned long mil;
+   unsigned long sec;
+
+   mil = ( _MIDI_TotalTime & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
+   sec = _MIDI_TotalTime >> TIME_PRECISION;
+
+   pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
+   pos->measure      = _MIDI_TotalMeasures;
+   pos->beat         = _MIDI_TotalBeats;
+   pos->tick         = _MIDI_TotalTicks;
+   pos->tickposition = 0;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_InitEMIDI
+
+   Sets up the EMIDI
+---------------------------------------------------------------------*/
+
+static void _MIDI_InitEMIDI
+   (
+   void
+   )
+
+   {
+   int    event;
+   int    command;
+   int    channel;
+   int    length;
+   int    IncludeFound;
+   track *Track;
+   int    tracknum;
+   int    type;
+   int    c1;
+   int    c2;
+
+   type = EMIDI_GeneralMIDI;
+   switch( MUSIC_SoundDevice )
+      {
+      case SoundBlaster :
+         type = EMIDI_SoundBlaster;
+         break;
+
+      case ProAudioSpectrum :
+         type = EMIDI_ProAudio;
+         break;
+
+      case SoundMan16 :
+         type = EMIDI_SoundMan16;
+         break;
+
+      case Adlib :
+         type = EMIDI_Adlib;
+         break;
+
+      case GenMidi :
+         type = EMIDI_GeneralMIDI;
+         break;
+
+      case SoundCanvas :
+         type = EMIDI_SoundCanvas;
+         break;
+
+      case Awe32 :
+         type = EMIDI_AWE32;
+         break;
+
+      case WaveBlaster :
+         type = EMIDI_WaveBlaster;
+         break;
+
+      case SoundScape :
+         type = EMIDI_Soundscape;
+         break;
+
+      case UltraSound :
+         type = EMIDI_Ultrasound;
+         break;
+      }
+
+   _MIDI_ResetTracks();
+
+   _MIDI_TotalTime     = 0;
+   _MIDI_TotalTicks    = 0;
+   _MIDI_TotalBeats    = 0;
+   _MIDI_TotalMeasures = 0;
+
+   Track = _MIDI_TrackPtr;
+   tracknum = 0;
+   while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+      {
+      _MIDI_Tick = 0;
+      _MIDI_Beat = 1;
+      _MIDI_Measure = 1;
+      _MIDI_Time = 0;
+      _MIDI_BeatsPerMeasure = 4;
+      _MIDI_TicksPerBeat = _MIDI_Division;
+      _MIDI_TimeBase = 4;
+
+      _MIDI_PositionInTicks = 0;
+      _MIDI_ActiveTracks    = 0;
+      _MIDI_Context         = -1;
+
+      Track->RunningStatus = 0;
+      Track->active        = TRUE;
+
+      Track->EMIDI_ProgramChange = FALSE;
+      Track->EMIDI_VolumeChange  = FALSE;
+      Track->EMIDI_IncludeTrack  = TRUE;
+
+      memset( Track->context, 0, sizeof( Track->context ) );
+
+      while( Track->delay > 0 )
+         {
+         _MIDI_AdvanceTick();
+         Track->delay--;
+         }
+
+      IncludeFound = FALSE;
+      while ( Track->active )
+         {
+         GET_NEXT_EVENT( Track, event );
+
+         if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+            {
+            switch( event )
+               {
+               case MIDI_SYSEX :
+               case MIDI_SYSEX_CONTINUE :
+                  _MIDI_SysEx( Track );
+                  break;
+
+               case MIDI_META_EVENT :
+                  _MIDI_MetaEvent( Track );
+                  break;
+               }
+
+            if ( Track->active )
+               {
+               Track->delay = _MIDI_ReadDelta( Track );
+               while( Track->delay > 0 )
+                  {
+                  _MIDI_AdvanceTick();
+                  Track->delay--;
+                  }
+               }
+
+            continue;
+            }
+
+         if ( event & MIDI_RUNNING_STATUS )
+            {
+            Track->RunningStatus = event;
+            }
+         else
+            {
+            event = Track->RunningStatus;
+            Track->pos--;
+            }
+
+         channel = GET_MIDI_CHANNEL( event );
+         command = GET_MIDI_COMMAND( event );
+         length = _MIDI_CommandLengths[ command ];
+
+         if ( command == MIDI_CONTROL_CHANGE )
+            {
+            if ( *Track->pos == MIDI_MONO_MODE_ON )
+               {
+               length++;
+               }
+            GET_NEXT_EVENT( Track, c1 );
+            GET_NEXT_EVENT( Track, c2 );
+            length -= 2;
+
+            switch( c1 )
+               {
+               case EMIDI_LOOP_START :
+               case EMIDI_SONG_LOOP_START :
+                  if ( c2 == 0 )
+                     {
+                     Track->context[ 0 ].loopcount = EMIDI_INFINITE;
+                     }
+                  else
+                     {
+                     Track->context[ 0 ].loopcount = c2;
+                     }
+
+                  Track->context[ 0 ].pos              = Track->pos;
+                  Track->context[ 0 ].loopstart        = Track->pos;
+                  Track->context[ 0 ].RunningStatus    = Track->RunningStatus;
+                  Track->context[ 0 ].time             = _MIDI_Time;
+                  Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+                  Track->context[ 0 ].tick             = _MIDI_Tick;
+                  Track->context[ 0 ].beat             = _MIDI_Beat;
+                  Track->context[ 0 ].measure          = _MIDI_Measure;
+                  Track->context[ 0 ].BeatsPerMeasure  = _MIDI_BeatsPerMeasure;
+                  Track->context[ 0 ].TicksPerBeat     = _MIDI_TicksPerBeat;
+                  Track->context[ 0 ].TimeBase         = _MIDI_TimeBase;
+                  break;
+
+               case EMIDI_LOOP_END :
+               case EMIDI_SONG_LOOP_END :
+                  if ( c2 == EMIDI_END_LOOP_VALUE )
+                     {
+                     Track->context[ 0 ].loopstart = NULL;
+                     Track->context[ 0 ].loopcount = 0;
+                     }
+                  break;
+
+               case EMIDI_INCLUDE_TRACK :
+                  if ( EMIDI_AffectsCurrentCard( c2, type ) )
+                     {
+                     //printf( "Include track %d on card %d\n", tracknum, c2 );
+                     IncludeFound = TRUE;
+                     Track->EMIDI_IncludeTrack = TRUE;
+                     }
+                  else if ( !IncludeFound )
+                     {
+                     //printf( "Track excluded %d on card %d\n", tracknum, c2 );
+                     IncludeFound = TRUE;
+                     Track->EMIDI_IncludeTrack = FALSE;
+                     }
+                  break;
+
+               case EMIDI_EXCLUDE_TRACK :
+                  if ( EMIDI_AffectsCurrentCard( c2, type ) )
+                     {
+                     //printf( "Exclude track %d on card %d\n", tracknum, c2 );
+                     Track->EMIDI_IncludeTrack = FALSE;
+                     }
+                  break;
+
+               case EMIDI_PROGRAM_CHANGE :
+                  if ( !Track->EMIDI_ProgramChange )
+                     //printf( "Program change on track %d\n", tracknum );
+                  Track->EMIDI_ProgramChange = TRUE;
+                  break;
+
+               case EMIDI_VOLUME_CHANGE :
+                  if ( !Track->EMIDI_VolumeChange )
+                     //printf( "Volume change on track %d\n", tracknum );
+                  Track->EMIDI_VolumeChange = TRUE;
+                  break;
+
+               case EMIDI_CONTEXT_START :
+                  if ( ( c2 > 0 ) && ( c2 < EMIDI_NUM_CONTEXTS ) )
+                     {
+                     Track->context[ c2 ].pos              = Track->pos;
+                     Track->context[ c2 ].loopstart        = Track->context[ 0 ].loopstart;
+                     Track->context[ c2 ].loopcount        = Track->context[ 0 ].loopcount;
+                     Track->context[ c2 ].RunningStatus    = Track->RunningStatus;
+                     Track->context[ c2 ].time             = _MIDI_Time;
+                     Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+                     Track->context[ c2 ].tick             = _MIDI_Tick;
+                     Track->context[ c2 ].beat             = _MIDI_Beat;
+                     Track->context[ c2 ].measure          = _MIDI_Measure;
+                     Track->context[ c2 ].BeatsPerMeasure  = _MIDI_BeatsPerMeasure;
+                     Track->context[ c2 ].TicksPerBeat     = _MIDI_TicksPerBeat;
+                     Track->context[ c2 ].TimeBase         = _MIDI_TimeBase;
+                     }
+                  break;
+
+               case EMIDI_CONTEXT_END :
+                  break;
+               }
+            }
+
+         Track->pos += length;
+         Track->delay = _MIDI_ReadDelta( Track );
+
+         while( Track->delay > 0 )
+            {
+            _MIDI_AdvanceTick();
+            Track->delay--;
+            }
+         }
+
+      _MIDI_TotalTime = max( _MIDI_TotalTime, _MIDI_Time );
+      if ( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) >
+         RELATIVE_BEAT( _MIDI_TotalMeasures, _MIDI_TotalBeats,
+         _MIDI_TotalTicks ) )
+         {
+         _MIDI_TotalTicks    = _MIDI_Tick;
+         _MIDI_TotalBeats    = _MIDI_Beat;
+         _MIDI_TotalMeasures = _MIDI_Measure;
+         }
+
+      Track++;
+      tracknum++;
+      }
+
+   _MIDI_ResetTracks();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_LoadTimbres
+
+   Preloads the timbres on cards that use patch-caching.
+---------------------------------------------------------------------*/
+
+void MIDI_LoadTimbres
+   (
+   void
+   )
+
+   {
+   int    event;
+   int    command;
+   int    channel;
+   int    length;
+   int    Finished;
+   track *Track;
+   int    tracknum;
+
+   Track = _MIDI_TrackPtr;
+   tracknum = 0;
+   while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+      {
+      Finished = FALSE;
+      while ( !Finished )
+         {
+         GET_NEXT_EVENT( Track, event );
+
+         if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+            {
+            switch( event )
+               {
+               case MIDI_SYSEX :
+               case MIDI_SYSEX_CONTINUE :
+                  length = _MIDI_ReadDelta( Track );
+                  Track->pos += length;
+                  break;
+
+               case MIDI_META_EVENT :
+                  GET_NEXT_EVENT( Track, command );
+                  GET_NEXT_EVENT( Track, length );
+
+                  if ( command == MIDI_END_OF_TRACK )
+                     {
+                     Finished = TRUE;
+                     }
+
+                  Track->pos += length;
+                  break;
+               }
+
+            if ( !Finished )
+               {
+               _MIDI_ReadDelta( Track );
+               }
+
+            continue;
+            }
+
+         if ( event & MIDI_RUNNING_STATUS )
+            {
+            Track->RunningStatus = event;
+            }
+         else
+            {
+            event = Track->RunningStatus;
+            Track->pos--;
+            }
+
+         channel = GET_MIDI_CHANNEL( event );
+         command = GET_MIDI_COMMAND( event );
+         length = _MIDI_CommandLengths[ command ];
+
+         if ( command == MIDI_CONTROL_CHANGE )
+            {
+            if ( *Track->pos == MIDI_MONO_MODE_ON )
+               {
+               length++;
+               }
+
+            if ( *Track->pos == EMIDI_PROGRAM_CHANGE )
+               {
+               _MIDI_Funcs->LoadPatch( *( Track->pos + 1 ) );
+               }
+            }
+
+         if ( channel == MIDI_RHYTHM_CHANNEL )
+            {
+            if ( command == MIDI_NOTE_ON )
+               {
+               _MIDI_Funcs->LoadPatch( 128 + *Track->pos );
+               }
+            }
+         else
+            {
+            if ( command == MIDI_PROGRAM_CHANGE )
+               {
+               _MIDI_Funcs->LoadPatch( *Track->pos );
+               }
+            }
+         Track->pos += length;
+         _MIDI_ReadDelta( Track );
+         }
+      Track++;
+      tracknum++;
+      }
+
+   _MIDI_ResetTracks();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MIDI_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MIDI_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
+   DPMI_UnlockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
+      sizeof( _MIDI_CommandLengths ) );
+   DPMI_Unlock( _MIDI_TrackPtr );
+   DPMI_Unlock( _MIDI_NumTracks );
+   DPMI_Unlock( _MIDI_SongActive );
+   DPMI_Unlock( _MIDI_SongLoaded );
+   DPMI_Unlock( _MIDI_Loop );
+   DPMI_Unlock( _MIDI_PlayRoutine );
+   DPMI_Unlock( _MIDI_Division );
+   DPMI_Unlock( _MIDI_ActiveTracks );
+   DPMI_Unlock( _MIDI_TotalVolume );
+   DPMI_Unlock( _MIDI_ChannelVolume );
+   DPMI_Unlock( _MIDI_Funcs );
+   DPMI_Unlock( _MIDI_PositionInTicks );
+   DPMI_Unlock( _MIDI_Division );
+   DPMI_Unlock( _MIDI_Tick );
+   DPMI_Unlock( _MIDI_Beat );
+   DPMI_Unlock( _MIDI_Measure );
+   DPMI_Unlock( _MIDI_Time );
+   DPMI_Unlock( _MIDI_BeatsPerMeasure );
+   DPMI_Unlock( _MIDI_TicksPerBeat );
+   DPMI_Unlock( _MIDI_TimeBase );
+   DPMI_Unlock( _MIDI_FPSecondsPerTick );
+   DPMI_Unlock( _MIDI_Context );
+   DPMI_Unlock( _MIDI_TotalTime );
+   DPMI_Unlock( _MIDI_TotalTicks );
+   DPMI_Unlock( _MIDI_TotalBeats );
+   DPMI_Unlock( _MIDI_TotalMeasures );
+   DPMI_Unlock( MIDI_Tempo );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MIDI_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MIDI_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
+   status |= DPMI_LockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
+      sizeof( _MIDI_CommandLengths ) );
+   status |= DPMI_Lock( _MIDI_TrackPtr );
+   status |= DPMI_Lock( _MIDI_NumTracks );
+   status |= DPMI_Lock( _MIDI_SongActive );
+   status |= DPMI_Lock( _MIDI_SongLoaded );
+   status |= DPMI_Lock( _MIDI_Loop );
+   status |= DPMI_Lock( _MIDI_PlayRoutine );
+   status |= DPMI_Lock( _MIDI_Division );
+   status |= DPMI_Lock( _MIDI_ActiveTracks );
+   status |= DPMI_Lock( _MIDI_TotalVolume );
+   status |= DPMI_Lock( _MIDI_ChannelVolume );
+   status |= DPMI_Lock( _MIDI_Funcs );
+   status |= DPMI_Lock( _MIDI_PositionInTicks );
+   status |= DPMI_Lock( _MIDI_Division );
+   status |= DPMI_Lock( _MIDI_Tick );
+   status |= DPMI_Lock( _MIDI_Beat );
+   status |= DPMI_Lock( _MIDI_Measure );
+   status |= DPMI_Lock( _MIDI_Time );
+   status |= DPMI_Lock( _MIDI_BeatsPerMeasure );
+   status |= DPMI_Lock( _MIDI_TicksPerBeat );
+   status |= DPMI_Lock( _MIDI_TimeBase );
+   status |= DPMI_Lock( _MIDI_FPSecondsPerTick );
+   status |= DPMI_Lock( _MIDI_Context );
+   status |= DPMI_Lock( _MIDI_TotalTime );
+   status |= DPMI_Lock( _MIDI_TotalTicks );
+   status |= DPMI_Lock( _MIDI_TotalBeats );
+   status |= DPMI_Lock( _MIDI_TotalMeasures );
+   status |= DPMI_Lock( MIDI_Tempo );
+
+   if ( status != DPMI_Ok )
+      {
+      MIDI_UnlockMemory();
+//      MIDI_SetErrorCode( MIDI_DPMI_Error );
+      return( MIDI_Error );
+      }
+
+   return( MIDI_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/midi.h
===================================================================
--- tags/rott-1.1/rott/audiolib/midi.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/midi.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,98 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MIDI.H
+
+   author: James R. Dose
+   date:   May 25, 1994
+
+   Public header for MIDI.C.  Midi song file playback routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MIDI_H
+#define __MIDI_H
+
+enum MIDI_Errors
+   {
+   MIDI_Warning = -2,
+   MIDI_Error   = -1,
+   MIDI_Ok      = 0,
+   MIDI_NullMidiModule,
+   MIDI_InvalidMidiFile,
+   MIDI_UnknownMidiFormat,
+   MIDI_NoTracks,
+   MIDI_InvalidTrack,
+   MIDI_NoMemory,
+   MIDI_DPMI_Error
+   };
+
+
+#define MIDI_PASS_THROUGH 1
+#define MIDI_DONT_PLAY    0
+
+#define MIDI_MaxVolume 255
+
+extern char MIDI_PatchMap[ 128 ];
+
+typedef struct
+   {
+   void ( *NoteOff )( int channel, int key, int velocity );
+   void ( *NoteOn )( int channel, int key, int velocity );
+   void ( *PolyAftertouch )( int channel, int key, int pressure );
+   void ( *ControlChange )( int channel, int number, int value );
+   void ( *ProgramChange )( int channel, int program );
+   void ( *ChannelAftertouch )( int channel, int pressure );
+   void ( *PitchBend )( int channel, int lsb, int msb );
+   void ( *ReleasePatches )( void );
+   void ( *LoadPatch )( int number );
+   void ( *SetVolume )( int volume );
+   int  ( *GetVolume )( void );
+   } midifuncs;
+
+void MIDI_RerouteMidiChannel( int channel, int cdecl ( *function )( int event, int c1, int c2 ) );
+int  MIDI_AllNotesOff( void );
+void MIDI_SetUserChannelVolume( int channel, int volume );
+void MIDI_ResetUserChannelVolume( void );
+int  MIDI_Reset( void );
+int  MIDI_SetVolume( int volume );
+int  MIDI_GetVolume( void );
+void MIDI_SetMidiFuncs( midifuncs *funcs );
+void MIDI_SetContext( int context );
+int  MIDI_GetContext( void );
+void MIDI_SetLoopFlag( int loopflag );
+void MIDI_ContinueSong( void );
+void MIDI_PauseSong( void );
+int  MIDI_SongPlaying( void );
+void MIDI_StopSong( void );
+int  MIDI_PlaySong( unsigned char *song, int loopflag );
+void MIDI_SetTempo( int tempo );
+int  MIDI_GetTempo( void );
+void MIDI_SetSongTick( unsigned long PositionInTicks );
+void MIDI_SetSongTime( unsigned long milliseconds );
+void MIDI_SetSongPosition( int measure, int beat, int tick );
+void MIDI_GetSongPosition( songposition *pos );
+void MIDI_GetSongLength( songposition *pos );
+void MIDI_LoadTimbres( void );
+void MIDI_UnlockMemory( void );
+int  MIDI_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/mpu401.c
===================================================================
--- tags/rott-1.1/rott/audiolib/mpu401.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mpu401.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,451 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MPU401.C
+
+   author: James R. Dose
+   date:   January 1, 1994
+
+   Low level routines to support sending of MIDI data to MPU401
+   compatible MIDI interfaces.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "dpmi.h"
+#include "user.h"
+#include "mpu401.h"
+
+#define MIDI_NOTE_OFF         0x80
+#define MIDI_NOTE_ON          0x90
+#define MIDI_POLY_AFTER_TCH   0xA0
+#define MIDI_CONTROL_CHANGE   0xB0
+#define MIDI_PROGRAM_CHANGE   0xC0
+#define MIDI_AFTER_TOUCH      0xD0
+#define MIDI_PITCH_BEND       0xE0
+#define MIDI_META_EVENT       0xFF
+#define MIDI_END_OF_TRACK     0x2F
+#define MIDI_TEMPO_CHANGE     0x51
+#define MIDI_MONO_MODE_ON     0x7E
+#define MIDI_ALL_NOTES_OFF    0x7B
+
+int MPU_BaseAddr = MPU_DefaultAddress;
+
+//unsigned MPU_Delay = 500;
+//unsigned MPU_Delay = 5000;
+unsigned MPU_Delay = 0x5000;
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define MPU_LockStart MPU_SendMidi
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_SendMidi
+
+   Sends a byte of MIDI data to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_SendMidi
+   (
+   int data
+   )
+
+   {
+   int      port = MPU_BaseAddr + 1;
+   unsigned count;
+
+   count = MPU_Delay;
+   while( count > 0 )
+      {
+      // check if status port says we're ready for write
+      if ( !( inp( port ) & MPU_ReadyToWrite ) )
+         {
+         break;
+         }
+
+      count--;
+      }
+
+   port--;
+
+   // Send the midi data
+   outp( port, data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_NoteOff
+
+   Sends a full MIDI note off event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_NoteOff
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   MPU_SendMidi( MIDI_NOTE_OFF | channel );
+   MPU_SendMidi( key );
+   MPU_SendMidi( velocity );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_NoteOn
+
+   Sends a full MIDI note on event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_NoteOn
+   (
+   int channel,
+   int key,
+   int velocity
+   )
+
+   {
+   MPU_SendMidi( MIDI_NOTE_ON | channel );
+   MPU_SendMidi( key );
+   MPU_SendMidi( velocity );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_PolyAftertouch
+
+   Sends a full MIDI polyphonic aftertouch event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_PolyAftertouch
+   (
+   int channel,
+   int key,
+   int pressure
+   )
+
+   {
+   MPU_SendMidi( MIDI_POLY_AFTER_TCH | channel );
+   MPU_SendMidi( key );
+   MPU_SendMidi( pressure );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_ControlChange
+
+   Sends a full MIDI control change event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ControlChange
+   (
+   int channel,
+   int number,
+   int value
+   )
+
+   {
+   MPU_SendMidi( MIDI_CONTROL_CHANGE | channel );
+   MPU_SendMidi( number );
+   MPU_SendMidi( value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_ProgramChange
+
+   Sends a full MIDI program change event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ProgramChange
+   (
+   int channel,
+   int program
+   )
+
+   {
+   MPU_SendMidi( MIDI_PROGRAM_CHANGE | channel );
+   MPU_SendMidi( program );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_ChannelAftertouch
+
+   Sends a full MIDI channel aftertouch event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ChannelAftertouch
+   (
+   int channel,
+   int pressure
+   )
+
+   {
+   MPU_SendMidi( MIDI_AFTER_TOUCH | channel );
+   MPU_SendMidi( pressure );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_PitchBend
+
+   Sends a full MIDI pitch bend event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_PitchBend
+   (
+   int channel,
+   int lsb,
+   int msb
+   )
+
+   {
+   MPU_SendMidi( MIDI_PITCH_BEND | channel );
+   MPU_SendMidi( lsb );
+   MPU_SendMidi( msb );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_SendCommand
+
+   Sends a command to the MPU401 card.
+---------------------------------------------------------------------*/
+
+void MPU_SendCommand
+   (
+   int data
+   )
+
+   {
+   int      port = MPU_BaseAddr + 1;
+   unsigned count;
+
+   count = 0xffff;
+   while( count > 0 )
+      {
+      // check if status port says we're ready for write
+      if ( !( inp( port ) & MPU_ReadyToWrite ) )
+         {
+         break;
+         }
+      count--;
+      }
+
+   outp( port, data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_Reset
+
+   Resets the MPU401 card.
+---------------------------------------------------------------------*/
+
+int MPU_Reset
+   (
+   void
+   )
+
+   {
+   int      port = MPU_BaseAddr + 1;
+   unsigned count;
+
+   // Output "Reset" command via Command port
+   MPU_SendCommand( MPU_CmdReset );
+
+   // Wait for status port to be ready for read
+   count = 0xffff;
+   while( count > 0 )
+      {
+      if ( !( inp( port ) & MPU_ReadyToRead ) )
+         {
+         port--;
+
+         // Check for a successful reset
+         if ( inp( port ) == MPU_CmdAcknowledge )
+            {
+            return( MPU_Ok );
+            }
+
+         port++;
+         }
+      count--;
+      }
+
+   // Failed to reset : MPU-401 not detected
+   return( MPU_NotFound );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_EnterUART
+
+   Sets the MPU401 card to operate in UART mode.
+---------------------------------------------------------------------*/
+
+int MPU_EnterUART
+   (
+   void
+   )
+
+   {
+   int      port = MPU_BaseAddr + 1;
+   unsigned count;
+
+   // Output "Enter UART" command via Command port
+   MPU_SendCommand( MPU_CmdEnterUART );
+
+   // Wait for status port to be ready for read
+   count = 0xffff;
+   while( count > 0 )
+      {
+      if ( !( inp( port ) & MPU_ReadyToRead ) )
+         {
+         port--;
+
+         // Check for a successful reset
+         if ( inp( port ) == MPU_CmdAcknowledge )
+            {
+            return( MPU_Ok );
+            }
+
+         port++;
+         }
+      count--;
+      }
+
+   // Failed to reset : MPU-401 not detected
+   return( MPU_UARTFailed );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_Init
+
+   Detects and initializes the MPU401 card.
+---------------------------------------------------------------------*/
+
+int MPU_Init
+   (
+   int addr
+   )
+
+   {
+   int status;
+   int count;
+   char *ptr;
+
+   ptr = USER_GetText( "MPUDELAY" );
+   if ( ptr != NULL )
+      {
+      MPU_Delay = ( unsigned )atol( ptr );
+      }
+
+   MPU_BaseAddr = addr;
+
+   count = 4;
+   while( count > 0 )
+      {
+      status = MPU_Reset();
+      if ( status == MPU_Ok )
+         {
+         return( MPU_EnterUART() );
+         }
+      count--;
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MPU_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_UnlockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MPU_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( MPU_LockStart, MPU_LockEnd );
+   DPMI_Unlock( MPU_BaseAddr );
+   DPMI_Unlock( MPU_Delay );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MPU_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MPU_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( MPU_LockStart, MPU_LockEnd );
+   status |= DPMI_Lock( MPU_BaseAddr );
+   status |= DPMI_Lock( MPU_Delay );
+
+   if ( status != DPMI_Ok )
+      {
+      MPU_UnlockMemory();
+      return( MPU_Error );
+      }
+
+   return( MPU_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/mpu401.h
===================================================================
--- tags/rott-1.1/rott/audiolib/mpu401.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mpu401.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,61 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __MPU401_H
+#define __MPU401_H
+
+#define MPU_DefaultAddress 0x330
+
+enum MPU_ERRORS
+   {
+   MPU_Warning = -2,
+   MPU_Error = -1,
+   MPU_Ok = 0,
+   MPU_DPMI_Error
+   };
+
+#define MPU_NotFound       -1
+#define MPU_UARTFailed     -2
+
+#define MPU_ReadyToWrite   0x40
+#define MPU_ReadyToRead    0x80
+#define MPU_CmdEnterUART   0x3f
+#define MPU_CmdReset       0xff
+#define MPU_CmdAcknowledge 0xfe
+
+extern int MPU_BaseAddr;
+extern unsigned MPU_Delay;
+
+void MPU_SendCommand( int data );
+void MPU_SendMidi( int data );
+int  MPU_Reset( void );
+int  MPU_EnterUART( void );
+int  MPU_Init( int addr );
+void MPU_ResetMidi( void );
+void MPU_NoteOff( int channel, int key, int velocity );
+void MPU_NoteOn( int channel, int key, int velocity );
+void MPU_PolyAftertouch( int channel, int key, int pressure );
+void MPU_ControlChange( int channel, int number, int value );
+void MPU_ProgramChange( int channel, int program );
+void MPU_ChannelAftertouch( int channel, int pressure );
+void MPU_PitchBend( int channel, int lsb, int msb );
+void MPU_UnlockMemory( void );
+int  MPU_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/multivoc.c
===================================================================
--- tags/rott-1.1/rott/audiolib/multivoc.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/multivoc.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,3555 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MULTIVOC.C
+
+   author: James R. Dose
+   date:   December 20, 1993
+
+   Routines to provide multichannel digitized sound playback for
+   Sound Blaster compatible sound cards.
+
+   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef PLAT_DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "util.h"
+#include "dpmi.h"
+#include "usrhooks.h"
+#include "interrup.h"
+#include "dma.h"
+#include "linklist.h"
+#include "sndcards.h"
+
+#ifdef PLAT_DOS
+#include "blaster.h"
+#include "sndscape.h"
+#include "sndsrc.h"
+#include "pas16.h"
+#include "guswave.h"
+#else
+#include "dsl.h"
+#endif
+
+#include "pitch.h"
+#include "multivoc.h"
+#include "_multivc.h"
+#include "debugio.h"
+
+#define RoundFixed( fixedval, bits )            \
+        (                                       \
+          (                                     \
+            (fixedval) + ( 1 << ( (bits) - 1 ) )\
+          ) >> (bits)                           \
+        )
+
+#define IS_QUIET( ptr )  ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] )
+
+static int       MV_ReverbLevel;
+static int       MV_ReverbDelay;
+static VOLUME16 *MV_ReverbTable = NULL;
+
+//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ];
+static signed short MV_VolumeTable[ 63 + 1 ][ 256 ];
+
+//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
+static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ];
+
+static int MV_Installed   = FALSE;
+static int MV_SoundCard   = SoundBlaster;
+static int MV_TotalVolume = MV_MaxTotalVolume;
+static int MV_MaxVoices   = 1;
+static int MV_Recording;
+
+static int MV_BufferSize = MixBufferSize;
+static int MV_BufferLength;
+
+static int MV_NumberOfBuffers = NumberOfBuffers;
+
+static int MV_MixMode    = MONO_8BIT;
+static int MV_Channels   = 1;
+static int MV_Bits       = 8;
+
+static int MV_Silence    = SILENCE_8BIT;
+static int MV_SwapLeftRight = FALSE;
+
+static int MV_RequestedMixRate;
+static int MV_MixRate;
+
+static int MV_DMAChannel = -1;
+static int MV_BuffShift;
+
+static int MV_TotalMemory;
+
+static long   MV_BufferDescriptor;
+static int   MV_BufferEmpty[ NumberOfBuffers ];
+char *MV_MixBuffer[ NumberOfBuffers + 1 ];
+
+static VoiceNode *MV_Voices = NULL;
+
+static volatile VoiceNode VoiceList;
+static volatile VoiceNode VoicePool;
+
+/*static*/ int MV_MixPage      = 0;
+static int MV_VoiceHandle  = MV_MinVoiceHandle;
+
+static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
+static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL;
+static void ( *MV_MixFunction )( VoiceNode *voice, int buffer );
+
+static int MV_MaxVolume = 63;
+
+char  *MV_HarshClipTable;
+char  *MV_MixDestination;
+short *MV_LeftVolume;
+short *MV_RightVolume;
+int    MV_SampleSize = 1;
+int    MV_RightChannelOffset;
+
+unsigned long MV_MixPosition;
+
+int MV_ErrorCode = MV_Ok;
+
+#define MV_SetErrorCode( status ) \
+   MV_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: MV_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *MV_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case MV_Warning :
+      case MV_Error :
+         ErrorString = MV_ErrorString( MV_ErrorCode );
+         break;
+
+      case MV_Ok :
+         ErrorString = "Multivoc ok.";
+         break;
+
+      case MV_UnsupportedCard :
+         ErrorString = "Selected sound card is not supported by Multivoc.";
+         break;
+
+      case MV_NotInstalled :
+         ErrorString = "Multivoc not installed.";
+         break;
+
+      case MV_NoVoices :
+         ErrorString = "No free voices available to Multivoc.";
+         break;
+
+      case MV_NoMem :
+         ErrorString = "Out of memory in Multivoc.";
+         break;
+
+      case MV_VoiceNotFound :
+         ErrorString = "No voice with matching handle found.";
+         break;
+
+#ifdef PLAT_DOS
+      case MV_BlasterError :
+         ErrorString = BLASTER_ErrorString( BLASTER_Error );
+         break;
+
+      case MV_PasError :
+         ErrorString = PAS_ErrorString( PAS_Error );
+         break;
+
+      case MV_SoundScapeError :
+         ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case MV_SoundSourceError :
+         ErrorString = SS_ErrorString( SS_Error );
+         break;
+      #endif
+#endif
+
+      case MV_DPMI_Error :
+         ErrorString = "DPMI Error in Multivoc.";
+         break;
+
+      case MV_InvalidVOCFile :
+         ErrorString = "Invalid VOC file passed in to Multivoc.";
+         break;
+
+      case MV_InvalidWAVFile :
+         ErrorString = "Invalid WAV file passed in to Multivoc.";
+         break;
+
+      case MV_InvalidMixMode :
+         ErrorString = "Invalid mix mode request in Multivoc.";
+         break;
+
+      case MV_SoundSourceFailure :
+         ErrorString = "Sound Source playback failed.";
+         break;
+
+      case MV_IrqFailure :
+         ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ.";
+         break;
+
+      case MV_DMAFailure :
+         ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.";
+         break;
+
+      case MV_DMA16Failure :
+         ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.  \n"
+                       "Make sure the 16-bit DMA channel is correct.";
+         break;
+
+      case MV_NullRecordFunction :
+         ErrorString = "Null record function passed to MV_StartRecording.";
+         break;
+
+      default :
+         ErrorString = "Unknown Multivoc error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define MV_LockStart MV_Mix
+
+
+/*---------------------------------------------------------------------
+   Function: MV_Mix
+
+   Mixes the sound into the buffer.
+---------------------------------------------------------------------*/
+
+static void MV_Mix
+   (
+   VoiceNode *voice,
+   int        buffer
+   )
+
+   {
+   char          *start;
+   int            length;
+   long           voclength;
+   unsigned long  position;
+   unsigned long  rate;
+   unsigned long  FixedPointBufferSize;
+
+   if ( ( voice->length == 0 ) &&
+        ( voice->GetSound != NULL ) &&
+        ( voice->GetSound( voice ) != KeepPlaying ) )
+      {
+      return;
+      }
+
+   length               = MixBufferSize;
+   FixedPointBufferSize = voice->FixedPointBufferSize;
+
+   MV_MixDestination    = MV_MixBuffer[ buffer ];
+   MV_LeftVolume        = voice->LeftVolume;
+   MV_RightVolume       = voice->RightVolume;
+
+   if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) )
+      {
+      MV_LeftVolume      = MV_RightVolume;
+      MV_MixDestination += MV_RightChannelOffset;
+      }
+
+   // Add this voice to the mix
+   while( length > 0 )
+      {
+      start    = voice->sound;
+      rate     = voice->RateScale;
+      position = voice->position;
+
+      // Check if the last sample in this buffer would be
+      // beyond the length of the sample block
+      if ( ( position + FixedPointBufferSize ) >= voice->length )
+         {
+         if ( position < voice->length )
+            {
+            voclength = ( voice->length - position + rate - 1 ) / rate;
+            }
+         else
+            {
+            voice->GetSound( voice );
+            return;
+            }
+         }
+      else
+         {
+         voclength = length;
+         }
+
+      voice->mix( position, rate, start, voclength );
+
+      if ( voclength & 1 )
+         {
+         MV_MixPosition += rate;
+         voclength -= 1;
+         }
+      voice->position = MV_MixPosition;
+
+      length -= voclength;
+
+      if ( voice->position >= voice->length )
+         {
+         // Get the next block of sound
+         if ( voice->GetSound( voice ) != KeepPlaying )
+            {
+            return;
+            }
+
+         if ( length > 0 )
+            {
+            // Get the position of the last sample in the buffer
+            FixedPointBufferSize = voice->RateScale * ( length - 1 );
+            }
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayVoice
+
+   Adds a voice to the play list.
+---------------------------------------------------------------------*/
+
+void MV_PlayVoice
+   (
+   VoiceNode *voice
+   )
+
+   {
+   unsigned flags;
+
+   flags = DisableInterrupts();
+   LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority );
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StopVoice
+
+   Removes the voice from the play list and adds it to the free list.
+---------------------------------------------------------------------*/
+
+void MV_StopVoice
+   (
+   VoiceNode *voice
+   )
+
+   {
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   // move the voice from the play list to the free list
+   LL_Remove( voice, next, prev );
+   LL_Add( (VoiceNode *)&VoicePool, voice, next, prev );
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_ServiceVoc
+
+   Starts playback of the waiting buffer and mixes the next one.
+---------------------------------------------------------------------*/
+
+// static int backcolor = 1;
+
+void MV_ServiceVoc
+   (
+   void
+   )
+
+   {
+   VoiceNode *voice;
+   VoiceNode *next;
+   char      *buffer;
+
+#ifdef PLAT_DOS
+   if ( MV_DMAChannel >= 0 )
+      {
+      // Get the currently playing buffer
+      buffer = ( char * )DMA_GetCurrentPos( MV_DMAChannel );
+      MV_MixPage   = ( unsigned )( buffer - MV_MixBuffer[ 0 ] );
+      MV_MixPage >>= MV_BuffShift;
+      }
+#endif
+
+   // Toggle which buffer we'll mix next
+   MV_MixPage++;
+   if ( MV_MixPage >= MV_NumberOfBuffers )
+      {
+      MV_MixPage -= MV_NumberOfBuffers;
+      }
+
+   if ( MV_ReverbLevel == 0 )
+      {
+      // Initialize buffer
+      //Commented out so that the buffer is always cleared.
+      //This is so the guys at Echo Speech can mix into the
+      //buffer even when no sounds are playing.
+      //if ( !MV_BufferEmpty[ MV_MixPage ] )
+         {
+         ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 );
+         if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+            {
+            ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset,
+               MV_Silence, MV_BufferSize >> 2 );
+            }
+         MV_BufferEmpty[ MV_MixPage ] = TRUE;
+         }
+      }
+   else
+      {
+      char *end;
+      char *source;
+      char *dest;
+      int   count;
+      int   length;
+
+      end = MV_MixBuffer[ 0 ] + MV_BufferLength;;
+      dest = MV_MixBuffer[ MV_MixPage ];
+      source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay;
+      if ( source < MV_MixBuffer[ 0 ] )
+         {
+         source += MV_BufferLength;
+         }
+
+      length = MV_BufferSize;
+      while( length > 0 )
+         {
+         count = length;
+         if ( source + count > end )
+            {
+            count = end - source;
+            }
+
+         if ( MV_Bits == 16 )
+            {
+            if ( MV_ReverbTable != NULL )
+               {
+               MV_16BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count / 2 );
+               if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+                  {
+                  MV_16BitReverb( source + MV_RightChannelOffset,
+                     dest + MV_RightChannelOffset, (const VOLUME16 *)MV_ReverbTable, count / 2 );
+                  }
+               }
+            else
+               {
+               MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel );
+               if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+                  {
+                  MV_16BitReverbFast( source + MV_RightChannelOffset,
+                     dest + MV_RightChannelOffset, count / 2, MV_ReverbLevel );
+                  }
+               }
+            }
+         else
+            {
+            if ( MV_ReverbTable != NULL )
+               {
+               MV_8BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count );
+               if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+                  {
+                  MV_8BitReverb( source + MV_RightChannelOffset,
+                     dest + MV_RightChannelOffset, (const VOLUME16 *)MV_ReverbTable, count );
+                  }
+               }
+            else
+               {
+               MV_8BitReverbFast( source, dest, count, MV_ReverbLevel );
+               if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+                  {
+                  MV_8BitReverbFast( source + MV_RightChannelOffset,
+                     dest + MV_RightChannelOffset, count, MV_ReverbLevel );
+                  }
+               }
+            }
+
+         // if we go through the loop again, it means that we've wrapped around the buffer
+         source  = MV_MixBuffer[ 0 ];
+         dest   += count;
+         length -= count;
+         }
+      }
+
+   // Play any waiting voices
+   for( voice = VoiceList.next; voice != &VoiceList; voice = next )
+      {
+//      if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) )
+//         {
+//         SetBorderColor(backcolor++);
+//         break;
+//         }
+
+      MV_BufferEmpty[ MV_MixPage ] = FALSE;
+
+      MV_MixFunction( voice, MV_MixPage );
+
+      next = voice->next;
+
+      // Is this voice done?
+      if ( !voice->Playing )
+         {
+         MV_StopVoice( voice );
+
+         if ( MV_CallBackFunc )
+            {
+            MV_CallBackFunc( voice->callbackval );
+            }
+         }
+      }
+   }
+
+
+int leftpage  = -1;
+int rightpage = -1;
+
+void MV_ServiceGus( char **ptr, unsigned long *length )
+   {
+   if ( leftpage == MV_MixPage )
+      {
+      MV_ServiceVoc();
+      }
+
+   leftpage = MV_MixPage;
+
+   *ptr = MV_MixBuffer[ MV_MixPage ];
+   *length = MV_BufferSize;
+   }
+
+void MV_ServiceRightGus( char **ptr, unsigned long *length )
+   {
+   if ( rightpage == MV_MixPage )
+      {
+      MV_ServiceVoc();
+      }
+
+   rightpage = MV_MixPage;
+
+   *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset;
+   *length = MV_BufferSize;
+   }
+
+/*---------------------------------------------------------------------
+   Function: MV_GetNextVOCBlock
+
+   Interperate the information of a VOC format sound file.
+---------------------------------------------------------------------*/
+static __inline unsigned int get_le32(void *p0)
+{
+	//unsigned char *p = p0;
+	//return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+	unsigned int val = *((unsigned int *) p0);
+	return(BUILDSWAP_INTEL32(val));
+}
+
+static __inline unsigned int get_le16(void *p0)
+{
+	//unsigned char *p = p0;
+	//return p[0] | (p[1]<<8);
+	unsigned short val = *((unsigned short *) p0);
+	return( (unsigned int) (BUILDSWAP_INTEL16(val)) );
+}
+
+playbackstatus MV_GetNextVOCBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   unsigned char *ptr;
+   int            blocktype=0;
+   int            lastblocktype=0;
+   unsigned long  blocklength=0l;
+   unsigned long  samplespeed=0l;
+   unsigned int   tc=0;
+   int            packtype=0;
+   int            voicemode=0;
+   int            done=0;
+   unsigned       BitsPerSample;
+   unsigned       Channels;
+   unsigned       Format;
+
+   if ( voice->BlockLength > 0 )
+      {
+      voice->position    -= voice->length;
+      voice->sound       += voice->length >> 16;
+      if ( voice->bits == 16 )
+         {
+         voice->sound += voice->length >> 16;
+         }
+      voice->length       = min( voice->BlockLength, 0x8000 );
+      voice->BlockLength -= voice->length;
+      voice->length     <<= 16;
+      return( KeepPlaying );
+      }
+
+   if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) &&
+      ( voice->LoopStart != NULL ) )
+      {
+      voice->BlockLength  = voice->LoopSize;
+      voice->sound        = voice->LoopStart;
+      voice->position     = 0;
+      voice->length       = min( voice->BlockLength, 0x8000 );
+      voice->BlockLength -= voice->length;
+      voice->length     <<= 16;
+      return( KeepPlaying );
+      }
+
+   ptr = ( unsigned char * )voice->NextBlock;
+
+   voice->Playing = TRUE;
+
+   voicemode = 0;
+   lastblocktype = 0;
+   packtype = 0;
+
+   done = FALSE;
+   while( !done )
+      {
+      // Stop playing if we get a NULL pointer
+      if ( ptr == NULL )
+         {
+         voice->Playing = FALSE;
+         done = TRUE;
+         break;
+         }
+
+      {
+      unsigned tmp = get_le32(ptr);
+      blocktype = tmp&255;
+      blocklength = tmp>>8;
+      }
+      ptr += 4;
+
+      switch( blocktype )
+         {
+         case 0 :
+            // End of data
+            if ( ( voice->LoopStart == NULL ) ||
+               ( (unsigned char *)voice->LoopStart >= ( ptr - 4 ) ) )
+               {
+               voice->Playing = FALSE;
+               done = TRUE;
+               }
+            else
+               {
+               voice->BlockLength  = ( ptr - 4 ) - (unsigned char *)voice->LoopStart;
+               voice->sound        = voice->LoopStart;
+               voice->position     = 0;
+               voice->length       = min( voice->BlockLength, 0x8000 );
+               voice->BlockLength -= voice->length;
+               voice->length     <<= 16;
+               return( KeepPlaying );
+               }
+            break;
+
+         case 1 :
+            // Sound data block
+            voice->bits  = 8;
+            if ( lastblocktype != 8 )
+               {
+               tc = ( unsigned int )*ptr << 8;
+               packtype = *( ptr + 1 );
+               }
+
+            ptr += 2;
+            blocklength -= 2;
+
+            samplespeed = 256000000L / ( 65536 - tc );
+
+            // Skip packed or stereo data
+            if ( ( packtype != 0 ) || ( voicemode != 0 ) )
+               {
+               ptr += blocklength;
+               }
+            else
+               {
+               done = TRUE;
+               }
+            voicemode = 0;
+            break;
+
+         case 2 :
+            // Sound continuation block
+            samplespeed = voice->SamplingRate;
+            done = TRUE;
+            break;
+
+         case 3 :
+            // Silence
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 4 :
+            // Marker
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 5 :
+            // ASCII string
+            // Not implimented.
+            ptr += blocklength;
+            break;
+
+         case 6 :
+            // Repeat begin
+            if ( voice->LoopEnd == NULL )
+               {
+               voice->LoopCount = get_le16(ptr);
+               voice->LoopStart = ptr + blocklength;
+               }
+            ptr += blocklength;
+            break;
+
+         case 7 :
+            // Repeat end
+            ptr += blocklength;
+            if ( lastblocktype == 6 )
+               {
+               voice->LoopCount = 0;
+               }
+            else
+               {
+               if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
+                  {
+                  ptr = voice->LoopStart;
+                  if ( voice->LoopCount < 0xffff )
+                     {
+                     voice->LoopCount--;
+                     if ( voice->LoopCount == 0 )
+                        {
+                        voice->LoopStart = NULL;
+                        }
+                     }
+                  }
+               }
+            break;
+
+         case 8 :
+            // Extended block
+            voice->bits  = 8;
+            tc = get_le16(ptr);
+            packtype = *( ptr + 2 );
+            voicemode = *( ptr + 3 );
+            ptr += blocklength;
+            break;
+
+         case 9 :
+            // New sound data block
+            samplespeed = get_le32(ptr);
+            BitsPerSample = ptr[4];
+            Channels = ptr[5];
+            Format = get_le16(ptr+6);
+
+            if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
+               ( Format == VOC_8BIT ) )
+               {
+               ptr         += 12;
+               blocklength -= 12;
+               voice->bits  = 8;
+               done         = TRUE;
+               }
+            else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
+               ( Format == VOC_16BIT ) )
+               {
+               ptr         += 12;
+               blocklength -= 12;
+               voice->bits  = 16;
+               done         = TRUE;
+               }
+            else
+               {
+               ptr += blocklength;
+               }
+            break;
+
+         default :
+            // Unknown data.  Probably not a VOC file.
+            voice->Playing = FALSE;
+            done = TRUE;
+            break;
+         }
+
+      lastblocktype = blocktype;
+      }
+
+   if ( voice->Playing )
+      {
+      voice->NextBlock    = ptr + blocklength;
+      voice->sound        = ptr;
+
+      voice->SamplingRate = samplespeed;
+      voice->RateScale    = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
+
+      // Multiply by MixBufferSize - 1
+      voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
+         voice->RateScale;
+
+      if ( voice->LoopEnd != NULL )
+         {
+         if ( blocklength > ( unsigned long )voice->LoopEnd )
+            {
+            blocklength = ( unsigned long )voice->LoopEnd;
+            }
+         else
+            {
+            voice->LoopEnd = ( char * )blocklength;
+            }
+
+         voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart;
+         voice->LoopEnd   = voice->sound + ( unsigned long )voice->LoopEnd;
+         voice->LoopSize  = voice->LoopEnd - voice->LoopStart;
+         }
+
+      if ( voice->bits == 16 )
+         {
+         blocklength /= 2;
+         }
+
+      voice->position     = 0;
+      voice->length       = min( blocklength, 0x8000 );
+      voice->BlockLength  = blocklength - voice->length;
+      voice->length     <<= 16;
+
+      MV_SetVoiceMixMode( voice );
+
+      return( KeepPlaying );
+      }
+
+   return( NoMoreData );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetNextDemandFeedBlock
+
+   Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextDemandFeedBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   if ( voice->BlockLength > 0 )
+      {
+      voice->position    -= voice->length;
+      voice->sound       += voice->length >> 16;
+      voice->length       = min( voice->BlockLength, 0x8000 );
+      voice->BlockLength -= voice->length;
+      voice->length     <<= 16;
+
+      return( KeepPlaying );
+      }
+
+   if ( voice->DemandFeed == NULL )
+      {
+      return( NoMoreData );
+      }
+
+   voice->position     = 0;
+   ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
+   voice->length       = min( voice->BlockLength, 0x8000 );
+   voice->BlockLength -= voice->length;
+   voice->length     <<= 16;
+
+   if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
+      {
+      return( KeepPlaying );
+      }
+   return( NoMoreData );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetNextRawBlock
+
+   Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextRawBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   if ( voice->BlockLength <= 0 )
+      {
+      if ( voice->LoopStart == NULL )
+         {
+         voice->Playing = FALSE;
+         return( NoMoreData );
+         }
+
+      voice->BlockLength = voice->LoopSize;
+      voice->NextBlock   = voice->LoopStart;
+      voice->length = 0;
+      voice->position = 0;
+      }
+
+   voice->sound        = voice->NextBlock;
+   voice->position    -= voice->length;
+   voice->length       = min( voice->BlockLength, 0x8000 );
+   voice->NextBlock   += voice->length;
+   if ( voice->bits == 16 )
+      {
+      voice->NextBlock += voice->length;
+      }
+   voice->BlockLength -= voice->length;
+   voice->length     <<= 16;
+
+   return( KeepPlaying );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetNextWAVBlock
+
+   Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextWAVBlock
+   (
+   VoiceNode *voice
+   )
+
+   {
+   if ( voice->BlockLength <= 0 )
+      {
+      if ( voice->LoopStart == NULL )
+         {
+         voice->Playing = FALSE;
+         return( NoMoreData );
+         }
+
+      voice->BlockLength = voice->LoopSize;
+      voice->NextBlock   = voice->LoopStart;
+      voice->length      = 0;
+      voice->position    = 0;
+      }
+
+   voice->sound        = voice->NextBlock;
+   voice->position    -= voice->length;
+   voice->length       = min( voice->BlockLength, 0x8000 );
+   voice->NextBlock   += voice->length;
+   if ( voice->bits == 16 )
+      {
+      voice->NextBlock += voice->length;
+      }
+   voice->BlockLength -= voice->length;
+   voice->length     <<= 16;
+
+   return( KeepPlaying );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_ServiceRecord
+
+   Starts recording of the waiting buffer.
+---------------------------------------------------------------------*/
+
+static void MV_ServiceRecord
+   (
+   void
+   )
+
+   {
+   if ( MV_RecordFunc )
+      {
+      MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize,
+         MixBufferSize );
+      }
+
+   // Toggle which buffer we'll mix next
+   MV_MixPage++;
+   if ( MV_MixPage >= NumberOfBuffers )
+      {
+      MV_MixPage = 0;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetVoice
+
+   Locates the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+VoiceNode *MV_GetVoice
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned  flags;
+
+   flags = DisableInterrupts();
+
+   for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
+      {
+      if ( handle == voice->handle )
+         {
+         break;
+         }
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( voice == &VoiceList )
+      {
+      MV_SetErrorCode( MV_VoiceNotFound );
+      
+      // SBF - should this return null?
+      return NULL;
+      }
+
+   return( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_VoicePlaying
+
+   Checks if the voice associated with the specified handle is
+   playing.
+---------------------------------------------------------------------*/
+
+int MV_VoicePlaying
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( FALSE );
+      }
+
+   voice = MV_GetVoice( handle );
+
+   if ( voice == NULL )
+      {
+      return( FALSE );
+      }
+
+   return( TRUE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_KillAllVoices
+
+   Stops output of all currently active voices.
+---------------------------------------------------------------------*/
+
+int MV_KillAllVoices
+   (
+   void
+   )
+
+   {
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   // Remove all the voices from the list
+   while( VoiceList.next != &VoiceList )
+      {
+      MV_Kill( VoiceList.next->handle );
+      }
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_Kill
+
+   Stops output of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_Kill
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned  flags;
+   unsigned  long callbackval;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   flags = DisableInterrupts();
+
+   voice = MV_GetVoice( handle );
+   if ( voice == NULL )
+      {
+      RestoreInterrupts( flags );
+      MV_SetErrorCode( MV_VoiceNotFound );
+      return( MV_Error );
+      }
+
+   callbackval = voice->callbackval;
+
+   MV_StopVoice( voice );
+
+   RestoreInterrupts( flags );
+
+   if ( MV_CallBackFunc )
+      {
+      MV_CallBackFunc( callbackval );
+      }
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_VoicesPlaying
+
+   Determines the number of currently active voices.
+---------------------------------------------------------------------*/
+
+int MV_VoicesPlaying
+   (
+   void
+   )
+
+   {
+   VoiceNode   *voice;
+   int         NumVoices = 0;
+   unsigned    flags;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( 0 );
+      }
+
+   flags = DisableInterrupts();
+
+   for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
+      {
+      NumVoices++;
+      }
+
+   RestoreInterrupts( flags );
+
+   return( NumVoices );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_AllocVoice
+
+   Retrieve an inactive or lower priority voice for output.
+---------------------------------------------------------------------*/
+
+VoiceNode *MV_AllocVoice
+   (
+   int priority
+   )
+
+   {
+   VoiceNode   *voice;
+   VoiceNode   *node;
+   unsigned    flags;
+
+//return( NULL );
+   if ( MV_Recording )
+      {
+      return( NULL );
+      }
+
+   flags = DisableInterrupts();
+
+   // Check if we have any free voices
+   if ( LL_Empty( &VoicePool, next, prev ) )
+      {
+      // check if we have a higher priority than a voice that is playing.
+      voice = VoiceList.next;
+      for( node = voice->next; node != &VoiceList; node = node->next )
+         {
+         if ( node->priority < voice->priority )
+            {
+            voice = node;
+            }
+         }
+
+      if ( priority >= voice->priority )
+         {
+         MV_Kill( voice->handle );
+         }
+      }
+
+   // Check if any voices are in the voice pool
+   if ( LL_Empty( &VoicePool, next, prev ) )
+      {
+      // No free voices
+      RestoreInterrupts( flags );
+      return( NULL );
+      }
+
+   voice = VoicePool.next;
+   LL_Remove( voice, next, prev );
+   RestoreInterrupts( flags );
+
+   // Find a free voice handle
+   do
+      {
+      MV_VoiceHandle++;
+      if ( MV_VoiceHandle < MV_MinVoiceHandle )
+         {
+         MV_VoiceHandle = MV_MinVoiceHandle;
+         }
+      }
+   while( MV_VoicePlaying( MV_VoiceHandle ) );
+
+   voice->handle = MV_VoiceHandle;
+
+   return( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_VoiceAvailable
+
+   Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int MV_VoiceAvailable
+   (
+   int priority
+   )
+
+   {
+   VoiceNode   *voice;
+   VoiceNode   *node;
+   unsigned    flags;
+
+   // Check if we have any free voices
+   if ( !LL_Empty( &VoicePool, next, prev ) )
+      {
+      return( TRUE );
+      }
+
+   flags = DisableInterrupts();
+
+   // check if we have a higher priority than a voice that is playing.
+   voice = VoiceList.next;
+   for( node = VoiceList.next; node != &VoiceList; node = node->next )
+      {
+      if ( node->priority < voice->priority )
+         {
+         voice = node;
+         }
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) )
+      {
+      return( TRUE );
+      }
+
+   return( FALSE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetVoicePitch
+
+   Sets the pitch for the specified voice.
+---------------------------------------------------------------------*/
+
+void MV_SetVoicePitch
+   (
+   VoiceNode *voice,
+   unsigned long rate,
+   int pitchoffset
+   )
+
+   {
+   voice->SamplingRate = rate;
+   voice->PitchScale   = PITCH_GetScale( pitchoffset );
+   voice->RateScale    = ( rate * voice->PitchScale ) / MV_MixRate;
+
+   // Multiply by MixBufferSize - 1
+   voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
+      voice->RateScale;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetPitch
+
+   Sets the pitch for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetPitch
+   (
+   int handle,
+   int pitchoffset
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   voice = MV_GetVoice( handle );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_VoiceNotFound );
+      return( MV_Error );
+      }
+
+   MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset );
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetFrequency
+
+   Sets the frequency for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetFrequency
+   (
+   int handle,
+   int frequency
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   voice = MV_GetVoice( handle );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_VoiceNotFound );
+      return( MV_Error );
+      }
+
+   MV_SetVoicePitch( voice, frequency, 0 );
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetVolumeTable
+
+   Returns a pointer to the volume table associated with the specified
+   volume.
+---------------------------------------------------------------------*/
+
+static short *MV_GetVolumeTable
+   (
+   int vol
+   )
+
+   {
+   int volume;
+   short *table;
+
+   volume = MIX_VOLUME( vol );
+
+   table = (short *)&MV_VolumeTable[ volume ];
+
+   return( table );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetVoiceMixMode
+
+   Selects which method should be used to mix the voice.
+---------------------------------------------------------------------*/
+
+static void MV_SetVoiceMixMode
+   (
+   VoiceNode *voice
+   )
+
+   {
+   unsigned flags;
+   int test;
+
+   flags = DisableInterrupts();
+
+   test = T_DEFAULT;
+   if ( MV_Bits == 8 )
+      {
+      test |= T_8BITS;
+      }
+
+   if ( voice->bits == 16 )
+      {
+      test |= T_16BITSOURCE;
+      }
+
+   if ( MV_Channels == 1 )
+      {
+      test |= T_MONO;
+      }
+   else
+      {
+      if ( IS_QUIET( voice->RightVolume ) )
+         {
+         test |= T_RIGHTQUIET;
+         }
+      else if ( IS_QUIET( voice->LeftVolume ) )
+         {
+         test |= T_LEFTQUIET;
+         }
+      }
+
+   // Default case
+   voice->mix = MV_Mix8BitMono;
+
+   switch( test )
+      {
+      case T_8BITS | T_MONO | T_16BITSOURCE :
+         voice->mix = MV_Mix8BitMono16;
+         break;
+
+      case T_8BITS | T_MONO :
+         voice->mix = MV_Mix8BitMono;
+         break;
+
+      case T_8BITS | T_16BITSOURCE | T_LEFTQUIET :
+         MV_LeftVolume = MV_RightVolume;
+         voice->mix = MV_Mix8BitMono16;
+         break;
+
+      case T_8BITS | T_LEFTQUIET :
+         MV_LeftVolume = MV_RightVolume;
+         voice->mix = MV_Mix8BitMono;
+         break;
+
+      case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET :
+         voice->mix = MV_Mix8BitMono16;
+         break;
+
+      case T_8BITS | T_RIGHTQUIET :
+         voice->mix = MV_Mix8BitMono;
+         break;
+
+      case T_8BITS | T_16BITSOURCE :
+         voice->mix = MV_Mix8BitStereo16;
+         break;
+
+      case T_8BITS :
+         voice->mix = MV_Mix8BitStereo;
+         break;
+
+      case T_MONO | T_16BITSOURCE :
+         voice->mix = MV_Mix16BitMono16;
+         break;
+
+      case T_MONO :
+         voice->mix = MV_Mix16BitMono;
+         break;
+
+      case T_16BITSOURCE | T_LEFTQUIET :
+         MV_LeftVolume = MV_RightVolume;
+         voice->mix = MV_Mix16BitMono16;
+         break;
+
+      case T_LEFTQUIET :
+         MV_LeftVolume = MV_RightVolume;
+         voice->mix = MV_Mix16BitMono;
+         break;
+
+      case T_16BITSOURCE | T_RIGHTQUIET :
+         voice->mix = MV_Mix16BitMono16;
+         break;
+
+      case T_RIGHTQUIET :
+         voice->mix = MV_Mix16BitMono;
+         break;
+
+      case T_16BITSOURCE :
+         voice->mix = MV_Mix16BitStereo16;
+         break;
+
+      case T_SIXTEENBIT_STEREO :
+         voice->mix = MV_Mix16BitStereo;
+         break;
+
+      default :
+         voice->mix = MV_Mix8BitMono;
+      }
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetVoiceVolume
+
+   Sets the stereo and mono volume level of the voice associated
+   with the specified handle.
+---------------------------------------------------------------------*/
+
+void MV_SetVoiceVolume
+   (
+   VoiceNode *voice,
+   int vol,
+   int left,
+   int right
+   )
+
+   {
+   if ( MV_Channels == 1 )
+      {
+      left  = vol;
+      right = vol;
+      }
+
+   if ( MV_SwapLeftRight )
+      {
+      // SBPro uses reversed panning
+      voice->LeftVolume  = MV_GetVolumeTable( right );
+      voice->RightVolume = MV_GetVolumeTable( left );
+      }
+   else
+      {
+      voice->LeftVolume  = MV_GetVolumeTable( left );
+      voice->RightVolume = MV_GetVolumeTable( right );
+      }
+
+   MV_SetVoiceMixMode( voice );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_EndLooping
+
+   Stops the voice associated with the specified handle from looping
+   without stoping the sound.
+---------------------------------------------------------------------*/
+
+int MV_EndLooping
+   (
+   int handle
+   )
+
+   {
+   VoiceNode *voice;
+   unsigned flags;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   flags = DisableInterrupts();
+
+   voice = MV_GetVoice( handle );
+   if ( voice == NULL )
+      {
+      RestoreInterrupts( flags );
+      MV_SetErrorCode( MV_VoiceNotFound );
+      return( MV_Warning );
+      }
+
+   voice->LoopCount = 0;
+   voice->LoopStart = NULL;
+   voice->LoopEnd   = NULL;
+
+   RestoreInterrupts( flags );
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetPan
+
+   Sets the stereo and mono volume level of the voice associated
+   with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetPan
+   (
+   int handle,
+   int vol,
+   int left,
+   int right
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   voice = MV_GetVoice( handle );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_VoiceNotFound );
+      return( MV_Warning );
+      }
+
+   MV_SetVoiceVolume( voice, vol, left, right );
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_Pan3D
+
+   Set the angle and distance from the listener of the voice associated
+   with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_Pan3D
+   (
+   int handle,
+   int angle,
+   int distance
+   )
+
+   {
+   int left;
+   int right;
+   int mid;
+   int volume;
+   int status;
+
+   if ( distance < 0 )
+      {
+      distance  = -distance;
+      angle    += MV_NumPanPositions / 2;
+      }
+
+   volume = MIX_VOLUME( distance );
+
+   // Ensure angle is within 0 - 31
+   angle &= MV_MaxPanPosition;
+
+   left  = MV_PanTable[ angle ][ volume ].left;
+   right = MV_PanTable[ angle ][ volume ].right;
+   mid   = max( 0, 255 - distance );
+
+   status = MV_SetPan( handle, mid, left, right );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetReverb
+
+   Sets the level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetReverb
+   (
+   int reverb
+   )
+
+   {
+   MV_ReverbLevel = MIX_VOLUME( reverb );
+   MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ];
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetFastReverb
+
+   Sets the level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetFastReverb
+   (
+   int reverb
+   )
+
+   {
+   MV_ReverbLevel = max( 0, min( 16, reverb ) );
+   MV_ReverbTable = NULL;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetMaxReverbDelay
+
+   Returns the maximum delay time for reverb.
+---------------------------------------------------------------------*/
+
+int MV_GetMaxReverbDelay
+   (
+   void
+   )
+
+   {
+   int maxdelay;
+
+   maxdelay = MixBufferSize * MV_NumberOfBuffers;
+
+   return maxdelay;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetReverbDelay
+
+   Returns the current delay time for reverb.
+---------------------------------------------------------------------*/
+
+int MV_GetReverbDelay
+   (
+   void
+   )
+
+   {
+   return MV_ReverbDelay / MV_SampleSize;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetReverbDelay
+
+   Sets the delay level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetReverbDelay
+   (
+   int delay
+   )
+
+   {
+   int maxdelay;
+
+   maxdelay = MV_GetMaxReverbDelay();
+   MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) );
+   MV_ReverbDelay *= MV_SampleSize;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetMixMode
+
+   Prepares Multivoc to play stereo of mono digitized sounds.
+---------------------------------------------------------------------*/
+
+int MV_SetMixMode
+   (
+   int numchannels,
+   int samplebits
+   )
+
+   {
+   int mode;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   mode = 0;
+   if ( numchannels == 2 )
+      {
+      mode |= STEREO;
+      }
+   if ( samplebits == 16 )
+      {
+      mode |= SIXTEEN_BIT;
+      }
+
+#ifdef PLAT_DOS
+   switch( MV_SoundCard )
+      {
+      case UltraSound :
+         MV_MixMode = mode;
+         break;
+
+      case SoundBlaster :
+      case Awe32 :
+         MV_MixMode = BLASTER_SetMixMode( mode );
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         MV_MixMode = PAS_SetMixMode( mode );
+         break;
+
+      case SoundScape :
+         MV_MixMode = SOUNDSCAPE_SetMixMode( mode );
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case SoundSource :
+      case TandySoundSource :
+         MV_MixMode = SS_SetMixMode( mode );
+         break;
+      #endif
+      }
+#else
+   MV_MixMode = mode;
+#endif
+
+   MV_Channels = 1;
+   if ( MV_MixMode & STEREO )
+      {
+      MV_Channels = 2;
+      }
+
+   MV_Bits = 8;
+   if ( MV_MixMode & SIXTEEN_BIT )
+      {
+      MV_Bits = 16;
+      }
+
+   MV_BuffShift  = 7 + MV_Channels;
+   MV_SampleSize = sizeof( MONO8 ) * MV_Channels;
+
+   if ( MV_Bits == 8 )
+      {
+      MV_Silence = SILENCE_8BIT;
+      }
+   else
+      {
+      MV_Silence     = SILENCE_16BIT;
+      MV_BuffShift  += 1;
+      MV_SampleSize *= 2;
+      }
+
+   MV_BufferSize = MixBufferSize * MV_SampleSize;
+   MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
+   MV_BufferLength = TotalBufferSize;
+
+   MV_RightChannelOffset = MV_SampleSize / 2;
+   if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+      {
+      MV_SampleSize         /= 2;
+      MV_BufferSize         /= 2;
+      MV_RightChannelOffset  = MV_BufferSize * MV_NumberOfBuffers;
+      MV_BufferLength       /= 2;
+      }
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StartPlayback
+
+   Starts the sound playback engine.
+---------------------------------------------------------------------*/
+
+int MV_StartPlayback
+   (
+   void
+   )
+
+   {
+   int status;
+   int buffer;
+
+   // Initialize the buffers
+   ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
+   for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
+      {
+      MV_BufferEmpty[ buffer ] = TRUE;
+      }
+
+   // Set the mix buffer variables
+   MV_MixPage = 1;
+
+   MV_MixFunction = MV_Mix;
+
+//JIM
+//   MV_MixRate = MV_RequestedMixRate;
+//   return( MV_Ok );
+
+   // Start playback
+#ifdef PLAT_DOS
+   switch( MV_SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         status = BLASTER_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+            TotalBufferSize, MV_NumberOfBuffers,
+            MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+         if ( status != BLASTER_Ok )
+            {
+            MV_SetErrorCode( MV_BlasterError );
+            return( MV_Error );
+            }
+
+         MV_MixRate = BLASTER_GetPlaybackRate();
+         MV_DMAChannel = BLASTER_DMAChannel;
+         break;
+
+      case UltraSound :
+
+         status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceGus, 1,
+            MV_Bits, MV_RequestedMixRate, 0, ( MV_Channels == 1 ) ?
+            0 : 24, 255, 0xffff, 0 );
+         if ( status < GUSWAVE_Ok )
+            {
+            MV_SetErrorCode( MV_BlasterError );
+            return( MV_Error );
+            }
+
+         if ( MV_Channels == 2 )
+            {
+            status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceRightGus, 1,
+               MV_Bits, MV_RequestedMixRate, 0, 8, 255, 0xffff, 0 );
+            if ( status < GUSWAVE_Ok )
+               {
+               GUSWAVE_KillAllVoices();
+               MV_SetErrorCode( MV_BlasterError );
+               return( MV_Error );
+               }
+            }
+
+         MV_MixRate = MV_RequestedMixRate;
+         MV_DMAChannel = -1;
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = PAS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+            TotalBufferSize, MV_NumberOfBuffers,
+            MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+         if ( status != PAS_Ok )
+            {
+            MV_SetErrorCode( MV_PasError );
+            return( MV_Error );
+            }
+
+         MV_MixRate = PAS_GetPlaybackRate();
+         MV_DMAChannel = PAS_DMAChannel;
+         break;
+
+      case SoundScape :
+         status = SOUNDSCAPE_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+            TotalBufferSize, MV_NumberOfBuffers, MV_RequestedMixRate,
+            MV_MixMode, MV_ServiceVoc );
+
+         if ( status != SOUNDSCAPE_Ok )
+            {
+            MV_SetErrorCode( MV_SoundScapeError );
+            return( MV_Error );
+            }
+
+         MV_MixRate = SOUNDSCAPE_GetPlaybackRate();
+         MV_DMAChannel = SOUNDSCAPE_DMAChannel;
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case SoundSource :
+      case TandySoundSource :
+         SS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+            TotalBufferSize, MV_NumberOfBuffers,
+            MV_ServiceVoc );
+         MV_MixRate = SS_SampleRate;
+         MV_DMAChannel = -1;
+         break;
+      #endif
+      }
+#else
+    status = DSL_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+            TotalBufferSize, MV_NumberOfBuffers,
+            MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+    if ( status != DSL_Ok )
+       {
+       MV_SetErrorCode( MV_BlasterError );
+       return( MV_Error );
+       }
+
+    MV_MixRate = DSL_GetPlaybackRate();
+#endif
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StopPlayback
+
+   Stops the sound playback engine.
+---------------------------------------------------------------------*/
+
+void MV_StopPlayback
+   (
+   void
+   )
+
+   {
+   VoiceNode   *voice;
+   VoiceNode   *next;
+   unsigned    flags;
+
+#ifdef PLAT_DOS
+   // Stop sound playback
+   switch( MV_SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         BLASTER_StopPlayback();
+         break;
+
+      case UltraSound :
+         GUSWAVE_KillAllVoices();
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         PAS_StopPlayback();
+         break;
+
+      case SoundScape :
+         SOUNDSCAPE_StopPlayback();
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case SoundSource :
+      case TandySoundSource :
+         SS_StopPlayback();
+         break;
+      #endif
+      }
+#else
+   DSL_StopPlayback();
+#endif
+
+   // Make sure all callbacks are done.
+   flags = DisableInterrupts();
+
+   for( voice = VoiceList.next; voice != &VoiceList; voice = next )
+      {
+      next = voice->next;
+
+      MV_StopVoice( voice );
+
+      if ( MV_CallBackFunc )
+         {
+         MV_CallBackFunc( voice->callbackval );
+         }
+      }
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StartRecording
+
+   Starts the sound recording engine.
+---------------------------------------------------------------------*/
+
+int MV_StartRecording
+   (
+   int MixRate,
+   void ( *function )( char *ptr, int length )
+   )
+
+   {
+#ifdef PLAT_DOS
+   int status;
+
+   switch( MV_SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         break;
+
+      default :
+         MV_SetErrorCode( MV_UnsupportedCard );
+         return( MV_Error );
+         break;
+      }
+
+   if ( function == NULL )
+      {
+      MV_SetErrorCode( MV_NullRecordFunction );
+      return( MV_Error );
+      }
+
+   MV_StopPlayback();
+
+   // Initialize the buffers
+   ClearBuffer_DW( MV_MixBuffer[ 0 ], SILENCE_8BIT, TotalBufferSize >> 2 );
+
+   // Set the mix buffer variables
+   MV_MixPage  = 0;
+
+   MV_RecordFunc = function;
+
+   // Start playback
+   switch( MV_SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         status = BLASTER_BeginBufferedRecord( MV_MixBuffer[ 0 ],
+            TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
+            MV_ServiceRecord );
+
+         if ( status != BLASTER_Ok )
+            {
+            MV_SetErrorCode( MV_BlasterError );
+            return( MV_Error );
+            }
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = PAS_BeginBufferedRecord( MV_MixBuffer[ 0 ],
+            TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
+            MV_ServiceRecord );
+
+         if ( status != PAS_Ok )
+            {
+            MV_SetErrorCode( MV_PasError );
+            return( MV_Error );
+            }
+         break;
+      }
+
+   MV_Recording = TRUE;
+   return( MV_Ok );
+#else
+   MV_SetErrorCode( MV_UnsupportedCard );
+   return( MV_Error );
+#endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StopRecord
+
+   Stops the sound record engine.
+---------------------------------------------------------------------*/
+
+void MV_StopRecord
+   (
+   void
+   )
+
+   {
+#ifdef PLAT_DOS
+   // Stop sound playback
+   switch( MV_SoundCard )
+      {
+      case SoundBlaster :
+      case Awe32 :
+         BLASTER_StopPlayback();
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         PAS_StopPlayback();
+         break;
+      }
+
+   MV_Recording = FALSE;
+   MV_StartPlayback();
+#endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_StartDemandFeedPlayback
+
+   Plays a digitized sound from a user controlled buffering system.
+---------------------------------------------------------------------*/
+
+int MV_StartDemandFeedPlayback
+   (
+   void ( *function )( char **ptr, unsigned long *length ),
+   int rate,
+   int pitchoffset,
+   int vol,
+   int left,
+   int right,
+   int priority,
+   unsigned long callbackval
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = MV_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_NoVoices );
+      return( MV_Error );
+      }
+
+   voice->wavetype    = DemandFeed;
+   voice->bits        = 8;
+   voice->GetSound    = MV_GetNextDemandFeedBlock;
+   voice->NextBlock   = NULL;
+   voice->DemandFeed  = function;
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->BlockLength = 0;
+   voice->position    = 0;
+   voice->sound       = NULL;
+   voice->length      = 0;
+   voice->BlockLength = 0;
+   voice->Playing     = TRUE;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+
+   MV_SetVoicePitch( voice, rate, pitchoffset );
+   MV_SetVoiceVolume( voice, vol, left, right );
+   MV_PlayVoice( voice );
+
+   return( voice->handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayRaw
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayRaw
+   (
+   char *ptr,
+   unsigned long length,
+   unsigned rate,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   int status;
+
+   status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset,
+      vol, left, right, priority, callbackval );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayLoopedRaw
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedRaw
+   (
+   char *ptr,
+   unsigned long length,
+   char *loopstart,
+   char *loopend,
+   unsigned rate,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   VoiceNode *voice;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = MV_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_NoVoices );
+      return( MV_Error );
+      }
+
+   voice->wavetype    = Raw;
+   voice->bits        = 8;
+   voice->GetSound    = MV_GetNextRawBlock;
+   voice->Playing     = TRUE;
+   voice->NextBlock   = ptr;
+   voice->position    = 0;
+   voice->BlockLength = length;
+   voice->length      = 0;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+   voice->LoopStart   = loopstart;
+   voice->LoopEnd     = loopend;
+   voice->LoopSize    = ( voice->LoopEnd - voice->LoopStart ) + 1;
+
+   MV_SetVoicePitch( voice, rate, pitchoffset );
+   MV_SetVoiceVolume( voice, vol, left, right );
+   MV_PlayVoice( voice );
+
+   return( voice->handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayWAV
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayWAV
+   (
+   char *ptr,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   int status;
+
+   status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right,
+      priority, callbackval );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayWAV3D
+
+   Begin playback of sound data at specified angle and distance
+   from listener.
+---------------------------------------------------------------------*/
+
+int MV_PlayWAV3D
+   (
+   char *ptr,
+   int  pitchoffset,
+   int  angle,
+   int  distance,
+   int  priority,
+   unsigned long callbackval
+   )
+
+   {
+   int left;
+   int right;
+   int mid;
+   int volume;
+   int status;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   if ( distance < 0 )
+      {
+      distance  = -distance;
+      angle    += MV_NumPanPositions / 2;
+      }
+
+   volume = MIX_VOLUME( distance );
+
+   // Ensure angle is within 0 - 31
+   angle &= MV_MaxPanPosition;
+
+   left  = MV_PanTable[ angle ][ volume ].left;
+   right = MV_PanTable[ angle ][ volume ].right;
+   mid   = max( 0, 255 - distance );
+
+   status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority,
+      callbackval );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayLoopedWAV
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedWAV
+   (
+   char *ptr,
+   long  loopstart,
+   long  loopend,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   riff_header   *riff;
+   format_header *format;
+   data_header   *data;
+   VoiceNode     *voice;
+   int length;
+   int absloopend;
+   int absloopstart;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   riff = ( riff_header * )ptr;
+
+   if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
+      ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
+      ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
+      {
+      MV_SetErrorCode( MV_InvalidWAVFile );
+      return( MV_Error );
+      }
+
+   format = ( format_header * )( riff + 1 );
+   data   = ( data_header * )( ( ( char * )format ) + riff->format_size );
+
+   // Check if it's PCM data.
+   if ( format->wFormatTag != 1 )
+      {
+      MV_SetErrorCode( MV_InvalidWAVFile );
+      return( MV_Error );
+      }
+
+   if ( format->nChannels != 1 )
+      {
+      MV_SetErrorCode( MV_InvalidWAVFile );
+      return( MV_Error );
+      }
+
+   if ( ( format->nBitsPerSample != 8 ) &&
+      ( format->nBitsPerSample != 16 ) )
+      {
+      MV_SetErrorCode( MV_InvalidWAVFile );
+      return( MV_Error );
+      }
+
+   if ( strncmp( data->DATA, "data", 4 ) != 0 )
+      {
+      MV_SetErrorCode( MV_InvalidWAVFile );
+      return( MV_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = MV_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_NoVoices );
+      return( MV_Error );
+      }
+
+   voice->wavetype    = WAV;
+   voice->bits        = format->nBitsPerSample;
+   voice->GetSound    = MV_GetNextWAVBlock;
+
+   length = data->size;
+   absloopstart = loopstart;
+   absloopend   = loopend;
+   if ( voice->bits == 16 )
+      {
+      loopstart  *= 2;
+      data->size &= ~1;
+      loopend    *= 2;
+      length     /= 2;
+      }
+
+   loopend    = min( loopend, (long)data->size );
+   absloopend = min( absloopend, length );
+
+   voice->Playing     = TRUE;
+   voice->DemandFeed  = NULL;
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->position    = 0;
+   voice->length      = 0;
+   voice->BlockLength = absloopend;
+   voice->NextBlock   = ( char * )( data + 1 );
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+   voice->LoopStart   = voice->NextBlock + loopstart;
+   voice->LoopEnd     = voice->NextBlock + loopend;
+   voice->LoopSize    = absloopend - absloopstart;
+
+   if ( ( loopstart >= (long)data->size ) || ( loopstart < 0 ) )
+      {
+      voice->LoopStart = NULL;
+      voice->LoopEnd   = NULL;
+      voice->BlockLength = length;
+      }
+
+   MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset );
+   MV_SetVoiceVolume( voice, vol, left, right );
+   MV_PlayVoice( voice );
+
+   return( voice->handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayVOC3D
+
+   Begin playback of sound data at specified angle and distance
+   from listener.
+---------------------------------------------------------------------*/
+
+int MV_PlayVOC3D
+   (
+   char *ptr,
+   int  pitchoffset,
+   int  angle,
+   int  distance,
+   int  priority,
+   unsigned long callbackval
+   )
+
+   {
+   int left;
+   int right;
+   int mid;
+   int volume;
+   int status;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   if ( distance < 0 )
+      {
+      distance  = -distance;
+      angle    += MV_NumPanPositions / 2;
+      }
+
+   volume = MIX_VOLUME( distance );
+
+   // Ensure angle is within 0 - 31
+   angle &= MV_MaxPanPosition;
+
+   left  = MV_PanTable[ angle ][ volume ].left;
+   right = MV_PanTable[ angle ][ volume ].right;
+   mid   = max( 0, 255 - distance );
+
+   status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority,
+      callbackval );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayVOC
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayVOC
+   (
+   char *ptr,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   int status;
+
+   status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right,
+      priority, callbackval );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_PlayLoopedVOC
+
+   Begin playback of sound data with the given sound levels and
+   priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedVOC
+   (
+   char *ptr,
+   long  loopstart,
+   long  loopend,
+   int   pitchoffset,
+   int   vol,
+   int   left,
+   int   right,
+   int   priority,
+   unsigned long callbackval
+   )
+
+   {
+   VoiceNode   *voice;
+   int          status;
+   unsigned short nextpos;
+
+   if ( !MV_Installed )
+      {
+      MV_SetErrorCode( MV_NotInstalled );
+      return( MV_Error );
+      }
+
+   // Make sure it's a valid VOC file.
+   status = strncmp( ptr, "Creative Voice File", 19 );
+   if ( status != 0 )
+      {
+      MV_SetErrorCode( MV_InvalidVOCFile );
+      return( MV_Error );
+      }
+
+   // Request a voice from the voice pool
+   voice = MV_AllocVoice( priority );
+   if ( voice == NULL )
+      {
+      MV_SetErrorCode( MV_NoVoices );
+      return( MV_Error );
+      }
+
+   voice->wavetype    = VOC;
+   voice->bits        = 8;
+   voice->GetSound    = MV_GetNextVOCBlock;
+
+   nextpos = *( unsigned short * )( ptr + 0x14 );
+   voice->NextBlock   = ptr + BUILDSWAP_INTEL16(nextpos);
+
+   voice->DemandFeed  = NULL;
+   voice->LoopStart   = NULL;
+   voice->LoopCount   = 0;
+   voice->BlockLength = 0;
+   voice->PitchScale  = PITCH_GetScale( pitchoffset );
+   voice->length      = 0;
+   voice->next        = NULL;
+   voice->prev        = NULL;
+   voice->priority    = priority;
+   voice->callbackval = callbackval;
+   voice->LoopStart   = ( char * )loopstart;
+   voice->LoopEnd     = ( char * )loopend;
+   voice->LoopSize    = loopend - loopstart + 1;
+
+   if ( loopstart < 0 )
+      {
+      voice->LoopStart = NULL;
+      voice->LoopEnd   = NULL;
+      }
+
+   MV_SetVoiceVolume( voice, vol, left, right );
+   MV_PlayVoice( voice );
+
+   return( voice->handle );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MV_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_CreateVolumeTable
+
+   Create the table used to convert sound data to a specific volume
+   level.
+---------------------------------------------------------------------*/
+
+void MV_CreateVolumeTable
+   (
+   int index,
+   int volume,
+   int MaxVolume
+   )
+
+   {
+   int val;
+   int level;
+   int i;
+
+   level = ( volume * MaxVolume ) / MV_MaxTotalVolume;
+   if ( MV_Bits == 16 )
+      {
+      for( i = 0; i < 65536; i += 256 )
+         {
+         val   = i - 0x8000;
+         val  *= level;
+         val  /= MV_MaxVolume;
+         MV_VolumeTable[ index ][ i / 256 ] = val;
+         }
+      }
+   else
+      {
+      for( i = 0; i < 256; i++ )
+         {
+         val   = i - 0x80;
+         val  *= level;
+         val  /= MV_MaxVolume;
+         MV_VolumeTable[ volume ][ i ] = val;
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_CalcVolume
+
+   Create the table used to convert sound data to a specific volume
+   level.
+---------------------------------------------------------------------*/
+
+void MV_CalcVolume
+   (
+   int MaxVolume
+   )
+
+   {
+   int volume;
+
+   for( volume = 0; volume < 128; volume++ )
+      {
+      MV_HarshClipTable[ volume ] = 0;
+      MV_HarshClipTable[ volume + 384 ] = 255;
+      }
+   for( volume = 0; volume < 256; volume++ )
+      {
+      MV_HarshClipTable[ volume + 128 ] = volume;
+      }
+
+   // For each volume level, create a translation table with the
+   // appropriate volume calculated.
+   for( volume = 0; volume <= MV_MaxVolume; volume++ )
+      {
+      MV_CreateVolumeTable( volume, volume, MaxVolume );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_CalcPanTable
+
+   Create the table used to determine the stereo volume level of
+   a sound located at a specific angle and distance from the listener.
+---------------------------------------------------------------------*/
+
+void MV_CalcPanTable
+   (
+   void
+   )
+
+   {
+   int   level;
+   int   angle;
+   int   distance;
+   int   HalfAngle;
+   int   ramp;
+
+   HalfAngle = ( MV_NumPanPositions / 2 );
+
+   for( distance = 0; distance <= MV_MaxVolume; distance++ )
+      {
+      level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
+      for( angle = 0; angle <= HalfAngle / 2; angle++ )
+         {
+         ramp = level - ( ( level * angle ) /
+            ( MV_NumPanPositions / 4 ) );
+
+         MV_PanTable[ angle ][ distance ].left = ramp;
+         MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
+         MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
+         MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
+
+         MV_PanTable[ angle ][ distance ].right = level;
+         MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
+         MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
+         MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetVolume
+
+   Sets the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+void MV_SetVolume
+   (
+   int volume
+   )
+
+   {
+   volume = max( 0, volume );
+   volume = min( volume, MV_MaxTotalVolume );
+
+   MV_TotalVolume = volume;
+
+   // Calculate volume table
+   MV_CalcVolume( volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetVolume
+
+   Returns the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int MV_GetVolume
+   (
+   void
+   )
+
+   {
+   return( MV_TotalVolume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetCallBack
+
+   Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void MV_SetCallBack
+   (
+   void ( *function )( unsigned long )
+   )
+
+   {
+   MV_CallBackFunc = function;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_SetReverseStereo
+
+   Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void MV_SetReverseStereo
+   (
+   int setting
+   )
+
+   {
+   MV_SwapLeftRight = setting;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_GetReverseStereo
+
+   Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int MV_GetReverseStereo
+   (
+   void
+   )
+
+   {
+   return( MV_SwapLeftRight );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_TestPlayback
+
+   Checks if playback has started.
+---------------------------------------------------------------------*/
+
+int MV_TestPlayback
+   (
+   void
+   )
+
+   {
+#ifdef PLAT_DOS
+   unsigned flags;
+   long time;
+   int  start;
+   int  status;
+   int  pos;
+
+   if ( MV_SoundCard == UltraSound )
+      {
+      return( MV_Ok );
+      }
+
+   flags = DisableInterrupts();
+   _enable();
+
+   status = MV_Error;
+   start  = MV_MixPage;
+   time   = clock() + CLOCKS_PER_SEC * 2;
+
+   while( clock() < time )
+      {
+      if ( MV_MixPage != start )
+         {
+         status = MV_Ok;
+         }
+      }
+
+   RestoreInterrupts( flags );
+
+   if ( status != MV_Ok )
+      {
+      // Just in case an error doesn't get reported
+      MV_SetErrorCode( MV_DMAFailure );
+
+      switch( MV_SoundCard )
+         {
+         case SoundBlaster :
+         case Awe32 :
+            pos = BLASTER_GetCurrentPos();
+            break;
+
+         case ProAudioSpectrum :
+         case SoundMan16 :
+            pos = PAS_GetCurrentPos();
+            break;
+
+         case SoundScape :
+            pos = SOUNDSCAPE_GetCurrentPos();
+            break;
+
+         #ifndef SOUNDSOURCE_OFF
+         case SoundSource :
+         case TandySoundSource :
+            MV_SetErrorCode( MV_SoundSourceFailure );
+            pos = -1;
+            break;
+         #endif
+
+         default :
+            MV_SetErrorCode( MV_UnsupportedCard );
+            pos = -2;
+            break;
+         }
+
+      if ( pos > 0 )
+         {
+         MV_SetErrorCode( MV_IrqFailure );
+         }
+      else if ( pos == 0 )
+         {
+         if ( MV_Bits == 16 )
+            {
+            MV_SetErrorCode( MV_DMA16Failure );
+            }
+         else
+            {
+            MV_SetErrorCode( MV_DMAFailure );
+            }
+         }
+      }
+
+   return( status );
+#else
+   return MV_Ok;
+#endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_Init
+
+   Perform the initialization of variables and memory used by
+   Multivoc.
+---------------------------------------------------------------------*/
+
+int MV_Init
+   (
+   int soundcard,
+   int MixRate,
+   int Voices,
+   int numchannels,
+   int samplebits
+   )
+
+   {
+   char *ptr;
+   int  status;
+   int  buffer;
+   int  index;
+
+   if ( MV_Installed )
+      {
+      MV_Shutdown();
+      }
+
+   MV_SetErrorCode( MV_Ok );
+
+   status = MV_LockMemory();
+   if ( status != MV_Ok )
+      {
+      return( status );
+      }
+
+   MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 );
+   status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory );
+   if ( status != USRHOOKS_Ok )
+      {
+      MV_UnlockMemory();
+      MV_SetErrorCode( MV_NoMem );
+      return( MV_Error );
+      }
+
+   status = DPMI_LockMemory( ptr, MV_TotalMemory );
+   if ( status != DPMI_Ok )
+      {
+      USRHOOKS_FreeMem( ptr );
+      MV_UnlockMemory();
+      MV_SetErrorCode( MV_DPMI_Error );
+      return( MV_Error );
+      }
+
+   MV_Voices = ( VoiceNode * )ptr;
+   MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) );
+
+   // Set number of voices before calculating volume table
+   MV_MaxVoices = Voices;
+
+   LL_Reset( (VoiceNode *)&VoiceList, next, prev );
+   LL_Reset( (VoiceNode *)&VoicePool, next, prev );
+
+   for( index = 0; index < Voices; index++ )
+      {
+      LL_Add( (VoiceNode *)&VoicePool, &MV_Voices[ index ], next, prev );
+      }
+
+   // Allocate mix buffer within 1st megabyte
+   status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor,
+      2 * TotalBufferSize );
+
+   if ( status )
+      {
+      DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+      USRHOOKS_FreeMem( MV_Voices );
+      MV_Voices      = NULL;
+      MV_TotalMemory = 0;
+      MV_UnlockMemory();
+
+      MV_SetErrorCode( MV_NoMem );
+      return( MV_Error );
+      }
+
+   MV_SetReverseStereo( FALSE );
+
+   // Initialize the sound card
+#ifdef PLAT_DOS
+   switch( soundcard )
+      {
+      case UltraSound :
+         status = GUSWAVE_Init( 2 );
+         if ( status != GUSWAVE_Ok )
+            {
+            //JIM
+            MV_SetErrorCode( MV_BlasterError );
+            }
+         break;
+
+      case SoundBlaster :
+      case Awe32 :
+         status = BLASTER_Init();
+         if ( status != BLASTER_Ok )
+            {
+            MV_SetErrorCode( MV_BlasterError );
+            }
+
+         if ( ( BLASTER_Config.Type == SBPro ) ||
+            ( BLASTER_Config.Type == SBPro2 ) )
+            {
+            MV_SetReverseStereo( TRUE );
+            }
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = PAS_Init();
+         if ( status != PAS_Ok )
+            {
+            MV_SetErrorCode( MV_PasError );
+            }
+         break;
+
+      case SoundScape :
+         status = SOUNDSCAPE_Init();
+         if ( status != SOUNDSCAPE_Ok )
+            {
+            MV_SetErrorCode( MV_SoundScapeError );
+            }
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case SoundSource :
+      case TandySoundSource :
+         status = SS_Init( soundcard );
+         if ( status != SS_Ok )
+            {
+            MV_SetErrorCode( MV_SoundSourceError );
+            }
+         break;
+      #endif
+
+      default :
+         MV_SetErrorCode( MV_UnsupportedCard );
+         break;
+      }
+#else
+   status = DSL_Init();
+   if ( status != DSL_Ok )
+      {
+      MV_SetErrorCode( MV_BlasterError );
+      }
+#endif
+
+   if ( MV_ErrorCode != MV_Ok )
+      {
+      status = MV_ErrorCode;
+
+      DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+      USRHOOKS_FreeMem( MV_Voices );
+      MV_Voices      = NULL;
+      MV_TotalMemory = 0;
+
+      DPMI_FreeDOSMemory( MV_BufferDescriptor );
+      MV_UnlockMemory();
+
+      MV_SetErrorCode( status );
+      return( MV_Error );
+      }
+
+   MV_SoundCard    = soundcard;
+   MV_Installed    = TRUE;
+   MV_CallBackFunc = NULL;
+   MV_RecordFunc   = NULL;
+   MV_Recording    = FALSE;
+   MV_ReverbLevel  = 0;
+   MV_ReverbTable  = NULL;
+
+   // Set the sampling rate
+   MV_RequestedMixRate = MixRate;
+
+   // Set Mixer to play stereo digitized sound
+   MV_SetMixMode( numchannels, samplebits );
+   MV_ReverbDelay = MV_BufferSize * 3;
+
+#ifdef PLAT_DOS
+   // Make sure we don't cross a physical page
+   if ( ( ( unsigned long )ptr & 0xffff ) + TotalBufferSize > 0x10000 )
+      {
+      ptr = ( char * )( ( ( unsigned long )ptr & 0xff0000 ) + 0x10000 );
+      }
+#endif
+
+   MV_MixBuffer[ MV_NumberOfBuffers ] = ptr;
+   for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
+      {
+      MV_MixBuffer[ buffer ] = ptr;
+      ptr += MV_BufferSize;
+      }
+
+   // Calculate pan table
+   MV_CalcPanTable();
+
+   MV_SetVolume( MV_MaxTotalVolume );
+
+   // Start the playback engine
+   status = MV_StartPlayback();
+   if ( status != MV_Ok )
+      {
+      // Preserve error code while we shutdown.
+      status = MV_ErrorCode;
+      MV_Shutdown();
+      MV_SetErrorCode( status );
+      return( MV_Error );
+      }
+
+   if ( MV_TestPlayback() != MV_Ok )
+      {
+      status = MV_ErrorCode;
+      MV_Shutdown();
+      MV_SetErrorCode( status );
+      return( MV_Error );
+      }
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_Shutdown
+
+   Restore any resources allocated by Multivoc back to the system.
+---------------------------------------------------------------------*/
+
+int MV_Shutdown
+   (
+   void
+   )
+
+   {
+   int      buffer;
+   unsigned flags;
+
+   if ( !MV_Installed )
+      {
+      return( MV_Ok );
+      }
+
+   flags = DisableInterrupts();
+
+   MV_KillAllVoices();
+
+   MV_Installed = FALSE;
+
+   // Stop the sound recording engine
+   if ( MV_Recording )
+      {
+      MV_StopRecord();
+      }
+
+   // Stop the sound playback engine
+   MV_StopPlayback();
+
+   // Shutdown the sound card
+#ifdef PLAT_DOS
+   switch( MV_SoundCard )
+      {
+      case UltraSound :
+         GUSWAVE_Shutdown();
+         break;
+
+      case SoundBlaster :
+      case Awe32 :
+         BLASTER_Shutdown();
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         PAS_Shutdown();
+         break;
+
+      case SoundScape :
+         SOUNDSCAPE_Shutdown();
+         break;
+
+      #ifndef SOUNDSOURCE_OFF
+      case SoundSource :
+      case TandySoundSource :
+         SS_Shutdown();
+         break;
+      #endif
+      }
+#else
+   DSL_Shutdown();
+#endif
+
+   RestoreInterrupts( flags );
+
+   // Free any voices we allocated
+   DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+   USRHOOKS_FreeMem( MV_Voices );
+   MV_Voices      = NULL;
+   MV_TotalMemory = 0;
+
+   LL_Reset( (VoiceNode *)&VoiceList, next, prev );
+   LL_Reset( (VoiceNode *)&VoicePool, next, prev );
+
+   MV_MaxVoices = 1;
+
+   // Release the descriptor from our mix buffer
+   DPMI_FreeDOSMemory( MV_BufferDescriptor );
+   for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
+      {
+      MV_MixBuffer[ buffer ] = NULL;
+      }
+
+   return( MV_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MV_UnlockMemory
+   (
+   void
+   )
+
+   {
+   PITCH_UnlockMemory();
+
+   DPMI_UnlockMemoryRegion( MV_LockStart, MV_LockEnd );
+   DPMI_Unlock( MV_VolumeTable );
+   DPMI_Unlock( MV_PanTable );
+   DPMI_Unlock( MV_Installed );
+   DPMI_Unlock( MV_SoundCard );
+   DPMI_Unlock( MV_TotalVolume );
+   DPMI_Unlock( MV_MaxVoices );
+   DPMI_Unlock( MV_BufferSize );
+   DPMI_Unlock( MV_BufferLength );
+   DPMI_Unlock( MV_SampleSize );
+   DPMI_Unlock( MV_NumberOfBuffers );
+   DPMI_Unlock( MV_MixMode );
+   DPMI_Unlock( MV_Channels );
+   DPMI_Unlock( MV_Bits );
+   DPMI_Unlock( MV_Silence );
+   DPMI_Unlock( MV_SwapLeftRight );
+   DPMI_Unlock( MV_RequestedMixRate );
+   DPMI_Unlock( MV_MixRate );
+   DPMI_Unlock( MV_BufferDescriptor );
+   DPMI_Unlock( MV_MixBuffer );
+   DPMI_Unlock( MV_BufferEmpty );
+   DPMI_Unlock( MV_Voices );
+   DPMI_Unlock( VoiceList );
+   DPMI_Unlock( VoicePool );
+   DPMI_Unlock( MV_MixPage );
+   DPMI_Unlock( MV_VoiceHandle );
+   DPMI_Unlock( MV_CallBackFunc );
+   DPMI_Unlock( MV_RecordFunc );
+   DPMI_Unlock( MV_Recording );
+   DPMI_Unlock( MV_MixFunction );
+   DPMI_Unlock( MV_HarshClipTable );
+   DPMI_Unlock( MV_MixDestination );
+   DPMI_Unlock( MV_LeftVolume );
+   DPMI_Unlock( MV_RightVolume );
+   DPMI_Unlock( MV_MixPosition );
+   DPMI_Unlock( MV_ErrorCode );
+   DPMI_Unlock( MV_DMAChannel );
+   DPMI_Unlock( MV_BuffShift );
+   DPMI_Unlock( MV_ReverbLevel );
+   DPMI_Unlock( MV_ReverbDelay );
+   DPMI_Unlock( MV_ReverbTable );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MV_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MV_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+   int pitchstatus;
+
+   status  = DPMI_LockMemoryRegion( MV_LockStart, MV_LockEnd );
+   status |= DPMI_Lock( MV_VolumeTable );
+   status |= DPMI_Lock( MV_PanTable );
+   status |= DPMI_Lock( MV_Installed );
+   status |= DPMI_Lock( MV_SoundCard );
+   status |= DPMI_Lock( MV_TotalVolume );
+   status |= DPMI_Lock( MV_MaxVoices );
+   status |= DPMI_Lock( MV_BufferSize );
+   status |= DPMI_Lock( MV_BufferLength );
+   status |= DPMI_Lock( MV_SampleSize );
+   status |= DPMI_Lock( MV_NumberOfBuffers );
+   status |= DPMI_Lock( MV_MixMode );
+   status |= DPMI_Lock( MV_Channels );
+   status |= DPMI_Lock( MV_Bits );
+   status |= DPMI_Lock( MV_Silence );
+   status |= DPMI_Lock( MV_SwapLeftRight );
+   status |= DPMI_Lock( MV_RequestedMixRate );
+   status |= DPMI_Lock( MV_MixRate );
+   status |= DPMI_Lock( MV_BufferDescriptor );
+   status |= DPMI_Lock( MV_MixBuffer );
+   status |= DPMI_Lock( MV_BufferEmpty );
+   status |= DPMI_Lock( MV_Voices );
+   status |= DPMI_Lock( VoiceList );
+   status |= DPMI_Lock( VoicePool );
+   status |= DPMI_Lock( MV_MixPage );
+   status |= DPMI_Lock( MV_VoiceHandle );
+   status |= DPMI_Lock( MV_CallBackFunc );
+   status |= DPMI_Lock( MV_RecordFunc );
+   status |= DPMI_Lock( MV_Recording );
+   status |= DPMI_Lock( MV_MixFunction );
+   status |= DPMI_Lock( MV_HarshClipTable );
+   status |= DPMI_Lock( MV_MixDestination );
+   status |= DPMI_Lock( MV_LeftVolume );
+   status |= DPMI_Lock( MV_RightVolume );
+   status |= DPMI_Lock( MV_MixPosition );
+   status |= DPMI_Lock( MV_ErrorCode );
+   status |= DPMI_Lock( MV_DMAChannel );
+   status |= DPMI_Lock( MV_BuffShift );
+   status |= DPMI_Lock( MV_ReverbLevel );
+   status |= DPMI_Lock( MV_ReverbDelay );
+   status |= DPMI_Lock( MV_ReverbTable );
+
+   pitchstatus = PITCH_LockMemory();
+   if ( ( pitchstatus != PITCH_Ok ) || ( status != DPMI_Ok ) )
+      {
+      MV_UnlockMemory();
+      MV_SetErrorCode( MV_DPMI_Error );
+      return( MV_Error );
+      }
+
+   return( MV_Ok );
+   }
+
+#ifndef PLAT_DOS
+void ClearBuffer_DW( void *ptr, unsigned data, int length )
+{
+	unsigned *d = (unsigned *)ptr;
+	
+	while (length--) {
+		*d = data;
+		
+		d++;
+	}
+}
+#endif

Added: tags/rott-1.1/rott/audiolib/multivoc.h
===================================================================
--- tags/rott-1.1/rott/audiolib/multivoc.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/multivoc.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,123 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   file:   MULTIVOC.H
+
+   author: James R. Dose
+   date:   December 20, 1993
+
+   Public header for MULTIVOC.C
+
+   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MULTIVOC_H
+#define __MULTIVOC_H
+
+// platform.h is in buildengine, but I need the byteswapping macros... --ryan.
+#include "platform.h"
+
+#define MV_MinVoiceHandle  1
+
+extern int MV_ErrorCode;
+
+enum MV_Errors
+   {
+   MV_Warning = -2,
+   MV_Error   = -1,
+   MV_Ok      = 0,
+   MV_UnsupportedCard,
+   MV_NotInstalled,
+   MV_NoVoices,
+   MV_NoMem,
+   MV_VoiceNotFound,
+   MV_BlasterError,
+   MV_PasError,
+   MV_SoundScapeError,
+   MV_SoundSourceError,
+   MV_DPMI_Error,
+   MV_InvalidVOCFile,
+   MV_InvalidWAVFile,
+   MV_InvalidMixMode,
+   MV_SoundSourceFailure,
+   MV_IrqFailure,
+   MV_DMAFailure,
+   MV_DMA16Failure,
+   MV_NullRecordFunction
+   };
+
+char *MV_ErrorString( int ErrorNumber );
+int   MV_VoicePlaying( int handle );
+int   MV_KillAllVoices( void );
+int   MV_Kill( int handle );
+int   MV_VoicesPlaying( void );
+int   MV_VoiceAvailable( int priority );
+int   MV_SetPitch( int handle, int pitchoffset );
+int   MV_SetFrequency( int handle, int frequency );
+int   MV_EndLooping( int handle );
+int   MV_SetPan( int handle, int vol, int left, int right );
+int   MV_Pan3D( int handle, int angle, int distance );
+void  MV_SetReverb( int reverb );
+void  MV_SetFastReverb( int reverb );
+int   MV_GetMaxReverbDelay( void );
+int   MV_GetReverbDelay( void );
+void  MV_SetReverbDelay( int delay );
+int   MV_SetMixMode( int numchannels, int samplebits );
+int   MV_StartPlayback( void );
+void  MV_StopPlayback( void );
+int   MV_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
+void  MV_StopRecord( void );
+int   MV_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+         int rate, int pitchoffset, int vol, int left, int right,
+         int priority, unsigned long callbackval );
+int   MV_PlayRaw( char *ptr, unsigned long length,
+         unsigned rate, int pitchoffset, int vol, int left,
+         int right, int priority, unsigned long callbackval );
+int   MV_PlayLoopedRaw( char *ptr, unsigned long length,
+         char *loopstart, char *loopend, unsigned rate, int pitchoffset,
+         int vol, int left, int right, int priority,
+         unsigned long callbackval );
+int   MV_PlayWAV( char *ptr, int pitchoffset, int vol, int left,
+         int right, int priority, unsigned long callbackval );
+int   MV_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+         int priority, unsigned long callbackval );
+int   MV_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+         int pitchoffset, int vol, int left, int right, int priority,
+         unsigned long callbackval );
+int   MV_PlayVOC3D( char *ptr, int pitchoffset, int angle, int distance,
+         int priority, unsigned long callbackval );
+int   MV_PlayVOC( char *ptr, int pitchoffset, int vol, int left, int right,
+         int priority, unsigned long callbackval );
+int   MV_PlayLoopedVOC( char *ptr, long loopstart, long loopend,
+         int pitchoffset, int vol, int left, int right, int priority,
+         unsigned long callbackval );
+void  MV_CreateVolumeTable( int index, int volume, int MaxVolume );
+void  MV_SetVolume( int volume );
+int   MV_GetVolume( void );
+void  MV_SetCallBack( void ( *function )( unsigned long ) );
+void  MV_SetReverseStereo( int setting );
+int   MV_GetReverseStereo( void );
+int   MV_Init( int soundcard, int MixRate, int Voices, int numchannels,
+         int samplebits );
+int   MV_Shutdown( void );
+void  MV_UnlockMemory( void );
+int   MV_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/music.c
===================================================================
--- tags/rott-1.1/rott/audiolib/music.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/music.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1035 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MUSIC.C
+
+   author: James R. Dose
+   date:   March 25, 1994
+
+   Device independant music playback routines.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "task_man.h"
+#include "sndcards.h"
+#include "music.h"
+#include "midi.h"
+#include "al_midi.h"
+#include "pas16.h"
+#include "blaster.h"
+#include "gusmidi.h"
+#include "mpu401.h"
+#include "awe32.h"
+#include "sndscape.h"
+#include "ll_man.h"
+#include "user.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+void TextMode( void );
+#pragma aux TextMode =  \
+    "mov    ax, 0003h", \
+    "int    10h"        \
+    modify [ ax ];
+
+int MUSIC_SoundDevice = -1;
+int MUSIC_ErrorCode = MUSIC_Ok;
+
+static midifuncs MUSIC_MidiFunctions;
+
+static int       MUSIC_FadeLength;
+static int       MUSIC_FadeRate;
+static unsigned  MUSIC_CurrentFadeVolume;
+static unsigned  MUSIC_LastFadeVolume;
+static int       MUSIC_EndingFadeVolume;
+static task     *MUSIC_FadeTask = NULL;
+
+int MUSIC_InitAWE32( midifuncs *Funcs );
+int MUSIC_InitFM( int card, midifuncs *Funcs );
+int MUSIC_InitMidi( int card, midifuncs *Funcs, int Address );
+int MUSIC_InitGUS( midifuncs *Funcs );
+
+#define MUSIC_SetErrorCode( status ) \
+   MUSIC_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *MUSIC_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case MUSIC_Warning :
+      case MUSIC_Error :
+         ErrorString = MUSIC_ErrorString( MUSIC_ErrorCode );
+         break;
+
+      case MUSIC_Ok :
+         ErrorString = "Music ok.";
+         break;
+
+      case MUSIC_ASSVersion :
+         ErrorString = "Apogee Sound System Version " ASS_VERSION_STRING "  "
+            "Programmed by Jim Dose\n"
+            "(c) Copyright 1996 James R. Dose.  All Rights Reserved.\n";
+         break;
+
+      case MUSIC_SoundCardError :
+         switch( MUSIC_SoundDevice )
+         {
+            case SoundBlaster :
+            case WaveBlaster :
+               ErrorString = BLASTER_ErrorString( BLASTER_Error );
+               break;
+
+            case ProAudioSpectrum :
+            case SoundMan16 :
+               ErrorString = PAS_ErrorString( PAS_Error );
+               break;
+
+            case Adlib :
+               ErrorString = "Adlib error.";
+               break;
+
+            case GenMidi :
+            case SoundCanvas :
+               ErrorString = "Could not detect MPU-401.";
+               break;
+
+            case SoundScape :
+               ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+               break;
+
+            case Awe32 :
+               ErrorString = AWE32_ErrorString( AWE32_Error );
+               break;
+
+            case UltraSound :
+               ErrorString = GUS_ErrorString( GUS_Error );
+               break;
+
+            default :
+               ErrorString = MUSIC_ErrorString( MUSIC_InvalidCard );
+               break;
+            }
+         break;
+
+      case MUSIC_MPU401Error :
+         ErrorString = "Could not detect MPU-401.";
+         break;
+
+      case MUSIC_InvalidCard :
+         ErrorString = "Invalid Music device.";
+         break;
+
+      case MUSIC_MidiError :
+         ErrorString = "Error playing MIDI file.";
+         break;
+
+      case MUSIC_TaskManError :
+         ErrorString = "TaskMan error.";
+         break;
+
+      case MUSIC_FMNotDetected :
+         ErrorString = "Could not detect FM chip.";
+         break;
+
+      case MUSIC_DPMI_Error :
+         ErrorString = "DPMI Error in MUSIC.";
+         break;
+
+      default :
+         ErrorString = "Unknown Music error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_Init
+
+   Selects which sound device to use.
+---------------------------------------------------------------------*/
+
+int MUSIC_Init
+   (
+   int SoundCard,
+   int Address
+   )
+
+   {
+   int i;
+   int status;
+
+   if ( USER_CheckParameter( "ASSVER" ) )
+      {
+      MUSIC_SetErrorCode( MUSIC_ASSVersion );
+      return( MUSIC_Error );
+      }
+
+   status = LL_LockMemory();
+   if ( status != LL_Ok )
+      {
+      MUSIC_SetErrorCode( MUSIC_DPMI_Error );
+      return( MUSIC_Error );
+      }
+
+   for( i = 0; i < 128; i++ )
+      {
+      MIDI_PatchMap[ i ] = i;
+      }
+
+   status = MUSIC_Ok;
+   MUSIC_SoundDevice = SoundCard;
+
+   switch( SoundCard )
+      {
+      case SoundBlaster :
+      case Adlib :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         status = MUSIC_InitFM( SoundCard, &MUSIC_MidiFunctions );
+         break;
+
+      case GenMidi :
+      case SoundCanvas :
+      case WaveBlaster :
+      case SoundScape :
+         status = MUSIC_InitMidi( SoundCard, &MUSIC_MidiFunctions, Address );
+         break;
+
+      case Awe32 :
+         status = MUSIC_InitAWE32( &MUSIC_MidiFunctions );
+         break;
+
+      case UltraSound :
+         status = MUSIC_InitGUS( &MUSIC_MidiFunctions );
+         break;
+
+      case SoundSource :
+      case PC :
+      default :
+         MUSIC_SetErrorCode( MUSIC_InvalidCard );
+         status = MUSIC_Error;
+      }
+
+   if ( status != MUSIC_Ok )
+      {
+      LL_UnlockMemory();
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_Shutdown
+
+   Terminates use of sound device.
+---------------------------------------------------------------------*/
+
+int MUSIC_Shutdown
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status = MUSIC_Ok;
+
+   MIDI_StopSong();
+
+   if ( MUSIC_FadeTask != NULL )
+      {
+      MUSIC_StopFade();
+      }
+
+   switch ( MUSIC_SoundDevice )
+      {
+      case Adlib :
+         AL_Shutdown();
+         break;
+
+      case SoundBlaster :
+         AL_Shutdown();
+         BLASTER_RestoreMidiVolume();
+         break;
+
+      case GenMidi :
+      case SoundCanvas :
+      case SoundScape :
+         MPU_Reset();
+         break;
+
+      case WaveBlaster :
+         BLASTER_ShutdownWaveBlaster();
+         MPU_Reset();
+         BLASTER_RestoreMidiVolume();
+         break;
+
+      case Awe32 :
+         AWE32_Shutdown();
+         BLASTER_RestoreMidiVolume();
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         AL_Shutdown();
+         PAS_RestoreMusicVolume();
+         break;
+
+      case UltraSound :
+         GUSMIDI_Shutdown();
+         break;
+      }
+
+   LL_UnlockMemory();
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetMaxFMMidiChannel
+
+   Sets the maximum MIDI channel that FM cards respond to.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetMaxFMMidiChannel
+   (
+   int channel
+   )
+
+   {
+   AL_SetMaxMidiChannel( channel );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetVolume
+
+   Sets the volume of music playback.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetVolume
+   (
+   int volume
+   )
+
+   {
+   volume = max( 0, volume );
+   volume = min( volume, 255 );
+
+   if ( MUSIC_SoundDevice != -1 )
+      {
+      MIDI_SetVolume( volume );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetMidiChannelVolume
+
+   Sets the volume of music playback on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetMidiChannelVolume
+   (
+   int channel,
+   int volume
+   )
+
+   {
+   MIDI_SetUserChannelVolume( channel, volume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_ResetMidiChannelVolumes
+
+   Sets the volume of music playback on all MIDI channels to full volume.
+---------------------------------------------------------------------*/
+
+void MUSIC_ResetMidiChannelVolumes
+   (
+   void
+   )
+
+   {
+   MIDI_ResetUserChannelVolume();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_GetVolume
+
+   Returns the volume of music playback.
+---------------------------------------------------------------------*/
+
+int MUSIC_GetVolume
+   (
+   void
+   )
+
+   {
+   if ( MUSIC_SoundDevice == -1 )
+      {
+      return( 0 );
+      }
+   return( MIDI_GetVolume() );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetLoopFlag
+
+   Set whether the music will loop or end when it reaches the end of
+   the song.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetLoopFlag
+   (
+   int loopflag
+   )
+
+   {
+   MIDI_SetLoopFlag( loopflag );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SongPlaying
+
+   Returns whether there is a song playing.
+---------------------------------------------------------------------*/
+
+int MUSIC_SongPlaying
+   (
+   void
+   )
+
+   {
+   return( MIDI_SongPlaying() );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_Continue
+
+   Continues playback of a paused song.
+---------------------------------------------------------------------*/
+
+void MUSIC_Continue
+   (
+   void
+   )
+
+   {
+   MIDI_ContinueSong();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_Pause
+
+   Pauses playback of a song.
+---------------------------------------------------------------------*/
+
+void MUSIC_Pause
+   (
+   void
+   )
+
+   {
+   MIDI_PauseSong();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_StopSong
+
+   Stops playback of current song.
+---------------------------------------------------------------------*/
+
+int MUSIC_StopSong
+   (
+   void
+   )
+
+   {
+   MUSIC_StopFade();
+   MIDI_StopSong();
+   MUSIC_SetErrorCode( MUSIC_Ok );
+   return( MUSIC_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_PlaySong
+
+   Begins playback of MIDI song.
+---------------------------------------------------------------------*/
+
+int MUSIC_PlaySong
+   (
+   unsigned char *song,
+   int loopflag
+   )
+
+   {
+   int status;
+
+   switch( MUSIC_SoundDevice )
+      {
+      case SoundBlaster :
+      case Adlib :
+      case ProAudioSpectrum :
+      case SoundMan16 :
+      case GenMidi :
+      case SoundCanvas :
+      case WaveBlaster :
+      case SoundScape :
+      case Awe32 :
+      case UltraSound :
+         MIDI_StopSong();
+         status = MIDI_PlaySong( song, loopflag );
+         if ( status != MIDI_Ok )
+            {
+            MUSIC_SetErrorCode( MUSIC_MidiError );
+            return( MUSIC_Warning );
+            }
+         break;
+
+      case SoundSource :
+      case PC :
+      default :
+         MUSIC_SetErrorCode( MUSIC_InvalidCard );
+         return( MUSIC_Warning );
+         break;
+      }
+
+   return( MUSIC_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetContext
+
+   Sets the song context.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetContext
+   (
+   int context
+   )
+
+   {
+   MIDI_SetContext( context );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_GetContext
+
+   Returns the current song context.
+---------------------------------------------------------------------*/
+
+int MUSIC_GetContext
+   (
+   void
+   )
+
+   {
+   return MIDI_GetContext();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetSongTick
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongTick
+   (
+   unsigned long PositionInTicks
+   )
+
+   {
+   MIDI_SetSongTick( PositionInTicks );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetSongTime
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongTime
+   (
+   unsigned long milliseconds
+   )
+
+   {
+   MIDI_SetSongTime( milliseconds );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_SetSongPosition
+
+   Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongPosition
+   (
+   int measure,
+   int beat,
+   int tick
+   )
+
+   {
+   MIDI_SetSongPosition( measure, beat, tick );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_GetSongPosition
+
+   Returns the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_GetSongPosition
+   (
+   songposition *pos
+   )
+
+   {
+   MIDI_GetSongPosition( pos );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_GetSongLength
+
+   Returns the length of the song.
+---------------------------------------------------------------------*/
+
+void MUSIC_GetSongLength
+   (
+   songposition *pos
+   )
+
+   {
+   MIDI_GetSongLength( pos );
+   }
+
+
+int MUSIC_InitAWE32
+   (
+   midifuncs *Funcs
+   )
+
+   {
+   int status;
+
+   status = AWE32_Init();
+   if ( status != AWE32_Ok )
+      {
+      MUSIC_SetErrorCode( MUSIC_SoundCardError );
+      return( MUSIC_Error );
+      }
+
+   Funcs->NoteOff           = AWE32_NoteOff;
+   Funcs->NoteOn            = AWE32_NoteOn;
+   Funcs->PolyAftertouch    = AWE32_PolyAftertouch;
+   Funcs->ControlChange     = AWE32_ControlChange;
+   Funcs->ProgramChange     = AWE32_ProgramChange;
+   Funcs->ChannelAftertouch = AWE32_ChannelAftertouch;
+   Funcs->PitchBend         = AWE32_PitchBend;
+   Funcs->ReleasePatches    = NULL;
+   Funcs->LoadPatch         = NULL;
+   Funcs->SetVolume         = NULL;
+   Funcs->GetVolume         = NULL;
+
+   if ( BLASTER_CardHasMixer() )
+      {
+      BLASTER_SaveMidiVolume();
+      Funcs->SetVolume = BLASTER_SetMidiVolume;
+      Funcs->GetVolume = BLASTER_GetMidiVolume;
+      }
+
+   status = MUSIC_Ok;
+   MIDI_SetMidiFuncs( Funcs );
+
+   return( status );
+   }
+
+
+int MUSIC_InitFM
+   (
+   int card,
+   midifuncs *Funcs
+   )
+
+   {
+   int status;
+   int passtatus;
+
+   status = MIDI_Ok;
+
+   if ( !AL_DetectFM() )
+      {
+      MUSIC_SetErrorCode( MUSIC_FMNotDetected );
+      return( MUSIC_Error );
+      }
+
+   // Init the fm routines
+   AL_Init( card );
+
+   Funcs->NoteOff           = AL_NoteOff;
+   Funcs->NoteOn            = AL_NoteOn;
+   Funcs->PolyAftertouch    = NULL;
+   Funcs->ControlChange     = AL_ControlChange;
+   Funcs->ProgramChange     = AL_ProgramChange;
+   Funcs->ChannelAftertouch = NULL;
+   Funcs->PitchBend         = AL_SetPitchBend;
+   Funcs->ReleasePatches    = NULL;
+   Funcs->LoadPatch         = NULL;
+   Funcs->SetVolume         = NULL;
+   Funcs->GetVolume         = NULL;
+
+   switch( card )
+      {
+      case SoundBlaster :
+         if ( BLASTER_CardHasMixer() )
+            {
+            BLASTER_SaveMidiVolume();
+            Funcs->SetVolume = BLASTER_SetMidiVolume;
+            Funcs->GetVolume = BLASTER_GetMidiVolume;
+            }
+         else
+            {
+            Funcs->SetVolume = NULL;
+            Funcs->GetVolume = NULL;
+            }
+         break;
+
+      case Adlib :
+         Funcs->SetVolume = NULL;
+         Funcs->GetVolume = NULL;
+         break;
+
+      case ProAudioSpectrum :
+      case SoundMan16 :
+         Funcs->SetVolume = NULL;
+         Funcs->GetVolume = NULL;
+
+         passtatus = PAS_SaveMusicVolume();
+         if ( passtatus == PAS_Ok )
+            {
+            Funcs->SetVolume = PAS_SetFMVolume;
+            Funcs->GetVolume = PAS_GetFMVolume;
+            }
+         break;
+      }
+
+   MIDI_SetMidiFuncs( Funcs );
+
+   return( status );
+   }
+
+int MUSIC_InitMidi
+   (
+   int        card,
+   midifuncs *Funcs,
+   int        Address
+   )
+
+   {
+   int status;
+
+   status = MUSIC_Ok;
+
+   if ( ( card == WaveBlaster ) || ( card == SoundCanvas ) ||
+      ( card == GenMidi ) )
+      {
+      // Setup WaveBlaster Daughterboard clone
+      // (ie. SoundCanvas DB, TurtleBeach Rio)
+      BLASTER_SetupWaveBlaster();
+      }
+
+   if ( card == SoundScape )
+      {
+      Address = SOUNDSCAPE_GetMIDIPort();
+      if ( Address < SOUNDSCAPE_Ok )
+         {
+         MUSIC_SetErrorCode( MUSIC_SoundCardError );
+         return( MUSIC_Error );
+         }
+      }
+
+   if ( MPU_Init( Address ) != MPU_Ok )
+      {
+      MUSIC_SetErrorCode( MUSIC_MPU401Error );
+      return( MUSIC_Error );
+      }
+
+   Funcs->NoteOff           = MPU_NoteOff;
+   Funcs->NoteOn            = MPU_NoteOn;
+   Funcs->PolyAftertouch    = MPU_PolyAftertouch;
+   Funcs->ControlChange     = MPU_ControlChange;
+   Funcs->ProgramChange     = MPU_ProgramChange;
+   Funcs->ChannelAftertouch = MPU_ChannelAftertouch;
+   Funcs->PitchBend         = MPU_PitchBend;
+   Funcs->ReleasePatches    = NULL;
+   Funcs->LoadPatch         = NULL;
+   Funcs->SetVolume         = NULL;
+   Funcs->GetVolume         = NULL;
+
+   if ( card == WaveBlaster )
+      {
+      if ( BLASTER_CardHasMixer() )
+         {
+         BLASTER_SaveMidiVolume();
+         Funcs->SetVolume = BLASTER_SetMidiVolume;
+         Funcs->GetVolume = BLASTER_GetMidiVolume;
+         }
+      }
+
+   MIDI_SetMidiFuncs( Funcs );
+
+   return( status );
+   }
+
+int MUSIC_InitGUS
+   (
+   midifuncs *Funcs
+   )
+
+   {
+   int status;
+
+   status = MUSIC_Ok;
+
+   if ( GUSMIDI_Init() != GUS_Ok )
+      {
+      MUSIC_SetErrorCode( MUSIC_SoundCardError );
+      return( MUSIC_Error );
+      }
+
+   Funcs->NoteOff           = GUSMIDI_NoteOff;
+   Funcs->NoteOn            = GUSMIDI_NoteOn;
+   Funcs->PolyAftertouch    = NULL;
+   Funcs->ControlChange     = GUSMIDI_ControlChange;
+   Funcs->ProgramChange     = GUSMIDI_ProgramChange;
+   Funcs->ChannelAftertouch = NULL;
+   Funcs->PitchBend         = GUSMIDI_PitchBend;
+   Funcs->ReleasePatches    = NULL;//GUSMIDI_ReleasePatches;
+   Funcs->LoadPatch         = NULL;//GUSMIDI_LoadPatch;
+   Funcs->SetVolume         = GUSMIDI_SetVolume;
+   Funcs->GetVolume         = GUSMIDI_GetVolume;
+
+   MIDI_SetMidiFuncs( Funcs );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_FadeRoutine
+
+   Fades music volume from current level to another over a specified
+   period of time.
+---------------------------------------------------------------------*/
+
+static void MUSIC_FadeRoutine
+   (
+   task *Task
+   )
+
+   {
+   int volume;
+
+   MUSIC_CurrentFadeVolume += MUSIC_FadeRate;
+   if ( MUSIC_FadeLength == 0 )
+      {
+      MIDI_SetVolume( MUSIC_EndingFadeVolume );
+      TS_Terminate( Task );
+      MUSIC_FadeTask = NULL;
+      }
+   else
+      {
+      MUSIC_FadeLength--;
+//      if ( ( MUSIC_SoundDevice == GenMidi ) &&
+//         ( ( MUSIC_FadeLength % 12 ) != 0 ) )
+//         {
+//         return;
+//         }
+
+      volume = MUSIC_CurrentFadeVolume >> 7;
+      if ( MUSIC_LastFadeVolume != volume )
+         {
+         MUSIC_LastFadeVolume = volume;
+         MIDI_SetVolume( volume );
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_FadeVolume
+
+   Fades music volume from current level to another over a specified
+   period of time.
+---------------------------------------------------------------------*/
+
+int MUSIC_FadeVolume
+   (
+   int tovolume,
+   int milliseconds
+   )
+
+   {
+   int fromvolume;
+
+   if ( ( MUSIC_SoundDevice == ProAudioSpectrum ) ||
+      ( MUSIC_SoundDevice == SoundMan16 ) ||
+      ( MUSIC_SoundDevice == GenMidi ) ||
+      ( MUSIC_SoundDevice == SoundScape ) ||
+      ( MUSIC_SoundDevice == SoundCanvas ) )
+      {
+      MIDI_SetVolume( tovolume );
+      return( MUSIC_Ok );
+      }
+
+   if ( MUSIC_FadeTask != NULL )
+      {
+      MUSIC_StopFade();
+      }
+
+   tovolume = max( 0, tovolume );
+   tovolume = min( 255, tovolume );
+   fromvolume = MUSIC_GetVolume();
+
+   MUSIC_FadeLength = milliseconds / 25;
+   MUSIC_FadeRate   = ( ( tovolume - fromvolume ) << 7 ) / MUSIC_FadeLength;
+   MUSIC_LastFadeVolume = fromvolume;
+   MUSIC_CurrentFadeVolume = fromvolume << 7;
+   MUSIC_EndingFadeVolume = tovolume;
+
+   MUSIC_FadeTask = TS_ScheduleTask( MUSIC_FadeRoutine, 40, 1, NULL );
+   if ( MUSIC_FadeTask == NULL )
+      {
+      MUSIC_SetErrorCode( MUSIC_TaskManError );
+      return( MUSIC_Warning );
+      }
+
+   TS_Dispatch();
+   return( MUSIC_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_FadeActive
+
+   Returns whether the fade routine is active.
+---------------------------------------------------------------------*/
+
+int MUSIC_FadeActive
+   (
+   void
+   )
+
+   {
+   return( MUSIC_FadeTask != NULL );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_StopFade
+
+   Stops fading the music.
+---------------------------------------------------------------------*/
+
+void MUSIC_StopFade
+   (
+   void
+   )
+
+   {
+   if ( MUSIC_FadeTask != NULL )
+      {
+      TS_Terminate( MUSIC_FadeTask );
+      MUSIC_FadeTask = NULL;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_RerouteMidiChannel
+
+   Sets callback function to reroute MIDI commands from specified
+   function.
+---------------------------------------------------------------------*/
+
+void MUSIC_RerouteMidiChannel
+   (
+   int channel,
+   int cdecl ( *function )( int event, int c1, int c2 )
+   )
+
+   {
+   MIDI_RerouteMidiChannel( channel, function );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: MUSIC_RegisterTimbreBank
+
+   Halts playback of all sounds.
+---------------------------------------------------------------------*/
+
+void MUSIC_RegisterTimbreBank
+   (
+   unsigned char *timbres
+   )
+
+   {
+   AL_RegisterTimbreBank( timbres );
+   }

Added: tags/rott-1.1/rott/audiolib/music.h
===================================================================
--- tags/rott-1.1/rott/audiolib/music.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/music.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,96 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: MUSIC.H
+
+   author: James R. Dose
+   date:   March 25, 1994
+
+   Public header for MUSIC.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MUSIC_H
+#define __MUSIC_H
+
+#include "sndcards.h"
+
+#ifndef PLAT_DOS
+#define cdecl
+#endif
+
+extern int MUSIC_ErrorCode;
+
+enum MUSIC_ERRORS
+   {
+   MUSIC_Warning = -2,
+   MUSIC_Error   = -1,
+   MUSIC_Ok      = 0,
+   MUSIC_ASSVersion,
+   MUSIC_SoundCardError,
+   MUSIC_MPU401Error,
+   MUSIC_InvalidCard,
+   MUSIC_MidiError,
+   MUSIC_TaskManError,
+   MUSIC_FMNotDetected,
+   MUSIC_DPMI_Error
+   };
+
+typedef struct
+   {
+   unsigned long tickposition;
+   unsigned long milliseconds;
+   unsigned int  measure;
+   unsigned int  beat;
+   unsigned int  tick;
+   } songposition;
+
+#define MUSIC_LoopSong ( 1 == 1 )
+#define MUSIC_PlayOnce ( !MUSIC_LoopSong )
+
+char *MUSIC_ErrorString( int ErrorNumber );
+int   MUSIC_Init( int SoundCard, int Address );
+int   MUSIC_Shutdown( void );
+void  MUSIC_SetMaxFMMidiChannel( int channel );
+void  MUSIC_SetVolume( int volume );
+void  MUSIC_SetMidiChannelVolume( int channel, int volume );
+void  MUSIC_ResetMidiChannelVolumes( void );
+int   MUSIC_GetVolume( void );
+void  MUSIC_SetLoopFlag( int loopflag );
+int   MUSIC_SongPlaying( void );
+void  MUSIC_Continue( void );
+void  MUSIC_Pause( void );
+int   MUSIC_StopSong( void );
+int   MUSIC_PlaySong( unsigned char *song, int loopflag );
+void  MUSIC_SetContext( int context );
+int   MUSIC_GetContext( void );
+void  MUSIC_SetSongTick( unsigned long PositionInTicks );
+void  MUSIC_SetSongTime( unsigned long milliseconds );
+void  MUSIC_SetSongPosition( int measure, int beat, int tick );
+void  MUSIC_GetSongPosition( songposition *pos );
+void  MUSIC_GetSongLength( songposition *pos );
+int   MUSIC_FadeVolume( int tovolume, int milliseconds );
+int   MUSIC_FadeActive( void );
+void  MUSIC_StopFade( void );
+void  MUSIC_RerouteMidiChannel( int channel, int cdecl ( *function )( int event, int c1, int c2 ) );
+void  MUSIC_RegisterTimbreBank( unsigned char *timbres );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/mv_mix.asm
===================================================================
--- tags/rott-1.1/rott/audiolib/mv_mix.asm	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mv_mix.asm	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,505 @@
+        IDEAL
+
+        p386
+        MODEL  flat
+
+        dataseg
+        CODESEG
+
+        MASM
+        ALIGN 4
+
+EXTRN   _MV_HarshClipTable:DWORD
+EXTRN   _MV_MixDestination:DWORD
+EXTRN   _MV_MixPosition:DWORD
+EXTRN   _MV_LeftVolume:DWORD
+EXTRN   _MV_RightVolume:DWORD
+EXTRN   _MV_SampleSize:DWORD
+EXTRN   _MV_RightChannelOffset:DWORD
+
+;================
+;
+; MV_Mix8BitMono
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix8BitMono_
+PUBLIC  MV_Mix8BitMono_
+; Two at once
+        pushad
+
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET apatch7+2            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET apatch8+2            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET apatch9+3            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume             ; Since we're mono, use left volume
+        mov     eax,OFFSET apatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET apatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Harsh Clip table ptr
+        mov     ebx, _MV_HarshClipTable
+        add     ebx, 128
+        mov     eax,OFFSET apatch3+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET apatch4+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET apatch5+2            ; convice tasm to modify code...
+        mov     [eax],edx
+        mov     eax,OFFSET apatch6+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        shr     ecx, 1                          ; double sample count
+        cmp     ecx, 0
+        je      short exit8m
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; apatch1 - volume table
+; apatch2 - volume table
+; apatch3 - harsh clip table
+; apatch4 - harsh clip table
+; apatch5 - sample rate
+; apatch6 - sample rate
+
+        mov     eax,ebp                         ; begin calculating first sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     eax,16                          ; finish calculation for first sample
+
+        mov     ebx,ebp                         ; begin calculating second sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     ebx,16                          ; finish calculation for second sample
+
+        movzx   eax, byte ptr [esi+eax]         ; get first sample
+        movzx   ebx, byte ptr [esi+ebx]         ; get second sample
+
+        ALIGN 4
+mix8Mloop:
+        movzx   edx, byte ptr [edi]             ; get current sample from destination
+apatch1:
+        movsx   eax, byte ptr [2*eax+12345678h] ; volume translate first sample
+apatch2:
+        movsx   ebx, byte ptr [2*ebx+12345678h] ; volume translate second sample
+        add     eax, edx                        ; mix first sample
+apatch9:
+        movzx   edx, byte ptr [edi + 1]         ; get current sample from destination
+apatch3:
+        mov     eax, [eax + 12345678h]          ; harsh clip new sample
+        add     ebx, edx                        ; mix second sample
+        mov     [edi], al                       ; write new sample to destination
+        mov     edx, ebp                        ; begin calculating third sample
+apatch4:
+        mov     ebx, [ebx + 12345678h]          ; harsh clip new sample
+apatch5:
+        add     ebp,12345678h                   ; advance frac pointer
+        shr     edx, 16                         ; finish calculation for third sample
+        mov     eax, ebp                        ; begin calculating fourth sample
+apatch7:
+        add     edi, 1                          ; move destination to second sample
+        shr     eax, 16                         ; finish calculation for fourth sample
+        mov     [edi], bl                       ; write new sample to destination
+apatch6:
+        add     ebp,12345678h                   ; advance frac pointer
+        movzx   ebx, byte ptr [esi+eax]         ; get fourth sample
+        movzx   eax, byte ptr [esi+edx]         ; get third sample
+apatch8:
+        add     edi, 2                          ; move destination to third sample
+        dec     ecx                             ; decrement count
+        jnz     mix8Mloop                       ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+exit8m:
+        popad
+        ret
+ENDP    MV_Mix8BitMono_
+
+;================
+;
+; MV_Mix8BitStereo
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix8BitStereo_
+PUBLIC  MV_Mix8BitStereo_
+
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET bpatch8+2            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Right channel offset
+        mov     ebx, _MV_RightChannelOffset
+        mov     eax,OFFSET bpatch6+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET bpatch7+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET bpatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        mov     ebx, _MV_RightVolume
+        mov     eax,OFFSET bpatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET bpatch3+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        ; Harsh Clip table ptr
+        mov     ebx, _MV_HarshClipTable
+        add     ebx,128
+        mov     eax,OFFSET bpatch4+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET bpatch5+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        cmp     ecx, 0
+        je      short exit8S
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; bpatch1 - left volume table
+; bpatch2 - right volume table
+; bpatch3 - sample rate
+; bpatch4 - harsh clip table
+; bpatch5 - harsh clip table
+
+        mov     eax,ebp                         ; begin calculating first sample
+        shr     eax,16                          ; finish calculation for first sample
+
+        movzx   ebx, byte ptr [esi+eax]         ; get first sample
+
+        ALIGN 4
+mix8Sloop:
+bpatch1:
+        movsx   eax, byte ptr [2*ebx+12345678h] ; volume translate left sample
+        movzx   edx, byte ptr [edi]             ; get current sample from destination
+bpatch2:
+        movsx   ebx, byte ptr [2*ebx+12345678h] ; volume translate right sample
+        add     eax, edx                        ; mix left sample
+bpatch3:
+        add     ebp,12345678h                   ; advance frac pointer
+bpatch6:
+        movzx   edx, byte ptr [edi+12345678h]   ; get current sample from destination
+bpatch4:
+        mov     eax, [eax + 12345678h]          ; harsh clip left sample
+        add     ebx, edx                        ; mix right sample
+        mov     [edi], al                       ; write left sample to destination
+bpatch5:
+        mov     ebx, [ebx + 12345678h]          ; harsh clip right sample
+        mov     edx, ebp                        ; begin calculating second sample
+bpatch7:
+        mov     [edi+12345678h], bl             ; write right sample to destination
+        shr     edx, 16                         ; finish calculation for second sample
+bpatch8:
+        add     edi, 2                          ; move destination to second sample
+        movzx   ebx, byte ptr [esi+edx]         ; get second sample
+        dec     ecx                             ; decrement count
+        jnz     mix8Sloop                       ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+
+EXIT8S:
+        popad
+        ret
+ENDP    MV_Mix8BitStereo_
+
+;================
+;
+; MV_Mix16BitMono
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix16BitMono_
+PUBLIC  MV_Mix16BitMono_
+; Two at once
+        pushad
+
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET cpatch5+3            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET cpatch6+3            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET cpatch7+2            ; convice tasm to modify code...
+        add     bl,bl
+        mov     [eax],bl
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET cpatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET cpatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET cpatch3+2            ; convice tasm to modify code...
+        mov     [eax],edx
+        mov     eax,OFFSET cpatch4+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        shr     ecx, 1                          ; double sample count
+        cmp     ecx, 0
+        je      exit16M
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; cpatch1 - volume table
+; cpatch2 - volume table
+; cpatch3 - sample rate
+; cpatch4 - sample rate
+
+        mov     eax,ebp                         ; begin calculating first sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     eax,16                          ; finish calculation for first sample
+
+        mov     ebx,ebp                         ; begin calculating second sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     ebx,16                          ; finish calculation for second sample
+
+        movzx   eax, byte ptr [esi+eax]         ; get first sample
+        movzx   ebx, byte ptr [esi+ebx]         ; get second sample
+
+        ALIGN 4
+mix16Mloop:
+        movsx   edx, word ptr [edi]             ; get current sample from destination
+cpatch1:
+        movsx   eax, word ptr [2*eax+12345678h] ; volume translate first sample
+cpatch2:
+        movsx   ebx, word ptr [2*ebx+12345678h] ; volume translate second sample
+        add     eax, edx                        ; mix first sample
+cpatch5:
+        movsx   edx, word ptr [edi + 2]         ; get current sample from destination
+
+        cmp     eax, -32768                     ; Harsh clip sample
+        jge     short m16skip1
+        mov     eax, -32768
+        jmp     short m16skip2
+m16skip1:
+        cmp     eax, 32767
+        jle     short m16skip2
+        mov     eax, 32767
+m16skip2:
+        add     ebx, edx                        ; mix second sample
+        mov     [edi], ax                       ; write new sample to destination
+        mov     edx, ebp                        ; begin calculating third sample
+
+        cmp     ebx, -32768                     ; Harsh clip sample
+        jge     short m16skip3
+        mov     ebx, -32768
+        jmp     short m16skip4
+m16skip3:
+        cmp     ebx, 32767
+        jle     short m16skip4
+        mov     ebx, 32767
+m16skip4:
+cpatch3:
+        add     ebp,12345678h                   ; advance frac pointer
+        shr     edx, 16                         ; finish calculation for third sample
+        mov     eax, ebp                        ; begin calculating fourth sample
+cpatch6:
+        mov     [edi + 2], bx                   ; write new sample to destination
+        shr     eax, 16                         ; finish calculation for fourth sample
+
+cpatch4:
+        add     ebp,12345678h                   ; advance frac pointer
+        movzx   ebx, byte ptr [esi+eax]         ; get fourth sample
+cpatch7:
+        add     edi, 4                          ; move destination to third sample
+        movzx   eax, byte ptr [esi+edx]         ; get third sample
+        dec     ecx                             ; decrement count
+        jnz     mix16Mloop                      ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+EXIT16M:
+        popad
+        ret
+ENDP    MV_Mix16BitMono_
+
+;================
+;
+; MV_Mix16BitStereo
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix16BitStereo_
+PUBLIC  MV_Mix16BitStereo_
+
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET dpatch6+2            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Right channel offset
+        mov     ebx, _MV_RightChannelOffset
+        mov     eax,OFFSET dpatch4+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET dpatch5+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET dpatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        mov     ebx, _MV_RightVolume
+        mov     eax,OFFSET dpatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET dpatch3+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        cmp     ecx, 0
+        je      exit16S
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; dpatch1 - left volume table
+; dpatch2 - right volume table
+; dpatch3 - sample rate
+
+        mov     eax,ebp                         ; begin calculating first sample
+        shr     eax,16                          ; finish calculation for first sample
+
+        movzx   ebx, byte ptr [esi+eax]         ; get first sample
+
+        ALIGN 4
+mix16Sloop:
+dpatch1:
+        movsx   eax, word ptr [2*ebx+12345678h] ; volume translate left sample
+        movsx   edx, word ptr [edi]             ; get current sample from destination
+dpatch2:
+        movsx   ebx, word ptr [2*ebx+12345678h] ; volume translate right sample
+        add     eax, edx                        ; mix left sample
+dpatch3:
+        add     ebp,12345678h                   ; advance frac pointer
+dpatch4:
+        movsx   edx, word ptr [edi+12345678h]   ; get current sample from destination
+
+        cmp     eax, -32768                     ; Harsh clip sample
+        jge     short s16skip1
+        mov     eax, -32768
+        jmp     short s16skip2
+s16skip1:
+        cmp     eax, 32767
+        jle     short s16skip2
+        mov     eax, 32767
+s16skip2:
+        add     ebx, edx                        ; mix right sample
+        mov     [edi], ax                       ; write left sample to destination
+
+        cmp     ebx, -32768                     ; Harsh clip sample
+        jge     short s16skip3
+        mov     ebx, -32768
+        jmp     short s16skip4
+s16skip3:
+        cmp     ebx, 32767
+        jle     short s16skip4
+        mov     ebx, 32767
+s16skip4:
+
+        mov     edx, ebp                        ; begin calculating second sample
+dpatch5:
+        mov     [edi+12345678h], bx             ; write right sample to destination
+        shr     edx, 16                         ; finish calculation for second sample
+dpatch6:
+        add     edi, 4                          ; move destination to second sample
+        movzx   ebx, byte ptr [esi+edx]         ; get second sample
+        dec     ecx                             ; decrement count
+        jnz     mix16Sloop                      ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+exit16S:
+        popad
+        ret
+ENDP    MV_Mix16BitStereo_
+
+        ENDS
+
+        END

Added: tags/rott-1.1/rott/audiolib/mv_mix.c
===================================================================
--- tags/rott-1.1/rott/audiolib/mv_mix.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mv_mix.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,293 @@
+#include "multivoc.h"
+
+extern char  *MV_MixDestination;
+extern unsigned long MV_MixPosition;
+
+extern char *MV_LeftVolume;
+extern char *MV_RightVolume;
+
+extern unsigned char *MV_HarshClipTable;
+
+extern int MV_RightChannelOffset;
+extern int MV_SampleSize;
+
+void MV_Mix8BitMono( unsigned long position, unsigned long rate,
+   const char *start, unsigned long length )
+{
+	const unsigned char *src;
+	unsigned char *dest;
+	unsigned int i;
+
+	src = (const unsigned char *)start;
+	dest = (unsigned char *)MV_MixDestination;
+
+	for (i = 0; i < length; i++) {
+		int s = src[position >> 16];
+		int d = *dest;
+		
+		s = MV_LeftVolume[s * 2];
+
+		s += d;
+		
+		s = MV_HarshClipTable[s + 0x80];
+		
+		*dest = (s & 0xff);
+		
+		position += rate;
+		dest += MV_SampleSize;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitStereo( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const unsigned char *src;
+	unsigned char *dest;
+	unsigned int i;
+	
+	src = (const unsigned char *)start;
+	dest = (unsigned char *)MV_MixDestination;
+
+	for (i = 0; i < length; i++) {
+		int s = src[(position >> 16)];
+		int dl = dest[0];
+		int dr = dest[MV_RightChannelOffset];
+		
+		dl += MV_LeftVolume[s * 2];
+		dr += MV_RightVolume[s * 2];
+		
+		dl = MV_HarshClipTable[dl + 0x80];
+		dr = MV_HarshClipTable[dr + 0x80];
+		
+		dest[0] = (dl & 0xff);
+		dest[MV_RightChannelOffset] = (dr & 0xff);
+		
+		position += rate;
+		dest += MV_SampleSize;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitMono( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const short *MV_LeftVolumeS;
+	const unsigned char *src;
+	short *dest;
+	unsigned int i;
+
+	src = (const unsigned char *)start;
+	dest = (short *)MV_MixDestination;
+	
+	MV_LeftVolumeS = (const short *)MV_LeftVolume;
+	
+	for (i = 0; i < length; i++) {
+		int s = src[position >> 16];
+		int d = dest[0];
+		
+		s = MV_LeftVolumeS[s];
+		
+		s += d;
+		
+		if (s < -32768) s = -32768;
+		if (s >  32767) s =  32767;
+		
+		*dest = (short) s;
+		
+		position += rate;
+		dest += MV_SampleSize/2;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitStereo( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const short *MV_LeftVolumeS;
+	const short *MV_RightVolumeS;
+	const unsigned char *src;
+	short *dest;
+	unsigned int i;
+
+	src = (unsigned char *)start;
+	dest = (short *)MV_MixDestination;
+	
+	MV_LeftVolumeS = (const short *)MV_LeftVolume;
+	MV_RightVolumeS = (const short *)MV_RightVolume;
+	
+	for (i = 0; i < length; i++) {
+		int s = src[position >> 16];
+		int dl = dest[0];
+		int dr = dest[MV_RightChannelOffset/2];
+		
+		dl += MV_LeftVolumeS[s];
+		dr += MV_RightVolumeS[s];
+		
+		if (dl < -32768) dl = -32768;
+		if (dl >  32767) dl =  32767;
+		if (dr < -32768) dr = -32768;
+		if (dr >  32767) dr =  32767;
+		
+		dest[0] = (short) dl;
+		dest[MV_RightChannelOffset/2] = (short) dr;
+		
+		position += rate;
+		dest += MV_SampleSize/2;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitMono16( unsigned long position, unsigned long rate,
+   const char *start, unsigned long length )
+{
+	const char *src;
+	unsigned char *dest;
+	unsigned int i;
+
+	src = (const char *)start + 1;
+	dest = (unsigned char *)MV_MixDestination;
+
+	for (i = 0; i < length; i++) {
+		int s = (int)src[(position >> 16) * 2] + 0x80;
+		int d = *dest;
+		
+		s = MV_LeftVolume[s * 2];
+		
+		s += d;
+		
+		s = MV_HarshClipTable[s + 0x80];
+		
+		*dest = (s & 0xff);
+		
+		position += rate;
+		dest += MV_SampleSize;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitStereo16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const char *src;
+	unsigned char *dest;
+	unsigned int i;
+	
+	src = (const char *)start + 1;
+	dest = (unsigned char *)MV_MixDestination;
+	
+	for (i = 0; i < length; i++) {
+		int s = src[(position >> 16) * 2] + 0x80;
+		int dl = dest[0];
+		int dr = dest[MV_RightChannelOffset];
+		
+		dl += MV_LeftVolume[s * 2];
+		dr += MV_RightVolume[s * 2];
+		
+		dl = MV_HarshClipTable[dl + 0x80];
+		dr = MV_HarshClipTable[dr + 0x80];
+		
+		dest[0] = (dl & 0xff);
+		dest[MV_RightChannelOffset] = (dr & 0xff);
+		
+		position += rate;
+		dest += MV_SampleSize;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitMono16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const short *MV_LeftVolumeS;
+	const unsigned char *src;
+	short *dest;
+	unsigned int i;
+	
+	src = (const unsigned char *)start;
+	dest = (short *)MV_MixDestination;
+	
+	MV_LeftVolumeS = (const short *)MV_LeftVolume;
+	
+	for (i = 0; i < length; i++) {
+		int sl = src[(position >> 16) * 2 + 0];
+		int sh = src[(position >> 16) * 2 + 1] ^ 0x80;
+		
+		int d = *dest;
+		
+		sl = MV_LeftVolume[sl * 2 + 1];
+		sh = MV_LeftVolumeS[sh];
+		
+		d = sl + sh + 0x80 + d;
+		
+		if (d < -32768) d = -32768;
+		if (d >  32767) d =  32767;
+		
+		*dest = (short) d;
+		
+		position += rate;
+		dest += MV_SampleSize/2;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitStereo16( unsigned long position,
+   unsigned long rate, const char *start, unsigned long length )
+{
+	const short *MV_LeftVolumeS;
+	const short *MV_RightVolumeS;
+	const unsigned char *src;
+	short *dest;
+	unsigned int i;
+	
+	src = (const unsigned char *)start;
+	dest = (short *)MV_MixDestination;
+	
+	MV_LeftVolumeS = (const short *)MV_LeftVolume;
+	MV_RightVolumeS = (const short *)MV_RightVolume;
+	
+	for (i = 0; i < length; i++) {
+		int sl = src[(position >> 16) * 2 + 0];
+		int sh = src[(position >> 16) * 2 + 1] ^ 0x80;
+		
+		int dl = dest[0];
+		int dr = dest[MV_RightChannelOffset/2];
+		
+		int sll = MV_LeftVolume[sl * 2 + 1];
+		int slh = MV_LeftVolumeS[sh];
+		
+		int srl = MV_RightVolume[sl * 2 + 1];
+		int srh = MV_RightVolumeS[sh];
+		
+		dl = sll + slh + 0x80 + dl;
+		dr = srl + srh + 0x80 + dr;
+		
+		if (dl < -32768) dl = -32768;
+		if (dl >  32767) dl =  32767;
+		if (dr < -32768) dr = -32768;
+		if (dr >  32767) dr =  32767;
+		
+		dest[0] = (short) dl;
+		dest[MV_RightChannelOffset/2] = (short) dr;
+		
+		position += rate;
+		dest += MV_SampleSize/2;
+	}
+	
+	MV_MixPosition = position;
+	MV_MixDestination = (char *)dest;
+}

Added: tags/rott-1.1/rott/audiolib/mv_mix16.asm
===================================================================
--- tags/rott-1.1/rott/audiolib/mv_mix16.asm	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mv_mix16.asm	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,524 @@
+        IDEAL
+
+        p386
+        MODEL  flat
+
+        dataseg
+        CODESEG
+
+        MASM
+        ALIGN 4
+
+EXTRN   _MV_HarshClipTable:DWORD
+EXTRN   _MV_MixDestination:DWORD
+EXTRN   _MV_MixPosition:DWORD
+EXTRN   _MV_LeftVolume:DWORD
+EXTRN   _MV_RightVolume:DWORD
+EXTRN   _MV_SampleSize:DWORD
+EXTRN   _MV_RightChannelOffset:DWORD
+
+;================
+;
+; MV_Mix8BitMono16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix8BitMono16_
+PUBLIC  MV_Mix8BitMono16_
+; Two at once
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+        inc     esi
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET apatch7+2            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET apatch8+2            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET apatch9+3            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume             ; Since we're mono, use left volume
+        mov     eax,OFFSET apatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET apatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Harsh Clip table ptr
+        mov     ebx, _MV_HarshClipTable
+        add     ebx, 128
+        mov     eax,OFFSET apatch3+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET apatch4+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET apatch5+2            ; convice tasm to modify code...
+        mov     [eax],edx
+        mov     eax,OFFSET apatch6+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        shr     ecx, 1                          ; double sample count
+        cmp     ecx, 0
+        je      exit8m
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; apatch1 - volume table
+; apatch2 - volume table
+; apatch3 - harsh clip table
+; apatch4 - harsh clip table
+; apatch5 - sample rate
+; apatch6 - sample rate
+
+        mov     eax,ebp                         ; begin calculating first sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     eax,16                          ; finish calculation for first sample
+
+        mov     ebx,ebp                         ; begin calculating second sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     ebx,16                          ; finish calculation for second sample
+
+        movsx   eax, byte ptr [esi+2*eax]       ; get first sample
+        movsx   ebx, byte ptr [esi+2*ebx]       ; get second sample
+        add     eax, 80h
+        add     ebx, 80h
+
+        ALIGN 4
+mix8Mloop:
+        movzx   edx, byte ptr [edi]             ; get current sample from destination
+apatch1:
+        movsx   eax, byte ptr [2*eax+12345678h] ; volume translate first sample
+apatch2:
+        movsx   ebx, byte ptr [2*ebx+12345678h] ; volume translate second sample
+        add     eax, edx                        ; mix first sample
+apatch9:
+        movzx   edx, byte ptr [edi + 1]         ; get current sample from destination
+apatch3:
+        mov     eax, [eax + 12345678h]          ; harsh clip new sample
+        add     ebx, edx                        ; mix second sample
+        mov     [edi], al                       ; write new sample to destination
+        mov     edx, ebp                        ; begin calculating third sample
+apatch4:
+        mov     ebx, [ebx + 12345678h]          ; harsh clip new sample
+apatch5:
+        add     ebp,12345678h                   ; advance frac pointer
+        shr     edx, 16                         ; finish calculation for third sample
+        mov     eax, ebp                        ; begin calculating fourth sample
+apatch7:
+        add     edi, 2                          ; move destination to second sample
+        shr     eax, 16                         ; finish calculation for fourth sample
+        mov     [edi], bl                       ; write new sample to destination
+apatch6:
+        add     ebp,12345678h                   ; advance frac pointer
+        movsx   ebx, byte ptr [esi+2*eax]         ; get fourth sample
+        movsx   eax, byte ptr [esi+2*edx]         ; get third sample
+        add     ebx, 80h
+        add     eax, 80h
+apatch8:
+        add     edi, 2                          ; move destination to third sample
+        dec     ecx                             ; decrement count
+        jnz     mix8Mloop                       ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+exit8m:
+        popad
+        ret
+ENDP    MV_Mix8BitMono16_
+
+;================
+;
+; MV_Mix8BitStereo16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix8BitStereo16_
+PUBLIC  MV_Mix8BitStereo16_
+
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+        inc     esi
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET bpatch8+2            ; convice tasm to modify code...
+        mov     [eax],bl
+ ;       mov     eax,OFFSET bpatch9+2            ; convice tasm to modify code...
+ ;       mov     [eax],bl
+
+        ; Right channel offset
+        mov     ebx, _MV_RightChannelOffset
+        mov     eax,OFFSET bpatch6+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET bpatch7+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET bpatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        mov     ebx, _MV_RightVolume
+        mov     eax,OFFSET bpatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET bpatch3+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        ; Harsh Clip table ptr
+        mov     ebx, _MV_HarshClipTable
+        add     ebx,128
+        mov     eax,OFFSET bpatch4+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET bpatch5+2            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        cmp     ecx, 0
+        je      short exit8S
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; bpatch1 - left volume table
+; bpatch2 - right volume table
+; bpatch3 - sample rate
+; bpatch4 - harsh clip table
+; bpatch5 - harsh clip table
+
+        mov     eax,ebp                         ; begin calculating first sample
+        shr     eax,16                          ; finish calculation for first sample
+
+        movsx   ebx, byte ptr [esi+2*eax]       ; get first sample
+        add     ebx, 80h
+
+        ALIGN 4
+mix8Sloop:
+bpatch1:
+        movsx   eax, byte ptr [2*ebx+12345678h] ; volume translate left sample
+        movzx   edx, byte ptr [edi]             ; get current sample from destination
+bpatch2:
+        movsx   ebx, byte ptr [2*ebx+12345678h] ; volume translate right sample
+        add     eax, edx                        ; mix left sample
+bpatch3:
+        add     ebp,12345678h                   ; advance frac pointer
+bpatch6:
+        movzx   edx, byte ptr [edi+12345678h]   ; get current sample from destination
+bpatch4:
+        mov     eax, [eax + 12345678h]          ; harsh clip left sample
+        add     ebx, edx                        ; mix right sample
+        mov     [edi], al                       ; write left sample to destination
+bpatch5:
+        mov     ebx, [ebx + 12345678h]          ; harsh clip right sample
+        mov     edx, ebp                        ; begin calculating second sample
+bpatch7:
+        mov     [edi+12345678h], bl             ; write right sample to destination
+        shr     edx, 16                         ; finish calculation for second sample
+bpatch8:
+        add     edi, 1                          ; move destination to second sample
+        movsx   ebx, byte ptr [esi+2*edx]       ; get second sample
+        add     ebx, 80h
+        dec     ecx                             ; decrement count
+        jnz     mix8Sloop                       ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+
+EXIT8S:
+        popad
+        ret
+ENDP    MV_Mix8BitStereo16_
+
+;================
+;
+; MV_Mix16BitMono16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix16BitMono16_
+PUBLIC  MV_Mix16BitMono16_
+
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET cpatch4+2            ; convice tasm to modify code...
+        mov     [eax],bl
+        mov     eax,OFFSET cpatch5+3            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET cpatch2+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET cpatch1+4            ; convice tasm to modify code...
+        inc     ebx
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET cpatch3+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        cmp     ecx, 0
+        je exit16M
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     ecx - count
+;     edi - destination
+;     esi - source
+;     ebp - frac pointer
+; cpatch1 - volume table
+; cpatch2 - volume table
+; cpatch3 - sample rate
+; cpatch4 - sample rate
+
+        mov     ebx,ebp                         ; begin calculating first sample
+        add     ebp,edx                         ; advance frac pointer
+        shr     ebx,16                          ; finish calculation for first sample
+        movzx   eax, word ptr [esi+2*ebx]       ; get low byte of sample
+        xor     eax, 8000h
+        movzx   ebx, ah
+        sub     ah, ah
+
+        movsx   edx, word ptr [edi]             ; get current sample from destination
+
+        ALIGN 4
+mix16Mloop:
+cpatch1:
+        movsx   eax, byte ptr [2*eax+12345678h] ; volume translate low byte of sample
+cpatch2:
+        movsx   ebx, word ptr [2*ebx+12345678h] ; volume translate high byte of sample
+        lea     eax, [ eax + ebx + 80h ]        ; mix high byte of sample
+        add     eax, edx                        ; mix low byte of sample
+cpatch5:
+        movsx   edx, word ptr [edi + 2]         ; get current sample from destination
+
+        cmp     eax, -32768                     ; Harsh clip sample
+        jge     short m16skip1
+        mov     eax, -32768
+        jmp     short m16skip2
+m16skip1:
+        cmp     eax, 32767
+        jle     short m16skip2
+        mov     eax, 32767
+m16skip2:
+        mov     ebx, ebp                        ; begin calculating second sample
+        mov     [edi], ax                       ; write new sample to destination
+
+        shr     ebx, 16                         ; finish calculation for second sample
+cpatch3:
+        add     ebp, 12345678h                  ; advance frac pointer
+
+        movzx   eax, word ptr [esi+2*ebx]       ; get second sample
+cpatch4:
+        add     edi, 2                          ; move destination to second sample
+        xor     eax, 8000h
+        movzx   ebx, ah
+        sub     ah, ah
+
+        dec     ecx                             ; decrement count
+        jnz     mix16Mloop                      ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+EXIT16M:
+        popad
+        ret
+ENDP    MV_Mix16BitMono16_
+
+;================
+;
+; MV_Mix16BitStereo16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC    MV_Mix16BitStereo16_
+PUBLIC  MV_Mix16BitStereo16_
+
+        pushad
+        mov     ebp, eax
+
+        mov     esi, ebx                        ; Source pointer
+
+        ; Sample size
+        mov     ebx, _MV_SampleSize
+        mov     eax,OFFSET dpatch9+2            ; convice tasm to modify code...
+        mov     [eax],bl
+
+        ; Right channel offset
+        mov     ebx, _MV_RightChannelOffset
+        mov     eax,OFFSET dpatch7+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET dpatch8+3            ; convice tasm to modify code...
+        mov     [eax],ebx
+
+        ; Volume table ptr
+        mov     ebx, _MV_LeftVolume
+        mov     eax,OFFSET dpatch1+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET dpatch2+4            ; convice tasm to modify code...
+        inc     ebx
+        mov     [eax],ebx
+
+        mov     ebx, _MV_RightVolume
+        mov     eax,OFFSET dpatch3+4            ; convice tasm to modify code...
+        mov     [eax],ebx
+        mov     eax,OFFSET dpatch4+4            ; convice tasm to modify code...
+        inc     ebx
+        mov     [eax],ebx
+
+        ; Rate scale ptr
+        mov     eax,OFFSET dpatch5+2            ; convice tasm to modify code...
+        mov     [eax],edx
+
+        ; Source ptr
+        mov     eax,OFFSET dpatch6+4            ; convice tasm to modify code...
+        mov     [eax],esi
+
+        mov     edi, _MV_MixDestination         ; Get the position to write to
+
+        ; Number of samples to mix
+        cmp     ecx, 0
+        je      exit16S
+
+;     eax - scratch
+;     ebx - scratch
+;     edx - scratch
+;     esi - scratch
+;     ecx - count
+;     edi - destination
+;     ebp - frac pointer
+; dpatch1 - left volume table
+; dpatch2 - right volume table
+; dpatch3 - sample rate
+
+        mov     ebx,ebp                         ; begin calculating first sample
+        shr     ebx,16                          ; finish calculation for first sample
+
+        movzx   edx, word ptr [esi+2*ebx]       ; get first sample
+        xor     edx, 8000h                      ; Change from signed to unsigned
+        movzx   esi, dh                         ; put high byte in esi
+        sub     dh, dh                          ; lo byte in edx
+
+        ALIGN 4
+mix16Sloop:
+        ; Left channel
+dpatch1:
+        movsx   eax, word ptr [2*esi+12345678h] ; volume translate high byte of sample
+dpatch2:
+        movsx   ebx, byte ptr [2*edx+12345678h] ; volume translate low byte of sample
+        lea     eax, [ eax + ebx + 80h ]        ; mix high byte of sample
+
+        ; Right channel
+dpatch3:
+        movsx   esi, word ptr [2*esi+12345678h] ; volume translate high byte of sample
+dpatch4:
+        movsx   ebx, byte ptr [2*edx+12345678h] ; volume translate low byte of sample
+        lea     ebx, [ esi + ebx + 80h ]        ; mix high byte of sample
+
+dpatch7:
+        movsx   edx, word ptr [edi+12345678h]   ; get current sample from destination
+dpatch5:
+        add     ebp,12345678h                   ; advance frac pointer
+
+        add     eax, edx                        ; mix left sample
+
+        cmp     eax, -32768                     ; Harsh clip sample
+        jge     short s16skip1
+        mov     eax, -32768
+        jmp     short s16skip2
+s16skip1:
+        cmp     eax, 32767
+        jle     short s16skip2
+        mov     eax, 32767
+s16skip2:
+        movsx   edx, word ptr [edi+2]           ; get current sample from destination
+        mov     [edi], ax                       ; write left sample to destination
+        add     ebx, edx                        ; mix right sample
+
+        cmp     ebx, -32768                     ; Harsh clip sample
+        jge     short s16skip3
+        mov     ebx, -32768
+        jmp     short s16skip4
+s16skip3:
+        cmp     ebx, 32767
+        jle     short s16skip4
+        mov     ebx, 32767
+s16skip4:
+
+        mov     edx, ebp                        ; begin calculating second sample
+dpatch8:
+        mov     [edi+12345678h], bx             ; write right sample to destination
+        shr     edx, 16                         ; finish calculation for second sample
+dpatch9:
+        add     edi, 4                          ; move destination to second sample
+
+dpatch6:
+        movzx   edx, word ptr [2*edx+12345678h] ; get second sample
+        xor     edx, 8000h                      ; Change from signed to unsigned
+        movzx   esi, dh                         ; put high byte in esi
+        sub     dh, dh                          ; lo byte in edx
+
+        dec     ecx                             ; decrement count
+        jnz     mix16Sloop                      ; loop
+
+        mov     _MV_MixDestination, edi         ; Store the current write position
+        mov     _MV_MixPosition, ebp            ; return position
+exit16S:
+        popad
+        ret
+ENDP    MV_Mix16BitStereo16_
+
+        ENDS
+
+        END

Added: tags/rott-1.1/rott/audiolib/mvreverb.asm
===================================================================
--- tags/rott-1.1/rott/audiolib/mvreverb.asm	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mvreverb.asm	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,181 @@
+        IDEAL
+
+        p386
+        MODEL  flat
+
+        dataseg
+        CODESEG
+
+        MASM
+        ALIGN 4
+
+;================
+;
+; MV_16BitReverb
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - Volume table
+; ecx - number of samples
+
+PROC    MV_16BitReverb_
+PUBLIC  MV_16BitReverb_
+
+        mov     esi, eax
+        lea     edi, [edx - 2]
+
+        ALIGN 4
+rev16loop:
+        movzx   eax, word ptr [esi]             ; get sample
+        add     edi, 2
+
+        movzx   edx, ah
+        sub     ah, ah
+
+        movsx   eax, byte ptr [2*eax+ebx+1]     ; volume translate low byte of sample
+        xor     edx, 80h
+
+        movsx   edx, word ptr [2*edx+ebx]       ; volume translate high byte of sample
+        add     esi, 2
+
+        lea     eax, [ eax + edx + 80h ]        ; mix high byte of sample
+        dec     ecx                             ; decrement count
+
+        mov     [edi], ax                       ; write new sample to destination
+        jnz     rev16loop                       ; loop
+
+        ret
+ENDP    MV_16BitReverb_
+
+;================
+;
+; MV_8BitReverb
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - Volume table
+; ecx - number of samples
+
+PROC    MV_8BitReverb_
+PUBLIC  MV_8BitReverb_
+
+        mov     esi, eax
+        lea     edi, [edx - 1]
+
+        xor     eax, eax
+
+        ALIGN 4
+rev8loop:
+;        movzx   eax, byte ptr [esi]             ; get sample
+        mov     al, byte ptr [esi]              ; get sample
+        inc     edi
+
+;        movsx   eax, byte ptr [2*eax+ebx]       ; volume translate sample
+        mov     al, byte ptr [2*eax+ebx]        ; volume translate sample
+        inc     esi
+
+;        add     eax, 80h
+        add     al, 80h
+        dec     ecx                             ; decrement count
+
+        mov     [edi], al                       ; write new sample to destination
+        jnz     rev8loop                        ; loop
+
+        ret
+ENDP    MV_8BitReverb_
+
+;================
+;
+; MV_16BitReverbFast
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - number of samples
+; ecx - shift
+
+PROC    MV_16BitReverbFast_
+PUBLIC  MV_16BitReverbFast_
+
+        mov     esi, eax
+        mov     eax,OFFSET rpatch16+3
+
+        mov     [eax],cl
+        lea     edi, [edx - 2]
+
+        ALIGN 4
+frev16loop:
+        mov     ax, word ptr [esi]             ; get sample
+        add     edi, 2
+
+rpatch16:
+        sar     ax, 5    ;;;;Add 1 before shift
+        add     esi, 2
+
+        mov     [edi], ax                       ; write new sample to destination
+        dec     ebx                             ; decrement count
+
+        jnz     frev16loop                      ; loop
+
+        ret
+ENDP    MV_16BITREVERBFAST_
+
+;================
+;
+; MV_8BitReverbFast
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - number of samples
+; ecx - shift
+
+PROC    MV_8BitReverbFast_
+PUBLIC  MV_8BitReverbFast_
+        mov     esi, eax
+        mov     eax,OFFSET rpatch8+2
+
+        mov     edi, edx
+        mov     edx, 80h
+
+        mov     [eax],cl
+        mov     eax, 80h
+
+        shr     eax, cl
+
+        dec     edi
+        sub     edx, eax
+
+        ALIGN 4
+frev8loop:
+        mov     al, byte ptr [esi]             ; get sample
+        inc     esi
+
+        mov     ecx, eax
+        inc     edi
+
+rpatch8:
+        shr     eax, 3
+        xor     ecx, 80h                        ; flip the sign bit
+
+        shr     ecx, 7                          ; shift the sign down to 1
+        add     eax, edx
+
+        add     eax, ecx                        ; add sign bit to round to 0
+        dec     ebx                             ; decrement count
+
+        mov     [edi], al                       ; write new sample to destination
+        jnz     frev8loop                       ; loop
+
+        ret
+ENDP    MV_8BITREVERBFAST_
+
+        ENDS
+
+        END

Added: tags/rott-1.1/rott/audiolib/mvreverb.c
===================================================================
--- tags/rott-1.1/rott/audiolib/mvreverb.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/mvreverb.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,58 @@
+#include "multivoc.h"
+#include "_multivc.h"
+
+void MV_16BitReverb( const char *src, char *dest, const VOLUME16 *volume, int count )
+{
+	int i;
+
+	short *pdest = (short *)dest;
+	
+	for (i = 0; i < count; i++) {
+		int sl = src[i*2+0];
+		int sh = src[i*2+1] ^ 0x80;
+		
+		sl = (*volume)[sl] >> 8;
+		sh = (*volume)[sh];
+		
+		pdest[i] = (short)(sl + sh + 0x80);
+	}
+}
+
+void MV_8BitReverb( const signed char *src, signed char *dest, const VOLUME16 *volume, int count )
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		unsigned char s = (unsigned char) src[i];
+		
+		s = (*volume)[s] & 0xff;
+		
+		dest[i] = (char)(s + 0x80);
+	}
+}
+
+void MV_16BitReverbFast( const char *src, char *dest, int count, int shift )
+{
+	int i;
+
+	short *pdest = (short *)dest;
+	const short *psrc = (const short *)src;
+	
+	for (i = 0; i < count; i++) {
+		pdest[i] = psrc[i] >> shift;
+	}
+}
+
+void MV_8BitReverbFast( const signed char *src, signed char *dest, int count, int shift )
+{
+	int i;
+
+	unsigned char sh = 0x80 - (0x80 >> shift);
+	
+	for (i = 0; i < count; i++) {
+		unsigned char a = ((unsigned char) src[i]) >> shift;
+		unsigned char c = (((unsigned char) src[i]) ^ 0x80) >> 7;
+		
+		dest[i] = (signed char) (a + sh + c);
+	}
+}

Added: tags/rott-1.1/rott/audiolib/myprint.c
===================================================================
--- tags/rott-1.1/rott/audiolib/myprint.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/myprint.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,310 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "myprint.h"
+
+static unsigned short disp_offset = 160 * 24;
+
+void DrawText
+   (
+   int x,
+   int y,
+   int ch,
+   int foreground,
+   int background
+   )
+
+   {
+   char *vid;
+
+   vid  = ( char * )( 0xb0000 );
+   vid += y * 160;
+   vid += x * 2;
+
+   if ( ch != NONE )
+      {
+      *vid = ch;
+      }
+   vid++;
+   *vid = ( ( background & 0x0f ) << 4 ) | ( foreground & 0x0f );
+   }
+
+void TextBox
+   (
+   int  x1,
+   int  y1,
+   int  x2,
+   int  y2,
+   int ch,
+   int  foreground,
+   int  background
+   )
+
+   {
+   int x;
+   int y;
+
+   for( x = x1; x <= x2; x++ )
+      {
+      for( y = y1; y <= y2; y++ )
+         {
+         DrawText( x, y, ch, foreground, background );
+         }
+      }
+   }
+
+void TextFrame
+   (
+   int x1,
+   int y1,
+   int x2,
+   int y2,
+   int type,
+   int foreground,
+   int background
+   )
+
+   {
+   int x;
+   int y;
+
+   if ( type == 0 )
+      {
+      for( x = x1 + 1; x < x2; x++ )
+         {
+         DrawText( x, y1, type, foreground, background );
+         DrawText( x, y2, type, foreground, background );
+         }
+      for( y = y1 + 1; y < y2; y++ )
+         {
+         DrawText( x1, y, type, foreground, background );
+         DrawText( x2, y, type, foreground, background );
+         }
+      }
+   if ( type == SINGLE_FRAME )
+      {
+      DrawText( x1, y1, 'Ú', foreground, background );
+      DrawText( x2, y1, '¿', foreground, background );
+      DrawText( x1, y2, 'À', foreground, background );
+      DrawText( x2, y2, 'Ù', foreground, background );
+      for( x = x1 + 1; x < x2; x++ )
+         {
+         DrawText( x, y1, 'Ä', foreground, background );
+         DrawText( x, y2, 'Ä', foreground, background );
+         }
+      for( y = y1 + 1; y < y2; y++ )
+         {
+         DrawText( x1, y, '³', foreground, background );
+         DrawText( x2, y, '³', foreground, background );
+         }
+      }
+   if ( type == DOUBLE_FRAME )
+      {
+      DrawText( x1, y1, 'É', foreground, background );
+      DrawText( x2, y1, '»', foreground, background );
+      DrawText( x1, y2, 'È', foreground, background );
+      DrawText( x2, y2, '¼', foreground, background );
+      for( x = x1 + 1; x < x2; x++ )
+         {
+         DrawText( x, y1, 'Í', foreground, background );
+         DrawText( x, y2, 'Í', foreground, background );
+         }
+      for( y = y1 + 1; y < y2; y++ )
+         {
+         DrawText( x1, y, 'º', foreground, background );
+         DrawText( x2, y, 'º', foreground, background );
+         }
+      }
+   }
+
+void mysetxy
+   (
+   int x,
+   int y
+   )
+
+   {
+   disp_offset = ( x * 2 ) + ( y * 160 );
+   }
+
+void myputch
+   (
+   char ch
+   )
+
+   {
+   int j;
+   char *disp_start = (char *)( 0xb0000 );
+
+   if ( disp_offset >= 160 * 24 )
+      {
+      for ( j = 160; j < 160 * 24; j += 2 )
+         {
+         *( disp_start + j - 160 ) = *( disp_start + j );
+         }
+
+      disp_offset = 160 * 23;
+
+      for ( j = disp_offset; j < ( 160 * 24 ); j += 2 )
+         {
+         *( disp_start + j ) = ' ';
+         }
+      }
+
+   if ( ch >= 32 )
+      {
+      *( disp_start + disp_offset ) = ch;
+      disp_offset = disp_offset + 2;
+      }
+
+   if ( ch == '\r' )
+      {
+      disp_offset = disp_offset / 160;
+      disp_offset = disp_offset * 160;
+      }
+
+   if ( ch == '\n' )
+      {
+      disp_offset = disp_offset + 160;
+      if ( disp_offset < 160 * 24 )
+         {
+         for ( j = disp_offset; j < ( ( ( disp_offset / 160 ) + 1 ) *
+            160 ); j += 2 )
+            {
+            *( disp_start + j ) = ' ';
+            }
+         }
+      }
+   }
+
+int printstring
+   (
+   char *string
+   )
+
+   {
+   int count;
+   char *ptr;
+
+   ptr = string;
+   count = 0;
+
+   while ( *ptr )
+      {
+      myputch( *ptr );
+      count++;
+      ptr++;
+      }
+
+   return( count );
+   }
+
+
+int printnum
+   (
+   int number
+   )
+
+   {
+   char string[ 100 ];
+   int  count;
+
+   itoa( number, string, 10 );
+   count = printstring( string );
+
+   return( count );
+   }
+
+int printunsigned
+   (
+   unsigned long number,
+   int radix
+   )
+
+   {
+   char string[ 100 ];
+   int  count;
+
+   ultoa( number, string, radix );
+   count = printstring( string );
+
+   return( count );
+   }
+
+int myprintf
+   (
+   char *fmt,
+   ...
+   )
+
+   {
+   va_list argptr;
+   int     count;
+   char    *ptr;
+
+   return( 0 );
+
+   // DEBUG
+   mysetxy( 0, 0 );
+
+   va_start( argptr, fmt );
+   ptr = fmt;
+   count = 0;
+
+   while( *ptr != 0 )
+      {
+      if ( *ptr == '%' )
+         {
+         ptr++;
+         switch( *ptr )
+            {
+            case 0 :
+               return( EOF );
+               break;
+            case 'd' :
+               count += printnum( va_arg( argptr, int ) );
+               break;
+            case 's' :
+               count += printstring( va_arg( argptr, char * ) );
+               break;
+            case 'u' :
+               count += printunsigned( va_arg( argptr, int ), 10 );
+               break;
+            case 'x' :
+            case 'X' :
+               count += printunsigned( va_arg( argptr, int ), 16 );
+               break;
+            }
+         ptr++;
+         }
+      else
+         {
+         myputch( *ptr );
+         count++;
+         ptr++;
+         }
+      }
+
+   va_end( argptr );
+
+   return( count );
+   }

Added: tags/rott-1.1/rott/audiolib/myprint.h
===================================================================
--- tags/rott-1.1/rott/audiolib/myprint.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/myprint.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,43 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+#ifndef __MYPRINT_H
+#define __MYPRINT_H
+
+enum COLORS
+   {
+   BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY,
+   LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
+   };
+
+#define NONE         -1
+#define SINGLE_FRAME -1
+#define DOUBLE_FRAME -2
+
+void DrawText( int x, int y, int ch, int foreground, int background );
+void TextBox( int x1, int y1, int x2, int y2, int ch, int foreground, int background );
+void TextFrame( int x1, int y1, int x2, int y2, int type, int foreground, int background );
+void mysetxy( int x, int y );
+void myputch( char ch );
+int  printstring( char *string );
+int  printnum( int number );
+int  printunsigned( unsigned long number, int radix );
+int  myprintf( char *fmt, ... );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/newgf1.h
===================================================================
--- tags/rott-1.1/rott/audiolib/newgf1.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/newgf1.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,431 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/***************************************************************************
+*	NAME:  GF1.H
+**	COPYRIGHT:
+**	"Copyright (c) 1991,1992, by FORTE
+**
+**       "This software is furnished under a license and may be used,
+**       copied, or disclosed only in accordance with the terms of such
+**       license and with the inclusion of the above copyright notice.
+**       This software or any other copies thereof may not be provided or
+**       otherwise made available to any other person. No title to and
+**       ownership of the software is hereby transfered."
+****************************************************************************
+*  CREATION DATE: 07/01/92
+*--------------------------------------------------------------------------*
+*     VERSION	DATE	   NAME		DESCRIPTION
+*>	1.0	07/01/92		Original
+***************************************************************************/
+
+#ifndef	_GF1_H		/* allow header to be processed only once */
+#define _GF1_H
+
+/* error codes */
+#define OK			0
+#define NO_MORE_VOICES		-1
+#define	BASE_NOT_FOUND		1
+#define BAD_IRQ			2
+#define BAD_DMA			3
+#define OS_LOADED		4
+#define NOT_LOADED		5
+#define NO_MEMORY		6
+#define DMA_BUSY		7
+#define NO_MORE_HANDLERS	8
+#define DMA_HUNG		9
+#define CARD_NOT_FOUND		10
+#define CARD_BEING_USED		11
+#define NO_MORE_INTERRUPTS	12
+#define BAD_TIMER		13
+#define BAD_PATCH		14
+#define OLD_PATCH		15
+#define DOS_ERROR		16
+#define FILE_NOT_FOUND		17
+
+/* bits */
+#define	BIT0	0x01
+#define	BIT1	0x02
+#define	BIT2	0x04
+#define	BIT3	0x08
+#define	BIT4	0x10
+#define	BIT5	0x20
+#define	BIT6	0x40
+#define	BIT7	0x80
+
+/* bounds for volume enveloping functions */
+#define MIN_OFFSET      5U
+#define MAX_OFFSET      251U
+
+/* bounds for voice allocation */
+#define MIN_VOICES	14
+#define MAX_VOICES	32
+
+/* DMA control bits */
+#define DMA_ENABLE		BIT0
+#define DMA_READ		BIT1
+#define DMA_WIDTH_16		BIT2 /* width of DMA channel */
+#define DMA_RATE_DIV_1		BIT3
+#define DMA_RATE_DIV_2		BIT4
+#define DMA_IRQ_ENABLE		BIT5
+#define DMA_IRQ_PRESENT		BIT6
+#define DMA_DATA_16		BIT6 /* width of data */
+#define DMA_INVERT_MSB		BIT7
+
+/* SAMPLE control bits */
+#define DMA_STEREO		2
+
+/* DMA flags */
+#define GF1_RECORD	0 /* use dma control or sample control */
+#define GF1_DMA		1
+
+/* MIDI control register */
+#define MIDI_RESET	(BIT0|BIT1)
+#define MIDI_TD_INT	BIT5
+#define MIDI_RD_INT	BIT7
+
+/* MIDI_STATUS_REGISTER */
+#define MIDI_RD		BIT0
+#define MIDI_TD		BIT1
+#define MIDI_ERR_FRAMING BIT4
+#define MIDI_ERR_OVERRUN BIT5
+
+/* digital playback flags */
+#define TYPE_8BIT	BIT0	/* 1 use 8 bit data */
+				/* 0 use 16 bit data */
+#define TYPE_PRELOAD	BIT1	/* preload data */
+#define TYPE_INVERT_MSB BIT2	/* invert most significant bit during dma */
+#define TYPE_STEREO	BIT3	/* 1 for stereo data */
+
+/* sound effects and digital music types */
+#define SND_LOOP_MASK		(BIT0|BIT1)
+#define SND_LOOP_NONE		0
+#define SND_LOOP		1
+#define SND_LOOP_BIDIR		2
+#define SND_8BIT		(BIT2)
+#define SND_BACKWARD		(BIT3)
+
+#define SOUND_PLAYING		2
+#define SOUND_ACTIVE		1
+
+/* patch macros */
+#define HEADER_SIZE	           12
+#define ID_SIZE		           10
+#define DESC_SIZE 	           60
+#define RESERVED_SIZE	           40
+#define PATCH_HEADER_RESERVED_SIZE 36
+#define LAYER_RESERVED_SIZE	   40
+#define PATCH_DATA_RESERVED_SIZE   36
+#define GF1_HEADER_TEXT            "GF1PATCH110"
+#define INST_NAME_SIZE		   16
+#define ENVELOPES		   6
+#define MAX_LAYERS		   4
+
+/* patch modes */
+#define PATCH_16		BIT0
+#define PATCH_UNSIGNED		BIT1
+#define PATCH_LOOPEN		BIT2
+#define PATCH_BIDIR		BIT3
+#define PATCH_BACKWARD  	BIT4
+#define PATCH_SUSTAIN   	BIT5
+#define PATCH_NO_SRELEASE	BIT6
+#define PATCH_FAST_REL		BIT7
+
+/* flags for patch loading */
+#define PATCH_LOAD_8_BIT BIT0
+
+/* digital playback callback reasons & return values */
+#define	DIG_DONE	   0
+#define DIG_MORE_DATA	   1
+#define DIG_BUFFER_DONE    2
+#define DIG_PAUSE          3
+
+/* log table used for vibrato and pitch bend.  log table made public for
+** developers use */
+#define LOG_TAB_SIZE 12
+extern long gf1_log_table[LOG_TAB_SIZE];
+
+#if defined(__BORLANDC__)
+#undef RFAR
+#define RFAR far
+#elif defined(_MSC_VER) && (_MSC_VER <= 600)
+#define RFAR far
+#elif defined(_MSC_VER) && (_MSC_VER > 600)
+#define RFAR __far
+#else
+#undef RFAR
+#define RFAR
+#endif
+
+/* structure definitions */
+struct	load_os	
+{
+	unsigned short 	voices;
+	unsigned short	forced_base_port;
+	unsigned char	forced_gf1_irq;
+	unsigned char	forced_midi_irq;
+	unsigned char	forced_channel_in;
+	unsigned char	forced_channel_out;
+};
+
+struct	patchheader
+{
+	char		header[ HEADER_SIZE ];	
+	char		gravis_id[ ID_SIZE ];	/* Id = "ID#000002" */
+	char		description[ DESC_SIZE ];
+	unsigned char	instruments;
+	char		voices;
+	char		channels;
+	unsigned short	wave_forms;
+	unsigned short	master_volume;
+	unsigned long	data_size;
+	char		reserved[ PATCH_HEADER_RESERVED_SIZE ];
+};
+
+struct	instrumentdata
+{
+	unsigned short	instrument;
+	char		instrument_name[ INST_NAME_SIZE ];
+	long		instrument_size;
+	char		layers;
+	char		reserved[ RESERVED_SIZE ];	
+};
+
+struct	layerdata
+{
+	char		layer_duplicate;
+	char		layer;
+	long		layer_size;
+	char		samples;
+	char		reserved[ LAYER_RESERVED_SIZE ];	
+};
+
+struct	patchdata
+{
+	char		wave_name[7];
+	unsigned char	fractions;
+	long		wave_size;
+	long		start_loop;
+	long		end_loop;
+	unsigned short	sample_rate;
+	long		low_frequency;
+	long		high_frequency;
+	long		root_frequency;
+	short		tune;
+	unsigned char	balance;
+	unsigned char	envelope_rate[ ENVELOPES ];
+	unsigned char	envelope_offset[ ENVELOPES ];	
+	unsigned char	tremolo_sweep;
+	unsigned char	tremolo_rate;
+	unsigned char	tremolo_depth;
+	unsigned char	vibrato_sweep;
+	unsigned char	vibrato_rate;
+	unsigned char	vibrato_depth;
+	char		modes;
+	short		scale_frequency;
+	unsigned short	scale_factor;		/* from 0 to 2048 or 0 to 2 */
+	char		reserved[ PATCH_DATA_RESERVED_SIZE ];
+};
+
+struct wave_struct
+{
+	unsigned long		start_loop;
+	unsigned long		end_loop;
+	long		low_frequency;
+	long		high_frequency;
+	long		root_frequency;
+	unsigned long	mem;
+	unsigned short	scale_frequency;
+	unsigned short	sample_rate;
+	unsigned short	scale_factor;
+	unsigned short	start_acc_low;
+	unsigned short	start_acc_high;
+	unsigned short	start_low;
+	unsigned short	start_high;
+	unsigned short	end_low;
+	unsigned short	end_high;
+	unsigned short	end_acc_low;
+	unsigned short	end_acc_high;
+	unsigned short	sample_ratio;
+	unsigned long	wave_size;
+	unsigned char	fractions;
+	unsigned char	balance;
+	unsigned char	envelope_rate[ ENVELOPES ];
+	unsigned char	envelope_offset[ ENVELOPES ];	
+	unsigned char	tremolo_sweep;
+	unsigned char	tremolo_rate;
+	unsigned char	tremolo_depth;
+	unsigned char	vibrato_sweep;
+	unsigned char	vibrato_rate;
+	unsigned char	vibrato_depth;
+	unsigned char	modes;
+};
+
+struct patchinfo {
+	struct patchheader header;
+	struct instrumentdata idata;
+};
+
+struct patch {
+	short nlayers;
+	struct wave_struct RFAR *layer_waves[MAX_LAYERS];
+	short layer_nwaves[MAX_LAYERS];
+	unsigned short detune;
+};
+
+struct gf1_dma_buff {
+	unsigned char RFAR *vptr;
+	unsigned long paddr;
+};
+
+struct gf1_sound {
+	unsigned long mem_pos;
+	unsigned long start_loop;
+	unsigned long end_loop;
+	unsigned char type;
+};
+
+/* GLOBAL VARIABLES (flags) */
+extern char gf1_linear_volumes;
+extern char gf1_dig_use_extra_voice;
+
+/* FUNCTION PROTOTYPES */
+/* Initializeation routines */
+int	gf1_init_ports(int);
+int	gf1_load_os(struct load_os RFAR *os);
+int	gf1_unload_os(void);
+void	gf1_set_appname(char RFAR *);
+void	reset_ultra(int);
+int	gf1_asm_init(void);
+unsigned char gf1_peek(unsigned long address);
+void gf1_poke(unsigned long address, unsigned char data);
+void gf1_poke_block(unsigned char RFAR *data, unsigned long address, unsigned long len, unsigned char dma_control);
+char gf1_good_dram(unsigned long address);
+int GetUltraCfg(struct load_os RFAR *os);
+unsigned long gf1_malloc(unsigned long);
+void gf1_free(unsigned long);
+unsigned long gf1_mem_avail(void);
+unsigned long gf1_mem_largest_avail(void);
+void gf1_delay(void);
+int gf1_allocate_voice(int priority, void (RFAR *steal_notify)(int));
+void gf1_free_voice(unsigned int i);
+void gf1_adjust_priority(int voice, int priority);
+int gf1_dram_xfer(struct gf1_dma_buff RFAR *dptr, unsigned long size, unsigned long dram_address, unsigned char dma_control, unsigned short flags);
+void gf1_stop_dma(void);
+long convert_to_16bit(long address);
+int gf1_wait_dma(void);
+int gf1_dma_ready(void);
+unsigned long gf1_amount_xferred(void);
+int gf1_detect_card(unsigned short port);
+char *gf1_error_str(int);
+int gf1_play_digital(unsigned short priority, unsigned char RFAR *buffer,
+	unsigned long size, unsigned long gf1_addr, unsigned short volume,
+	unsigned short pan, unsigned short frequency, unsigned char type,
+	struct gf1_dma_buff RFAR *dptr,
+	int (RFAR *callback)(int, int, unsigned char RFAR * RFAR *, unsigned long RFAR *));
+void gf1_restart_digital(int voice);
+void gf1_start_digital(int voice);
+void gf1_pause_digital(int voice);
+void RFAR gf1_stop_digital(int voice);
+void gf1_dig_set_dma_rate(unsigned short rate);
+unsigned long gf1_digital_position(int voice);
+int gf1_myatoi(void);
+int gf1_update_waveform(struct wave_struct RFAR *wave_info);
+int gf1_get_patch_info(char RFAR *patch_file, struct patchinfo RFAR *patch);
+int gf1_load_patch(char RFAR *patch_file, struct patchinfo RFAR *patchinfo,
+	struct patch RFAR *patch,
+	struct gf1_dma_buff RFAR *dptr, unsigned short size,
+	unsigned char RFAR *wavemem, int flags);
+void gf1_unload_patch(struct patch RFAR *patch);
+void gf1_detune_patch(struct patch RFAR *patch, unsigned short detune);
+unsigned short gf1_calc_fc(unsigned int sample_ratio,long root,long frequency);
+void gf1_midi_stop_voice(int voice);
+void gf1_midi_wait_voice(int voice);
+unsigned short gf1_midi_status_note(int voice);
+unsigned short gf1_midi_status_voice(int voice);
+void RFAR gf1_midi_stop_note(int note_voice);
+void gf1_midi_note_on(struct patch RFAR *patch, int priority, int note, int velocity, int channel);
+void gf1_midi_note_off(int note, int channel);
+void gf1_midi_silence_patch_notes(struct patch RFAR *patch);
+void gf1_midi_patch_removed(struct patch RFAR *patch);
+int gf1_enable_timer1(int (RFAR *callback)(void), int resolution);
+int gf1_enable_timer2(int (RFAR *callback)(void), int resolution);
+void gf1_disable_timer1(void);
+void gf1_disable_timer2(void);
+void gf1_channel_pitch_bend(int channel, unsigned int bend);
+void gf1_midi_synth_volume(unsigned short synth, int master_volume);
+void gf1_midi_change_program(struct patch RFAR *patch, int channel);
+void gf1_midi_set_vibrato(int channel, int value);
+void gf1_midi_change_volume(int channel, unsigned int volume);
+void gf1_midi_set_balance(int balance, int channel);
+void gf1_midi_channel_sustain(int channel, int sustain);
+void gf1_midi_all_notes_off(int channel);
+void gf1_midi_pitch_bend(int channel, int lsb, int msb);
+void gf1_midi_parameter(int channel, int control, int value);
+int gf1_midi_get_channel_notes(int channel, int notes[]);
+int gf1_midi_get_channel_volume(int channel);
+int gf1_midi_get_master_volume(void);
+int gf1_midi_get_volume(int voice);
+unsigned short gf1_read(int handle, void RFAR *io_buffer, unsigned short size);
+unsigned short gf1_close_file(int handle);
+unsigned int gf1_seek(int handle, unsigned long offset, int method);
+int gf1_open(char RFAR *name);
+#ifdef __FLAT__
+int gf1_atoi(char RFAR **str, int base);
+#else
+int gf1_atoi(void);
+#endif
+void gf1_leave(void);
+short gf1_enter(void);
+void gf1_enter1(void);
+int gf1_play_next_buffer(int voice, unsigned char RFAR *buff, unsigned long size);
+void gf1_dig_set_vol(unsigned short voice, unsigned short vol);
+void gf1_dig_set_pan(unsigned short voice, unsigned short pan);
+int gf1_set_external_semaphore(void RFAR *addr);
+int gf1_clear_external_semaphore(void RFAR *addr);
+void gf1_midi_reset(int c);
+int gf1_add_midi_recv_handler(int (RFAR *handler)());
+int gf1_add_dma_handler(int (*handler)());
+int gf1_add_voice_handler(int (*handler)(int));
+int gf1_add_volume_handler(int (*handler)(int));
+int gf1_add_timer_handler(int timer, int (RFAR *handler)(void));
+void gf1_set_record_rate(unsigned long rate);
+void gf1_create_patch(struct patch RFAR *patch);
+int gf1_add_layer(struct patch RFAR *patch, int layer, char RFAR *wavemem);
+void gf1_get_waveform_info(struct patch RFAR *patch, int layer, int waven,
+	struct wave_struct RFAR *wave);
+void gf1_set_waveform_info(struct patch RFAR *patch, int layer, int waven,
+	struct wave_struct RFAR *wave);
+void gf1_enable_line_in(void);
+void gf1_disable_line_in(void);
+void gf1_enable_mic_in(void);
+void gf1_disable_mic_in(void);
+void gf1_enable_output(void);
+void gf1_disable_output(void);
+void gf1_sound_volume(unsigned short voice, int volume,
+	unsigned long period /* us*10 */);
+void gf1_sound_pan(unsigned short voice, unsigned short pan);
+void gf1_sound_frequency(unsigned short voice, unsigned long freq);
+void RFAR gf1_sound_stop(int voice);
+void gf1_sound_mode(int voice, struct gf1_sound RFAR *sound,
+	unsigned char type);
+int gf1_sound_start(unsigned short priority, struct gf1_sound RFAR *sound,
+	short volume, unsigned long period, short pan, unsigned long freq);
+int gf1_sound_playing(int voice);
+#endif

Added: tags/rott-1.1/rott/audiolib/nodpmi.c
===================================================================
--- tags/rott-1.1/rott/audiolib/nodpmi.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/nodpmi.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,179 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: DPMI.C
+
+   author: James R. Dose
+   date:   April 8, 1994
+
+   Functions for performing DPMI calls.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "dpmi.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+/*---------------------------------------------------------------------
+   Function: DPMI_GetRealModeVector
+
+   Returns the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+unsigned long DPMI_GetRealModeVector
+   (
+   int num
+   )
+
+   {
+   return 0;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_SetRealModeVector
+
+   Sets the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+void DPMI_SetRealModeVector
+   (
+   int num,
+   unsigned long vector
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_CallRealModeFunction
+
+   Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int DPMI_CallRealModeFunction
+   (
+   dpmi_regs *callregs
+   )
+
+   {
+   return( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_LockMemory
+
+   Locks a region of memory to keep the virtual memory manager from
+   paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemory
+   (
+   void *address,
+   unsigned length
+   )
+
+   {
+   return ( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_LockMemoryRegion
+
+   Locks a region of memory to keep the virtual memory manager from
+   paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemoryRegion
+   (
+   void *start,
+   void *end
+   )
+
+   {
+   int status;
+
+   status = DPMI_LockMemory( start, ( char * )end - ( char * )start );
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_UnlockMemory
+
+   Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemory
+   (
+   void *address,
+   unsigned length
+   )
+
+   {
+   return ( DPMI_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: DPMI_UnlockMemoryRegion
+
+   Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemoryRegion
+   (
+   void *start,
+   void *end
+   )
+
+   {
+   int status;
+
+   status = DPMI_UnlockMemory( start, ( char * )end - ( char * )start );
+
+   return( status );
+   }
+
+int DPMI_GetDOSMemory( void **ptr, long *descriptor, unsigned length )
+{
+	/* Lovely... */
+	
+	*ptr = (void *)malloc(length);
+	
+	*descriptor = (long) *ptr;
+	
+	return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
+}
+
+int DPMI_FreeDOSMemory( long descriptor )
+{
+	free((void *)descriptor);
+	
+	return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
+}

Added: tags/rott-1.1/rott/audiolib/nomusic.c
===================================================================
--- tags/rott-1.1/rott/audiolib/nomusic.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/nomusic.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,115 @@
+#include "music.h"
+
+char *MUSIC_ErrorString(int ErrorNumber)
+{
+	return "";
+}
+
+int MUSIC_Init(int SoundCard, int Address)
+{
+	return 0;
+}
+
+int MUSIC_Shutdown(void)
+{
+	return 0;
+}
+
+void MUSIC_SetMaxFMMidiChannel(int channel)
+{
+}
+
+void MUSIC_SetVolume(int volume)
+{
+}
+
+void MUSIC_SetMidiChannelVolume(int channel, int volume)
+{
+}
+
+void MUSIC_ResetMidiChannelVolumes(void)
+{
+}
+
+int MUSIC_GetVolume(void)
+{
+	return 0;
+}
+
+void MUSIC_SetLoopFlag(int loopflag)
+{
+}
+
+int MUSIC_SongPlaying(void)
+{
+	return 0;
+}
+
+void MUSIC_Continue(void)
+{
+}
+
+void MUSIC_Pause(void)
+{
+}
+
+int MUSIC_StopSong(void)
+{
+	return 0;
+}
+
+int MUSIC_PlaySong(unsigned char *song, int loopflag)
+{
+	return 0;
+}
+
+void MUSIC_SetContext(int context)
+{
+}
+
+int MUSIC_GetContext(void)
+{
+	return 0;
+}
+
+void MUSIC_SetSongTick(unsigned long PositionInTicks)
+{
+}
+
+void MUSIC_SetSongTime(unsigned long milliseconds)
+{
+}
+
+void MUSIC_SetSongPosition(int measure, int beat, int tick)
+{
+}
+
+void MUSIC_GetSongPosition(songposition *pos)
+{
+}
+
+void MUSIC_GetSongLength(songposition *pos)
+{
+}
+
+int MUSIC_FadeVolume(int tovolume, int milliseconds)
+{
+	return 0;
+}
+
+int MUSIC_FadeActive(void)
+{
+	return 0;
+}
+
+void MUSIC_StopFade(void)
+{
+}
+
+void MUSIC_RerouteMidiChannel(int channel, int cdecl function( int event, int c1, int c2 ))
+{
+}
+
+void MUSIC_RegisterTimbreBank(unsigned char *timbres)
+{
+}

Added: tags/rott-1.1/rott/audiolib/pas16.c
===================================================================
--- tags/rott-1.1/rott/audiolib/pas16.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/pas16.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1924 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: PAS16.C
+
+   author: James R. Dose
+   date:   March 27, 1994
+
+   Low level routines to support Pro AudioSpectrum and compatible
+   sound cards.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "dpmi.h"
+#include "dma.h"
+#include "interrup.h"
+#include "irq.h"
+#include "pas16.h"
+#include "_pas16.h"
+
+#define USESTACK
+
+static const int PAS_Interrupts[ PAS_MaxIrq + 1 ]  =
+   {
+   INVALID, INVALID,     0xa,     0xb,
+   INVALID,     0xd, INVALID,     0xf,
+   INVALID, INVALID,    0x72,    0x73,
+      0x74, INVALID, INVALID,    0x77
+   };
+
+static void    ( interrupt far *PAS_OldInt )( void );
+
+static int PAS_IntController1Mask;
+static int PAS_IntController2Mask;
+
+static int PAS_Installed = FALSE;
+static int PAS_TranslateCode = DEFAULT_BASE;
+
+static int PAS_OriginalPCMLeftVolume  = 75;
+static int PAS_OriginalPCMRightVolume = 75;
+
+static int PAS_OriginalFMLeftVolume  = 75;
+static int PAS_OriginalFMRightVolume = 75;
+
+unsigned int PAS_DMAChannel;
+static int PAS_Irq;
+
+static MVState *PAS_State = NULL;
+static MVFunc  *PAS_Func  = NULL;
+
+static MVState PAS_OriginalState;
+static int     PAS_SampleSizeConfig;
+
+static char   *PAS_DMABuffer;
+static char   *PAS_DMABufferEnd;
+static char   *PAS_CurrentDMABuffer;
+static int     PAS_TotalDMABufferSize;
+
+static int      PAS_TransferLength   = 0;
+static int      PAS_MixMode          = PAS_DefaultMixMode;
+static unsigned PAS_SampleRate       = PAS_DefaultSampleRate;
+static int      PAS_TimeInterval     = 0;
+
+volatile int   PAS_SoundPlaying;
+
+void ( *PAS_CallBack )( void );
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long  StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long  oldStackPointer;
+
+// This is defined because we can't create local variables in a
+// function that switches stacks.
+static int irqstatus;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack =  \
+   "mov  [edi],esp"     \
+   "mov  ax,ss"         \
+   "mov  [esi],ax"      \
+   parm [esi] [edi]     \
+   modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack =  \
+   "mov  ss,ax"         \
+   "mov  esp,edx"       \
+   parm [ax] [edx]      \
+   modify [eax edx];
+
+int PAS_ErrorCode = PAS_Ok;
+
+#define PAS_SetErrorCode( status ) \
+   PAS_ErrorCode   = ( status );
+
+/*---------------------------------------------------------------------
+   Function: PAS_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *PAS_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case PAS_Warning :
+      case PAS_Error :
+         ErrorString = PAS_ErrorString( PAS_ErrorCode );
+         break;
+
+      case PAS_Ok :
+         ErrorString = "Pro AudioSpectrum ok.";
+         break;
+
+      case PAS_DriverNotFound :
+         ErrorString = "MVSOUND.SYS not loaded.";
+         break;
+
+      case PAS_DmaError :
+         ErrorString = DMA_ErrorString( DMA_Error );
+         break;
+
+      case PAS_InvalidIrq :
+         ErrorString = "Invalid Pro AudioSpectrum Irq.";
+         break;
+
+      case PAS_UnableToSetIrq :
+         ErrorString = "Unable to set Pro AudioSpectrum IRQ.  Try selecting an IRQ of 7 or below.";
+         break;
+
+      case PAS_Dos4gwIrqError :
+         ErrorString = "Unsupported Pro AudioSpectrum Irq.";
+         break;
+
+      case PAS_NoSoundPlaying :
+         ErrorString = "No sound playing on Pro AudioSpectrum.";
+         break;
+
+      case PAS_CardNotFound :
+         ErrorString = "Could not find Pro AudioSpectrum.";
+         break;
+
+      case PAS_DPMI_Error :
+         ErrorString = "DPMI Error in PAS16.";
+         break;
+
+      case PAS_OutOfMemory :
+         ErrorString = "Out of conventional memory in PAS16.";
+         break;
+
+      default :
+         ErrorString = "Unknown Pro AudioSpectrum error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define PAS_LockStart PAS_CheckForDriver
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_CheckForDriver
+
+   Checks to see if MVSOUND.SYS is installed.
+---------------------------------------------------------------------*/
+
+int PAS_CheckForDriver
+   (
+   void
+   )
+
+   {
+   union REGS regs;
+   unsigned   result;
+
+   regs.w.ax = MV_CheckForDriver;
+   regs.w.bx = 0x3f3f;
+
+   #ifdef __386__
+      int386( MV_SoundInt, &regs, &regs );
+   #else
+      int86( MV_SoundInt, &regs, &regs );
+   #endif
+
+   if ( regs.w.ax != MV_CheckForDriver )
+      {
+      PAS_SetErrorCode( PAS_DriverNotFound );
+      return( PAS_Error );
+      }
+
+   result = regs.w.bx ^ regs.w.cx ^ regs.w.dx;
+   if ( result != MV_Signature )
+      {
+      PAS_SetErrorCode( PAS_DriverNotFound );
+      return( PAS_Error );
+      }
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetStateTable
+
+   Returns a pointer to the state table containing hardware state
+   information.  The state table is necessary because the Pro Audio-
+   Spectrum contains only write-only registers.
+---------------------------------------------------------------------*/
+
+MVState *PAS_GetStateTable
+   (
+   void
+   )
+
+   {
+   union REGS   regs;
+   MVState *ptr;
+
+   regs.w.ax = MV_GetPointerToStateTable;
+
+   #ifdef __386__
+      int386( MV_SoundInt, &regs, &regs );
+   #else
+      int86( MV_SoundInt, &regs, &regs );
+   #endif
+
+   if ( regs.w.ax != MV_Signature )
+      {
+      PAS_SetErrorCode( PAS_DriverNotFound );
+      return( NULL );
+      }
+
+   #if defined(__WATCOMC__) && defined(__FLAT__)
+      ptr = ( MVState * )( ( ( ( unsigned )regs.w.dx ) << 4 ) +
+         ( ( unsigned )regs.w.bx ) );
+   #else
+      ptr = MK_FP( regs.w.dx, regs.w.bx );
+   #endif
+
+   return( ptr );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetFunctionTable
+
+   Returns a pointer to the function table containing addresses of
+   driver functions.
+---------------------------------------------------------------------*/
+
+MVFunc *PAS_GetFunctionTable
+   (
+   void
+   )
+
+   {
+   union REGS   regs;
+   MVFunc *ptr;
+
+   regs.w.ax = MV_GetPointerToFunctionTable;
+
+   #ifdef __386__
+      int386( MV_SoundInt, &regs, &regs );
+   #else
+      int86( MV_SoundInt, &regs, &regs );
+   #endif
+
+   if ( regs.w.ax != MV_Signature )
+      {
+      PAS_SetErrorCode( PAS_DriverNotFound );
+      return( NULL );
+      }
+
+   #if defined(__WATCOMC__) && defined(__FLAT__)
+      ptr = ( MVFunc * )( ( ( ( unsigned )regs.w.dx ) << 4 ) +
+         ( ( unsigned )regs.w.bx ) );
+   #else
+      ptr = MK_FP( regs.w.dx, regs.w.bx );
+   #endif
+
+   return( ptr );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetCardSettings
+
+   Returns the DMA and the IRQ channels of the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_GetCardSettings
+   (
+   void
+   )
+
+   {
+   union REGS   regs;
+   int          status;
+
+   regs.w.ax = MV_GetDmaIrqInt;
+
+   #ifdef __386__
+      int386( MV_SoundInt, &regs, &regs );
+   #else
+      int86( MV_SoundInt, &regs, &regs );
+   #endif
+
+   if ( regs.w.ax != MV_Signature )
+      {
+      PAS_SetErrorCode( PAS_DriverNotFound );
+      return( PAS_Error );
+      }
+
+   PAS_DMAChannel = regs.w.bx;
+   PAS_Irq        = regs.w.cx;
+
+   if ( PAS_Irq > PAS_MaxIrq )
+      {
+      PAS_SetErrorCode( PAS_Dos4gwIrqError );
+      return( PAS_Error );
+      }
+
+   if ( !VALID_IRQ( PAS_Irq ) )
+      {
+      PAS_SetErrorCode( PAS_InvalidIrq );
+      return( PAS_Error );
+      }
+
+   if ( PAS_Interrupts[ PAS_Irq ] == INVALID )
+      {
+      PAS_SetErrorCode( PAS_InvalidIrq );
+      return( PAS_Error );
+      }
+
+   status = DMA_VerifyChannel( PAS_DMAChannel );
+   if ( status == DMA_Error )
+      {
+      PAS_SetErrorCode( PAS_DmaError );
+      return( PAS_Error );
+      }
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_EnableInterrupt
+
+   Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void PAS_EnableInterrupt
+   (
+   void
+   )
+
+   {
+   int mask;
+   int data;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   if ( PAS_Irq < 8 )
+      {
+      mask = inp( 0x21 ) & ~( 1 << PAS_Irq );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask = inp( 0xA1 ) & ~( 1 << ( PAS_Irq - 8 ) );
+      outp( 0xA1, mask  );
+
+      mask = inp( 0x21 ) & ~( 1 << 2 );
+      outp( 0x21, mask  );
+      }
+
+   // Flush any pending interrupts
+   PAS_Write( InterruptStatus, PAS_Read( InterruptStatus ) & 0x40 );
+
+   // Enable the interrupt on the PAS
+   data = PAS_State->intrctlr;
+   data |= SampleBufferInterruptFlag;
+   PAS_Write( InterruptControl, data );
+   PAS_State->intrctlr = data;
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_DisableInterrupt
+
+   Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void PAS_DisableInterrupt
+   (
+   void
+   )
+
+   {
+   int mask;
+   int data;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   // Disable the interrupt on the PAS
+   data = PAS_State->intrctlr;
+   data &= ~( SampleRateInterruptFlag | SampleBufferInterruptFlag );
+   PAS_Write( InterruptControl, data );
+   PAS_State->intrctlr = data;
+
+   // Restore interrupt mask
+   if ( PAS_Irq < 8 )
+      {
+      mask  = inp( 0x21 ) & ~( 1 << PAS_Irq );
+      mask |= PAS_IntController1Mask & ( 1 << PAS_Irq );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask  = inp( 0x21 ) & ~( 1 << 2 );
+      mask |= PAS_IntController1Mask & ( 1 << 2 );
+      outp( 0x21, mask  );
+
+      mask  = inp( 0xA1 ) & ~( 1 << ( PAS_Irq - 8 ) );
+      mask |= PAS_IntController2Mask & ( 1 << ( PAS_Irq - 8 ) );
+      outp( 0xA1, mask  );
+      }
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_ServiceInterrupt
+
+   Handles interrupt generated by sound card at the end of a voice
+   transfer.  Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+void interrupt far PAS_ServiceInterrupt
+   (
+   void
+   )
+
+   {
+   #ifdef USESTACK
+   // save stack
+   GetStack( &oldStackSelector, &oldStackPointer );
+
+   // set our stack
+   SetStack( StackSelector, StackPointer );
+   #endif
+
+   irqstatus = PAS_Read( InterruptStatus );
+   if ( ( irqstatus & SampleBufferInterruptFlag ) == 0 )
+      {
+      #ifdef USESTACK
+      // restore stack
+      SetStack( oldStackSelector, oldStackPointer );
+      #endif
+
+      _chain_intr( PAS_OldInt );
+      }
+
+   // Clear the interrupt
+   irqstatus &= ~SampleBufferInterruptFlag;
+   PAS_Write( InterruptStatus, irqstatus );
+
+   // send EOI to Interrupt Controller
+   if ( PAS_Irq > 7 )
+      {
+      outp( 0xA0, 0x20 );
+      }
+   outp( 0x20, 0x20 );
+
+
+   // Keep track of current buffer
+   PAS_CurrentDMABuffer += PAS_TransferLength;
+   if ( PAS_CurrentDMABuffer >= PAS_DMABufferEnd )
+      {
+      PAS_CurrentDMABuffer = PAS_DMABuffer;
+      }
+
+   // Call the caller's callback function
+   if ( PAS_CallBack != NULL )
+      {
+      PAS_CallBack();
+      }
+
+   #ifdef USESTACK
+   // restore stack
+   SetStack( oldStackSelector, oldStackPointer );
+   #endif
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_Write
+
+   Writes a byte of data to the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_Write
+   (
+   int Register,
+   int Data
+   )
+
+   {
+   int port;
+
+   port = Register ^ PAS_TranslateCode;
+   outp( port, Data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_Read
+
+   Reads a byte of data from the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_Read
+   (
+   int Register
+   )
+
+   {
+   int port;
+   int data;
+
+   port = Register ^ PAS_TranslateCode;
+   data = inp( port );
+   return( data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetSampleRateTimer
+
+   Programs the Sample Rate Timer.
+---------------------------------------------------------------------*/
+
+void PAS_SetSampleRateTimer
+   (
+   void
+   )
+
+   {
+   int LoByte;
+   int HiByte;
+   int data;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   // Disable the Sample Rate Timer
+   data = PAS_State->audiofilt;
+   data &= ~SampleRateTimerGateFlag;
+   PAS_Write( AudioFilterControl, data );
+   PAS_State->audiofilt = data;
+
+   // Select the Sample Rate Timer
+   data = SelectSampleRateTimer;
+   PAS_Write( LocalTimerControl, data );
+   PAS_State->tmrctlr = data;
+
+   LoByte = lobyte( PAS_TimeInterval );
+   HiByte = hibyte( PAS_TimeInterval );
+
+   // Program the Sample Rate Timer
+   PAS_Write( SampleRateTimer, LoByte );
+   PAS_Write( SampleRateTimer, HiByte );
+   PAS_State->samplerate = PAS_TimeInterval;
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetSampleBufferCount
+
+   Programs the Sample Buffer Count.
+---------------------------------------------------------------------*/
+
+void PAS_SetSampleBufferCount
+   (
+   void
+   )
+
+   {
+   int LoByte;
+   int HiByte;
+   int count;
+   int data;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   // Disable the Sample Buffer Count
+   data = PAS_State->audiofilt;
+   data &= ~SampleBufferCountGateFlag;
+   PAS_Write( AudioFilterControl, data );
+   PAS_State->audiofilt = data;
+
+   // Select the Sample Buffer Count
+   data = SelectSampleBufferCount;
+   PAS_Write( LocalTimerControl, data );
+   PAS_State->tmrctlr = data;
+
+   count = PAS_TransferLength;
+
+   // Check if we're using a 16-bit DMA channel
+   if ( PAS_DMAChannel > 3 )
+      {
+      count >>= 1;
+      }
+
+   LoByte = lobyte( count );
+   HiByte = hibyte( count );
+
+   // Program the Sample Buffer Count
+   PAS_Write( SampleBufferCount, LoByte );
+   PAS_Write( SampleBufferCount, HiByte );
+   PAS_State->samplecnt = count;
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetPlaybackRate
+
+   Sets the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+void PAS_SetPlaybackRate
+   (
+   unsigned rate
+   )
+
+   {
+   if ( rate < PAS_MinSamplingRate )
+      {
+      rate = PAS_MinSamplingRate;
+      }
+
+   if ( rate > PAS_MaxSamplingRate )
+      {
+      rate = PAS_MaxSamplingRate;
+      }
+
+   PAS_TimeInterval = ( unsigned )CalcTimeInterval( rate );
+   if ( PAS_MixMode & STEREO )
+      {
+      PAS_TimeInterval /= 2;
+      }
+
+   // Keep track of what the actual rate is
+   PAS_SampleRate = CalcSamplingRate( PAS_TimeInterval );
+   if ( PAS_MixMode & STEREO )
+      {
+      PAS_SampleRate /= 2;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetPlaybackRate
+
+   Returns the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+unsigned PAS_GetPlaybackRate
+   (
+   void
+   )
+
+   {
+   return( PAS_SampleRate );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetMixMode
+
+   Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int PAS_SetMixMode
+   (
+   int mode
+   )
+
+   {
+   mode &= PAS_MaxMixMode;
+
+   // Check board revision.  Revision # 0 can't play 16-bit data.
+   if ( ( PAS_State->intrctlr & 0xe0 ) == 0 )
+      {
+      // Force the mode to 8-bit data.
+      mode &= ~SIXTEEN_BIT;
+      }
+
+   PAS_MixMode = mode;
+
+   PAS_SetPlaybackRate( PAS_SampleRate );
+
+   return( mode );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_StopPlayback
+
+   Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_StopPlayback
+   (
+   void
+   )
+
+   {
+   int data;
+
+   // Don't allow anymore interrupts
+   PAS_DisableInterrupt();
+
+   // Stop the transfer of digital data
+   data = PAS_State->crosschannel;
+   data &= PAS_PCMStopMask;
+   PAS_Write( CrossChannelControl, data );
+   PAS_State->crosschannel = data;
+
+   // Turn off 16-bit unsigned data
+   data = PAS_Read( SampleSizeConfiguration );
+   data &= PAS_SampleSizeMask;
+   PAS_Write( SampleSizeConfiguration, data );
+
+   // Disable the DMA channel
+   DMA_EndTransfer( PAS_DMAChannel );
+
+   PAS_SoundPlaying = FALSE;
+
+   PAS_DMABuffer = NULL;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetupDMABuffer
+
+   Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+int PAS_SetupDMABuffer
+   (
+   char *BufferPtr,
+   int   BufferSize,
+   int   mode
+   )
+
+   {
+   int DmaStatus;
+   int data;
+
+   // Enable PAS Dma
+   data  = PAS_State->crosschannel;
+   data |= PAS_DMAEnable;
+   PAS_Write( CrossChannelControl, data );
+   PAS_State->crosschannel = data;
+
+   DmaStatus = DMA_SetupTransfer( PAS_DMAChannel, BufferPtr, BufferSize, mode );
+   if ( DmaStatus == DMA_Error )
+      {
+      PAS_SetErrorCode( PAS_DmaError );
+      return( PAS_Error );
+      }
+
+   PAS_DMABuffer          = BufferPtr;
+   PAS_CurrentDMABuffer   = BufferPtr;
+   PAS_TotalDMABufferSize = BufferSize;
+   PAS_DMABufferEnd       = BufferPtr + BufferSize;
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetCurrentPos
+
+   Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int PAS_GetCurrentPos
+   (
+   void
+   )
+
+   {
+   char *CurrentAddr;
+   int   offset;
+
+   if ( !PAS_SoundPlaying )
+      {
+      PAS_SetErrorCode( PAS_NoSoundPlaying );
+      return( PAS_Error );
+      }
+
+   CurrentAddr = DMA_GetCurrentPos( PAS_DMAChannel );
+   if ( CurrentAddr == NULL )
+      {
+      PAS_SetErrorCode( PAS_DmaError );
+      return( PAS_Error );
+      }
+
+   offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+      ( ( unsigned long )PAS_CurrentDMABuffer ) );
+
+   if ( PAS_MixMode & SIXTEEN_BIT )
+      {
+      offset >>= 1;
+      }
+
+   if ( PAS_MixMode & STEREO )
+      {
+      offset >>= 1;
+      }
+
+   return( offset );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetFilterSetting
+
+   Returns the bit settings for the appropriate filter level.
+---------------------------------------------------------------------*/
+
+int PAS_GetFilterSetting
+   (
+   int rate
+   )
+
+   {
+   /* CD Quality 17897hz */
+   if ( ( unsigned long )rate > ( unsigned long )17897L * 2 )
+      {
+      /* 00001b 20hz to 17.8khz */
+      return( 0x01 );
+      }
+
+   /* Cassette Quality 15090hz */
+   if ( ( unsigned long )rate > ( unsigned long )15909L * 2 )
+      {
+      /* 00010b 20hz to 15.9khz */
+      return( 0x02 );
+      }
+
+   /* FM Radio Quality 11931hz */
+   if ( ( unsigned long )rate > ( unsigned long )11931L * 2 )
+      {
+      /* 01001b 20hz to 11.9khz */
+      return( 0x09 );
+      }
+
+   /* AM Radio Quality  8948hz */
+   if ( ( unsigned long )rate > ( unsigned long )8948L * 2 )
+      {
+      /* 10001b 20hz to 8.9khz */
+      return( 0x11 );
+      }
+
+   /* Telphone Quality  5965hz */
+   if ( ( unsigned long )rate > ( unsigned long )5965L * 2 )
+      {
+      /* 00100b 20hz to 5.9khz */
+      return( 0x19 );
+      }
+
+   /* Male voice quality 2982hz */
+   /* 111001b 20hz to 2.9khz */
+   return( 0x04 );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_BeginTransfer
+
+   Starts playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_BeginTransfer
+   (
+   int mode
+   )
+
+   {
+   int data;
+
+   PAS_SetSampleRateTimer();
+
+   PAS_SetSampleBufferCount();
+
+   PAS_EnableInterrupt();
+
+   // Get sample size configuration
+   data = PAS_Read( SampleSizeConfiguration );
+
+   // Check board revision.  Revision # 0 can't play 16-bit data.
+   if ( PAS_State->intrctlr & 0xe0 )
+      {
+      data &= PAS_SampleSizeMask;
+
+      // set sample size bit
+      if ( PAS_MixMode & SIXTEEN_BIT )
+         {
+         data |= PAS_16BitSampleFlag;
+         }
+      }
+
+   // set oversampling rate
+   data &= PAS_OverSamplingMask;
+   data |= PAS_4xOverSampling;
+
+   // Set sample size configuration
+   PAS_Write( SampleSizeConfiguration, data );
+
+   // Get Cross channel setting
+   data  = PAS_State->crosschannel;
+   data &= PAS_ChannelConnectMask;
+   if ( mode == RECORD )
+      {
+      data |= PAS_PCMStartADC;
+      }
+   else
+      {
+      data |= PAS_PCMStartDAC;
+      }
+
+   // set stereo mode bit
+   if ( !( PAS_MixMode & STEREO ) )
+      {
+      data |= PAS_StereoFlag;
+      }
+
+   PAS_Write( CrossChannelControl, data );
+   PAS_State->crosschannel = data;
+
+   // Get the filter appropriate filter setting
+   data = PAS_GetFilterSetting( PAS_SampleRate );
+
+   // Enable the Sample Rate Timer and Sample Buffer Count
+   data |= SampleRateTimerGateFlag | SampleBufferCountGateFlag;
+
+   if ( mode != RECORD )
+      {
+      // Enable audio (not Audio Mute)
+      data |= PAS_AudioMuteFlag;
+      }
+
+   PAS_Write( AudioFilterControl, data );
+   PAS_State->audiofilt = data;
+
+   PAS_SoundPlaying = TRUE;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_BeginBufferedPlayback
+
+   Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_BeginBufferedPlayback
+   (
+   char *BufferStart,
+   int   BufferSize,
+   int   NumDivisions,
+   unsigned SampleRate,
+   int   MixMode,
+   void ( *CallBackFunc )( void )
+   )
+
+   {
+   int DmaStatus;
+
+   PAS_StopPlayback();
+
+   PAS_SetMixMode( MixMode );
+   PAS_SetPlaybackRate( SampleRate );
+
+   PAS_TransferLength = BufferSize / NumDivisions;
+   PAS_SetCallBack( CallBackFunc );
+
+   DmaStatus = PAS_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitRead );
+   if ( DmaStatus == PAS_Error )
+      {
+      return( PAS_Error );
+      }
+
+   PAS_BeginTransfer( PLAYBACK );
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_BeginBufferedRecord
+
+   Begins multibuffered recording of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_BeginBufferedRecord
+   (
+   char *BufferStart,
+   int   BufferSize,
+   int   NumDivisions,
+   unsigned SampleRate,
+   int   MixMode,
+   void ( *CallBackFunc )( void )
+   )
+
+   {
+   int DmaStatus;
+
+   PAS_StopPlayback();
+
+   PAS_SetMixMode( MixMode );
+   PAS_SetPlaybackRate( SampleRate );
+
+   PAS_TransferLength = BufferSize / NumDivisions;
+   PAS_SetCallBack( CallBackFunc );
+
+   DmaStatus = PAS_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitWrite );
+   if ( DmaStatus == PAS_Error )
+      {
+      return( PAS_Error );
+      }
+
+   PAS_BeginTransfer( RECORD );
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_CallInt
+
+   Calls interrupt 2fh.
+---------------------------------------------------------------------*/
+
+int PAS_CallInt( int ebx, int ecx, int edx );
+#pragma aux PAS_CallInt = \
+   "int 2fh",         \
+   parm [ ebx ] [ ecx ] [ edx ] modify exact [ eax ebx ecx edx esi edi ] value [ ebx ];
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_CallMVFunction
+
+   Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int PAS_CallMVFunction
+   (
+   unsigned long function,
+   int ebx,
+   int ecx,
+   int edx
+   )
+
+   {
+   dpmi_regs callregs;
+   int       status;
+
+   callregs.EBX = ebx;
+   callregs.ECX = ecx;
+   callregs.EDX = edx;
+
+   callregs.SS  = 0;
+   callregs.SP  = 0;
+
+   callregs.DS  = 0;
+   callregs.ES  = 0;
+   callregs.FS  = 0;
+   callregs.GS  = 0;
+
+   callregs.IP = function;
+   callregs.CS = function >> 16;
+
+   status = DPMI_CallRealModeFunction( &callregs );
+   if ( status != DPMI_Ok )
+      {
+      return( PAS_Error );
+      }
+
+   return( callregs.EBX & 0xff );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetPCMVolume
+
+   Sets the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_SetPCMVolume
+   (
+   int volume
+   )
+
+   {
+   int status;
+
+   volume = max( 0, volume );
+   volume = min( volume, 255 );
+
+   volume *= 100;
+   volume /= 255;
+
+   status = PAS_CallMVFunction( PAS_Func->SetMixer, volume,
+      OUTPUTMIXER, L_PCM );
+   if ( status == PAS_Error )
+      {
+      return( status );
+      }
+
+   status = PAS_CallMVFunction( PAS_Func->SetMixer, volume,
+      OUTPUTMIXER, R_PCM );
+   if ( status == PAS_Error )
+      {
+      return( status );
+      }
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetPCMVolume
+
+   Returns the current volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_GetPCMVolume
+   (
+   void
+   )
+
+   {
+   int leftvolume;
+   int rightvolume;
+   int totalvolume;
+
+   if ( PAS_Func == NULL )
+      {
+      return( PAS_Error );
+      }
+
+   leftvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, L_PCM );
+   rightvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, R_PCM );
+
+   if ( ( leftvolume == PAS_Error ) || ( rightvolume == PAS_Error ) )
+      {
+      return( PAS_Error );
+      }
+
+   leftvolume  &= 0xff;
+   rightvolume &= 0xff;
+
+   totalvolume = ( rightvolume + leftvolume ) / 2;
+   totalvolume *= 255;
+   totalvolume /= 100;
+   return( totalvolume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetFMVolume
+
+   Sets the volume of FM sound playback.
+---------------------------------------------------------------------*/
+
+void PAS_SetFMVolume
+   (
+   int volume
+   )
+
+   {
+   volume = max( 0, volume );
+   volume = min( volume, 255 );
+
+   volume *= 100;
+   volume /= 255;
+   if ( PAS_Func )
+      {
+      PAS_CallMVFunction( PAS_Func->SetMixer, volume, OUTPUTMIXER, L_FM );
+      PAS_CallMVFunction( PAS_Func->SetMixer, volume, OUTPUTMIXER, R_FM );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetFMVolume
+
+   Returns the current volume of FM sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_GetFMVolume
+   (
+   void
+   )
+
+   {
+   int leftvolume;
+   int rightvolume;
+   int totalvolume;
+
+   if ( PAS_Func == NULL )
+      {
+      return( 255 );
+      }
+
+   leftvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, L_FM ) & 0xff;
+   rightvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, R_FM ) & 0xff;
+
+   totalvolume  = ( rightvolume + leftvolume ) / 2;
+   totalvolume *= 255;
+   totalvolume /= 100;
+   totalvolume  = min( 255, totalvolume );
+
+   return( totalvolume );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_GetCardInfo
+
+   Returns the maximum number of bits that can represent a sample
+   (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int PAS_GetCardInfo
+   (
+   int *MaxSampleBits,
+   int *MaxChannels
+   )
+
+   {
+   int status;
+
+   if ( PAS_State == NULL )
+      {
+      status = PAS_CheckForDriver();
+      if ( status != PAS_Ok )
+         {
+         return( status );
+         }
+
+      PAS_State = PAS_GetStateTable();
+      if ( PAS_State == NULL )
+         {
+         return( PAS_Error );
+         }
+      }
+
+   *MaxChannels = 2;
+
+   // Check board revision.  Revision # 0 can't play 16-bit data.
+   if ( ( PAS_State->intrctlr & 0xe0 ) == 0 )
+      {
+      *MaxSampleBits = 8;
+      }
+   else
+      {
+      *MaxSampleBits = 16;
+      }
+
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SetCallBack
+
+   Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void PAS_SetCallBack
+   (
+   void ( *func )( void )
+   )
+
+   {
+   PAS_CallBack = func;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_FindCard
+
+   Auto-detects the port the Pro AudioSpectrum is set for.
+---------------------------------------------------------------------*/
+
+int PAS_FindCard
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status = PAS_TestAddress( DEFAULT_BASE );
+   if ( status == 0 )
+      {
+      PAS_TranslateCode = DEFAULT_BASE;
+      return( PAS_Ok );
+      }
+
+   status = PAS_TestAddress( ALT_BASE_1 );
+   if ( status == 0 )
+      {
+      PAS_TranslateCode = ALT_BASE_1;
+      return( PAS_Ok );
+      }
+
+   status = PAS_TestAddress( ALT_BASE_2 );
+   if ( status == 0 )
+      {
+      PAS_TranslateCode = ALT_BASE_2;
+      return( PAS_Ok );
+      }
+
+   status = PAS_TestAddress( ALT_BASE_3 );
+   if ( status == 0 )
+      {
+      PAS_TranslateCode = ALT_BASE_3;
+      return( PAS_Ok );
+      }
+
+   PAS_SetErrorCode( PAS_CardNotFound );
+   return( PAS_Error );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SaveMusicVolume
+
+   Saves the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+int PAS_SaveMusicVolume
+   (
+   void
+   )
+
+   {
+   int status;
+   int data;
+
+   if ( !PAS_Installed )
+      {
+      status = PAS_CheckForDriver();
+      if ( status != PAS_Ok )
+         {
+         return( status );
+         }
+
+      PAS_State = PAS_GetStateTable();
+      if ( PAS_State == NULL )
+         {
+         return( PAS_Error );
+         }
+
+      PAS_Func = PAS_GetFunctionTable();
+      if ( PAS_Func == NULL )
+         {
+         return( PAS_Error );
+         }
+
+      status = PAS_GetCardSettings();
+      if ( status != PAS_Ok )
+         {
+         return( status );
+         }
+
+      status = PAS_FindCard();
+      if ( status != PAS_Ok )
+         {
+         return( status );
+         }
+
+      // Enable PAS Sound
+      data  = PAS_State->audiofilt;
+      data |= PAS_AudioMuteFlag;
+
+      PAS_Write( AudioFilterControl, data );
+      PAS_State->audiofilt = data;
+      }
+
+   status = PAS_CallMVFunction( PAS_Func->GetMixer, 0, OUTPUTMIXER, L_FM );
+   if ( status != PAS_Error )
+      {
+      PAS_OriginalFMLeftVolume  = PAS_CallMVFunction( PAS_Func->GetMixer,
+         0, OUTPUTMIXER, L_FM ) & 0xff;
+
+      PAS_OriginalFMRightVolume = PAS_CallMVFunction( PAS_Func->GetMixer,
+         0, OUTPUTMIXER, R_FM ) & 0xff;
+
+      return( PAS_Ok );
+      }
+
+   return( PAS_Warning );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_RestoreMusicVolume
+
+   Restores the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void PAS_RestoreMusicVolume
+   (
+   void
+   )
+
+   {
+   if ( PAS_Func )
+      {
+      PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalFMLeftVolume,
+         OUTPUTMIXER, L_FM );
+      PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalFMRightVolume,
+         OUTPUTMIXER, R_FM );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_SaveState
+
+   Saves the original state of the PAS prior to use.
+---------------------------------------------------------------------*/
+
+void PAS_SaveState
+   (
+   void
+   )
+
+   {
+   PAS_OriginalState.intrctlr     = PAS_State->intrctlr;
+   PAS_OriginalState.audiofilt    = PAS_State->audiofilt;
+   PAS_OriginalState.tmrctlr      = PAS_State->tmrctlr;
+   PAS_OriginalState.samplerate   = PAS_State->samplerate;
+   PAS_OriginalState.samplecnt    = PAS_State->samplecnt;
+   PAS_OriginalState.crosschannel = PAS_State->crosschannel;
+   PAS_SampleSizeConfig = PAS_Read( SampleSizeConfiguration );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_RestoreState
+
+   Restores the original state of the PAS after use.
+---------------------------------------------------------------------*/
+
+void PAS_RestoreState
+   (
+   void
+   )
+
+   {
+   int LoByte;
+   int HiByte;
+
+   // Select the Sample Rate Timer
+   PAS_Write( LocalTimerControl, SelectSampleRateTimer );
+   PAS_State->tmrctlr = SelectSampleRateTimer;
+
+   PAS_Write( SampleRateTimer, PAS_OriginalState.samplerate );
+   PAS_State->samplerate = PAS_OriginalState.samplerate;
+
+   // Select the Sample Buffer Count
+   PAS_Write( LocalTimerControl, SelectSampleBufferCount );
+   PAS_State->tmrctlr = SelectSampleBufferCount;
+
+   LoByte = lobyte( PAS_OriginalState.samplecnt );
+   HiByte = hibyte( PAS_OriginalState.samplecnt );
+   PAS_Write( SampleRateTimer, LoByte );
+   PAS_Write( SampleRateTimer, HiByte );
+   PAS_State->samplecnt = PAS_OriginalState.samplecnt;
+
+   PAS_Write( CrossChannelControl, PAS_OriginalState.crosschannel );
+   PAS_State->crosschannel = PAS_OriginalState.crosschannel;
+
+   PAS_Write( SampleSizeConfiguration, PAS_SampleSizeConfig );
+
+   PAS_Write( InterruptControl, PAS_OriginalState.intrctlr );
+   PAS_State->intrctlr = PAS_OriginalState.intrctlr;
+
+   PAS_Write( AudioFilterControl, PAS_OriginalState.audiofilt );
+   PAS_State->audiofilt = PAS_OriginalState.audiofilt;
+
+   PAS_Write( LocalTimerControl, PAS_OriginalState.tmrctlr );
+   PAS_State->tmrctlr = PAS_OriginalState.tmrctlr;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void PAS_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: allocateTimerStack
+
+   Allocate a block of memory from conventional (low) memory and return
+   the selector (which can go directly into a segment register) of the
+   memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+   (
+   unsigned short size
+   )
+
+   {
+   union REGS regs;
+
+   // clear all registers
+   memset( &regs, 0, sizeof( regs ) );
+
+   // DPMI allocate conventional memory
+   regs.w.ax = 0x100;
+
+   // size in paragraphs
+   regs.w.bx = ( size + 15 ) / 16;
+
+   int386( 0x31, &regs, &regs );
+   if (!regs.w.cflag)
+      {
+      // DPMI call returns selector in dx
+      // (ax contains real mode segment
+      // which is ignored here)
+
+      return( regs.w.dx );
+      }
+
+   // Couldn't allocate memory.
+   return( NULL );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: deallocateTimerStack
+
+   Deallocate a block of conventional (low) memory given a selector to
+   it.  Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+   (
+   unsigned short selector
+   )
+
+   {
+   union REGS regs;
+
+   if ( selector != NULL )
+      {
+      // clear all registers
+      memset( &regs, 0, sizeof( regs ) );
+
+      regs.w.ax = 0x101;
+      regs.w.dx = selector;
+      int386( 0x31, &regs, &regs );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_Init
+
+   Initializes the sound card and prepares the module to play
+   digitized sounds.
+---------------------------------------------------------------------*/
+
+int PAS_Init
+   (
+   void
+   )
+
+   {
+   int Interrupt;
+   int status;
+   int data;
+
+   if ( PAS_Installed )
+      {
+      return( PAS_Ok );
+      }
+
+   PAS_IntController1Mask = inp( 0x21 );
+   PAS_IntController2Mask = inp( 0xA1 );
+
+   status = PAS_CheckForDriver();
+   if ( status != PAS_Ok )
+      {
+      return( status );
+      }
+
+   PAS_State = PAS_GetStateTable();
+   if ( PAS_State == NULL )
+      {
+      return( PAS_Error );
+      }
+
+   PAS_Func = PAS_GetFunctionTable();
+   if ( PAS_Func == NULL )
+      {
+      return( PAS_Error );
+      }
+
+   status = PAS_GetCardSettings();
+   if ( status != PAS_Ok )
+      {
+      return( status );
+      }
+
+   status = PAS_FindCard();
+   if ( status != PAS_Ok )
+      {
+      return( status );
+      }
+
+   PAS_SaveState();
+
+   PAS_OriginalPCMLeftVolume  = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, L_PCM ) & 0xff;
+   PAS_OriginalPCMRightVolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+      OUTPUTMIXER, R_PCM ) & 0xff;
+
+   PAS_SoundPlaying = FALSE;
+
+   PAS_SetCallBack( NULL );
+
+   PAS_DMABuffer = NULL;
+
+   status = PAS_LockMemory();
+   if ( status != PAS_Ok )
+      {
+      PAS_UnlockMemory();
+      return( status );
+      }
+
+   StackSelector = allocateTimerStack( kStackSize );
+   if ( StackSelector == NULL )
+      {
+      PAS_UnlockMemory();
+      PAS_SetErrorCode( PAS_OutOfMemory );
+      return( PAS_Error );
+      }
+
+   // Leave a little room at top of stack just for the hell of it...
+   StackPointer = kStackSize - sizeof( long );
+
+   // Install our interrupt handler
+   Interrupt = PAS_Interrupts[ PAS_Irq ];
+   PAS_OldInt = _dos_getvect( Interrupt );
+   if ( PAS_Irq < 8 )
+      {
+      _dos_setvect( Interrupt, PAS_ServiceInterrupt );
+      }
+   else
+      {
+      status = IRQ_SetVector( Interrupt, PAS_ServiceInterrupt );
+      if ( status != IRQ_Ok )
+         {
+         PAS_UnlockMemory();
+         deallocateTimerStack( StackSelector );
+         StackSelector = NULL;
+         PAS_SetErrorCode( PAS_UnableToSetIrq );
+         return( PAS_Error );
+         }
+      }
+
+   // Enable PAS Sound
+   data  = PAS_State->audiofilt;
+   data |= PAS_AudioMuteFlag;
+
+   PAS_Write( AudioFilterControl, data );
+   PAS_State->audiofilt = data;
+
+   PAS_SetPlaybackRate( PAS_DefaultSampleRate );
+   PAS_SetMixMode( PAS_DefaultMixMode );
+
+   PAS_Installed = TRUE;
+
+   PAS_SetErrorCode( PAS_Ok );
+   return( PAS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_Shutdown
+
+   Ends transfer of sound data to the sound card and restores the
+   system resources used by the card.
+---------------------------------------------------------------------*/
+
+void PAS_Shutdown
+   (
+   void
+   )
+
+   {
+   int Interrupt;
+
+   if ( PAS_Installed )
+      {
+      // Halt the DMA transfer
+      PAS_StopPlayback();
+
+      // Restore the original interrupt
+      Interrupt = PAS_Interrupts[ PAS_Irq ];
+      if ( PAS_Irq >= 8 )
+         {
+         IRQ_RestoreVector( Interrupt );
+         }
+      _dos_setvect( Interrupt, PAS_OldInt );
+
+      PAS_SoundPlaying = FALSE;
+
+      PAS_DMABuffer = NULL;
+
+      PAS_SetCallBack( NULL );
+
+      PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalPCMLeftVolume,
+         OUTPUTMIXER, L_PCM );
+      PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalPCMRightVolume,
+         OUTPUTMIXER, R_PCM );
+
+// DEBUG
+//      PAS_RestoreState();
+
+      PAS_UnlockMemory();
+
+      deallocateTimerStack( StackSelector );
+      StackSelector = NULL;
+
+      PAS_Installed = FALSE;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void PAS_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( PAS_LockStart, PAS_LockEnd );
+   DPMI_Unlock( PAS_Interrupts );
+   DPMI_Unlock( PAS_OldInt );
+   DPMI_Unlock( PAS_IntController1Mask );
+   DPMI_Unlock( PAS_IntController2Mask  );
+   DPMI_Unlock( PAS_Installed );
+   DPMI_Unlock( PAS_TranslateCode );
+   DPMI_Unlock( PAS_OriginalPCMLeftVolume );
+   DPMI_Unlock( PAS_OriginalPCMRightVolume );
+   DPMI_Unlock( PAS_OriginalFMLeftVolume );
+   DPMI_Unlock( PAS_OriginalFMRightVolume );
+   DPMI_Unlock( PAS_DMAChannel );
+   DPMI_Unlock( PAS_Irq );
+   DPMI_Unlock( PAS_State );
+   DPMI_Unlock( PAS_Func );
+   DPMI_Unlock( PAS_OriginalState );
+   DPMI_Unlock( PAS_SampleSizeConfig );
+   DPMI_Unlock( PAS_DMABuffer );
+   DPMI_Unlock( PAS_DMABufferEnd );
+   DPMI_Unlock( PAS_CurrentDMABuffer );
+   DPMI_Unlock( PAS_TotalDMABufferSize );
+   DPMI_Unlock( PAS_TransferLength );
+   DPMI_Unlock( PAS_MixMode );
+   DPMI_Unlock( PAS_SampleRate );
+   DPMI_Unlock( PAS_TimeInterval );
+   DPMI_Unlock( PAS_SoundPlaying );
+   DPMI_Unlock( PAS_CallBack );
+   DPMI_Unlock( PAS_ErrorCode );
+   DPMI_Unlock( irqstatus );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PAS_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int PAS_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( PAS_LockStart, PAS_LockEnd );
+   status |= DPMI_Lock( PAS_Interrupts );
+   status |= DPMI_Lock( PAS_OldInt );
+   status |= DPMI_Lock( PAS_IntController1Mask );
+   status |= DPMI_Lock( PAS_IntController2Mask  );
+   status |= DPMI_Lock( PAS_Installed );
+   status |= DPMI_Lock( PAS_TranslateCode );
+   status |= DPMI_Lock( PAS_OriginalPCMLeftVolume );
+   status |= DPMI_Lock( PAS_OriginalPCMRightVolume );
+   status |= DPMI_Lock( PAS_OriginalFMLeftVolume );
+   status |= DPMI_Lock( PAS_OriginalFMRightVolume );
+   status |= DPMI_Lock( PAS_DMAChannel );
+   status |= DPMI_Lock( PAS_Irq );
+   status |= DPMI_Lock( PAS_State );
+   status |= DPMI_Lock( PAS_Func );
+   status |= DPMI_Lock( PAS_OriginalState );
+   status |= DPMI_Lock( PAS_SampleSizeConfig );
+   status |= DPMI_Lock( PAS_DMABuffer );
+   status |= DPMI_Lock( PAS_DMABufferEnd );
+   status |= DPMI_Lock( PAS_CurrentDMABuffer );
+   status |= DPMI_Lock( PAS_TotalDMABufferSize );
+   status |= DPMI_Lock( PAS_TransferLength );
+   status |= DPMI_Lock( PAS_MixMode );
+   status |= DPMI_Lock( PAS_SampleRate );
+   status |= DPMI_Lock( PAS_TimeInterval );
+   status |= DPMI_Lock( PAS_SoundPlaying );
+   status |= DPMI_Lock( PAS_CallBack );
+   status |= DPMI_Lock( PAS_ErrorCode );
+   status |= DPMI_Lock( irqstatus );
+
+   if ( status != DPMI_Ok )
+      {
+      PAS_UnlockMemory();
+      PAS_SetErrorCode( PAS_DPMI_Error );
+      return( PAS_Error );
+      }
+
+   return( PAS_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/pas16.h
===================================================================
--- tags/rott-1.1/rott/audiolib/pas16.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/pas16.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,81 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: PAS16.H
+
+   author: James R. Dose
+   date:   March 27, 1994
+
+   Public header for for PAS16.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __PAS16_H
+#define __PAS16_H
+
+enum PAS_ERRORS
+   {
+   PAS_Warning = -2,
+   PAS_Error   = -1,
+   PAS_Ok      = 0,
+   PAS_DriverNotFound,
+   PAS_DmaError,
+   PAS_InvalidIrq,
+   PAS_UnableToSetIrq,
+   PAS_Dos4gwIrqError,
+   PAS_NoSoundPlaying,
+   PAS_CardNotFound,
+   PAS_DPMI_Error,
+   PAS_OutOfMemory
+   };
+
+#define PAS_MaxMixMode        STEREO_16BIT
+#define PAS_DefaultSampleRate 11000
+#define PAS_DefaultMixMode    MONO_8BIT
+#define PAS_MaxIrq            15
+
+#define PAS_MinSamplingRate   4000
+#define PAS_MaxSamplingRate   44000
+
+extern unsigned int PAS_DMAChannel;
+
+char *PAS_ErrorString( int ErrorNumber );
+void  PAS_SetPlaybackRate( unsigned rate );
+unsigned PAS_GetPlaybackRate( void );
+int   PAS_SetMixMode( int mode );
+void  PAS_StopPlayback( void );
+int   PAS_GetCurrentPos( void );
+int   PAS_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int   PAS_BeginBufferedRecord( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int   PAS_SetPCMVolume( int volume );
+int   PAS_GetPCMVolume( void );
+void  PAS_SetFMVolume( int volume );
+int   PAS_GetFMVolume( void );
+int   PAS_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void  PAS_SetCallBack( void ( *func )( void ) );
+int   PAS_SaveMusicVolume( void );
+void  PAS_RestoreMusicVolume( void );
+int   PAS_Init( void );
+void  PAS_Shutdown( void );
+void  PAS_UnlockMemory( void );
+int   PAS_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/pitch.c
===================================================================
--- tags/rott-1.1/rott/audiolib/pitch.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/pitch.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,258 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: PITCH.C
+
+   author: James R. Dose
+   date:   June 14, 1993
+
+   Routines for pitch scaling.
+
+   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+//#include <math.h>
+#include "dpmi.h"
+#include "standard.h"
+#include "pitch.h"
+
+#define MAXDETUNE 25
+
+static unsigned long PitchTable[ 12 ][ MAXDETUNE ] =
+   {
+      { 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c,
+      0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907,
+      0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8,
+      0x10e98 },
+      { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5,
+      0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9,
+      0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06,
+      0x11eaf },
+      { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409,
+      0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b,
+      0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08,
+      0x12fbc },
+      { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566,
+      0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c,
+      0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d,
+      0x141cb },
+      { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc,
+      0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea,
+      0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424,
+      0x154ee },
+      { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a,
+      0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5,
+      0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e,
+      0x16934 },
+      { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1,
+      0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce,
+      0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc,
+      0x17eae },
+      { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2,
+      0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17,
+      0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480,
+      0x1956f },
+      { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00,
+      0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4,
+      0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d,
+      0x1ad8b },
+      { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f,
+      0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8,
+      0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609,
+      0x1c716 },
+      { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93,
+      0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839,
+      0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109,
+      0x1e225 },
+      { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24,
+      0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e,
+      0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3,
+      0x1fed1 }
+   };
+
+
+//static int PITCH_Installed = FALSE;
+
+
+/*---------------------------------------------------------------------
+   Function: PITCH_Init
+
+   Initializes pitch table.
+---------------------------------------------------------------------*/
+/*
+void PITCH_Init
+   (
+   void
+   )
+
+   {
+   int note;
+   int detune;
+
+   if ( !PITCH_Installed )
+      {
+      for( note = 0; note < 12; note++ )
+         {
+         for( detune = 0; detune < MAXDETUNE; detune++ )
+            {
+            PitchTable[ note ][ detune ] = 0x10000 *
+               pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) );
+            }
+         }
+
+      PITCH_Installed = TRUE;
+      }
+   }
+*/
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define PITCH_LockStart PITCH_GetScale
+
+
+/*---------------------------------------------------------------------
+   Function: PITCH_GetScale
+
+   Returns a fixed-point value to scale number the specified amount.
+---------------------------------------------------------------------*/
+
+unsigned long PITCH_GetScale
+   (
+   int pitchoffset
+   )
+
+   {
+   unsigned long scale;
+   int octaveshift;
+   int noteshift;
+   int note;
+   int detune;
+
+//   if ( !PITCH_Installed )
+//      {
+//      PITCH_Init();
+//      }
+
+   if ( pitchoffset == 0 )
+      {
+      return( PitchTable[ 0 ][ 0 ] );
+      }
+
+   noteshift = pitchoffset % 1200;
+   if ( noteshift < 0 )
+      {
+      noteshift += 1200;
+      }
+
+   note   = noteshift / 100;
+   detune = ( noteshift % 100 ) / ( 100 / MAXDETUNE );
+   octaveshift = ( pitchoffset - noteshift ) / 1200;
+
+   if ( detune < 0 )
+      {
+      detune += ( 100 / MAXDETUNE );
+      note--;
+      if ( note < 0 )
+         {
+         note += 12;
+         octaveshift--;
+         }
+      }
+
+   scale = PitchTable[ note ][ detune ];
+
+   if ( octaveshift < 0 )
+      {
+      scale >>= -octaveshift;
+      }
+   else
+      {
+      scale <<= octaveshift;
+      }
+
+   return( scale );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PITCH_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void PITCH_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PITCH_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void PITCH_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( PITCH_LockStart, PITCH_LockEnd );
+   DPMI_Unlock( PitchTable );
+//   DPMI_Unlock( PITCH_Installed );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: PITCH_LockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+int PITCH_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( PITCH_LockStart, PITCH_LockEnd );
+   status |= DPMI_Lock( PitchTable );
+//   status |= DPMI_Lock( PITCH_Installed );
+
+   if ( status != DPMI_Ok )
+      {
+      PITCH_UnlockMemory();
+      return( PITCH_Error );
+      }
+
+   return( PITCH_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/pitch.h
===================================================================
--- tags/rott-1.1/rott/audiolib/pitch.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/pitch.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: PITCH.H
+
+   author: James R. Dose
+   date:   June 14, 1994
+
+   Public header for PITCH.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __PITCH_H
+#define __PITCH_H
+
+enum PITCH_ERRORS
+   {
+   PITCH_Warning = -2,
+   PITCH_Error = -1,
+   PITCH_Ok = 0,
+   };
+
+//void          PITCH_Init( void );
+unsigned long PITCH_GetScale( int pitchoffset );
+void          PITCH_UnlockMemory( void );
+int           PITCH_LockMemory( void );
+#endif

Added: tags/rott-1.1/rott/audiolib/platform.h
===================================================================
--- tags/rott-1.1/rott/audiolib/platform.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/platform.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,77 @@
+#ifndef _INCLUDE_PLATFORM_H_
+#define _INCLUDE_PLATFORM_H_
+
+/* this file originally from buildengine */
+#ifdef BUILDENGINE
+
+#if (defined PLATFORM_WIN32)
+#include "win32_compat.h"
+#elif (defined PLATFORM_UNIX)
+#include "unix_compat.h"
+#elif (defined PLATFORM_DOS)
+#include "doscmpat.h"
+#else
+#error Define your platform!
+#endif
+
+#if (!defined __EXPORT__)
+#define __EXPORT__
+#endif
+
+#if ((defined PLATFORM_SUPPORTS_SDL) && (!defined PLATFORM_TIMER_HZ))
+#define PLATFORM_TIMER_HZ 100
+#endif
+
+#if (!defined PLATFORM_TIMER_HZ)
+#error You need to define PLATFORM_TIMER_HZ for your platform.
+#endif
+
+#if (defined __WATCOMC__)
+#define snprintf _snprintf
+#endif
+
+#endif
+
+static __inline unsigned short _swap16(unsigned short D)
+{
+#if PLATFORM_MACOSX
+    register unsigned short returnValue;
+    __asm__ volatile("lhbrx %0,0,%1"
+        : "=r" (returnValue)
+        : "r" (&D)
+    );
+    return returnValue;
+#else
+    return((D<<8)|(D>>8));
+#endif
+}
+
+static __inline unsigned int _swap32(unsigned int D)
+{
+#if PLATFORM_MACOSX
+    register unsigned int returnValue;
+    __asm__ volatile("lwbrx %0,0,%1"
+        : "=r" (returnValue)
+        : "r" (&D)
+    );
+    return returnValue;
+#else
+    return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
+#endif
+}
+
+#if PLATFORM_MACOSX
+#define PLATFORM_BIGENDIAN 1
+#define BUILDSWAP_INTEL16(x) _swap16(x)
+#define BUILDSWAP_INTEL32(x) _swap32(x)
+#else
+#define PLATFORM_LITTLEENDIAN 1
+#define BUILDSWAP_INTEL16(x) (x)
+#define BUILDSWAP_INTEL32(x) (x)
+#endif
+
+#endif  /* !defined _INCLUDE_PLATFORM_H_ */
+
+/* end of platform.h ... */
+
+

Added: tags/rott-1.1/rott/audiolib/sndcards.h
===================================================================
--- tags/rott-1.1/rott/audiolib/sndcards.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/sndcards.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,55 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: SNDCARDS.H
+
+   author: James R. Dose
+   date:   March 31, 1994
+
+   Contains enumerated type definitions for sound cards.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDCARDS_H
+#define __SNDCARDS_H
+
+#define ASS_VERSION_STRING "1.12"
+
+typedef enum
+   {
+//   ASS_NoSound,
+   SoundBlaster,
+   ProAudioSpectrum,
+   SoundMan16,
+   Adlib,
+   GenMidi,
+   SoundCanvas,
+   Awe32,
+   WaveBlaster,
+   SoundScape,
+   UltraSound,
+   SoundSource,
+   TandySoundSource,
+   PC,
+   NumSoundCards
+   } soundcardnames;
+
+#endif

Added: tags/rott-1.1/rott/audiolib/sndscape.c
===================================================================
--- tags/rott-1.1/rott/audiolib/sndscape.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/sndscape.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,1661 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: SNDSCAPE.C
+
+   author: James R. Dose
+   date:   October 25, 1994
+
+   Low level routines to support the Ensoniq Soundscape.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include "interrup.h"
+#include "dpmi.h"
+#include "dma.h"
+#include "irq.h"
+#include "sndscape.h"
+#include "_sndscap.h"
+
+const int SOUNDSCAPE_Interrupts[ SOUNDSCAPE_MaxIrq + 1 ]  =
+   {
+   INVALID, INVALID,     0xa, INVALID,
+   INVALID,     0xd, INVALID,     0xf,
+   INVALID, INVALID,    0x72, INVALID,
+   INVALID, INVALID, INVALID, INVALID
+   };
+
+const int SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MaxMixMode + 1 ] =
+   {
+   MONO_8BIT_SAMPLE_SIZE,  STEREO_8BIT_SAMPLE_SIZE,
+   MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
+   };
+
+static void ( __interrupt __far *SOUNDSCAPE_OldInt )( void );
+
+static int SOUNDSCAPE_Installed = FALSE;
+static int SOUNDSCAPE_FoundCard = FALSE;
+
+static char   *SOUNDSCAPE_DMABuffer;
+static char   *SOUNDSCAPE_DMABufferEnd;
+static char   *SOUNDSCAPE_CurrentDMABuffer;
+static int     SOUNDSCAPE_TotalDMABufferSize;
+
+static int      SOUNDSCAPE_TransferLength   = 0;
+static int      SOUNDSCAPE_MixMode          = SOUNDSCAPE_DefaultMixMode;
+static int      SOUNDSCAPE_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
+static unsigned SOUNDSCAPE_SampleRate       = SOUNDSCAPE_DefaultSampleRate;
+
+volatile int   SOUNDSCAPE_SoundPlaying;
+
+void ( *SOUNDSCAPE_CallBack )( void );
+
+static int  SOUNDSCAPE_IntController1Mask;
+static int  SOUNDSCAPE_IntController2Mask;
+
+// some globals for chip type, ports, DMA, IRQs ... and stuff
+static struct
+   {
+   int BasePort;  // base address of the Ensoniq gate-array chip
+   int WavePort;  // the AD-1848 base address
+   int DMAChan;   // the DMA channel used for PCM
+   int WaveIRQ;   // the PCM IRQ
+   int MIDIIRQ;   // the MPU-401 IRQ
+   int ChipID;    // the Ensoniq chip type
+   int SBEmul;    // SoundBlaster emulation flag
+   int CDROM;     // CD-ROM flag
+   int IRQIndx;   // the Wave IRQ index - for hardware regs
+   int OldIRQs;   // Old IRQs flag to support older HW
+   } SOUNDSCAPE_Config;
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long  StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long  oldStackPointer;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack =	\
+	"mov  [edi],esp"		\
+	"mov	ax,ss"	 		\
+	"mov  [esi],ax" 		\
+	parm [esi] [edi]		\
+	modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack =	\
+	"mov  ss,ax"			\
+	"mov  esp,edx"			\
+	parm [ax] [edx]		\
+	modify [eax edx];
+
+int SOUNDSCAPE_DMAChannel = -1;
+
+int SOUNDSCAPE_ErrorCode = SOUNDSCAPE_Ok;
+
+#define SOUNDSCAPE_SetErrorCode( status ) \
+   SOUNDSCAPE_ErrorCode   = ( status );
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *SOUNDSCAPE_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case SOUNDSCAPE_Warning :
+      case SOUNDSCAPE_Error :
+         ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_ErrorCode );
+         break;
+
+      case SOUNDSCAPE_Ok :
+         ErrorString = "SoundScape ok.";
+         break;
+
+      case SOUNDSCAPE_EnvNotFound :
+         ErrorString = "SNDSCAPE environment variable not set.  This is used to locate \n"
+                       "SNDSCAPE.INI which is used to describe your sound card setup.";
+         break;
+
+      case SOUNDSCAPE_InitFileNotFound :
+         ErrorString = "Missing SNDSCAPE.INI file for SoundScape.  This file should be \n"
+                       "located in the directory indicated by the SNDSCAPE environment \n"
+                       "variable or in 'C:\SNDSCAPE' if SNDSCAPE is not set.";
+         break;
+
+      case SOUNDSCAPE_MissingProductInfo :
+         ErrorString = "Missing 'Product' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingPortInfo :
+         ErrorString = "Missing 'Port' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingDMAInfo :
+         ErrorString = "Missing 'DMA' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingIRQInfo :
+         ErrorString = "Missing 'IRQ' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingSBIRQInfo :
+         ErrorString = "Missing 'SBIRQ' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingSBENABLEInfo :
+         ErrorString = "Missing 'SBEnable' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_MissingWavePortInfo :
+         ErrorString = "Missing 'WavePort' field in SNDSCAPE.INI file for SoundScape.";
+         break;
+
+      case SOUNDSCAPE_HardwareError :
+         ErrorString = "Could not detect SoundScape.  Make sure your SNDSCAPE.INI file \n"
+                       "contains correct information about your hardware setup.";
+         break;
+
+      case SOUNDSCAPE_NoSoundPlaying :
+         ErrorString = "No sound playing on SoundScape.";
+         break;
+
+      case SOUNDSCAPE_InvalidSBIrq :
+         ErrorString = "Invalid SoundScape Irq in SBIRQ field of SNDSCAPE.INI.";
+         break;
+
+      case SOUNDSCAPE_UnableToSetIrq :
+         ErrorString = "Unable to set SoundScape IRQ.  Try selecting an IRQ of 7 or below.";
+         break;
+
+      case SOUNDSCAPE_DmaError :
+         ErrorString = DMA_ErrorString( DMA_Error );
+         break;
+
+      case SOUNDSCAPE_DPMI_Error :
+         ErrorString = "DPMI Error in SoundScape.";
+         break;
+
+      case SOUNDSCAPE_OutOfMemory :
+         ErrorString = "Out of conventional memory in SoundScape.";
+         break;
+
+      default :
+         ErrorString = "Unknown SoundScape error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define SOUNDSCAPE_LockStart SOUNDSCAPE_EnableInterrupt
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_EnableInterrupt
+
+   Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_EnableInterrupt
+   (
+   void
+   )
+
+   {
+   int mask;
+
+   // Unmask system interrupt
+   if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+      {
+      mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+      outp( 0xA1, mask  );
+
+      mask = inp( 0x21 ) & ~( 1 << 2 );
+      outp( 0x21, mask  );
+      }
+
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_DisableInterrupt
+
+   Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_DisableInterrupt
+   (
+   void
+   )
+
+   {
+   int mask;
+
+   // Restore interrupt mask
+   if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+      {
+      mask  = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
+      mask |= SOUNDSCAPE_IntController1Mask & ( 1 << SOUNDSCAPE_Config.WaveIRQ );
+      outp( 0x21, mask  );
+      }
+   else
+      {
+      mask  = inp( 0x21 ) & ~( 1 << 2 );
+      mask |= SOUNDSCAPE_IntController1Mask & ( 1 << 2 );
+      outp( 0x21, mask  );
+
+      mask  = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+      mask |= SOUNDSCAPE_IntController2Mask & ( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+      outp( 0xA1, mask  );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_ServiceInterrupt
+
+   Handles interrupt generated by sound card at the end of a voice
+   transfer.  Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+static void __interrupt __far SOUNDSCAPE_ServiceInterrupt
+   (
+   void
+   )
+
+   {
+   // save stack
+   GetStack( &oldStackSelector, &oldStackPointer );
+
+   // set our stack
+   SetStack( StackSelector, StackPointer );
+
+	if ( !( inp( SOUNDSCAPE_Config.WavePort + AD_STATUS ) & 0x01 ) )
+      {
+      // restore stack
+      SetStack( oldStackSelector, oldStackPointer );
+
+      // Wasn't our interrupt.  Call the old one.
+      _chain_intr( SOUNDSCAPE_OldInt );
+      }
+
+   // clear the AD-1848 interrupt
+	outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
+
+   // Keep track of current buffer
+   SOUNDSCAPE_CurrentDMABuffer += SOUNDSCAPE_TransferLength;
+   if ( SOUNDSCAPE_CurrentDMABuffer >= SOUNDSCAPE_DMABufferEnd )
+      {
+      SOUNDSCAPE_CurrentDMABuffer = SOUNDSCAPE_DMABuffer;
+      }
+
+   // Call the caller's callback function
+   if ( SOUNDSCAPE_CallBack != NULL )
+      {
+      SOUNDSCAPE_CallBack();
+      }
+
+   // restore stack
+   SetStack( oldStackSelector, oldStackPointer );
+
+   // send EOI to Interrupt Controller
+   if ( SOUNDSCAPE_Config.WaveIRQ > 7 )
+      {
+      outp( 0xA0, 0x20 );
+      }
+   outp( 0x20, 0x20 );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ga_read
+
+   Reads Ensoniq indirect registers.
+---------------------------------------------------------------------*/
+
+static int ga_read
+   (
+   int rnum
+   )
+
+   {
+   int data;
+
+   outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
+   data = inp( SOUNDSCAPE_Config.BasePort + GA_REGDATA );
+   return( data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ga_write
+
+   Writes to Ensoniq indirect registers.
+---------------------------------------------------------------------*/
+
+static void ga_write
+   (
+   int rnum,
+   int value
+   )
+
+   {
+	outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
+	outp( SOUNDSCAPE_Config.BasePort + GA_REGDATA, value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ad_read
+
+   Reads the AD-1848 indirect registers.  This function should not be
+   used while the AD-1848 mode change is enabled
+---------------------------------------------------------------------*/
+
+static int ad_read
+   (
+   int rnum
+   )
+
+   {
+   int data;
+
+	outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
+	data = inp( SOUNDSCAPE_Config.WavePort + AD_REGDATA );
+   return( data );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: ad_write
+
+   Writes to the AD-1848 indirect registers.  This function should
+   not be used while the AD-1848 mode change is enabled.
+---------------------------------------------------------------------*/
+
+static void ad_write
+   (
+   int rnum,
+   int value
+   )
+
+   {
+   outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
+   outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, value );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: tdelay
+
+   Delay function - 250ms - for AD-1848 re-synch and autocalibration.
+---------------------------------------------------------------------*/
+
+static void tdelay
+   (
+   void
+   )
+
+   {
+	long time;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+   _enable();
+	time = clock() + CLOCKS_PER_SEC/4;
+	while(clock() < time)
+		;
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: pcm_format
+
+   Sets the PCM data format.
+---------------------------------------------------------------------*/
+
+static void pcm_format
+   (
+   void
+   )
+
+   {
+	int format;
+
+	// build the register value based on format
+	format = 0;
+
+   switch( SOUNDSCAPE_SampleRate )
+      {
+      case 11025:
+         format = 0x03;
+         break;
+
+      case 22050:
+         format = 0x07;
+         break;
+
+      case 44100:
+         format = 0x0b;
+         break;
+
+      default:
+         // Set it to 11025 hz
+         format = 0x03;
+         break;
+      }
+
+	// set other format bits and format globals
+   if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+      {
+      format |= 0x40;
+      }
+
+   if ( SOUNDSCAPE_MixMode & STEREO )
+      {
+      format |= 0x10;
+      }
+
+	// enable mode change, point to format reg
+	outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_FORMAT );
+
+	// write the format
+	outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, format );
+
+	// delay for internal re-synch
+	tdelay();
+
+	// exit mode change state
+	outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
+
+	// delay for autocalibration
+	tdelay();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_SetPlaybackRate
+
+   Sets the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_SetPlaybackRate
+   (
+   unsigned rate
+   )
+
+   {
+   if ( rate < 20000 )
+      {
+      rate = 11025;
+      }
+   else if ( rate < 30000 )
+      {
+      rate = 22050;
+      }
+   else
+      {
+      rate = 44100;
+      }
+
+   SOUNDSCAPE_SampleRate = rate;
+
+   // Set the rate
+   pcm_format();
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_GetPlaybackRate
+
+   Returns the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+unsigned SOUNDSCAPE_GetPlaybackRate
+   (
+   void
+   )
+
+   {
+   return( SOUNDSCAPE_SampleRate );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_SetMixMode
+
+   Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_SetMixMode
+   (
+   int mode
+   )
+
+   {
+   SOUNDSCAPE_MixMode = mode & SOUNDSCAPE_MaxMixMode;
+   SOUNDSCAPE_SamplePacketSize = SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MixMode ];
+
+   // Set the mixmode
+   pcm_format();
+
+   return( mode );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_StopPlayback
+
+   Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_StopPlayback
+   (
+   void
+   )
+
+   {
+   // Don't allow anymore interrupts
+   SOUNDSCAPE_DisableInterrupt();
+
+	/* stop the AD-1848 */
+	ad_write( AD_CONFIG, 0x00 );
+
+	/* let it finish it's cycles */
+	tdelay();
+
+   // Disable the DMA channel
+   DMA_EndTransfer( SOUNDSCAPE_Config.DMAChan );
+
+   SOUNDSCAPE_SoundPlaying = FALSE;
+
+   SOUNDSCAPE_DMABuffer = NULL;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_SetupDMABuffer
+
+   Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_SetupDMABuffer
+   (
+   char *BufferPtr,
+   int   BufferSize,
+   int   mode
+   )
+
+   {
+   int DmaStatus;
+
+   DmaStatus = DMA_SetupTransfer( SOUNDSCAPE_Config.DMAChan, BufferPtr, BufferSize, mode );
+   if ( DmaStatus == DMA_Error )
+      {
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
+      return( SOUNDSCAPE_Error );
+      }
+
+   SOUNDSCAPE_DMAChannel         = SOUNDSCAPE_Config.DMAChan;
+   SOUNDSCAPE_DMABuffer          = BufferPtr;
+   SOUNDSCAPE_CurrentDMABuffer   = BufferPtr;
+   SOUNDSCAPE_TotalDMABufferSize = BufferSize;
+   SOUNDSCAPE_DMABufferEnd       = BufferPtr + BufferSize;
+
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_GetCurrentPos
+
+   Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetCurrentPos
+   (
+   void
+   )
+
+   {
+   char *CurrentAddr;
+   int   offset;
+
+   if ( !SOUNDSCAPE_SoundPlaying )
+      {
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_NoSoundPlaying );
+      return( SOUNDSCAPE_Error );
+      }
+
+   CurrentAddr = DMA_GetCurrentPos( SOUNDSCAPE_Config.DMAChan );
+
+   offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+      ( ( unsigned long )SOUNDSCAPE_CurrentDMABuffer ) );
+
+   if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+      {
+      offset >>= 1;
+      }
+
+   if ( SOUNDSCAPE_MixMode & STEREO )
+      {
+      offset >>= 1;
+      }
+
+   return( offset );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_BeginPlayback
+
+   Starts playback of digitized sound.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_BeginPlayback
+   (
+   int length
+   )
+
+   {
+   int SampleLength;
+   int LoByte;
+   int HiByte;
+
+   if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+      {
+      SampleLength = length / 2;
+      }
+   else
+      {
+      SampleLength = length;
+      }
+
+   if ( SOUNDSCAPE_MixMode & STEREO )
+      {
+      SampleLength >>= 1;
+      }
+
+   SampleLength--;
+
+	// setup the AD-1848 interrupt count
+	// set the interrupt count value based on the format.
+	// count will decrement every sample period and generate
+	// an interrupt when in rolls over. we want this always
+	// to be at every 1/2 buffer, regardless of the data format,
+	// so the count must be adjusted accordingly.
+   HiByte = hibyte( SampleLength );
+   LoByte = lobyte( SampleLength );
+	ad_write( AD_LCOUNT, LoByte );
+	ad_write( AD_UCOUNT, HiByte );
+
+	/* unmask the host DMA controller */
+   SOUNDSCAPE_EnableInterrupt();
+
+	/* start the AD-1848 */
+	ad_write(AD_CONFIG, 0x01);
+
+   SOUNDSCAPE_SoundPlaying = TRUE;
+
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_BeginBufferedPlayback
+
+   Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_BeginBufferedPlayback
+   (
+   char    *BufferStart,
+   int      BufferSize,
+   int      NumDivisions,
+   unsigned SampleRate,
+   int      MixMode,
+   void  ( *CallBackFunc )( void )
+   )
+
+   {
+   int DmaStatus;
+   int TransferLength;
+
+   if ( SOUNDSCAPE_SoundPlaying )
+      {
+      SOUNDSCAPE_StopPlayback();
+      }
+
+   SOUNDSCAPE_SetMixMode( MixMode );
+
+   DmaStatus = SOUNDSCAPE_SetupDMABuffer( BufferStart, BufferSize,
+      DMA_AutoInitRead );
+   if ( DmaStatus == SOUNDSCAPE_Error )
+      {
+      return( SOUNDSCAPE_Error );
+      }
+
+   SOUNDSCAPE_SetPlaybackRate( SampleRate );
+
+   SOUNDSCAPE_SetCallBack( CallBackFunc );
+
+   SOUNDSCAPE_EnableInterrupt();
+
+   TransferLength = BufferSize / NumDivisions;
+   SOUNDSCAPE_TransferLength = TransferLength;
+
+   SOUNDSCAPE_BeginPlayback( TransferLength );
+
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_GetCardInfo
+
+   Returns the maximum number of bits that can represent a sample
+   (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetCardInfo
+   (
+   int *MaxSampleBits,
+   int *MaxChannels
+   )
+
+   {
+   int status;
+
+   status = SOUNDSCAPE_FindCard();
+   if ( status == SOUNDSCAPE_Ok )
+      {
+      *MaxChannels = 2;
+      *MaxSampleBits = 16;
+      return( SOUNDSCAPE_Ok );
+      }
+
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_SetCallBack
+
+   Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_SetCallBack
+   (
+   void ( *func )( void )
+   )
+
+   {
+   SOUNDSCAPE_CallBack = func;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
+   DPMI_Unlock( SOUNDSCAPE_Config );
+   DPMI_Unlock( SOUNDSCAPE_OldInt );
+   DPMI_Unlock( SOUNDSCAPE_Installed );
+   DPMI_Unlock( SOUNDSCAPE_DMABuffer );
+   DPMI_Unlock( SOUNDSCAPE_DMABufferEnd );
+   DPMI_Unlock( SOUNDSCAPE_CurrentDMABuffer );
+   DPMI_Unlock( SOUNDSCAPE_TotalDMABufferSize );
+   DPMI_Unlock( SOUNDSCAPE_TransferLength );
+   DPMI_Unlock( SOUNDSCAPE_MixMode );
+   DPMI_Unlock( SOUNDSCAPE_SamplePacketSize );
+   DPMI_Unlock( SOUNDSCAPE_SampleRate );
+   DPMI_Unlock( SOUNDSCAPE_SoundPlaying );
+   DPMI_Unlock( SOUNDSCAPE_CallBack );
+   DPMI_Unlock( SOUNDSCAPE_IntController1Mask );
+   DPMI_Unlock( SOUNDSCAPE_IntController2Mask );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
+   status |= DPMI_Lock( SOUNDSCAPE_Config );
+   status |= DPMI_Lock( SOUNDSCAPE_OldInt );
+   status |= DPMI_Lock( SOUNDSCAPE_Installed );
+   status |= DPMI_Lock( SOUNDSCAPE_DMABuffer );
+   status |= DPMI_Lock( SOUNDSCAPE_DMABufferEnd );
+   status |= DPMI_Lock( SOUNDSCAPE_CurrentDMABuffer );
+   status |= DPMI_Lock( SOUNDSCAPE_TotalDMABufferSize );
+   status |= DPMI_Lock( SOUNDSCAPE_TransferLength );
+   status |= DPMI_Lock( SOUNDSCAPE_MixMode );
+   status |= DPMI_Lock( SOUNDSCAPE_SamplePacketSize );
+   status |= DPMI_Lock( SOUNDSCAPE_SampleRate );
+   status |= DPMI_Lock( SOUNDSCAPE_SoundPlaying );
+   status |= DPMI_Lock( SOUNDSCAPE_CallBack );
+   status |= DPMI_Lock( SOUNDSCAPE_IntController1Mask );
+   status |= DPMI_Lock( SOUNDSCAPE_IntController2Mask );
+
+   if ( status != DPMI_Ok )
+      {
+      SOUNDSCAPE_UnlockMemory();
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DPMI_Error );
+      return( SOUNDSCAPE_Error );
+      }
+
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: allocateTimerStack
+
+   Allocate a block of memory from conventional (low) memory and return
+   the selector (which can go directly into a segment register) of the
+   memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+   (
+   unsigned short size
+   )
+
+   {
+   union REGS regs;
+
+   // clear all registers
+   memset( &regs, 0, sizeof( regs ) );
+
+   // DPMI allocate conventional memory
+   regs.w.ax = 0x100;
+
+   // size in paragraphs
+   regs.w.bx = ( size + 15 ) / 16;
+
+   int386( 0x31, &regs, &regs );
+   if (!regs.w.cflag)
+      {
+      // DPMI call returns selector in dx
+      // (ax contains real mode segment
+      // which is ignored here)
+
+      return( regs.w.dx );
+      }
+
+   // Couldn't allocate memory.
+   return( NULL );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: deallocateTimerStack
+
+   Deallocate a block of conventional (low) memory given a selector to
+   it.  Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+   (
+   unsigned short selector
+   )
+
+   {
+   union REGS regs;
+
+   if ( selector != NULL )
+      {
+      // clear all registers
+      memset( &regs, 0, sizeof( regs ) );
+
+      regs.w.ax = 0x101;
+      regs.w.dx = selector;
+      int386( 0x31, &regs, &regs );
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: parse
+
+   Parses for the right hand string of an .INI file equate.
+---------------------------------------------------------------------*/
+
+static int parse
+   (
+   char *val,
+   char *str,
+   FILE *p1
+   )
+
+   {
+	int  i;
+	int  j;
+   char tmpstr[ 81 ];
+
+	rewind( p1 );
+
+	while( !feof( p1 ) )
+      {
+      // get a new string
+      fgets( tmpstr, 81, p1 );
+      if( ( tmpstr[ 0 ] == '[' ) || ( tmpstr[ 0 ] == ';' ) ||
+         ( tmpstr[ 0 ] == '\n' ) )
+         {
+         continue;
+         }
+
+		// parse up to the '='
+      i = 0;
+      while( ( tmpstr[ i ] != '=' ) && ( tmpstr[ i ] != '\n' ) )
+         {
+         i++;
+         }
+
+		if( tmpstr[ i ] != '=' )
+         {
+         continue;
+         }
+
+		tmpstr[ i ] = '\0';
+
+		// see if it's the one we want
+		if ( strcmp( tmpstr, str ) )
+         {
+         continue;
+         }
+
+		// copy the right hand value to the destination string
+      i++;
+		for( j = 0; j < 32; j++ )
+         {
+         if ( ( tmpstr[ i ] == ' ' ) || ( tmpstr[ i ] == '\t' ) ||
+            ( tmpstr[ i ] == ',' ) || ( tmpstr[ i ] == '\n' ) )
+            {
+            break;
+            }
+
+			val[ j ] = tmpstr[ i ];
+         i++;
+         }
+		val[j] = '\0';
+
+      return( TRUE );
+      }
+
+   return( FALSE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_FindCard
+
+   Determines if a SoundScape is present and where it is located.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_FindCard
+   (
+   void
+   )
+
+   {
+   int   found;
+   int   status;
+   int   tmp;
+	char *cp;
+   char  str[ 33 ];
+	FILE *fp;
+
+   if ( SOUNDSCAPE_FoundCard )
+      {
+      return( SOUNDSCAPE_Ok );
+      }
+
+	cp = getenv( "SNDSCAPE" );
+   if ( cp == NULL )
+      {
+      strcpy( str, "C:\\SNDSCAPE" );
+      }
+   else
+      {
+      strcpy( str, cp );
+      }
+
+   strcat(str, "\\SNDSCAPE.INI");
+
+	fp = fopen( str, "r" );
+   if ( fp == NULL )
+      {
+      if ( cp == NULL )
+         {
+         SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_EnvNotFound );
+         return( SOUNDSCAPE_Error );
+         }
+
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InitFileNotFound );
+      return( SOUNDSCAPE_Error );
+      }
+
+	found = parse( str, "Product", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingProductInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	if( strstr( str, "SoundFX" ) == NULL )
+      {
+      SOUNDSCAPE_Config.OldIRQs = FALSE;
+      }
+	else
+      {
+		SOUNDSCAPE_Config.OldIRQs = TRUE;
+      }
+
+	found = parse( str, "Port", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingPortInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	SOUNDSCAPE_Config.BasePort = strtol( str, ( char ** )0, 16);
+
+	found = parse( str, "DMA", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingDMAInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	SOUNDSCAPE_Config.DMAChan = ( int )strtol( str, ( char ** )0, 10 );
+   status = DMA_VerifyChannel( SOUNDSCAPE_Config.DMAChan );
+   if ( status == DMA_Error )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
+      return( SOUNDSCAPE_Error );
+      }
+
+	found = parse( str, "IRQ", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingIRQInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	SOUNDSCAPE_Config.MIDIIRQ = ( int )strtol( str, ( char ** )0, 10 );
+   if ( SOUNDSCAPE_Config.MIDIIRQ == 2 )
+      {
+      SOUNDSCAPE_Config.MIDIIRQ = 9;
+      }
+
+	found = parse( str, "SBIRQ", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBIRQInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	SOUNDSCAPE_Config.WaveIRQ = ( int )strtol( str, ( char ** )0, 10 );
+	if ( SOUNDSCAPE_Config.WaveIRQ == 2 )
+      {
+		SOUNDSCAPE_Config.WaveIRQ = 9;
+      }
+
+   if ( !VALID_IRQ( SOUNDSCAPE_Config.WaveIRQ ) )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
+      return( SOUNDSCAPE_Error );
+      }
+
+   if ( SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ] == INVALID )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
+      return( SOUNDSCAPE_Error );
+      }
+
+	found = parse( str, "SBEnable", fp );
+   if ( !found )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBENABLEInfo );
+      return( SOUNDSCAPE_Error );
+      }
+
+	if( !strcmp( str, "false" ) )
+      {
+      SOUNDSCAPE_Config.SBEmul = FALSE;
+      }
+	else
+      {
+      SOUNDSCAPE_Config.SBEmul = TRUE;
+      }
+
+	// do a hardware test
+	outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, 0x00f5 );
+	tmp = inp( SOUNDSCAPE_Config.BasePort + GA_REGADDR );
+	if ( ( tmp & 0x000f ) != 0x0005 )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
+      return( SOUNDSCAPE_Error );
+      }
+
+	if( ( tmp & 0x00f0 ) == 0x00f0 )
+      {
+      fclose( fp );
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
+      return( SOUNDSCAPE_Error );
+      }
+
+	// formulate the chip ID
+	tmp >>= 4;
+	if( tmp == 0 )
+      {
+      SOUNDSCAPE_Config.ChipID = ODIE;
+      }
+	else if ( !( tmp & 0x0008 ) )
+      {
+		SOUNDSCAPE_Config.ChipID = OPUS;
+      }
+	else
+      {
+		SOUNDSCAPE_Config.ChipID = MMIC;
+      }
+
+	// parse for the AD-1848 address if necessary
+	if( SOUNDSCAPE_Config.ChipID == ODIE )
+      {
+      found = parse( str, "WavePort", fp );
+      if ( !found )
+         {
+         fclose( fp );
+         SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingWavePortInfo );
+         return( SOUNDSCAPE_Error );
+         }
+
+      SOUNDSCAPE_Config.WavePort = strtol( str, ( char ** )0, 16 );
+      }
+	else
+      {
+      // otherwise, the base address is fixed
+      SOUNDSCAPE_Config.WavePort = SOUNDSCAPE_Config.BasePort + AD_OFFSET;
+      }
+
+	// we're done with the file
+	fclose( fp );
+
+	// if it's an ODIE board, note CD-ROM decode enable
+	if ( SOUNDSCAPE_Config.ChipID == ODIE )
+      {
+		SOUNDSCAPE_Config.CDROM = ga_read( GA_CDCFG ) & 0x80;
+      }
+
+	// build the Wave IRQ index value
+	if( !SOUNDSCAPE_Config.OldIRQs )
+      {
+      switch( SOUNDSCAPE_Config.WaveIRQ )
+         {
+         case 9 :
+            SOUNDSCAPE_Config.IRQIndx = 0;
+            break;
+
+         case 5 :
+            SOUNDSCAPE_Config.IRQIndx = 1;
+            break;
+
+         case 7 :
+            SOUNDSCAPE_Config.IRQIndx = 2;
+            break;
+
+         default :
+            SOUNDSCAPE_Config.IRQIndx = 3;
+            break;
+         }
+      }
+   else
+      {
+      switch( SOUNDSCAPE_Config.WaveIRQ )
+         {
+         case 9 :
+            SOUNDSCAPE_Config.IRQIndx = 0;
+            break;
+
+         case 5 :
+            SOUNDSCAPE_Config.IRQIndx = 2;
+            break;
+
+         case 7 :
+            SOUNDSCAPE_Config.IRQIndx = 1;
+            break;
+
+         default :
+            SOUNDSCAPE_Config.IRQIndx = 3;
+            break;
+         }
+      }
+
+   SOUNDSCAPE_FoundCard = TRUE;
+   SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_Setup
+
+   Setup the Soundscape card for native mode PCM.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_Setup
+   (
+   void
+   )
+
+   {
+   int tmp;
+   int Interrupt;
+   int status;
+
+	// if necessary, clear any pending SB ints
+	if ( SOUNDSCAPE_Config.SBEmul )
+      {
+      inp( SB_IACK );
+      }
+
+   SOUNDSCAPE_DisableInterrupt();
+
+	// make sure the AD-1848 is not running
+	if ( ad_read( AD_CONFIG ) & 0x01 )
+      {
+      SOUNDSCAPE_StopPlayback();
+      }
+
+	// if necessary, do some signal re-routing
+	if( SOUNDSCAPE_Config.ChipID != MMIC )
+      {
+      // get the gate-array off of the DMA channel
+		ga_write( GA_DMACHB, 0x20 );
+
+      if ( !SOUNDSCAPE_Config.OldIRQs )
+         {
+         switch( SOUNDSCAPE_Config.MIDIIRQ )
+            {
+            case 5 :
+               tmp = 1;
+               break;
+
+            case 7 :
+               tmp = 2;
+               break;
+
+            case 9 :
+               tmp = 0;
+               break;
+
+            default :
+               tmp = 3;
+               break;
+            }
+         }
+      else
+         {
+         switch( SOUNDSCAPE_Config.MIDIIRQ )
+            {
+            case 5 :
+               tmp = 2;
+               break;
+
+            case 7 :
+               tmp = 1;
+               break;
+
+            case 9 :
+               tmp = 0;
+               break;
+
+            default :
+               tmp = 3;
+               break;
+            }
+         }
+
+      // set HostIRQ to MIDIIRQ for now
+      ga_write( GA_INTCFG, 0xf0 | ( tmp << 2 ) | tmp );
+
+      // now, route the AD-1848 stuff ...
+		if ( SOUNDSCAPE_Config.ChipID == OPUS )
+         {
+         // set the AD-1848 chip decode
+         ga_write( GA_HMCTL, ( ga_read( GA_HMCTL ) & 0xcf ) | 0x10 );
+         }
+      // setup the DMA polarity
+		ga_write( GA_DMACFG, 0x50 );
+
+		// init the CD-ROM (AD-1848) config register
+		ga_write( GA_CDCFG, 0x89 | ( SOUNDSCAPE_Config.DMAChan << 4 ) | ( SOUNDSCAPE_Config.IRQIndx << 1 ) );
+
+      // enable mode change, point to config reg
+		outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_CONFIG );
+
+      // set interf cnfg reg for DMA mode, single chan, autocal on
+		outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, 0x0c );
+
+      // exit mode change state
+		outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
+
+      // delay for autocalibration
+      tdelay();
+      }
+
+   // Install our interrupt handler
+   Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
+   SOUNDSCAPE_OldInt = _dos_getvect( Interrupt );
+   if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+      {
+      _dos_setvect( Interrupt, SOUNDSCAPE_ServiceInterrupt );
+      }
+   else
+      {
+      status = IRQ_SetVector( Interrupt, SOUNDSCAPE_ServiceInterrupt );
+      if ( status != IRQ_Ok )
+         {
+         SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_UnableToSetIrq );
+         return( SOUNDSCAPE_Error );
+         }
+      }
+
+	// max left and right volumes
+	ad_write( AD_LEFTOUT, 0 );
+	ad_write( AD_RIGHTOUT, 0 );
+
+	// clear any pending interrupt condition
+	outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
+
+	// enable the interrupt pin
+	ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) | 0x02 );
+
+   SOUNDSCAPE_EnableInterrupt();
+
+   SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_GetMIDIPort
+
+   Gets the address of the SoundScape MIDI port.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetMIDIPort
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status = SOUNDSCAPE_FindCard();
+   if ( status != SOUNDSCAPE_Ok )
+      {
+      return( status );
+      }
+
+   return( SOUNDSCAPE_Config.BasePort );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_Init
+
+   Initializes the sound card and prepares the module to play
+   digitized sounds.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_Init
+   (
+   void
+   )
+
+   {
+   int status;
+
+   if ( SOUNDSCAPE_Installed )
+      {
+      SOUNDSCAPE_Shutdown();
+      }
+
+   // Save the interrupt masks
+   SOUNDSCAPE_IntController1Mask = inp( 0x21 );
+   SOUNDSCAPE_IntController2Mask = inp( 0xA1 );
+
+   SOUNDSCAPE_SoundPlaying = FALSE;
+   SOUNDSCAPE_SetCallBack( NULL );
+   SOUNDSCAPE_DMABuffer = NULL;
+
+   status = SOUNDSCAPE_FindCard();
+   if ( status != SOUNDSCAPE_Ok )
+      {
+      return( status );
+      }
+
+   status = SOUNDSCAPE_LockMemory();
+   if ( status != SOUNDSCAPE_Ok )
+      {
+      SOUNDSCAPE_UnlockMemory();
+      return( status );
+      }
+
+   StackSelector = allocateTimerStack( kStackSize );
+   if ( StackSelector == NULL )
+      {
+      SOUNDSCAPE_UnlockMemory();
+      SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_OutOfMemory );
+      return( SOUNDSCAPE_Error );
+      }
+
+   // Leave a little room at top of stack just for the hell of it...
+   StackPointer = kStackSize - sizeof( long );
+
+   SOUNDSCAPE_Installed = TRUE;
+
+   status = SOUNDSCAPE_Setup();
+   if ( status != SOUNDSCAPE_Ok )
+      {
+      SOUNDSCAPE_Shutdown();
+      return( status );
+      }
+
+//	printf("Testing DMA and IRQ ...\n");
+//	if( test_dma_irq() )
+//      {
+//      printf("\t\007Hardware Not Responding\n\n");
+//      close_soundscape();
+//      return( SOUNDSCAPE_Error );
+//      }
+
+   SOUNDSCAPE_SetPlaybackRate( SOUNDSCAPE_DefaultSampleRate );
+   SOUNDSCAPE_SetMixMode( SOUNDSCAPE_DefaultMixMode );
+
+   SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+   return( SOUNDSCAPE_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SOUNDSCAPE_Shutdown
+
+   Ends transfer of sound data to the sound card and restores the
+   system resources used by the card.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_Shutdown
+   (
+   void
+   )
+
+   {
+   int Interrupt;
+
+   // Halt the DMA transfer
+   SOUNDSCAPE_StopPlayback();
+
+	// disable the AD-1848 interrupt pin
+	ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) & 0xfd );
+
+	// if necessary, do some signal re-routing
+	if ( SOUNDSCAPE_Config.ChipID != MMIC )
+      {
+		// re-init the CD-ROM (AD-1848) config register as needed.
+		// this will disable the AD-1848 interface.
+		if ( SOUNDSCAPE_Config.ChipID == ODIE )
+         {
+         ga_write( GA_CDCFG, SOUNDSCAPE_Config.CDROM );
+         }
+		else
+         {
+         ga_write( GA_CDCFG, ga_read( GA_CDCFG ) & 0x7f);
+         }
+
+		// if necessary, reset the SoundBlaster IRQ
+		if ( SOUNDSCAPE_Config.SBEmul )
+         {
+         ga_write( GA_INTCFG, ( ga_read( GA_INTCFG ) & 0xf3 ) |
+            ( SOUNDSCAPE_Config.IRQIndx << 2 ) );
+         }
+
+      // re-assign the gate-array DMA channel
+		ga_write( GA_DMACHB, 0x80 | ( SOUNDSCAPE_Config.DMAChan << 4 ) );
+      }
+
+   // Restore the original interrupt
+   Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
+   if ( SOUNDSCAPE_Config.WaveIRQ >= 8 )
+      {
+      IRQ_RestoreVector( Interrupt );
+      }
+   _dos_setvect( Interrupt, SOUNDSCAPE_OldInt );
+
+   SOUNDSCAPE_SoundPlaying = FALSE;
+
+   SOUNDSCAPE_DMABuffer = NULL;
+
+   SOUNDSCAPE_SetCallBack( NULL );
+
+   SOUNDSCAPE_UnlockMemory();
+
+   if ( StackSelector != NULL )
+      {
+      deallocateTimerStack( StackSelector );
+      StackSelector = NULL;
+      }
+
+   SOUNDSCAPE_Installed = FALSE;
+   }

Added: tags/rott-1.1/rott/audiolib/sndscape.h
===================================================================
--- tags/rott-1.1/rott/audiolib/sndscape.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/sndscape.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,73 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: SNDSCAPE.H
+
+   author: James R. Dose
+   date:   October 26, 1994
+
+   Public header for SNDSCAPE.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDSCAPE_H
+#define __SNDSCAPE_H
+
+extern int SOUNDSCAPE_DMAChannel;
+extern int SOUNDSCAPE_ErrorCode;
+
+enum SOUNDSCAPE_ERRORS
+   {
+   SOUNDSCAPE_Warning = -2,
+   SOUNDSCAPE_Error = -1,
+   SOUNDSCAPE_Ok = 0,
+   SOUNDSCAPE_EnvNotFound,
+   SOUNDSCAPE_InitFileNotFound,
+   SOUNDSCAPE_MissingProductInfo,
+   SOUNDSCAPE_MissingPortInfo,
+   SOUNDSCAPE_MissingDMAInfo,
+   SOUNDSCAPE_MissingIRQInfo,
+   SOUNDSCAPE_MissingSBIRQInfo,
+   SOUNDSCAPE_MissingSBENABLEInfo,
+   SOUNDSCAPE_MissingWavePortInfo,
+   SOUNDSCAPE_HardwareError,
+   SOUNDSCAPE_NoSoundPlaying,
+   SOUNDSCAPE_InvalidSBIrq,
+   SOUNDSCAPE_UnableToSetIrq,
+   SOUNDSCAPE_DmaError,
+   SOUNDSCAPE_DPMI_Error,
+   SOUNDSCAPE_OutOfMemory
+   };
+
+char    *SOUNDSCAPE_ErrorString( int ErrorNumber );
+void     SOUNDSCAPE_SetPlaybackRate( unsigned rate );
+unsigned SOUNDSCAPE_GetPlaybackRate( void );
+int      SOUNDSCAPE_SetMixMode( int mode );
+void     SOUNDSCAPE_StopPlayback( void );
+int      SOUNDSCAPE_GetCurrentPos( void );
+int      SOUNDSCAPE_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int      SOUNDSCAPE_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void     SOUNDSCAPE_SetCallBack( void ( *func )( void ) );
+int      SOUNDSCAPE_GetMIDIPort( void );
+int      SOUNDSCAPE_Init( void );
+void     SOUNDSCAPE_Shutdown( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/sndsrc.c
===================================================================
--- tags/rott-1.1/rott/audiolib/sndsrc.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/sndsrc.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,658 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: SNDSRC.C
+
+   author: James R. Dose
+   date:   March 26, 1994
+
+   Low level routines to support the Disney Sound Source.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#define STEREO      1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT    0
+#define STEREO_8BIT  ( STEREO )
+#define MONO_16BIT   ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#include <stdlib.h>
+#include <dos.h>
+#include <conio.h>
+#include "dpmi.h"
+#include "task_man.h"
+#include "sndcards.h"
+#include "user.h"
+#include "sndsrc.h"
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static int SS_Installed = FALSE;
+
+static int SS_Port = SS_DefaultPort;
+static int SS_OffCommand = 0xc;
+
+static char   *SS_BufferStart;
+static char   *SS_BufferEnd;
+static char   *SS_CurrentBuffer;
+static int     SS_BufferNum = 0;
+static int     SS_NumBuffers = 0;
+static int     SS_TotalBufferSize = 0;
+static int     SS_TransferLength  = 0;
+static int     SS_CurrentLength   = 0;
+
+static char   *SS_SoundPtr;
+volatile int   SS_SoundPlaying;
+
+static task   *SS_Timer;
+
+void ( *SS_CallBack )( void );
+
+int SS_ErrorCode = SS_Ok;
+
+#define SS_SetErrorCode( status ) \
+   SS_ErrorCode   = ( status );
+
+/*---------------------------------------------------------------------
+   Function: SS_ErrorString
+
+   Returns a pointer to the error message associated with an error
+   number.  A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *SS_ErrorString
+   (
+   int ErrorNumber
+   )
+
+   {
+   char *ErrorString;
+
+   switch( ErrorNumber )
+      {
+      case SS_Error :
+         ErrorString = SS_ErrorString( SS_ErrorCode );
+         break;
+
+      case SS_Ok :
+         ErrorString = "Sound Source ok.";
+         break;
+
+      case SS_NotFound :
+         ErrorString = "Could not detect Sound Source.";
+         break;
+
+      case SS_NoSoundPlaying :
+         ErrorString = "No sound playing in SndSrc.";
+         break;
+
+      case SS_DPMI_Error :
+         ErrorString = "DPMI Error in SndSrc.";
+         break;
+
+      default :
+         ErrorString = "Unknown Sound Source error code.";
+         break;
+      }
+
+   return( ErrorString );
+   }
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define SS_LockStart SS_ServiceInterrupt
+
+
+/*---------------------------------------------------------------------
+   Function: SS_ServiceInterrupt
+
+   Handles interrupt generated by sound card at the end of a voice
+   transfer.  Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+static void SS_ServiceInterrupt
+   (
+   task *Task
+   )
+
+   {
+   int port = SS_Port;
+   int count;
+
+   count = 0;
+   while( ( inp( port + 1 ) & 0x40 ) == 0 )
+      {
+      outp( port, *SS_SoundPtr++ );
+      outp( port + 2, SS_OffCommand );
+      outp( port + 2, 4 );
+
+      SS_CurrentLength--;
+      if ( SS_CurrentLength == 0 )
+         {
+         // Keep track of current buffer
+         SS_CurrentBuffer += SS_TransferLength;
+         SS_BufferNum++;
+         if ( SS_BufferNum >= SS_NumBuffers )
+            {
+            SS_BufferNum = 0;
+            SS_CurrentBuffer = SS_BufferStart;
+            }
+
+         SS_CurrentLength = SS_TransferLength;
+         SS_SoundPtr = SS_CurrentBuffer;
+
+         // Call the caller's callback function
+         if ( SS_CallBack != NULL )
+            {
+            SS_CallBack();
+            }
+         }
+
+      count++;
+      // Only do at most 14 samples per tick
+      if ( count > 13 )
+         {
+         break;
+         }
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_StopPlayback
+
+   Ends the transfer of digitized sound to the Sound Source.
+---------------------------------------------------------------------*/
+
+void SS_StopPlayback
+   (
+   void
+   )
+
+   {
+   if ( SS_SoundPlaying )
+      {
+      TS_Terminate( SS_Timer );
+
+      outp( SS_Port, 0x80 );
+      outp( SS_Port + 2, SS_OffCommand );
+      outp( SS_Port + 2, 4 );
+
+      SS_SoundPlaying = FALSE;
+
+      SS_BufferStart = NULL;
+      }
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_GetCurrentPos
+
+   Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int SS_GetCurrentPos
+   (
+   void
+   )
+
+   {
+   int offset;
+
+   if ( !SS_SoundPlaying )
+      {
+      SS_SetErrorCode( SS_NoSoundPlaying );
+      return( SS_Warning );
+      }
+
+   offset = ( int )( ( ( unsigned long )SS_SoundPtr ) -
+      ( ( unsigned long )SS_CurrentBuffer ) );
+
+   return( offset );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_LockEnd
+
+   Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void SS_LockEnd
+   (
+   void
+   )
+
+   {
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_BeginBufferedPlayback
+
+   Begins multibuffered playback of digitized sound on the Sound Source.
+---------------------------------------------------------------------*/
+
+int SS_BeginBufferedPlayback
+   (
+   char *BufferStart,
+   int   BufferSize,
+   int   NumDivisions,
+   void ( *CallBackFunc )( void )
+   )
+
+   {
+   if ( SS_SoundPlaying )
+      {
+      SS_StopPlayback();
+      }
+
+   SS_SetCallBack( CallBackFunc );
+
+   SS_BufferStart     = BufferStart;
+   SS_CurrentBuffer   = BufferStart;
+   SS_SoundPtr        = BufferStart;
+   SS_TotalBufferSize = BufferSize;
+   SS_BufferEnd       = BufferStart + BufferSize;
+   SS_TransferLength  = BufferSize / NumDivisions;
+   SS_CurrentLength   = SS_TransferLength;
+   SS_BufferNum       = 0;
+   SS_NumBuffers      = NumDivisions;
+
+   SS_SoundPlaying = TRUE;
+
+//   SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 438, 1, NULL );
+   SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 510, 1, NULL );
+   TS_Dispatch();
+
+   return( SS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_GetPlaybackRate
+
+   Returns the rate at which the digitized sound will be played in
+   hertz.
+---------------------------------------------------------------------*/
+
+int SS_GetPlaybackRate
+   (
+   void
+   )
+
+   {
+   return( SS_SampleRate );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_SetMixMode
+
+   Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int SS_SetMixMode
+   (
+   int mode
+   )
+
+   {
+   mode = MONO_8BIT;
+   return( mode );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_SetPort
+
+   Selects which port to use to write to the Sound Source.
+---------------------------------------------------------------------*/
+
+int SS_SetPort
+   (
+   int port
+   )
+
+   {
+   if ( SS_Installed )
+      {
+      SS_Shutdown();
+      }
+
+   SS_Port = port;
+
+   return( SS_Ok );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_SetCallBack
+
+   Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void SS_SetCallBack
+   (
+   void ( *func )( void )
+   )
+
+   {
+   SS_CallBack = func;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_TestTimer
+
+   Used as a delay in SS_TestSoundSource.
+---------------------------------------------------------------------*/
+
+void SS_TestTimer
+   (
+   task *Task
+   )
+
+   {
+   ( *( int * )( Task->data ) )++;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_TestSoundSource
+
+   Detect if the Sound Source is located at the specified port.
+---------------------------------------------------------------------*/
+
+int SS_TestSoundSource
+   (
+   int port
+   )
+
+   {
+   int   present;
+   task *timer;
+   volatile int ticks;
+   int   i;
+
+   present = FALSE;
+
+   timer = TS_ScheduleTask( SS_TestTimer, 140, 1, &ticks );
+   TS_Dispatch();
+
+   outp( port + 2, 4 );
+
+   ticks = 0;
+
+   while( ticks < 4 )
+      {
+      // Do nothing for a while
+      }
+
+   TS_Terminate( timer );
+
+   if ( ( inp( port + 1 ) & 0x40 ) == 0 )
+      {
+      for( i = 32; i > 0; i-- )
+         {
+         outp( port, 0x80 );
+         outp( port + 2, SS_OffCommand );
+         outp( port + 2, 4 );
+         }
+
+      if ( inp( port + 1 ) & 0x40 )
+         {
+         present = TRUE;
+         }
+      }
+
+   outp( port + 2, SS_OffCommand );
+
+   return( present );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_DetectSoundSource
+
+   Detects which port the Sound Source is located.
+---------------------------------------------------------------------*/
+
+int SS_DetectSoundSource
+   (
+   void
+   )
+
+   {
+   if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT1 ) )
+      {
+      SS_Port = SS_Port1;
+      return( TRUE );
+      }
+
+   if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT2 ) )
+      {
+      SS_Port = SS_Port2;
+      return( TRUE );
+      }
+
+   if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT3 ) )
+      {
+      SS_Port = SS_Port3;
+      return( TRUE );
+      }
+
+   if ( SS_TestSoundSource( SS_Port1 ) )
+      {
+      SS_Port = SS_Port1;
+      return( TRUE );
+      }
+
+   if ( SS_TestSoundSource( SS_Port2 ) )
+      {
+      SS_Port = SS_Port2;
+      return( TRUE );
+      }
+
+   if ( SS_TestSoundSource( SS_Port3 ) )
+      {
+      SS_Port = SS_Port3;
+      return( TRUE );
+      }
+
+   return( FALSE );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_Init
+
+   Initializes the Sound Source prepares the module to play digitized
+   sounds.
+---------------------------------------------------------------------*/
+
+int SS_Init
+   (
+   int soundcard
+   )
+
+   {
+   int status;
+
+   if ( SS_Installed )
+      {
+      SS_Shutdown();
+      }
+
+   if ( ( soundcard == TandySoundSource ) ||
+      ( USER_CheckParameter( SELECT_TANDY_SOUNDSOURCE ) ) )
+      {
+      // Tandy
+      SS_OffCommand = 0x0e;
+      }
+   else
+      {
+      // Disney
+      SS_OffCommand = 0x0c;
+      }
+
+   status = SS_DetectSoundSource();
+   if ( !status )
+      {
+      SS_SetErrorCode( SS_NotFound );
+      return( SS_Warning );
+      }
+
+   status = SS_LockMemory();
+   if ( status != SS_Ok )
+      {
+      SS_UnlockMemory();
+      return( status );
+      }
+
+   status = SS_Ok;
+
+   outp( SS_Port + 2, 4 );
+
+   SS_SoundPlaying = FALSE;
+
+   SS_SetCallBack( NULL );
+
+   SS_BufferStart = NULL;
+
+   SS_Installed = TRUE;
+
+   SS_SetErrorCode( status );
+   return( status );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_Shutdown
+
+   Ends transfer of sound data to the Sound Source.
+---------------------------------------------------------------------*/
+
+void SS_Shutdown
+   (
+   void
+   )
+
+   {
+   // Halt the transfer
+   SS_StopPlayback();
+
+   outp( SS_Port + 2, SS_OffCommand );
+
+   SS_SoundPlaying = FALSE;
+
+   SS_BufferStart = NULL;
+
+   SS_SetCallBack( NULL );
+
+   SS_UnlockMemory();
+
+   SS_Installed = FALSE;
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_UnlockMemory
+
+   Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void SS_UnlockMemory
+   (
+   void
+   )
+
+   {
+   DPMI_UnlockMemoryRegion( SS_LockStart, SS_LockEnd );
+   DPMI_Unlock( SS_Installed );
+   DPMI_Unlock( SS_Port );
+   DPMI_Unlock( SS_OffCommand );
+   DPMI_Unlock( SS_BufferStart );
+   DPMI_Unlock( SS_BufferEnd );
+   DPMI_Unlock( SS_CurrentBuffer );
+   DPMI_Unlock( SS_BufferNum );
+   DPMI_Unlock( SS_NumBuffers );
+   DPMI_Unlock( SS_TotalBufferSize );
+   DPMI_Unlock( SS_TransferLength );
+   DPMI_Unlock( SS_CurrentLength );
+   DPMI_Unlock( SS_SoundPtr );
+   DPMI_Unlock( SS_SoundPlaying );
+   DPMI_Unlock( SS_Timer );
+   DPMI_Unlock( SS_CallBack );
+   DPMI_Unlock( SS_ErrorCode );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: SS_LockMemory
+
+   Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int SS_LockMemory
+   (
+   void
+   )
+
+   {
+   int status;
+
+   status  = DPMI_LockMemoryRegion( SS_LockStart, SS_LockEnd );
+   status |= DPMI_Lock( SS_Installed );
+   status |= DPMI_Lock( SS_Port );
+   status |= DPMI_Lock( SS_OffCommand );
+   status |= DPMI_Lock( SS_BufferStart );
+   status |= DPMI_Lock( SS_BufferEnd );
+   status |= DPMI_Lock( SS_CurrentBuffer );
+   status |= DPMI_Lock( SS_BufferNum );
+   status |= DPMI_Lock( SS_NumBuffers );
+   status |= DPMI_Lock( SS_TotalBufferSize );
+   status |= DPMI_Lock( SS_TransferLength );
+   status |= DPMI_Lock( SS_CurrentLength );
+   status |= DPMI_Lock( SS_SoundPtr );
+   status |= DPMI_Lock( SS_SoundPlaying );
+   status |= DPMI_Lock( SS_Timer );
+   status |= DPMI_Lock( SS_CallBack );
+   status |= DPMI_Lock( SS_ErrorCode );
+
+   if ( status != DPMI_Ok )
+      {
+      SS_UnlockMemory();
+      SS_SetErrorCode( SS_DPMI_Error );
+      return( SS_Error );
+      }
+
+   return( SS_Ok );
+   }

Added: tags/rott-1.1/rott/audiolib/sndsrc.h
===================================================================
--- tags/rott-1.1/rott/audiolib/sndsrc.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/sndsrc.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,70 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: SNDSRC.H
+
+   author: James R. Dose
+   date:   March 26, 1994
+
+   Public header for for SNDSRC.C
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDSRC_H
+#define __SNDSRC_H
+
+enum SS_ERRORS
+   {
+   SS_Warning = -2,
+   SS_Error   = -1,
+   SS_Ok      = 0,
+   SS_NotFound,
+   SS_NoSoundPlaying,
+   SS_DPMI_Error
+   };
+
+#define SELECT_SOUNDSOURCE_PORT1 "ss1"
+#define SELECT_SOUNDSOURCE_PORT2 "ss2"
+#define SELECT_SOUNDSOURCE_PORT3 "ss3"
+#define SELECT_TANDY_SOUNDSOURCE "sst"
+
+#define SS_Port1 0x3bc
+#define SS_Port2 0x378
+#define SS_Port3 0x278
+
+#define SS_DefaultPort 0x378
+#define SS_SampleRate  7000
+#define SS_DMAChannel  -1
+
+char *SS_ErrorString( int ErrorNumber );
+void  SS_StopPlayback( void );
+int   SS_GetCurrentPos( void );
+int   SS_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, void ( *CallBackFunc )( void ) );
+int   SS_GetPlaybackRate( void );
+int   SS_SetMixMode( int mode );
+int   SS_SetPort( int port );
+void  SS_SetCallBack( void ( *func )( void ) );
+int   SS_Init( int soundcard );
+void  SS_Shutdown( void );
+void  SS_UnlockMemory( void );
+int   SS_LockMemory( void );
+
+#endif

Added: tags/rott-1.1/rott/audiolib/standard.h
===================================================================
--- tags/rott-1.1/rott/audiolib/standard.h	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/standard.h	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,72 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: STANDARD.H
+
+   author: James R. Dose
+   date:   May 25, 1994
+
+   Header containing standard definitions.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#ifndef __STANDARD_H
+#define __STANDARD_H
+
+typedef int boolean;
+typedef int errorcode;
+
+#ifndef TRUE
+   #define TRUE ( 1 == 1 )
+   #define FALSE ( !TRUE )
+#endif
+
+enum STANDARD_ERRORS
+   {
+   Warning = -2,
+   FatalError = -1,
+   Success = 0
+   };
+
+#define BITSET( data, bit ) \
+   ( ( ( data ) & ( bit ) ) == ( bit ) )
+
+#define ARRAY_LENGTH( array ) \
+   ( sizeof( array ) / sizeof( ( array )[ 0 ] ) )
+
+#define WITHIN_BOUNDS( array, index ) \
+   ( ( 0 <= ( index ) ) && ( ( index ) < ARRAY_LENGTH( array ) ) )
+
+#define FOREVER    for( ; ; )
+
+#ifdef NDEBUG
+   #define DEBUGGING 0
+#else
+   #define DEBUGGING 1
+#endif
+
+#define DEBUG_CODE \
+   if ( DEBUGGING == 0 ) \
+      { \
+      } \
+   else
+
+#endif

Added: tags/rott-1.1/rott/audiolib/task_man.c
===================================================================
--- tags/rott-1.1/rott/audiolib/task_man.c	                        (rev 0)
+++ tags/rott-1.1/rott/audiolib/task_man.c	2008-07-14 17:09:15 UTC (rev 239)
@@ -0,0 +1,976 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+/**********************************************************************
+   module: TASK_MAN.C
+
+   author: James R. Dose
+   date:   July 25, 1994
+
+   Low level timer task scheduler.
+
+   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
+**********************************************************************/
+
+#define TRUE  ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+//#define USESTACK
+#define LOCKMEMORY
+#define NOINTS
+#define USE_USRHOOKS
+
+#include <stdlib.h>
+#include <dos.h>
+#include <conio.h>
+#include <string.h>
+#include "interrup.h"
+#include "linklist.h"
+#include "task_man.h"
+
+#ifdef USESTACK
+#include "dpmi.h"
+#endif
+#ifdef LOCKMEMORY
+#include "dpmi.h"
+#endif
+
+#ifdef USE_USRHOOKS
+#include "usrhooks.h"
+#define FreeMem( ptr )   USRHOOKS_FreeMem( ( ptr ) )
+#else
+#define FreeMem( ptr )   free( ( ptr ) )
+#endif
+
+typedef struct
+   {
+   task *start;
+   task *end;
+   } tasklist;
+
+
+/*---------------------------------------------------------------------
+   Global variables
+---------------------------------------------------------------------*/
+
+#ifdef USESTACK
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long  StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long  oldStackPointer;
+
+#endif
+
+static task HeadTask;
+static task *TaskList = &HeadTask;
+
+static void ( __interrupt __far *OldInt8 )( void );
+
+static volatile long TaskServiceRate  = 0x10000L;
+static volatile long TaskServiceCount = 0;
+
+#ifndef NOINTS
+static volatile int  TS_TimesInInterrupt;
+#endif
+
+static char TS_Installed = FALSE;
+
+volatile int TS_InInterrupt = FALSE;
+
+/*---------------------------------------------------------------------
+   Function prototypes
+---------------------------------------------------------------------*/
+
+static void TS_FreeTaskList( void );
+static void TS_SetClockSpeed( long speed );
+static long TS_SetTimer( long TickBase );
+static void TS_SetTimerToMaxTaskRate( void );
+static void __interrupt __far TS_ServiceSchedule( void );
+static void __interrupt __far TS_ServiceScheduleIntEnabled( void );
+static void TS_AddTask( task *ptr );
+static int  TS_Startup( void );
+static void RestoreRealTimeClock( void );
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack =	\
+	"mov  [edi],esp"		\
+	"mov	ax,ss"	 		\
+	"mov  [esi],ax" 		\
+	parm [esi] [edi]		\
+	modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack =	\
+	"mov  ss,ax"			\
+	"mov  esp,edx"			\
+	parm [ax] [edx]		\
+	modify [eax edx];
+
+
+/**********************************************************************
+
+   Memory locked functions:
+
+**********************************************************************/
+
+
+#define TS_LockStart TS_FreeTaskList
+
+
+/*---------------------------------------------------------------------
+   Function: TS_FreeTaskList
+
+   Terminates all tasks and releases any memory used for control
+   structures.
+---------------------------------------------------------------------*/
+
+static void TS_FreeTaskList
+   (
+   void
+   )
+
+   {
+   task *node;
+   task *next;
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   node = TaskList->next;
+   while( node != TaskList )
+      {
+      next = node->next;
+      FreeMem( node );
+      node = next;
+      }
+
+   TaskList->next = TaskList;
+   TaskList->prev = TaskList;
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: TS_SetClockSpeed
+
+   Sets the rate of the 8253 timer.
+---------------------------------------------------------------------*/
+
+static void TS_SetClockSpeed
+   (
+   long speed
+   )
+
+   {
+   unsigned flags;
+
+   flags = DisableInterrupts();
+
+   if ( ( speed > 0 ) && ( speed < 0x10000L ) )
+      {
+      TaskServiceRate = speed;
+      }
+   else
+      {
+      TaskServiceRate = 0x10000L;
+      }
+
+   outp( 0x43, 0x36 );
+   outp( 0x40, TaskServiceRate );
+   outp( 0x40, TaskServiceRate >> 8 );
+
+   RestoreInterrupts( flags );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: TS_SetTimer
+
+   Calculates the rate at which a task will occur and sets the clock
+   speed if necessary.
+---------------------------------------------------------------------*/
+
+static long TS_SetTimer
+   (
+   long TickBase
+   )
+
+   {
+   long speed;
+
+   speed = 1192030L / TickBase;
+   if ( speed < TaskServiceRate )
+      {
+      TS_SetClockSpeed( speed );
+      }
+
+   return( speed );
+   }
+
+
+/*---------------------------------------------------------------------
+   Function: TS_SetTimerToMaxTaskRate
+
+   Finds the fastest running task and sets the clock to operate at
+   that speed.
+---------------------------------------------------------------------*/
+
+static void TS_SetTimerToMaxTaskRate
+   (
+