]> git.alsa-project.org Git - alsa-tools.git/commitdiff
Add ld10k1 tool
authorTakashi Iwai <tiwai@suse.de>
Fri, 18 Mar 2005 13:40:44 +0000 (13:40 +0000)
committerTakashi Iwai <tiwai@suse.de>
Fri, 18 Mar 2005 13:40:44 +0000 (13:40 +0000)
Added ld10k1 tool by Peter Zubaj.

98 files changed:
Makefile
ld10k1/AUTHORS [new file with mode: 0644]
ld10k1/COPYING [new file with mode: 0644]
ld10k1/COPYING.LIB [new file with mode: 0644]
ld10k1/ChangeLog [new file with mode: 0644]
ld10k1/INSTALL [new file with mode: 0644]
ld10k1/Makefile.am [new file with mode: 0644]
ld10k1/NEWS [new file with mode: 0644]
ld10k1/README [new file with mode: 0644]
ld10k1/TODO [new file with mode: 0644]
ld10k1/configure.in [new file with mode: 0644]
ld10k1/contrib/Makefile.am [new file with mode: 0644]
ld10k1/contrib/README [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/Makefile.am [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/freberv.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/pontodo5 [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc [new file with mode: 0644]
ld10k1/contrib/emu10k1MIDIEffects/volLR.asm [new file with mode: 0644]
ld10k1/cvscompile [new file with mode: 0644]
ld10k1/doc/Audigy-mixer.txt [new file with mode: 0644]
ld10k1/doc/AudigyTRAM.txt [new file with mode: 0644]
ld10k1/doc/Makefile.am [new file with mode: 0644]
ld10k1/doc/README [new file with mode: 0644]
ld10k1/doc/dl10k1_usage [new file with mode: 0644]
ld10k1/doc/ld10k1_usage [new file with mode: 0644]
ld10k1/doc/lo10k1_usage [new file with mode: 0644]
ld10k1/dump/Makefile.am [new file with mode: 0644]
ld10k1/dump/README [new file with mode: 0644]
ld10k1/dump/audigy.dl10k1 [new file with mode: 0644]
ld10k1/dump/audigy_ms.dl10k1 [new file with mode: 0644]
ld10k1/include/Makefile.am [new file with mode: 0644]
ld10k1/include/comm.h [new file with mode: 0644]
ld10k1/include/ld10k1_error.h [new file with mode: 0644]
ld10k1/include/ld10k1_fnc.h [new file with mode: 0644]
ld10k1/include/liblo10k1.h [new file with mode: 0644]
ld10k1/include/liblo10k1ef.h [new file with mode: 0644]
ld10k1/include/liblo10k1lf.h [new file with mode: 0644]
ld10k1/include/lo10k1.h [new file with mode: 0644]
ld10k1/include/version.h [new file with mode: 0644]
ld10k1/ld10k1.m4 [new file with mode: 0644]
ld10k1/ld10k1d.in [new file with mode: 0644]
ld10k1/patch/Makefile.am [new file with mode: 0644]
ld10k1/patch/README [new file with mode: 0644]
ld10k1/setup/Makefile.am [new file with mode: 0644]
ld10k1/setup/effects/Makefile.am [new file with mode: 0644]
ld10k1/setup/effects/README [new file with mode: 0644]
ld10k1/setup/effects/copy_2.asm [new file with mode: 0644]
ld10k1/setup/effects/emu_constants.asm [new file with mode: 0644]
ld10k1/setup/effects/fxbus.asm [new file with mode: 0644]
ld10k1/setup/effects/output.asm [new file with mode: 0644]
ld10k1/setup/effects/prologic.asm [new file with mode: 0644]
ld10k1/setup/effects/simple.asm [new file with mode: 0644]
ld10k1/setup/effects/sto51.asm [new file with mode: 0644]
ld10k1/setup/effects/switch_2.asm [new file with mode: 0644]
ld10k1/setup/effects/switch_6.asm [new file with mode: 0644]
ld10k1/setup/effects/tone.asm [new file with mode: 0644]
ld10k1/setup/effects/vol_2.asm [new file with mode: 0644]
ld10k1/setup/effects/vol_master.asm [new file with mode: 0644]
ld10k1/setup/init_audigy.in [new file with mode: 0644]
ld10k1/setup/init_live.in [new file with mode: 0644]
ld10k1/src/Makefile.am [new file with mode: 0644]
ld10k1/src/bitops.h [new file with mode: 0644]
ld10k1/src/comm.c [new file with mode: 0644]
ld10k1/src/dl10k1.c [new file with mode: 0644]
ld10k1/src/ld10k1.c [new file with mode: 0644]
ld10k1/src/ld10k1.h [new file with mode: 0644]
ld10k1/src/ld10k1_debug.c [new file with mode: 0644]
ld10k1/src/ld10k1_debug.h [new file with mode: 0644]
ld10k1/src/ld10k1_driver.c [new file with mode: 0644]
ld10k1/src/ld10k1_driver.h [new file with mode: 0644]
ld10k1/src/ld10k1_dump.c [new file with mode: 0644]
ld10k1/src/ld10k1_dump.h [new file with mode: 0644]
ld10k1/src/ld10k1_dump_file.h [new file with mode: 0644]
ld10k1/src/ld10k1_fnc.c [new file with mode: 0644]
ld10k1/src/ld10k1_fnc1.c [new file with mode: 0644]
ld10k1/src/ld10k1_fnc1.h [new file with mode: 0644]
ld10k1/src/ld10k1_fnc_int.h [new file with mode: 0644]
ld10k1/src/ld10k1_mixer.c [new file with mode: 0644]
ld10k1/src/ld10k1_mixer.h [new file with mode: 0644]
ld10k1/src/ld10k1_tram.c [new file with mode: 0644]
ld10k1/src/ld10k1_tram.h [new file with mode: 0644]
ld10k1/src/liblo10k1.c [new file with mode: 0644]
ld10k1/src/liblo10k1ef.c [new file with mode: 0644]
ld10k1/src/liblo10k1lf.c [new file with mode: 0644]
ld10k1/src/lo10k1.c [new file with mode: 0644]

index 8fb3f7535a4cb60e7987a8a5d676e043a6133346..f18a26930b49d8dd7640200c70e4020067988d7b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ VERSION = 1.0.9rc1
 TOP = .
 SUBDIRS = ac3dec as10k1 envy24control hdsploader hdspconf hdspmixer \
        mixartloader pcxhrloader rmedigicontrol sb16_csp seq sscape_ctl us428control \
-       usx2yloader vxloader echomixer
+       usx2yloader vxloader echomixer ld10k1
 
 all:
        @for i in $(SUBDIRS); do cd $(TOP)/$$i; ./cvscompile $(CVSCOMPILE_ARGS); cd ..; make -C $$i; done
diff --git a/ld10k1/AUTHORS b/ld10k1/AUTHORS
new file mode 100644 (file)
index 0000000..468a355
--- /dev/null
@@ -0,0 +1,4 @@
+Peter Zubaj <pzad@pobox.sk>
+
+Contributors:
+Mikael Magnusson <mikma@users.sourceforge.net>
\ No newline at end of file
diff --git a/ld10k1/COPYING b/ld10k1/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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.
diff --git a/ld10k1/COPYING.LIB b/ld10k1/COPYING.LIB
new file mode 100644 (file)
index 0000000..b1e3f5a
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, 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 library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+  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.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+  If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be 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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+  9. 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 Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+\f
+  11. 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 Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  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 library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ld10k1/ChangeLog b/ld10k1/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ld10k1/INSTALL b/ld10k1/INSTALL
new file mode 100644 (file)
index 0000000..56b077d
--- /dev/null
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
+
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/ld10k1/Makefile.am b/ld10k1/Makefile.am
new file mode 100644 (file)
index 0000000..f126058
--- /dev/null
@@ -0,0 +1,26 @@
+SUBDIRS = setup doc patch dump contrib include src
+
+aclocaldir=$(datadir)/aclocal
+aclocal_DATA=ld10k1.m4
+
+sbin_SCRIPTS = ld10k1d
+
+do_subst = sed -e 's,[@]sbindir[@],$(sbindir),g' \
+ -e 's,[@]binarydir[@],$(bindir),g' \
+ -e 's,[@]sysconfdir[@],$(sysconfdir),g'
+ld10k1d : ld10k1d.in
+       $(do_subst) $(srcdir)/ld10k1d.in > ld10k1d
+
+CLEANFILES = ld10k1d
+
+noinst_HEADERS =
+
+EXTRA_DIST = ld10k1.m4 AUTHORS COPYING COPYING.LIB ChangeLog INSTALL \
+       README TODO ld10k1d.in
+
+alsa-dist: distdir
+       @rm -rf ../distdir/ld10k1
+       @mkdir -p ../distdir/ld10k1
+       @cp -RLpv $(distdir)/* ../distdir/ld10k1
+       @rm -rf $(distdir)
diff --git a/ld10k1/NEWS b/ld10k1/NEWS
new file mode 100644 (file)
index 0000000..dd95883
--- /dev/null
@@ -0,0 +1,61 @@
+0.1.8
+       Sync with ALSA 1.0.8rc1
+0.1.7test4
+       ld10k1 options for pid file and log file  - Mikael Magnusson
+       Script for start and end of ld10k1
+0.1.7test3
+       Fixed bug in liblo10k1lf_save_patch - Mikael Magnusson
+       ld10k1 will exit with error code if it can not connect to ld10k1 - Mikael Magnusson
+0.1.7test2
+       License for liblo10k1 was changed from GPL to LGPL. Other parts are still GPLed.
+       Fixed getopt_long handling - Mikael Magnusson
+       Fixed free bug in liblo10k1lf_get_dsp_config - Mikael Magnusson
+       Fixed (copy & paste) bug in liblo10k1lf_load_patch - thanks to Mikael Magnusson
+0.1.7test1
+       !!! This version of ld10k1 requires ALSA 1.0.7 - both alsa-lib and alsa-driver !!!
+       !!! In current kernel 2.6.8.1 is still ALSA 1.0.4 !!!
+       Moved emu patch loading to liblo10k1
+       Moved emu patch to ld10k1 patch transforming to liblo10k1
+       DSP config can by stored and restored.
+       New lo10k1 options --store, --restore, --save_patch, --load_patch, --wait
+       Some source reorganization.
+       Source cleaning - Mikael Magnusson
+0.1.6
+       Moved ld10k1 and dl10k1 to sbin directory - Mikael Magnusson
+       Fixed bug in call to ld10k1_free_reserved_ctls - Mikael Magnusson
+       Some cleanup from Mikael Magnusson
+       ld10k1 not use list.h header from linux kernel - Mikael Magnusson
+       configure.in and makefile.am cleanup - Mikael Magnusson
+       Init script for sb live, effect path - Mikael Magnusson
+       Daemonize of ld10k1, some ideas from Mikael Magnusson.
+       Aditional cleanups.
+0.1.5
+       Fixed bug in control index.
+       Reworking of communication between client and server.
+       Some work on liblo10k1 to support GUI.
+       Support for ALSA 1.0.6rc1
+       Fixed bug in connecion add
+0.1.4
+       Control indexes can be used now - see -ctrl (i option)
+       Check for AC97 controls which can not be deleted.
+       Corrected bug in free_comm - Mikael Magnusson
+       Some cleanup from Mikael Magnusson
+       Splitted lo10k1 to two parts - lo10k1 and liblo10k1.
+       Fixed bug in tram allocation.
+       Some effects for SB Live from Josep Andreu (holborn) in contrib subdir
+       Check if ld10k1 run under root
+0.1.3p2
+       Corected bug in accept_comm. Thanks to Mikael Magnusson and Joachim Falk
+0.1.3p1
+       Corrected bug for constant registers
+0.1.3
+       Dump loader (dl10k1).
+       ld10k1 can now use named socked or normal netework socket
+       Simpler connecting outputs from multiple outputs to input
+0.1.2
+       Rewriten some parts (many new bugs)
+       Simpler connecting
+0.1.1
+       Working TRAM on Audigy, many bugs fixed, many new bugs
+0.1
+       Initial release
\ No newline at end of file
diff --git a/ld10k1/README b/ld10k1/README
new file mode 100644 (file)
index 0000000..c1ed3ae
--- /dev/null
@@ -0,0 +1,34 @@
+This is attempt to make EMU10K1 (EMU10K2) patch loader for ALSA.
+This is work in progress. It is not very user friendly.
+Loading, unloading, connecting, disconnecting patches works.
+It should by able to load identical setup for Audigy as it is in kernel driver.
+This dissables AC3 passthrough on SB Live.
+
+ALSA (both alsa-lib and in kernel drivers) version 1.0.7rc1 and higher are required.
+
+There are two parts:
+Server - ld10k1 - runing as service - it is storing driver state - it must run
+               under root or by setuided
+Client - lo10k1 - controls server
+and dump loader dl10k1 - loads dumps previously created with lo10k1 & ld10k1.
+
+For options list run 
+./ld10k1 -h 
+and 
+./lo10k1 -h
+and 
+./dl10k1 -h
+and look in doc directory.
+
+ld10k1 will clear card DSP program and you will hear nothing.
+You must load some patches to route sound from inputs to outputs (use audigy_init script for
+audigy 1, 2 or init_live for sb live).
+After loading patch check and set oss mixer emulation through proc file (/proc/asound/card/oss_mixer)
+
+In directory setup are some patches which I use on my Audigy for testing.
+With this you will have exactly same mixer as with original driver (+headphone control, not tested 
+AudigyDrive inputs and outputs, AC3 passthrought).
+Most of them are from emu-tools-0.9.4 package from OSS driver (but not all).
+Use as10k1 compiler from alsa-tools package to compile patches.
+
+Peter Zubaj
\ No newline at end of file
diff --git a/ld10k1/TODO b/ld10k1/TODO
new file mode 100644 (file)
index 0000000..ec413ea
--- /dev/null
@@ -0,0 +1,19 @@
+Priority:
+
+High
+    - TRAM sharing between AC3 passthrough and other effects
+    - ac3 passthrough for SB Live - now is dissabled
+Medium
+    - effect repositry
+    - clean source
+    - optimalize GPR ussage for connect
+    - change notification for ld10k1 clients
+    - control range checking against translation
+    - optimalization - is getting slow
+    - conection del - returned id is sometime invalid
+Low
+    - little and big endian conversion on save and read
+    - utility to enable control of mixer elements from midi
+    - modify as10k1 to support feature that alsa allows for emu10k1
+        
+and much more
diff --git a/ld10k1/configure.in b/ld10k1/configure.in
new file mode 100644 (file)
index 0000000..a17076d
--- /dev/null
@@ -0,0 +1,55 @@
+AC_INIT(src/ld10k1.c)
+AM_INIT_AUTOMAKE(ld10k1, 0.1.8)
+
+AC_CONFIG_HEADERS(config.h)
+AC_PROG_CC
+AC_PROG_LD
+AC_PROG_INSTALL
+AC_HEADER_STDC
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AM_PATH_ALSA(1.0.8, [], [])
+CFLAGS="$CFLAGS $ALSA_CFLAGS -Wall"
+LIBS="$LIBS $ALSA_LIBS"
+
+effectsdir='$(pkgdatadir)/effects'
+AC_SUBST(effectsdir)
+
+#taken from alsa-lib
+dnl Make a symlink for inclusion of lo10k1/xxx.h
+if test ! -L include/lo10k1 ; then
+  echo "Making a symlink include/lo10k1"
+  rm -f include/lo10k1
+  ln -sf . include/lo10k1
+fi
+
+#taken from aclocal.m4 for alsa-lib - start
+AC_DEFUN([SAVE_LIBRARY_VERSION], [
+AC_MSG_CHECKING(for library version)
+LD10K1_LIB_VERSION=$VERSION
+echo $VERSION > $srcdir/version
+AC_DEFINE_UNQUOTED(VERSION, "$LD10K1_LIB_VERSION", [ld10k1 library version string])
+AC_SUBST(LD10K1_LIB_VERSION)
+LD10K1_LIB_MAJOR=`echo $VERSION | cut -d . -f 1`
+AC_SUBST(LD10K1_LIB_MAJOR)
+LD10K1_LIB_MINOR=`echo $VERSION | cut -d . -f 2`
+AC_SUBST(LD10K1_LIB_MINOR)
+LD10K1_LIB_SUBMINOR=`echo $VERSION | cut -d . -f 3 | sed -e 's/^\([[^[:alpha:]]]*\)\(.*\)$/\1/g'`
+AC_SUBST(LD10K1_LIB_SUBMINOR)
+AC_MSG_RESULT(major $LD10K1_LIB_MAJOR minor $LD10K1_LIB_MINOR subminor $LD10K1_LIB_SUBMINOR)
+AC_SUBST(LD10K1_LIB_EXTRAVER)
+])
+
+SAVE_LIBRARY_VERSION
+#taken from aclocal.m4 for alsa-lib - end
+
+AC_OUTPUT(Makefile
+       setup/Makefile
+       setup/effects/Makefile
+       doc/Makefile
+       patch/Makefile
+       dump/Makefile
+       contrib/Makefile
+       contrib/emu10k1MIDIEffects/Makefile
+       include/Makefile
+       src/Makefile)
diff --git a/ld10k1/contrib/Makefile.am b/ld10k1/contrib/Makefile.am
new file mode 100644 (file)
index 0000000..f6b01b2
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST = README emu10k1MIDIEffects.tar.gz
diff --git a/ld10k1/contrib/README b/ld10k1/contrib/README
new file mode 100644 (file)
index 0000000..90d2d99
--- /dev/null
@@ -0,0 +1,2 @@
+These files are from holborn (Josep Andreu).
+They are for SB Live.
\ No newline at end of file
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm
new file mode 100644 (file)
index 0000000..1bd180d
--- /dev/null
@@ -0,0 +1,17 @@
+       name  "3volBUS1"
+       
+
+       include "emu_constants.asm"
+;volBUS1   control  #1,0,#1
+
+inl    IO
+inr     IO
+in3     IO
+
+out    equ     inl
+
+       acc3    out,inl,inr,in3
+
+       end
+       
+       
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm
new file mode 100644 (file)
index 0000000..c37c21c
--- /dev/null
@@ -0,0 +1,18 @@
+       name  "volBUS2"
+       
+
+       include "emu_constants.asm"
+;volBUS2   control  #1,0,#1
+
+
+inl    IO
+inr     IO
+in3     IO
+out    equ     inl
+
+        
+       acc3    out,inl,inr,in3
+        
+               end
+       
+       
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/Makefile.am b/ld10k1/contrib/emu10k1MIDIEffects/Makefile.am
new file mode 100644 (file)
index 0000000..f773708
--- /dev/null
@@ -0,0 +1,34 @@
+EXTRA_DIST = \
+       volBUS1.asm \
+       3volBUS2.asm \
+       emu_constants.asm \
+       freberv.asm \
+       gain_4.asm \
+       michorusL.asm \
+       michorusR.asm \
+       volLR.asm \
+       emu_constants.inc \
+       fv-basstreble.inc \
+       fv-controls.inc \
+       fv-filters-reduced.inc \
+       fv-filters.inc \
+       fv-routes.inc \
+       refl-big.inc \
+       refl-default.inc \
+       pontodo5
+
+dist_effects_DATA = \
+       3volBUS1.emu10k1 \
+       3volBUS2.emu10k1 \
+       freberv.emu10k1 \
+       gain_4.emu10k1 \
+       michorusL.emu10k1 \
+       michorusR.emu10k1 \
+       volLR.emu10k1
+
+CLEANFILES = $(dist_effects_DATA)
+
+SUFFIXEC = .asm .emu10k1
+
+.asm.emu10k1:
+       as10k1 -o $@ $<
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm
new file mode 100644 (file)
index 0000000..d385104
--- /dev/null
@@ -0,0 +1,117 @@
+;some hardware constants C_[n]<DecimalValue>, 'n' indicates negative value
+;              
+;these are in 2's complement representation
+C_0    equ $040        ;;00000000
+C_1    equ $041        ;;00000001
+C_2    equ $042        ;;00000002
+C_3    equ $043        ;;00000003
+C_4    equ $044        ;;00000004      
+C_8    equ $045        ;;00000008
+C_16   equ $046        ;;00000010
+C_32   equ $047        ;;00000020
+C_256  equ $048        ;;00000100
+C_65536 equ $049       ;;00010000
+C_2^23         equ $04A        ;;00080000
+C_2^28 equ $04b        ;;10000000
+C_2^29 equ $04c        ;;20000000 (C_max /4) +1
+C_2^30 equ $04d        ;;40000000 ( C_max / 2 ) + 1 (almost half)      
+C_nmax equ $04e        ;;80000000 most negative number
+C_max  equ $04f        ;;7fffffff most positive number 
+C_n1   equ $050        ;;ffffffff -1
+C_n2   equ $051        ;;fffffffe -2
+C_n2^30        equ $052        ;;c0000000 C_nmax /2
+
+C_LSshift equ $55      ;;to left shift an address by using macsints
+                       ;;for fractional addresses
+
+
+ZERO equ C_0;
+ONE equ        C_1;
+       
+;;; Hardware Registers:        
+               
+ACCUM  equ $56
+CCR    equ $57 
+NOISE1 equ $58
+NOISE2 equ $59 
+IRQ    equ $5A 
+DBAC   equ $5B 
+       
+and    macro   dest,srcA,srcB
+       andxor  dest,srcA,srcB,C_0
+       endm
+       
+xor    macro   dest,srcA,srcB
+       andxor  dest,C_n1,srcA,srcB
+       endm
+       
+not    macro    dest,src
+       andxor   dest,src,C_n1,C_n1             
+       endm
+
+nand   macro   dest,srcA,srcB  
+       andxor  dest,srcA,srcB,C_n1
+       endm
+       
+or     macro    dest,srcA,srcB
+       not      C_0,srcA
+       andxor   dest,ACCUM,srcA,srcB   
+       endm    
+
+nor    macro   dest,srcA,scrB
+       not     dest,srcA
+       andxor  dest,srcB,dest,srcA     
+       not     dest,dest
+       endm
+
+
+neg     macro   dest,src
+       macs1   dest,C_0,C_1,C_nmax     
+       endm    
+       
+;;; branch on:
+;;; ==0
+beq    macro   count
+       skip    CCR,CCR,C_8,count       
+       endm
+;;; !=0
+bne    macro   count
+       skip    CCR,CCR,C_256,count
+       endm
+;;; <0
+blt    macro   count
+       skip    CCR,CCR,C_4,count
+       endm
+;;; always branch
+bra    macro   count
+       skip    C_0,C_max,C_max,count
+       endm
+;;; on saturation
+bsa     macro count
+       skip CCR,CCR,C_16,count
+       endm
+bge    macro  count
+C___80 con $80
+       skip CCR,CCR,C___80,count       
+       endm
+               
+bgt    macro   count
+C___180        con $180
+       skip CCR,CCR,C___180,count
+       endm
+       
+move   macro dest,src
+       macs  dest,src,C_0,C_0
+       endm            
+       
+       end
+
+;;; usefull for testing values before a skip
+test   macro test
+       macs C_0,test,C_0,C_0
+       endm
+
+cmp    macro src1.scr2
+       macints C_0,src1,C_n1,src2
+       endm
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc
new file mode 100644 (file)
index 0000000..7e07717
--- /dev/null
@@ -0,0 +1,118 @@
+;some hardware constants C_[n]<DecimalValue>, 'n' indicates negative value
+;              
+;these are in 2's complement representation
+C_0    equ $040        ;;00000000
+C_1    equ $041        ;;00000001
+C_2    equ $042        ;;00000002
+C_3    equ $043        ;;00000003
+C_4    equ $044        ;;00000004      
+C_8    equ $045        ;;00000008
+C_16   equ $046        ;;00000010
+C_32   equ $047        ;;00000020
+C_256  equ $048        ;;00000100
+C_65536 equ $049       ;;00010000
+C_2^23         equ $04A        ;;00080000
+C_2^28 equ $04b        ;;10000000
+C_2^29 equ $04c        ;;20000000 (C_max /4) +1
+C_2^30 equ $04d        ;;40000000 ( C_max / 2 ) + 1 (almost half)      
+C_nmax equ $04e        ;;80000000 most negative number
+C_max  equ $04f        ;;7fffffff most positive number 
+C_n1   equ $050        ;;ffffffff -1
+C_n2   equ $051        ;;fffffffe -2
+C_n2^30        equ $052        ;;c0000000 C_nmax /2
+
+C_LSshift equ $55      ;;to left shift an address by using macsints
+                       ;;for fractional addresses
+
+
+ZERO equ C_0;
+ONE equ        C_1;
+       
+;;; Hardware Registers:        
+               
+ACCUM  equ $56
+CCR    equ $57 
+NOISE1 equ $58
+NOISE2 equ $59 
+IRQ    equ $5A 
+DBAC   equ $5B 
+       
+and    macro   dest,srcA,srcB
+       andxor  dest,srcA,srcB,C_0
+       endm
+       
+xor    macro   dest,srcA,srcB
+       andxor  dest,C_n1,srcA,srcB
+       endm
+       
+not    macro    dest,src
+       andxor   dest,src,C_n1,C_n1             
+       endm
+
+nand   macro   dest,srcA,srcB  
+       andxor  dest,srcA,srcB,C_n1
+       endm
+       
+or     macro    dest,srcA,srcB
+       not      C_0,srcA
+       andxor   dest,ACCUM,srcA,srcB   
+       endm    
+
+nor    macro   dest,srcA,scrB
+       not     dest,srcA
+       andxor  dest,srcB,dest,srcA     
+       not     dest,dest
+       endm
+
+
+neg     macro   dest,src
+       macs1   dest,C_0,C_1,C_nmax     
+       endm    
+       
+;;; branch on:
+;;; ==0
+beq    macro   count
+       skip    CCR,CCR,C_8,count       
+       endm
+;;; !=0
+bne    macro   count
+       skip    CCR,CCR,C_256,count
+       endm
+;;; <0
+blt    macro   count
+       skip    CCR,CCR,C_4,count
+       endm
+;;; always branch
+bra    macro   count
+       skip    C_0,C_max,C_max,count
+       endm
+;;; on saturation
+bsa     macro count
+       skip CCR,CCR,C_16,count
+       endm
+bge    macro  count
+C___80 con $80
+       skip CCR,CCR,C___80,count       
+       endm
+               
+bgt    macro   count
+C___180        con $180
+       skip CCR,CCR,C___180,count
+       endm
+       
+move   macro dest,src
+       macs  dest,src,C_0,C_0
+       endm            
+       
+
+;;; usefull for testing values before a skip
+test   macro test
+       macs C_0,test,C_0,C_0
+       endm
+
+cmp    macro src1,scr2
+       macints C_0,src1,C_n1,src2
+       endm
+
+       end
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/freberv.asm b/ld10k1/contrib/emu10k1MIDIEffects/freberv.asm
new file mode 100644 (file)
index 0000000..3fe1b9e
--- /dev/null
@@ -0,0 +1,156 @@
+;;     fv10k1.m4 - fv10k1 package
+;;     This implements Jezar Wakefield's Freeverb algorithm
+;;         
+;;     Copyright (C) 2001 Oleg Smirnov <smirnov@astron.nl>
+;;    
+;;     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
+;; 
+;; $Id: fv10k1.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+  name "Freeverb"
+  
+  include "emu_constants.inc"
+  include "fv-routes.inc"
+  include "fv-controls.inc"
+  include "fv-basstreble.inc"
+  
+       ; IO lines right/left
+ior io
+iol io
+       
+
+  ; No room reflection support - load full set of Freeverb filters and put 
+  ; them into ITRAM first
+  include "fv-filters.inc"
+  ; delay lines for channel & reverb predelay will use XTRAM
+dlyr delay &2   
+dlyl delay &2   
+
+
+writer twrite dlyr,0
+writel twrite dlyl,0
+oreadr tread dlyr,64     ; use 64 samples to avoid some TRAM glitches
+oreadl tread dlyl,64
+revreadr tread dlyr,64
+revreadl tread dlyl,64
+       
+input dyn 1         ; wet reverb input [== (inl+inr)*gain ]
+
+dly_b2 sta 0,0   ; storage for second bass/treble filter
+dly_t2 sta 0,0
+
+
+dly_b3 sta 0,0   
+dly_t3 sta 0,0
+dly_b4 sta 0,0   
+dly_t4 sta 0,0
+
+reflr dyn 2
+refll dyn 2
+reverbr dyn 1
+reverbl dyn 1
+ptr dyn 2
+ptl dyn 2
+  
+
+
+
+
+  
+
+  ;;; update TRAM read addresses from control GPRs
+  acc3 oreadr.a,delay_r,writer.a,C_0
+  acc3 oreadl.a,delay_l,writel.a,C_0
+  acc3 revreadr.a,revdelay,writer.a,C_0
+  acc3 revreadl.a,revdelay,writel.a,C_0
+
+  ;;; init reverb outputs (and clear ACCUM for code below)
+  macs fvrev_l,C_0,C_0,C_0
+  macs fvrev_r,C_0,C_0,C_0
+
+  ;;; accumulate reverb inputs ( predelayed R+L * revgain )
+  ;;; and at the same time pass input to output w/delay
+  macmv ior,oreadr,revreadr,revgain
+  macs input,ACCUM,revreadl,revgain
+       acc3 iol,oreadl,C_0,C_0
+  acc3 writer,ior,C_0,C_0
+  acc3 writel,iol,C_0,C_0
+
+  ;;; apply & accumulate comb filters
+  do_comb_filters fvrev_l,fvrev_r
+  
+  ;;; apply allpass filters
+  do_allpass_filters fvrev_l,fvrev_r
+  
+  ;;; feed accumulated values to outputs, multiplying by wet & dry controls
+  interp tmp,fvrev_l,wet1,fvrev_r
+  interp tmpout,fvrev_r,wet1,fvrev_l
+  macs fvrev_l,tmp,revreadl,dry
+  macs fvrev_r,tmpout,revreadr,dry
+  
+  ;;; apply bass/treble controls to output
+  test revdefeat
+  bne .skipbasstreble
+  basstreble fvrev_l,fvrev_l,revbass,revtreble,dly_b1,dly_t1
+  basstreble fvrev_r,fvrev_r,revbass,revtreble,dly_b2,dly_t2
+.skipbasstreble
+
+  ;;; reset level meters at specified interval (use DBAC to track it)
+  andxor tmp,DBAC,level_interval,C_0
+  bne .skipreset
+  acc3 maxlev_fr,C_0,C_0,C_0
+  acc3 maxlev_fl,C_0,C_0,C_0
+  acc3 maxlev_rr,C_0,C_0,C_0
+  acc3 maxlev_rl,C_0,C_0,C_0
+.skipreset
+  
+
+  ;;; apply reflection levels and bass/treble
+  macs reflr,C_0,fvrefl_fr,refl_f
+  macs refll,C_0,fvrefl_fl,refl_f
+  
+  macs reflr,reflr,fvrefl_rr,refl_f   ; two-speaker mode - add in other line
+  macs refll,refll,fvrefl_rl,refl_f
+  
+  
+  ;;; apply reverb levels
+  macs  reverbr,C_0,fvrev_r,reverb_f
+  macs  reverbl,C_0,fvrev_l,reverb_f
+  
+
+  
+
+  ;;; write in+reverb_reflections to output    
+  ;;; use macmv accumulation for extra precision
+makeoutput MACRO io,refl,reverb,passthru
+  macs C_0,C_0,C_0,C_0
+  macmv tmp,tmp,refl,C_max
+  
+    macmv tmp,C_0,io,ptf_level
+  
+  macs io,ACCUM,reverb,C_max
+  ENDM
+  makeoutput ior,reflr,reverbr,ptr
+  makeoutput iol,refll,reverbl,ptl
+  
+  ;;; maintain the maximum level 
+maxlevel MACRO io,maxlev
+  tstneg tmp,io,io,C_0             ; tmp = abs(io)
+  limit maxlev,tmp,tmp,maxlev  ; maxlevel=max(tmp,maxlevel)
+  ENDM
+  maxlevel ior.o,maxlev_fr
+  maxlevel iol.o,maxlev_fl
+  
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc
new file mode 100644 (file)
index 0000000..e727673
--- /dev/null
@@ -0,0 +1,112 @@
+;;     fv-basstreble.m4 - fv10k1 package
+;;     Defines macros for bass/treble filters
+;; 
+;;     This is wholly derived from Daniel Bertrand's tone.asm in the emu10k1 
+;;     driver (see emu10k1/utils/as10k1/effects/tone.asm).
+;;    
+;;     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
+;; 
+;; $Id: fv-basstreble.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+;;; a and b coefs for bass:    
+
+
+b_b    con   2.736129417e-01    5.240710533e-01    2.620355267e-01
+a_b    con   9.560258858e-01    -4.576868881e-01
+       
+;;; a and b coef for treble:   
+b_t con                -4.982305773e-01   9.964611547e-01    -4.982305773e-01
+a_t con         9.317583774e-01    -4.356836381e-01
+       
+scalein  con 2.449e-05, 1.157407407e-04
+scaleout con 128, 16192
+
+dly_b1 sta 0,0
+dly_t1 sta 0,0
+
+tmp dyn 1     ; miscellaneous temp storage
+tmpout dyn 1
+
+;;; end of bass/treble definitions
+
+;;;
+;;; This macro applies the bass/treble controls (based on eq2.asm)
+;;;
+basstreble MACRO dest,source,tone_bass,tone_treble,dly_b,dly_t
+       ;;; tone_bass filter(iir):
+       macw    tmp, C_0,  dly_b+1,  a_b+1
+       macw    tmp, tmp,  dly_b  ,  a_b
+       macw    tmp,tmp,source,scalein
+       macints tmp, C_0, tmp, C_2
+  
+       macs    C_0,C_0,C_0,C_0
+       macmv   dly_b+1,dly_b,  dly_b+1, b_b+2
+       macmv   dly_b,tmp,      dly_b,   b_b+1
+       macw    tmp,ACCUM,      tmp,     b_b    
+       macs    tmp,C_0,tone_bass,tmp
+       macints tmpout,C_0,tmp,scaleout
+
+  ;;; tone_treble
+       macw    tmp, C_0,  dly_t+1,  a_t+1      
+       macw    tmp, tmp,  dly_t  ,  a_t
+       macw    tmp, tmp, source,scalein+1
+       macints tmp,C_0,tmp,C_2
+       
+       macs    C_0,C_0,C_0,C_0
+       macmv   dly_t+1,dly_t,  dly_t+1, b_t+2
+       macmv   dly_t,tmp,      dly_t,   b_t+1
+       macw    tmp,ACCUM,      tmp,     b_t    
+       macs    tmp,C_0,tone_treble,tmp
+  
+       macints dest,tmpout,tmp,scaleout+1
+  
+  ENDM
+
+;;;
+;;; This macro applies the bass/treble controls (based on eq2.asm)
+;;; and stores results into two separate GPRs
+;;;
+basstreblesep MACRO dest_b,dest_t,source,tone_bass,tone_treble,dly_b,dly_t
+       ;;; tone_bass filter(iir):
+       macw    tmp, C_0,  dly_b+1,  a_b+1
+       macw    tmp, tmp,  dly_b  ,  a_b
+       macw    tmp,tmp,source,scalein
+       macints tmp, C_0, tmp, C_2
+  
+       macs    C_0,C_0,C_0,C_0
+       macmv   dly_b+1,dly_b,  dly_b+1, b_b+2
+       macmv   dly_b,tmp,      dly_b,   b_b+1
+       macw    tmp,ACCUM,      tmp,     b_b    
+       macs    tmp,C_0,tone_bass,tmp
+       macints tmpout,C_0,tmp,scaleout
+
+  ;;; tone_treble
+       macw    tmp, C_0,  dly_t+1,  a_t+1      
+       macw    tmp, tmp,  dly_t  ,  a_t
+       macw    tmp, tmp, source,scalein+1
+       macints tmp,C_0,tmp,C_2
+       
+       macs    C_0,C_0,C_0,C_0
+       macmv   dly_t+1,dly_t,  dly_t+1, b_t+2
+       macmv   dly_t,tmp,      dly_t,   b_t+1
+       macw    tmp,ACCUM,      tmp,     b_t    
+       macs    tmp,C_0,tone_treble,tmp
+  
+       macints dest_t,C_0,tmp,scaleout+1
+  acc3    dest_b,tmpout,C_0,C_0
+  
+  ENDM
+
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc
new file mode 100644 (file)
index 0000000..d2ac8cb
--- /dev/null
@@ -0,0 +1,121 @@
+;;     fv-controls.asm - fv10k1 package
+;;     Defines control GPRs for the fv10k1 package
+;;         
+;;     Copyright (C) 2001 Oleg Smirnov <smirnov@astron.nl>
+;;    
+;;     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
+;; 
+;; $Id: fv-controls.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+  ; debugging registers
+;debug control #0,#0,#1
+;debug2 control #0,#0,#1
+;debug3 control #0,#0,#1
+;debug4 control #0,#0,#1
+
+
+       ; This delay is applied to the input before passing it through
+       ; to the output. Note that this is independent of the room reflections 
+       ; or reverb delays, and mainly intended to compensate for pathlength 
+       ; differential in an environment where the speakers are not equidistant 
+       ; from the listening position (i.e. a car!). 1/Vsound is about 3 ms/m.
+delay_r control &0,&0,&0.8
+delay_l control &0,&0,&0.8
+
+  ; high-frequency damping for room reflections
+refldamp control #0,#0,#1
+
+  ; delay for start of reverbrations. Note that this control is ignored
+  ; when using input patches with a room reflection engine -- there we use
+  ; a constant revdelay instead.
+revdelay control &.002,&0,&1
+
+  ; gains for "wet" reverbrations
+revgain control #0.10,#0,#1
+
+  ; room size parameter, 0-1. Bigger values produce deeper reverb.
+roomsize control #.90,#0,#1
+
+  ; room dampening 0-1
+damp control #.2,#0,#1
+
+  ; allpass filter feedback -- normally constant at .5
+allpassfeed control #.2,#0,#1
+
+  ; "wet1" level controls the amount of left/right reverb intermixing:
+  ;   L = L*(1-wet1) + R*wet1
+  ;   R = R*(1-wet1) + L*wet1 
+  ; (original Freeverb uses wet1 and wet2, computed from "wet" and "width":
+  ;     wet1 = wet*(width+1)/2
+  ;     wet2 = wet*(1-width)/2 )
+wet1 control #0,#0,#1
+
+  ; "dry" reverb level:
+  ; output = reverb + input*dry
+  ; Note that this is somewhat different from the "passthru" level, since
+  ; reverb bass/treble [and predelay, if any] are applied to the dry signal,
+  ; but not to the passthru signal
+dry control #0,#0,#1
+
+  ; bass and treble controls for the reverb engine
+revbass   control #0,#0,#1
+revtreble control #0,#0,#1
+  ; set to 1 to skip reverb bass/treble filters
+revdefeat control #1,#0,#1
+
+  ; fractional levels of reflections for F and R speakers
+refl_f control #0,#0,#1
+refl_r control #0,#0,#1
+  ; additional integer gains for rear reflections
+refl_rgain control #0,#0,#1
+
+  
+  ; fractional levels of reverbs for F and R speakers
+reverb_f control #0.8,#0,#1
+reverb_r control #0.0,#0,#1
+  ; additional integer gains for rear reverbs
+reverb_rgain control #0,#0,#1
+
+  ; passthru controls (separate for front/rear)
+  ; output = input*passthru + reverbs + reflections
+ptf_level control #1,#0,#1
+ptr_level control #0,#0,#1
+  ; additional integer gains for rear passthru
+ptr_gain control #0,#0,#1
+
+  ; separate bass/treble controls are available for the rear passthrus
+ptr_bass control #0,#0,#1
+ptr_treble control #0,#0,#1
+ptr_defeat control #0,#0,1
+
+  ; Max output level meters. Output patches update these GPRs with the 
+  ; maximum output level encountered.
+maxlev_fr control #1,#0,#1
+maxlev_fl control #1,#0,#1
+maxlev_rr control #.0,#0,#1
+maxlev_rl control #.0,#0,#1
+
+  ; interval at which level meters are reset. For an interval of 2N samples,
+  ; it should be set to (2^N-1)*$800.
+  ; The DBAC register is ANDed by this value, and if the result is 0,
+  ; the meters are reset. $800 corresponds to 1 sample.
+  ; $0efff00 is  4096 samples
+  ; $0fffE00 is  8192 samples
+  ; $1fffC00 is 16384 samples
+  ; $3fff800 is 32768 samples
+  ; $7fff800 is 65536 samples
+level_interval control $1fffC00,$0,$8000000
+
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc
new file mode 100644 (file)
index 0000000..e7357cd
--- /dev/null
@@ -0,0 +1,174 @@
+;;     fv-filters.m4 - fv10k1 package
+;;     defines delay lines and GPRs for Freeverb's comb and allpass filters
+;;         
+;;     Copyright (C) 2001 Oleg Smirnov <smirnov@astron.nl>
+;;    
+;;     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
+;; 
+;; $Id: fv-filters.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+; This is a shorter version that only uses 32 address lines
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+;;; macro to apply & accumulate a comb filter
+comb MACRO dest,rdelay,wdelay,filterstore
+  acc3 dest,dest,rdelay,C_0
+  interp filterstore,rdelay,damp,filterstore
+  macs wdelay,input,filterstore,roomsize
+  endm
+
+;;; macro to apply an allpass filter
+allpass MACRO dest,rdelay,wdelay
+  macs wdelay,dest,rdelay,allpassfeed
+  macs1 dest,rdelay,dest,C_max
+  endm
+
+
+
+
+
+
+
+;;; Freeverb reduced mode - comb filter delay lines go ahead, since for 
+;;; reduced Freeverb we do not want to use internal TRAM -- it may be out 
+;;; of address lines thanks to the reflection engine, so external TRAM 
+;;; is preferrable. Hence longer delays (for comb filters) go first.
+
+;;; Freeverb reduced mode - 4 comb filters only
+
+csl5 sta 0
+csr5 sta 0
+
+cdl5 delay 1569
+cdr5 delay 1594
+wcdl5 twrite cdl5,0
+wcdr5 twrite cdr5,0
+rcdl5 tread cdl5,1549
+rcdr5 tread cdr5,1574
+
+
+
+csl6 sta 0
+csr6 sta 0
+
+cdl6 delay 1645
+cdr6 delay 1670
+wcdl6 twrite cdl6,0
+wcdr6 twrite cdr6,0
+rcdl6 tread cdl6,1625
+rcdr6 tread cdr6,1650
+
+
+
+csl7 sta 0
+csr7 sta 0
+
+cdl7 delay 1717
+cdr7 delay 1742
+wcdl7 twrite cdl7,0
+wcdr7 twrite cdr7,0
+rcdl7 tread cdl7,1697
+rcdr7 tread cdr7,1722
+
+
+
+csl8 sta 0
+csr8 sta 0
+
+cdl8 delay 1782
+cdr8 delay 1807
+wcdl8 twrite cdl8,0
+wcdr8 twrite cdr8,0
+rcdl8 tread cdl8,1762
+rcdr8 tread cdr8,1787
+
+
+;;; define macro to apply all comb filters to land r
+do_comb_filters MACRO l,r
+  comb l,rcdl5,wcdl5,csl5
+  comb l,rcdl6,wcdl6,csl6
+  comb l,rcdl7,wcdl7,csl7
+  comb l,rcdl8,wcdl8,csl8
+  comb r,rcdr5,wcdr5,csr5
+  comb r,rcdr6,wcdr6,csr6
+  comb r,rcdr7,wcdr7,csr7
+  comb r,rcdr8,wcdr8,csr8
+  ENDM
+
+;;; Now define the allpass filter delay lines
+;;; 4 allpass filters
+
+apl1 delay 626
+apr1 delay 651
+wapl1 twrite apl1,0
+wapr1 twrite apr1,0
+rapl1 tread apl1,606
+rapr1 tread apr1,631
+
+
+
+apl2 delay 500
+apr2 delay 525
+wapl2 twrite apl2,0
+wapr2 twrite apr2,0
+rapl2 tread apl2,480
+rapr2 tread apr2,505
+
+
+
+apl3 delay 391
+apr3 delay 416
+wapl3 twrite apl3,0
+wapr3 twrite apr3,0
+rapl3 tread apl3,371
+rapr3 tread apr3,396
+
+
+
+apl4 delay 265
+apr4 delay 290
+wapl4 twrite apl4,0
+wapr4 twrite apr4,0
+rapl4 tread apl4,245
+rapr4 tread apr4,270
+
+
+do_allpass_filters MACRO l,r
+  allpass l,rapl1,wapl1
+  allpass l,rapl2,wapl2
+  allpass l,rapl3,wapl3
+  allpass l,rapl4,wapl4
+  allpass r,rapr1,wapr1
+  allpass r,rapr2,wapr2
+  allpass r,rapr3,wapr3
+  allpass r,rapr4,wapr4
+  ENDM
+
+
+
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc
new file mode 100644 (file)
index 0000000..12ee8a0
--- /dev/null
@@ -0,0 +1,227 @@
+;;     fv-filters.m4 - fv10k1 package
+;;     defines delay lines and GPRs for Freeverb's comb and allpass filters
+;;         
+;;     Copyright (C) 2001 Oleg Smirnov <smirnov@astron.nl>
+;;    
+;;     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
+;; 
+;; $Id: fv-filters.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+;;; macro to apply & accumulate a comb filter
+comb MACRO dest,rdelay,wdelay,filterstore
+  acc3 dest,dest,rdelay,C_0
+  interp filterstore,rdelay,damp,filterstore
+  macs wdelay,input,filterstore,roomsize
+  endm
+
+;;; macro to apply an allpass filter
+allpass MACRO dest,rdelay,wdelay
+  macs wdelay,dest,rdelay,allpassfeed
+  macs1 dest,rdelay,dest,C_max
+  endm
+
+
+
+
+
+
+;
+;;; Freeverb full mode - allpass filter delay lines go ahead, since
+;;; wed rather use internal TRAM. Hence shorter delays  go first.
+;;; 4 allpass filters
+
+apl1 delay 626
+apr1 delay 651
+wapl1 twrite apl1,0
+wapr1 twrite apr1,0
+rapl1 tread apl1,606
+rapr1 tread apr1,631
+
+
+
+apl2 delay 500
+apr2 delay 525
+wapl2 twrite apl2,0
+wapr2 twrite apr2,0
+rapl2 tread apl2,480
+rapr2 tread apr2,505
+
+
+
+apl3 delay 391
+apr3 delay 416
+wapl3 twrite apl3,0
+wapr3 twrite apr3,0
+rapl3 tread apl3,371
+rapr3 tread apr3,396
+
+
+
+apl4 delay 265
+apr4 delay 290
+wapl4 twrite apl4,0
+wapr4 twrite apr4,0
+rapl4 tread apl4,245
+rapr4 tread apr4,270
+
+
+do_allpass_filters MACRO l,r
+  allpass l,rapl1,wapl1
+  allpass l,rapl2,wapl2
+  allpass l,rapl3,wapl3
+  allpass l,rapl4,wapl4
+  allpass r,rapr1,wapr1
+  allpass r,rapr2,wapr2
+  allpass r,rapr3,wapr3
+  allpass r,rapr4,wapr4
+  ENDM
+
+;;; Now define the comb filter delay lines
+
+;;; Freeverb full mode - 8 comb filters
+
+csl1 sta 0
+csr1 sta 0
+
+cdl1 delay 1236
+cdr1 delay 1261
+wcdl1 twrite cdl1,0
+wcdr1 twrite cdr1,0
+rcdl1 tread cdl1,1216
+rcdr1 tread cdr1,1241
+
+
+
+csl2 sta 0
+csr2 sta 0
+
+cdl2 delay 1314
+cdr2 delay 1339
+wcdl2 twrite cdl2,0
+wcdr2 twrite cdr2,0
+rcdl2 tread cdl2,1294
+rcdr2 tread cdr2,1319
+
+
+
+csl3 sta 0
+csr3 sta 0
+
+cdl3 delay 1411
+cdr3 delay 1436
+wcdl3 twrite cdl3,0
+wcdr3 twrite cdr3,0
+rcdl3 tread cdl3,1391
+rcdr3 tread cdr3,1416
+
+
+
+csl4 sta 0
+csr4 sta 0
+
+cdl4 delay 1498
+cdr4 delay 1523
+wcdl4 twrite cdl4,0
+wcdr4 twrite cdr4,0
+rcdl4 tread cdl4,1478
+rcdr4 tread cdr4,1503
+
+
+
+csl5 sta 0
+csr5 sta 0
+
+cdl5 delay 1569
+cdr5 delay 1594
+wcdl5 twrite cdl5,0
+wcdr5 twrite cdr5,0
+rcdl5 tread cdl5,1549
+rcdr5 tread cdr5,1574
+
+
+
+csl6 sta 0
+csr6 sta 0
+
+cdl6 delay 1645
+cdr6 delay 1670
+wcdl6 twrite cdl6,0
+wcdr6 twrite cdr6,0
+rcdl6 tread cdl6,1625
+rcdr6 tread cdr6,1650
+
+
+
+csl7 sta 0
+csr7 sta 0
+
+cdl7 delay 1717
+cdr7 delay 1742
+wcdl7 twrite cdl7,0
+wcdr7 twrite cdr7,0
+rcdl7 tread cdl7,1697
+rcdr7 tread cdr7,1722
+
+
+
+csl8 sta 0
+csr8 sta 0
+
+cdl8 delay 1782
+cdr8 delay 1807
+wcdl8 twrite cdl8,0
+wcdr8 twrite cdr8,0
+rcdl8 tread cdl8,1762
+rcdr8 tread cdr8,1787
+
+
+do_comb_filters MACRO l,r
+  comb l,rcdl1,wcdl1,csl1
+  comb l,rcdl2,wcdl2,csl2
+  comb l,rcdl3,wcdl3,csl3
+  comb l,rcdl4,wcdl4,csl4
+  comb l,rcdl5,wcdl5,csl5
+  comb l,rcdl6,wcdl6,csl6
+  comb l,rcdl7,wcdl7,csl7
+  comb l,rcdl8,wcdl8,csl8
+  comb r,rcdr1,wcdr1,csr1
+  comb r,rcdr2,wcdr2,csr2
+  comb r,rcdr3,wcdr3,csr3
+  comb r,rcdr4,wcdr4,csr4
+  comb r,rcdr5,wcdr5,csr5
+  comb r,rcdr6,wcdr6,csr6
+  comb r,rcdr7,wcdr7,csr7
+  comb r,rcdr8,wcdr8,csr8
+  ENDM
+
+;'
+
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc
new file mode 100644 (file)
index 0000000..a45a9cb
--- /dev/null
@@ -0,0 +1,37 @@
+;;     fv-routes.asm - fv10k1 package
+;;     Defines routing GPRs
+;;         
+;;     Copyright (C) 2001 Oleg Smirnov <smirnov@astron.nl>
+;;    
+;;     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
+;; 
+;; $Id: fv-routes.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $
+
+  ; These registers are used to pass samples from the fv10k1 engine.
+  ; fv10k1 attaches to two (R+L) input lines, and generates three sets
+  ; of outputs: reverbs, reflections front, reflections rear.
+  ; Separate output patches are responsible for mixing these outputs
+  ; into their respective output lines
+
+fvrev_r control #1,#0,#1
+fvrev_l control #1,#0,#1
+
+  ; Directional outputs of room reflection engine
+fvrefl_fl control #1,#0,#1
+fvrefl_rl control #0,#0,#1
+fvrefl_fr control #1,#0,#1
+fvrefl_rr control #0,#0,#1
+
+  END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm b/ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm
new file mode 100644 (file)
index 0000000..6cb3bd3
--- /dev/null
@@ -0,0 +1,19 @@
+       name "4-channel Gain"
+
+;;; The next line controls the amount of gain (must be an integer)
+gain   constant        4
+
+       
+signal1        io
+signal2        io
+signal3        io
+signal4 io
+
+       
+       macints signal1, $40, signal1, gain ; signal= 0 + signal * gain
+       macints signal2, $40, signal2, gain
+       macints signal3, $40, signal3, gain
+       macints signal4, $40, signal4, gain
+
+
+       end
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm b/ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm
new file mode 100644 (file)
index 0000000..8d279a5
--- /dev/null
@@ -0,0 +1,87 @@
+;;; Simple Chorus
+;;; Author:Daniel Bertrand
+;;; Date: Oct 12, 2000
+
+;;; 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.
+
+;;; References:        
+;;; http://www.harmony-central.com/Effects/Articles/Chorus
+
+                       
+;;;  speed(formerly "delta")=2*pi*freq/48000
+;;;  this give us our delta value for a specific freq (0.1-0.3Hz is good)
+               
+
+       include "emu_constants.asm"
+       name "ChorusL"
+               
+in     IO
+   
+outl   equ in
+
+       
+       
+speedL   control  4e-05 , 0 , 1e-4     ; Controls frequency (radians)
+delayL   control  &32e-3  ,&10e-3 , &80e-3; twice (2*) average delay (sec)
+widthL   control  #0.8   ,0     ,#1    ; width control 
+mixL     control  #1    ,0      ,#1    ; forward mix 
+
+;; sine generator storage spaces:      
+sinx  sta  0   
+cosx  sta  #0.5
+                       
+tmp  dyn       
+tmp2 dyn
+       
+;;; Two Delay Lines:   
+       
+       
+dly   delay  &80e-3            ;10msec delay line
+       
+write  twrite dly,0            ; tram writes
+ready  tread dly,0             ; tram reads
+reada   tread dly,0
+                               
+;;;The code:   
+       
+               
+;;; two opcode sinewave generator (I love this chip!):
+       macs  sinx,sinx,speedL,cosx
+       macs1 cosx,cosx,speedL,sinx 
+
+;;; 0.5Asint+0.5:      
+       macs tmp,C_2^30,sinx,widthL
+       
+;;; calculate address:
+       macs  ready.a,write.a,delayL,tmp
+
+;second addresses for interpolation:
+;(interesting how the emu engineers decided that $800 wasn't a needed value) 
+       macints reada.a,ready.a,C_8,C_256 
+
+       
+;;; Write to the delay line:
+       
+       macs  write,C_0,in,C_2^29
+               
+               
+       
+;;; output values:             
+;;; 0x55 is 00100000 (?)
+       macints tmp,C_0,reada.a,C_LSshift; get least significant part of address
+       
+       interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings
+       
+       macs  outl,tmp2,tmp2,mixL
+       
+               
+       
+       end
+
+
+
+
+
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm b/ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm
new file mode 100644 (file)
index 0000000..fabe17e
--- /dev/null
@@ -0,0 +1,87 @@
+;;; Simple Chorus
+;;; Author:Daniel Bertrand
+;;; Date: Oct 12, 2000
+
+;;; 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.
+
+;;; References:        
+;;; http://www.harmony-central.com/Effects/Articles/Chorus
+
+                       
+;;;  speed(formerly "delta")=2*pi*freq/48000
+;;;  this give us our delta value for a specific freq (0.1-0.3Hz is good)
+               
+
+       include "emu_constants.asm"
+       name "ChorusR"
+               
+in     IO
+   
+outr   equ in
+
+       
+speedR   control  5e-05 , 0 , 1e-4     ; Controls frequency (radians)
+delayR   control  &30e-3  ,&10e-3 , &80e-3; twice (2*) average delay (sec)
+widthR   control  #0.78   ,0    ,#1    ; width control 
+mixR     control  #1    ,0      ,#1    ; forward mix 
+
+;; sine generator storage spaces:      
+sinx  sta  0   
+cosx  sta  #0.5
+                       
+tmp  dyn       
+tmp2 dyn
+       
+;;; Two Delay Lines:   
+       
+       
+dly   delay  &80e-3            ;10msec delay line
+       
+write  twrite dly,0            ; tram writes
+ready  tread dly,0             ; tram reads
+reada   tread dly,0
+                               
+;;;The code:   
+       
+               
+;;; two opcode sinewave generator (I love this chip!):
+       macs  sinx,sinx,speedR,cosx
+       macs1 cosx,cosx,speedR,sinx 
+
+;;; 0.5Asint+0.5:      
+       macs tmp,C_2^30,sinx,widthR
+       
+;;; calculate address:
+       macs  ready.a,write.a,delayR,tmp
+
+;second addresses for interpolation:
+;(interesting how the emu engineers decided that $800 wasn't a needed value) 
+       macints reada.a,ready.a,C_8,C_256 
+
+       
+;;; Write to the delay line:
+       
+       macs  write,C_0,in,C_2^29
+               
+               
+       
+;;; output values:             
+;;; 0x55 is 00100000 (?)
+       macints tmp,C_0,reada.a,C_LSshift; get least significant part of address
+       
+       interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings
+       
+       macs  outr,tmp2,tmp2,mixR
+
+
+               
+       
+       end
+
+
+
+
+
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/pontodo5 b/ld10k1/contrib/emu10k1MIDIEffects/pontodo5
new file mode 100644 (file)
index 0000000..ef2b41b
--- /dev/null
@@ -0,0 +1,64 @@
+#Reset DSP
+lo10k1 -s
+
+#load MASTER L,R
+lo10k1 -n -a volLR.emu10k1
+
+#load Bus L and BUS R
+lo10k1 -n -a 3volBUS1.emu10k1
+lo10k1 -n -a 3volBUS2.emu10k1
+
+#load Chorus Effect
+lo10k1 -n -a michorusL.emu10k1
+lo10k1 -n -a michorusR.emu10k1
+
+#load gain
+lo10k1 -n -a gain_4.emu10k1
+
+#load reverb 
+lo10k1 -n -a freberv.emu10k1
+
+lo10k1 -q "PIN(5,0)=FX(4)"
+lo10k1 -q "PIN(5,1)=FX(5)"
+lo10k1 -q "PIN(5,2)=FX(13)"
+lo10k1 -q "PIN(5,3)=FX(13)"
+
+#Input Chorus with FX(13) MIDI_Chorus_FX
+lo10k1 -q "PIN(3)=POUT(5,2)"
+lo10k1 -q "PIN(4)=POUT(5,3)"
+
+#reverb
+
+lo10k1 -q "PIN(6,0)=FX(12)"
+lo10k1 -q "PIN(6,1)=FX(12)"
+
+
+
+#Mix in BUS L FX_MIDI_Left + Chorus Effect
+lo10k1 -q "PIN(1,1)=POUT(5,0)"
+lo10k1 -q "PIN(1,0)=POUT(3)"
+lo10k1 -q "PIN(1,2)=POUT(6,0)"
+
+#Mix in BUS R FX:MIDI_Right + Chorus Effect
+lo10k1 -q "PIN(2,1)=POUT(5,1)"
+lo10k1 -q "PIN(2,0)=POUT(4)"
+lo10k1 -q "PIN(2,2)=POUT(6,1)"
+
+
+
+#BUS L to Master L
+lo10k1 -q "PIN(0,0)=POUT(1,0)"
+
+#BUS R to Master R
+lo10k1 -q "PIN(0,1)=POUT(2,0)"
+
+
+
+
+
+#Master to Ouputs
+lo10k1 -q "POUT(0,0)=OUT(0)"
+lo10k1 -q "POUT(0,1)=OUT(1)"
+
+
+
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc b/ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc
new file mode 100644 (file)
index 0000000..298e053
--- /dev/null
@@ -0,0 +1,337 @@
+;;; FV10K1 room relections code
+;;; Generates room reflections according to file big.room.rp, and stores
+;;; them in GPRs fvrefl_[fl|fr|rl|rr].
+;;; Built on Sat Jan 24 13:18:00 2004 from room definition file big.room.rp.
+
+  ; define delays and dampening constants
+readr0 tread dlyr,&0.070249
+readl0 tread dlyl,&0.070249
+fl0 constant #-0.028783
+fr0 constant #-0.011243
+dmpstore_r0 sta 0,0,0
+dmpstore_l0 sta 0,0,0
+readr1 tread dlyr,&0.070249
+readl1 tread dlyl,&0.070249
+fl1 constant #-0.011243
+fr1 constant #-0.028783
+dmpstore_r1 sta 0,0,0
+dmpstore_l1 sta 0,0,0
+readr2 tread dlyr,&0.059064
+readl2 tread dlyl,&0.059064
+fl2 constant #0.054798
+fr2 constant #0.021405
+dmpstore_r2 sta 0,0
+dmpstore_l2 sta 0,0
+readr3 tread dlyr,&0.059064
+readl3 tread dlyl,&0.059064
+fl3 constant #0.021405
+fr3 constant #0.054798
+dmpstore_r3 sta 0,0
+dmpstore_l3 sta 0,0
+readr4 tread dlyr,&0.001778
+readl4 tread dlyl,&0.001778
+fl4 constant #-0.428866
+fr4 constant #-0.167526
+dmpstore_r4 sta 0
+dmpstore_l4 sta 0
+readr5 tread dlyr,&0.001778
+readl5 tread dlyl,&0.001778
+fl5 constant #-0.167526
+fr5 constant #-0.428866
+dmpstore_r5 sta 0
+dmpstore_l5 sta 0
+readr6 tread dlyr,&0.048126
+readl6 tread dlyl,&0.048126
+fl6 constant #-0.106417
+fr6 constant #-0.041569
+dmpstore_r6 sta 0
+dmpstore_l6 sta 0
+readr7 tread dlyr,&0.048126
+readl7 tread dlyl,&0.048126
+fl7 constant #-0.041569
+fr7 constant #-0.106417
+dmpstore_r7 sta 0
+dmpstore_l7 sta 0
+readr8 tread dlyr,&0.059064
+readl8 tread dlyl,&0.059064
+fl8 constant #0.054798
+fr8 constant #0.021405
+dmpstore_r8 sta 0,0
+dmpstore_l8 sta 0,0
+readr9 tread dlyr,&0.059064
+readl9 tread dlyl,&0.059064
+fl9 constant #0.021405
+fr9 constant #0.054798
+dmpstore_r9 sta 0,0
+dmpstore_l9 sta 0,0
+readr10 tread dlyr,&0.077324
+readl10 tread dlyl,&0.077324
+fr10 constant #-0.047167
+rr10 constant #-0.002611
+dmpstore_r10 sta 0,0,0
+dmpstore_l10 sta 0,0,0
+readr11 tread dlyr,&0.051184
+readl11 tread dlyl,&0.051184
+fr11 constant #0.103186
+rr11 constant #0.012640
+dmpstore_r11 sta 0,0
+dmpstore_l11 sta 0,0
+readr12 tread dlyr,&0.035389
+readl12 tread dlyl,&0.035389
+fr12 constant #0.160243
+rr12 constant #0.008872
+dmpstore_r12 sta 0,0
+dmpstore_l12 sta 0,0
+readr13 tread dlyr,&0.050379
+readl13 tread dlyl,&0.050379
+fr13 constant #-0.161577
+rr13 constant #-0.019793
+dmpstore_r13 sta 0
+dmpstore_l13 sta 0
+readr14 tread dlyr,&0.034414
+readl14 tread dlyl,&0.034414
+fr14 constant #-0.252993
+rr14 constant #-0.014007
+dmpstore_r14 sta 0
+dmpstore_l14 sta 0
+readr15 tread dlyr,&0.079794
+readl15 tread dlyl,&0.079794
+fr15 constant #0.065450
+rr15 constant #0.008018
+dmpstore_r15 sta 0,0
+dmpstore_l15 sta 0,0
+readr16 tread dlyr,&0.068240
+readl16 tread dlyl,&0.068240
+fr16 constant #0.085203
+rr16 constant #0.004717
+dmpstore_r16 sta 0,0
+dmpstore_l16 sta 0,0
+readr17 tread dlyr,&0.077324
+readl17 tread dlyl,&0.077324
+fr17 constant #-0.047167
+rr17 constant #-0.002611
+dmpstore_r17 sta 0,0,0
+dmpstore_l17 sta 0,0,0
+
+
+       ;;; Accumulate reflections for FL
+       interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0
+       interp dmpstore_l0+1,dmpstore_l0+0,refldamp,dmpstore_l0+1
+       interp dmpstore_l0+2,dmpstore_l0+1,refldamp,dmpstore_l0+2
+       interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0
+       interp dmpstore_r0+1,dmpstore_r0+0,refldamp,dmpstore_r0+1
+       interp dmpstore_r0+2,dmpstore_r0+1,refldamp,dmpstore_r0+2
+       interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0
+       interp dmpstore_r1+1,dmpstore_r1+0,refldamp,dmpstore_r1+1
+       interp dmpstore_r1+2,dmpstore_r1+1,refldamp,dmpstore_r1+2
+       interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0
+       interp dmpstore_l1+1,dmpstore_l1+0,refldamp,dmpstore_l1+1
+       interp dmpstore_l1+2,dmpstore_l1+1,refldamp,dmpstore_l1+2
+       interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0
+       interp dmpstore_l2+1,dmpstore_l2+0,refldamp,dmpstore_l2+1
+       interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0
+       interp dmpstore_r2+1,dmpstore_r2+0,refldamp,dmpstore_r2+1
+       interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0
+       interp dmpstore_r3+1,dmpstore_r3+0,refldamp,dmpstore_r3+1
+       interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0
+       interp dmpstore_l3+1,dmpstore_l3+0,refldamp,dmpstore_l3+1
+       interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0
+       interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0
+       interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0
+       interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0
+       interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0
+       interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0
+       interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0
+       interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0
+       interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0
+       interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1
+       interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0
+       interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1
+       interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0
+       interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1
+       interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0
+       interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1
+       interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0
+       interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1
+       interp dmpstore_l10+2,dmpstore_l10+1,refldamp,dmpstore_l10+2
+       interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0
+       interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1
+       interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0
+       interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1
+       interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0
+       interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0
+       interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0
+       interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1
+       interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0
+       interp dmpstore_l16+1,dmpstore_l16+0,refldamp,dmpstore_l16+1
+       interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0
+       interp dmpstore_l17+1,dmpstore_l17+0,refldamp,dmpstore_l17+1
+       interp dmpstore_l17+2,dmpstore_l17+1,refldamp,dmpstore_l17+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l0+2,fl0
+       macmv tmp,C_0,dmpstore_r0+2,fr0
+       macmv tmp,C_0,dmpstore_r1+2,fl1
+       macmv tmp,C_0,dmpstore_l1+2,fr1
+       macmv tmp,C_0,dmpstore_l2+1,fl2
+       macmv tmp,C_0,dmpstore_r2+1,fr2
+       macmv tmp,C_0,dmpstore_r3+1,fl3
+       macmv tmp,C_0,dmpstore_l3+1,fr3
+       macmv tmp,C_0,dmpstore_l4+0,fl4
+       macmv tmp,C_0,dmpstore_r4+0,fr4
+       macmv tmp,C_0,dmpstore_r5+0,fl5
+       macmv tmp,C_0,dmpstore_l5+0,fr5
+       macmv tmp,C_0,dmpstore_l6+0,fl6
+       macmv tmp,C_0,dmpstore_r6+0,fr6
+       macmv tmp,C_0,dmpstore_r7+0,fl7
+       macmv tmp,C_0,dmpstore_l7+0,fr7
+       macmv tmp,C_0,dmpstore_l8+1,fl8
+       macmv tmp,C_0,dmpstore_r8+1,fr8
+       macmv tmp,C_0,dmpstore_r9+1,fl9
+       macmv tmp,C_0,dmpstore_l9+1,fr9
+       macmv tmp,C_0,dmpstore_l10+2,fr10
+       macmv tmp,C_0,dmpstore_r11+1,fr11
+       macmv tmp,C_0,dmpstore_l12+1,fr12
+       macmv tmp,C_0,dmpstore_r13+0,fr13
+       macmv tmp,C_0,dmpstore_l14+0,fr14
+       macmv tmp,C_0,dmpstore_r15+1,fr15
+       macmv tmp,C_0,dmpstore_l16+1,fr16
+       macs fvrefl_fl,ACCUM,dmpstore_l17+2,fr17
+
+       ;;; Accumulate reflections for FR
+       interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0
+       interp dmpstore_l0+1,dmpstore_l0+0,refldamp,dmpstore_l0+1
+       interp dmpstore_l0+2,dmpstore_l0+1,refldamp,dmpstore_l0+2
+       interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0
+       interp dmpstore_r0+1,dmpstore_r0+0,refldamp,dmpstore_r0+1
+       interp dmpstore_r0+2,dmpstore_r0+1,refldamp,dmpstore_r0+2
+       interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0
+       interp dmpstore_r1+1,dmpstore_r1+0,refldamp,dmpstore_r1+1
+       interp dmpstore_r1+2,dmpstore_r1+1,refldamp,dmpstore_r1+2
+       interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0
+       interp dmpstore_l1+1,dmpstore_l1+0,refldamp,dmpstore_l1+1
+       interp dmpstore_l1+2,dmpstore_l1+1,refldamp,dmpstore_l1+2
+       interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0
+       interp dmpstore_l2+1,dmpstore_l2+0,refldamp,dmpstore_l2+1
+       interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0
+       interp dmpstore_r2+1,dmpstore_r2+0,refldamp,dmpstore_r2+1
+       interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0
+       interp dmpstore_r3+1,dmpstore_r3+0,refldamp,dmpstore_r3+1
+       interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0
+       interp dmpstore_l3+1,dmpstore_l3+0,refldamp,dmpstore_l3+1
+       interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0
+       interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0
+       interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0
+       interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0
+       interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0
+       interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0
+       interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0
+       interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0
+       interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0
+       interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1
+       interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0
+       interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1
+       interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0
+       interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1
+       interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0
+       interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1
+       interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0
+       interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1
+       interp dmpstore_r10+2,dmpstore_r10+1,refldamp,dmpstore_r10+2
+       interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0
+       interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1
+       interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0
+       interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1
+       interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0
+       interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0
+       interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0
+       interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1
+       interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0
+       interp dmpstore_r16+1,dmpstore_r16+0,refldamp,dmpstore_r16+1
+       interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0
+       interp dmpstore_r17+1,dmpstore_r17+0,refldamp,dmpstore_r17+1
+       interp dmpstore_r17+2,dmpstore_r17+1,refldamp,dmpstore_r17+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l0+2,fr0
+       macmv tmp,C_0,dmpstore_r0+2,fl0
+       macmv tmp,C_0,dmpstore_r1+2,fr1
+       macmv tmp,C_0,dmpstore_l1+2,fl1
+       macmv tmp,C_0,dmpstore_l2+1,fr2
+       macmv tmp,C_0,dmpstore_r2+1,fl2
+       macmv tmp,C_0,dmpstore_r3+1,fr3
+       macmv tmp,C_0,dmpstore_l3+1,fl3
+       macmv tmp,C_0,dmpstore_l4+0,fr4
+       macmv tmp,C_0,dmpstore_r4+0,fl4
+       macmv tmp,C_0,dmpstore_r5+0,fr5
+       macmv tmp,C_0,dmpstore_l5+0,fl5
+       macmv tmp,C_0,dmpstore_l6+0,fr6
+       macmv tmp,C_0,dmpstore_r6+0,fl6
+       macmv tmp,C_0,dmpstore_r7+0,fr7
+       macmv tmp,C_0,dmpstore_l7+0,fl7
+       macmv tmp,C_0,dmpstore_l8+1,fr8
+       macmv tmp,C_0,dmpstore_r8+1,fl8
+       macmv tmp,C_0,dmpstore_r9+1,fr9
+       macmv tmp,C_0,dmpstore_l9+1,fl9
+       macmv tmp,C_0,dmpstore_r10+2,fr10
+       macmv tmp,C_0,dmpstore_l11+1,fr11
+       macmv tmp,C_0,dmpstore_r12+1,fr12
+       macmv tmp,C_0,dmpstore_l13+0,fr13
+       macmv tmp,C_0,dmpstore_r14+0,fr14
+       macmv tmp,C_0,dmpstore_l15+1,fr15
+       macmv tmp,C_0,dmpstore_r16+1,fr16
+       macs fvrefl_fr,ACCUM,dmpstore_r17+2,fr17
+
+       ;;; Accumulate reflections for RL
+       interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0
+       interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1
+       interp dmpstore_l10+2,dmpstore_l10+1,refldamp,dmpstore_l10+2
+       interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0
+       interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1
+       interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0
+       interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1
+       interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0
+       interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0
+       interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0
+       interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1
+       interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0
+       interp dmpstore_l16+1,dmpstore_l16+0,refldamp,dmpstore_l16+1
+       interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0
+       interp dmpstore_l17+1,dmpstore_l17+0,refldamp,dmpstore_l17+1
+       interp dmpstore_l17+2,dmpstore_l17+1,refldamp,dmpstore_l17+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l10+2,rr10
+       macmv tmp,C_0,dmpstore_r11+1,rr11
+       macmv tmp,C_0,dmpstore_l12+1,rr12
+       macmv tmp,C_0,dmpstore_r13+0,rr13
+       macmv tmp,C_0,dmpstore_l14+0,rr14
+       macmv tmp,C_0,dmpstore_r15+1,rr15
+       macmv tmp,C_0,dmpstore_l16+1,rr16
+       macs fvrefl_rl,ACCUM,dmpstore_l17+2,rr17
+
+       ;;; Accumulate reflections for RR
+       interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0
+       interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1
+       interp dmpstore_r10+2,dmpstore_r10+1,refldamp,dmpstore_r10+2
+       interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0
+       interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1
+       interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0
+       interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1
+       interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0
+       interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0
+       interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0
+       interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1
+       interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0
+       interp dmpstore_r16+1,dmpstore_r16+0,refldamp,dmpstore_r16+1
+       interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0
+       interp dmpstore_r17+1,dmpstore_r17+0,refldamp,dmpstore_r17+1
+       interp dmpstore_r17+2,dmpstore_r17+1,refldamp,dmpstore_r17+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_r10+2,rr10
+       macmv tmp,C_0,dmpstore_l11+1,rr11
+       macmv tmp,C_0,dmpstore_r12+1,rr12
+       macmv tmp,C_0,dmpstore_l13+0,rr13
+       macmv tmp,C_0,dmpstore_r14+0,rr14
+       macmv tmp,C_0,dmpstore_l15+1,rr15
+       macmv tmp,C_0,dmpstore_r16+1,rr16
+       macs fvrefl_rr,ACCUM,dmpstore_r17+2,rr17
+
+       END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc b/ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc
new file mode 100644 (file)
index 0000000..30e7d6b
--- /dev/null
@@ -0,0 +1,320 @@
+;;; FV10K1 room relections code
+;;; Generates room reflections according to file default.room.rp, and stores
+;;; them in GPRs fvrefl_[fl|fr|rl|rr].
+;;; Built on Sat Jan 24 13:18:00 2004 from room definition file default.room.rp.
+
+  ; define delays and dampening constants
+readr0 tread dlyr,&0.003511
+readl0 tread dlyl,&0.003511
+fl0 constant #-0.371429
+fr0 constant #-0.092857
+dmpstore_r0 sta 0
+dmpstore_l0 sta 0
+readr1 tread dlyr,&0.003511
+readl1 tread dlyl,&0.003511
+fl1 constant #-0.092857
+fr1 constant #-0.371429
+dmpstore_r1 sta 0
+dmpstore_l1 sta 0
+readr2 tread dlyr,&0.006548
+readl2 tread dlyl,&0.006548
+fr2 constant #-0.508333
+dmpstore_r2 sta 0
+dmpstore_l2 sta 0
+readr3 tread dlyr,&0.007252
+readl3 tread dlyl,&0.007252
+fl3 constant #-0.298947
+fr3 constant #-0.074737
+dmpstore_r3 sta 0
+dmpstore_l3 sta 0
+readr4 tread dlyr,&0.007252
+readl4 tread dlyl,&0.007252
+fl4 constant #-0.074737
+fr4 constant #-0.298947
+dmpstore_r4 sta 0
+dmpstore_l4 sta 0
+readr5 tread dlyr,&0.009261
+readl5 tread dlyl,&0.009261
+fr5 constant #0.270341
+dmpstore_r5 sta 0,0
+dmpstore_l5 sta 0,0
+readr6 tread dlyr,&0.012327
+readl6 tread dlyl,&0.012327
+fr6 constant #0.240611
+dmpstore_r6 sta 0,0
+dmpstore_l6 sta 0,0
+readr7 tread dlyr,&0.016174
+readl7 tread dlyl,&0.016174
+fr7 constant #-0.253287
+rr7 constant #-0.015830
+dmpstore_r7 sta 0
+dmpstore_l7 sta 0
+readr8 tread dlyr,&0.016690
+readl8 tread dlyl,&0.016690
+fl8 constant #0.105486
+fr8 constant #0.026371
+dmpstore_r8 sta 0,0
+dmpstore_l8 sta 0,0
+readr9 tread dlyr,&0.016690
+readl9 tread dlyl,&0.016690
+fl9 constant #0.026371
+fr9 constant #0.105486
+dmpstore_r9 sta 0,0
+dmpstore_l9 sta 0,0
+readr10 tread dlyr,&0.016690
+readl10 tread dlyl,&0.016690
+fl10 constant #0.105486
+fr10 constant #0.026371
+dmpstore_r10 sta 0,0
+dmpstore_l10 sta 0,0
+readr11 tread dlyr,&0.016690
+readl11 tread dlyl,&0.016690
+fl11 constant #0.026371
+fr11 constant #0.105486
+dmpstore_r11 sta 0,0
+dmpstore_l11 sta 0,0
+readr12 tread dlyr,&0.018195
+readl12 tread dlyl,&0.018195
+fr12 constant #0.147307
+rr12 constant #0.009207
+dmpstore_r12 sta 0,0
+dmpstore_l12 sta 0,0
+readr13 tread dlyr,&0.020577
+readl13 tread dlyl,&0.020577
+fr13 constant #-0.098203
+dmpstore_r13 sta 0,0,0
+dmpstore_l13 sta 0,0,0
+readr14 tread dlyr,&0.020577
+readl14 tread dlyl,&0.020577
+fr14 constant #0.142194
+rr14 constant #0.008887
+dmpstore_r14 sta 0,0
+dmpstore_l14 sta 0,0
+readr15 tread dlyr,&0.020577
+readl15 tread dlyl,&0.020577
+fr15 constant #-0.098203
+dmpstore_r15 sta 0,0,0
+dmpstore_l15 sta 0,0,0
+readr16 tread dlyr,&0.021591
+readl16 tread dlyl,&0.021591
+rl16 constant #-0.130920
+rr16 constant #-0.071413
+dmpstore_r16 sta 0
+dmpstore_l16 sta 0
+readr17 tread dlyr,&0.021591
+readl17 tread dlyl,&0.021591
+rl17 constant #-0.071413
+rr17 constant #-0.130920
+dmpstore_r17 sta 0
+dmpstore_l17 sta 0
+readr18 tread dlyr,&0.023355
+readl18 tread dlyl,&0.023355
+rl18 constant #0.078182
+rr18 constant #0.042646
+dmpstore_r18 sta 0,0
+dmpstore_l18 sta 0,0
+readr19 tread dlyr,&0.023355
+readl19 tread dlyl,&0.023355
+rl19 constant #0.042646
+rr19 constant #0.078182
+dmpstore_r19 sta 0,0
+dmpstore_l19 sta 0,0
+
+
+       ;;; Accumulate reflections for FL
+       interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0
+       interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0
+       interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0
+       interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0
+       interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0
+       interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0
+       interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0
+       interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0
+       interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0
+       interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0
+       interp dmpstore_l5+1,dmpstore_l5+0,refldamp,dmpstore_l5+1
+       interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0
+       interp dmpstore_l6+1,dmpstore_l6+0,refldamp,dmpstore_l6+1
+       interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0
+       interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0
+       interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1
+       interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0
+       interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1
+       interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0
+       interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1
+       interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0
+       interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1
+       interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0
+       interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1
+       interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0
+       interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1
+       interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0
+       interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1
+       interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0
+       interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1
+       interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0
+       interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1
+       interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0
+       interp dmpstore_l13+1,dmpstore_l13+0,refldamp,dmpstore_l13+1
+       interp dmpstore_l13+2,dmpstore_l13+1,refldamp,dmpstore_l13+2
+       interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0
+       interp dmpstore_r14+1,dmpstore_r14+0,refldamp,dmpstore_r14+1
+       interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0
+       interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1
+       interp dmpstore_l15+2,dmpstore_l15+1,refldamp,dmpstore_l15+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l0+0,fl0
+       macmv tmp,C_0,dmpstore_r0+0,fr0
+       macmv tmp,C_0,dmpstore_r1+0,fl1
+       macmv tmp,C_0,dmpstore_l1+0,fr1
+       macmv tmp,C_0,dmpstore_l2+0,fr2
+       macmv tmp,C_0,dmpstore_l3+0,fl3
+       macmv tmp,C_0,dmpstore_r3+0,fr3
+       macmv tmp,C_0,dmpstore_r4+0,fl4
+       macmv tmp,C_0,dmpstore_l4+0,fr4
+       macmv tmp,C_0,dmpstore_l5+1,fr5
+       macmv tmp,C_0,dmpstore_l6+1,fr6
+       macmv tmp,C_0,dmpstore_r7+0,fr7
+       macmv tmp,C_0,dmpstore_l8+1,fl8
+       macmv tmp,C_0,dmpstore_r8+1,fr8
+       macmv tmp,C_0,dmpstore_r9+1,fl9
+       macmv tmp,C_0,dmpstore_l9+1,fr9
+       macmv tmp,C_0,dmpstore_l10+1,fl10
+       macmv tmp,C_0,dmpstore_r10+1,fr10
+       macmv tmp,C_0,dmpstore_r11+1,fl11
+       macmv tmp,C_0,dmpstore_l11+1,fr11
+       macmv tmp,C_0,dmpstore_r12+1,fr12
+       macmv tmp,C_0,dmpstore_l13+2,fr13
+       macmv tmp,C_0,dmpstore_r14+1,fr14
+       macs fvrefl_fl,ACCUM,dmpstore_l15+2,fr15
+
+       ;;; Accumulate reflections for FR
+       interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0
+       interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0
+       interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0
+       interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0
+       interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0
+       interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0
+       interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0
+       interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0
+       interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0
+       interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0
+       interp dmpstore_r5+1,dmpstore_r5+0,refldamp,dmpstore_r5+1
+       interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0
+       interp dmpstore_r6+1,dmpstore_r6+0,refldamp,dmpstore_r6+1
+       interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0
+       interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0
+       interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1
+       interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0
+       interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1
+       interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0
+       interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1
+       interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0
+       interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1
+       interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0
+       interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1
+       interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0
+       interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1
+       interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0
+       interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1
+       interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0
+       interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1
+       interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0
+       interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1
+       interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0
+       interp dmpstore_r13+1,dmpstore_r13+0,refldamp,dmpstore_r13+1
+       interp dmpstore_r13+2,dmpstore_r13+1,refldamp,dmpstore_r13+2
+       interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0
+       interp dmpstore_l14+1,dmpstore_l14+0,refldamp,dmpstore_l14+1
+       interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0
+       interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1
+       interp dmpstore_r15+2,dmpstore_r15+1,refldamp,dmpstore_r15+2
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l0+0,fr0
+       macmv tmp,C_0,dmpstore_r0+0,fl0
+       macmv tmp,C_0,dmpstore_r1+0,fr1
+       macmv tmp,C_0,dmpstore_l1+0,fl1
+       macmv tmp,C_0,dmpstore_r2+0,fr2
+       macmv tmp,C_0,dmpstore_l3+0,fr3
+       macmv tmp,C_0,dmpstore_r3+0,fl3
+       macmv tmp,C_0,dmpstore_r4+0,fr4
+       macmv tmp,C_0,dmpstore_l4+0,fl4
+       macmv tmp,C_0,dmpstore_r5+1,fr5
+       macmv tmp,C_0,dmpstore_r6+1,fr6
+       macmv tmp,C_0,dmpstore_l7+0,fr7
+       macmv tmp,C_0,dmpstore_l8+1,fr8
+       macmv tmp,C_0,dmpstore_r8+1,fl8
+       macmv tmp,C_0,dmpstore_r9+1,fr9
+       macmv tmp,C_0,dmpstore_l9+1,fl9
+       macmv tmp,C_0,dmpstore_l10+1,fr10
+       macmv tmp,C_0,dmpstore_r10+1,fl10
+       macmv tmp,C_0,dmpstore_r11+1,fr11
+       macmv tmp,C_0,dmpstore_l11+1,fl11
+       macmv tmp,C_0,dmpstore_l12+1,fr12
+       macmv tmp,C_0,dmpstore_r13+2,fr13
+       macmv tmp,C_0,dmpstore_l14+1,fr14
+       macs fvrefl_fr,ACCUM,dmpstore_r15+2,fr15
+
+       ;;; Accumulate reflections for RL
+       interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0
+       interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0
+       interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1
+       interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0
+       interp dmpstore_r14+1,dmpstore_r14+0,refldamp,dmpstore_r14+1
+       interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0
+       interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0
+       interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0
+       interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0
+       interp dmpstore_l18+0,readl18,refldamp,dmpstore_l18+0
+       interp dmpstore_l18+1,dmpstore_l18+0,refldamp,dmpstore_l18+1
+       interp dmpstore_r18+0,readr18,refldamp,dmpstore_r18+0
+       interp dmpstore_r18+1,dmpstore_r18+0,refldamp,dmpstore_r18+1
+       interp dmpstore_r19+0,readr19,refldamp,dmpstore_r19+0
+       interp dmpstore_r19+1,dmpstore_r19+0,refldamp,dmpstore_r19+1
+       interp dmpstore_l19+0,readl19,refldamp,dmpstore_l19+0
+       interp dmpstore_l19+1,dmpstore_l19+0,refldamp,dmpstore_l19+1
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_r7+0,rr7
+       macmv tmp,C_0,dmpstore_r12+1,rr12
+       macmv tmp,C_0,dmpstore_r14+1,rr14
+       macmv tmp,C_0,dmpstore_l16+0,rl16
+       macmv tmp,C_0,dmpstore_r16+0,rr16
+       macmv tmp,C_0,dmpstore_r17+0,rl17
+       macmv tmp,C_0,dmpstore_l17+0,rr17
+       macmv tmp,C_0,dmpstore_l18+1,rl18
+       macmv tmp,C_0,dmpstore_r18+1,rr18
+       macmv tmp,C_0,dmpstore_r19+1,rl19
+       macs fvrefl_rl,ACCUM,dmpstore_l19+1,rr19
+
+       ;;; Accumulate reflections for RR
+       interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0
+       interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0
+       interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1
+       interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0
+       interp dmpstore_l14+1,dmpstore_l14+0,refldamp,dmpstore_l14+1
+       interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0
+       interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0
+       interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0
+       interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0
+       interp dmpstore_l18+0,readl18,refldamp,dmpstore_l18+0
+       interp dmpstore_l18+1,dmpstore_l18+0,refldamp,dmpstore_l18+1
+       interp dmpstore_r18+0,readr18,refldamp,dmpstore_r18+0
+       interp dmpstore_r18+1,dmpstore_r18+0,refldamp,dmpstore_r18+1
+       interp dmpstore_r19+0,readr19,refldamp,dmpstore_r19+0
+       interp dmpstore_r19+1,dmpstore_r19+0,refldamp,dmpstore_r19+1
+       interp dmpstore_l19+0,readl19,refldamp,dmpstore_l19+0
+       interp dmpstore_l19+1,dmpstore_l19+0,refldamp,dmpstore_l19+1
+       macs C_0,C_0,C_0,C_0   ; reset accumulator
+       macmv tmp,C_0,dmpstore_l7+0,rr7
+       macmv tmp,C_0,dmpstore_l12+1,rr12
+       macmv tmp,C_0,dmpstore_l14+1,rr14
+       macmv tmp,C_0,dmpstore_l16+0,rr16
+       macmv tmp,C_0,dmpstore_r16+0,rl16
+       macmv tmp,C_0,dmpstore_r17+0,rr17
+       macmv tmp,C_0,dmpstore_l17+0,rl17
+       macmv tmp,C_0,dmpstore_l18+1,rr18
+       macmv tmp,C_0,dmpstore_r18+1,rl18
+       macmv tmp,C_0,dmpstore_r19+1,rr19
+       macs fvrefl_rr,ACCUM,dmpstore_l19+1,rl19
+
+       END
diff --git a/ld10k1/contrib/emu10k1MIDIEffects/volLR.asm b/ld10k1/contrib/emu10k1MIDIEffects/volLR.asm
new file mode 100644 (file)
index 0000000..f2041f0
--- /dev/null
@@ -0,0 +1,16 @@
+       name  "volLR"
+       
+
+       include "emu_constants.asm"
+volLR   control  #1,0,#1
+       
+inl    IO
+inr     IO
+outl   equ     inl
+outr    equ     inr
+
+       macs    outl,inl.o,inl,volLR
+        macs    outr,inr.o,inr,volLR
+       end
+       
+       
diff --git a/ld10k1/cvscompile b/ld10k1/cvscompile
new file mode 100644 (file)
index 0000000..3a5537d
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+if test "x$AUTOMAKE_DIR" = "x"; then
+  if test -d /usr/local/share/automake; then
+    AUTOMAKE_DIR=/usr/local/share/automake
+  fi
+  if test -d /usr/share/automake; then
+    AUTOMAKE_DIR="/usr/share/automake"
+  fi
+fi
+
+for f in install-sh mkinstalldirs missing; do
+  cp -av $AUTOMAKE_DIR/$f .
+done
+
+aclocal $ACLOCAL_FLAGS
+automake --add-missing --copy
+touch depcomp
+autoconf
+export CFLAGS='-O2 -Wall -pipe -g'
+echo "CFLAGS=$CFLAGS"
+echo "./configure $@"
+./configure $@
+unset CFLAGS
+make
diff --git a/ld10k1/doc/Audigy-mixer.txt b/ld10k1/doc/Audigy-mixer.txt
new file mode 100644 (file)
index 0000000..5132fd9
--- /dev/null
@@ -0,0 +1,345 @@
+
+               Sound Blaster Audigy mixer / default DSP code
+               ===========================================
+
+This is based on SB-Live-mixer.txt.
+
+The EMU10K2 chips have a DSP part which can be programmed to support 
+various ways of sample processing, which is described here.
+(This acticle does not deal with the overall functionality of the 
+EMU10K2 chips. See the manuals section for further details.)
+
+The ALSA driver programs this portion of chip by default code
+(can be altered later) which offers the following functionality:
+
+
+1) Digital mixer controls
+-------------------------
+
+These controls are built using the DSP instructions. They offer extended
+functionality. Only the default build-in code in the ALSA driver is described
+here. Note that the controls work as attenuators: the maximum value is the 
+neutral position leaving the signal unchanged. Note that if the  same destination 
+is mentioned in multiple controls, the signal is accumulated and can be wrapped 
+(set to maximal or minimal value without checking of overflow).
+
+
+Explanation of used abbreviations:
+
+DAC    - digital to analog converter
+ADC    - analog to digital converter
+I2S    - one-way three wire serial bus for digital sound by Philips Semiconductors
+         (this standard is used for connecting standalone DAC and ADC converters)
+LFE    - low frequency effects (subwoofer signal)
+AC97   - a chip containing an analog mixer, DAC and ADC converters
+IEC958 - S/PDIF
+FX-bus - the EMU10K2 chip has an effect bus containing 64 accumulators.
+         Each of the synthesizer voices can feed its output to these accumulators
+         and the DSP microcontroller can operate with the resulting sum.
+
+name='PCM Front Playback Volume',index=0
+
+This control is used to attenuate samples for left and right front PCM FX-bus
+accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM 
+samples for 5.1 playback. The result samples are forwarded to the front DAC PCM 
+slots of the Philips DAC.
+
+name='PCM Surround Playback Volume',index=0
+
+This control is used to attenuate samples for left and right surround PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM 
+samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM 
+slots of the Philips DAC.
+
+name='PCM Center Playback Volume',index=0
+
+This control is used to attenuate samples for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample
+is forwarded to the center DAC PCM slot of the Philips DAC.
+
+name='PCM LFE Playback Volume',index=0
+
+This control is used to attenuate sample for LFE PCM FX-bus accumulator. 
+ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample 
+is forwarded to the LFE DAC PCM slot of the Philips DAC.
+
+name='PCM Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
+stereo playback. The result samples are forwarded to the front DAC PCM slots 
+of the Philips DAC.
+
+name='PCM Capture Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Music Playback Volume',index=0
+
+This control is used to attenuate samples for left and right MIDI FX-bus
+accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Music Capture Volume',index=0
+
+These controls are used to attenuate samples for left and right MIDI FX-bus
+accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Mic Playback Volume',index=0
+
+This control is used to attenuate samples for left and right Mic input.
+For Mic input is used AC97 codec. The result samples are forwarded to 
+the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic
+capture FIFO (device 1 - 16bit/8KHz mono) too without volume control.
+
+name='Mic Capture Volume',index=0
+
+This control is used to attenuate samples for left and right Mic input.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Audigy CD Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the Philips DAC.
+
+name='Audigy CD Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='IEC958 Optical Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital input. The result samples are forwarded to the front DAC PCM slots
+of the Philips DAC.
+
+name='IEC958 Optical Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='Line2 Playback Volume',index=0
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC.
+
+name='Line2 Capture Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Analog Mix Playback Volume',index=0
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs from Philips ADC. The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC. This contains mix from analog sources
+like CD, Line In, Aux, ....
+
+name='Analog Mix Capture Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs Philips ADC. The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Aux2 Playback Volume',index=0
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC.
+
+name='Aux2 Capture Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Front Playback Volume',index=0
+
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate samples for left and right front speakers of
+this mix.
+
+name='Surround Playback Volume',index=0
+
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate samples for left and right surround speakers of
+this mix.
+
+name='Center Playback Volume',index=0
+
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate sample for center speaker of this mix.
+
+name='LFE Playback Volume',index=0
+
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate sample for LFE speaker of this mix.
+
+name='Tone Control - Switch',index=0
+
+This control turns the tone control on or off. The samples for front, rear
+and center / LFE outputs are affected.
+
+name='Tone Control - Bass',index=0
+
+This control sets the bass intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Tone Control - Treble',index=0
+
+This control sets the treble intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Master Playback Volume',index=0
+
+This control is used to attenuate samples for front, surround, center and 
+LFE outputs.
+
+name='IEC958 Optical Raw Playback Switch',index=0
+
+If this switch is on, then the samples for the IEC958 (S/PDIF) digital
+output are taken only from the raw FX8010 PCM, otherwise standard front
+PCM samples are taken.
+
+
+2) PCM stream related controls
+------------------------------
+
+name='EMU10K1 PCM Volume',index 0-31
+
+Channel volume attenuation in range 0-0xffff. The maximum value (no
+attenuation) is default. The channel mapping for three values is
+as follows:
+
+       0 - mono, default 0xffff (no attenuation)
+       1 - left, default 0xffff (no attenuation)
+       2 - right, default 0xffff (no attenuation)
+
+name='EMU10K1 PCM Send Routing',index 0-31
+
+This control specifies the destination - FX-bus accumulators. There 24
+values with this mapping:
+
+        0 -  mono, A destination (FX-bus 0-63), default 0
+        1 -  mono, B destination (FX-bus 0-63), default 1
+        2 -  mono, C destination (FX-bus 0-63), default 2
+        3 -  mono, D destination (FX-bus 0-63), default 3
+        4 -  mono, E destination (FX-bus 0-63), default 0
+        5 -  mono, F destination (FX-bus 0-63), default 0
+        6 -  mono, G destination (FX-bus 0-63), default 0
+        7 -  mono, H destination (FX-bus 0-63), default 0
+        8 -  left, A destination (FX-bus 0-63), default 0
+        9 -  left, B destination (FX-bus 0-63), default 1
+       10 -  left, C destination (FX-bus 0-63), default 2
+       11 -  left, D destination (FX-bus 0-63), default 3
+       12 -  left, E destination (FX-bus 0-63), default 0
+       13 -  left, F destination (FX-bus 0-63), default 0
+       14 -  left, G destination (FX-bus 0-63), default 0
+       15 -  left, H destination (FX-bus 0-63), default 0
+       16 - right, A destination (FX-bus 0-63), default 0
+       17 - right, B destination (FX-bus 0-63), default 1
+       18 - right, C destination (FX-bus 0-63), default 2
+       19 - right, D destination (FX-bus 0-63), default 3
+       20 - right, E destination (FX-bus 0-63), default 0
+       21 - right, F destination (FX-bus 0-63), default 0
+       22 - right, G destination (FX-bus 0-63), default 0
+       23 - right, H destination (FX-bus 0-63), default 0
+
+Don't forget that it's illegal to assign a channel to the same FX-bus accumulator 
+more than once (it means 0=0 && 1=0 is an invalid combination).
+name='EMU10K1 PCM Send Volume',index 0-31
+
+It specifies the attenuation (amount) for given destination in range 0-255.
+The channel mapping is following:
+
+        0 -  mono, A destination attn, default 255 (no attenuation)
+        1 -  mono, B destination attn, default 255 (no attenuation)
+        2 -  mono, C destination attn, default 0 (mute)
+        3 -  mono, D destination attn, default 0 (mute)
+        4 -  mono, E destination attn, default 0 (mute)
+        5 -  mono, F destination attn, default 0 (mute)
+        6 -  mono, G destination attn, default 0 (mute)
+        7 -  mono, H destination attn, default 0 (mute)
+        8 -  left, A destination attn, default 255 (no attenuation)
+        9 -  left, B destination attn, default 0 (mute)
+       10 -  left, C destination attn, default 0 (mute)
+       11 -  left, D destination attn, default 0 (mute)
+       12 -  left, E destination attn, default 0 (mute)
+       13 -  left, F destination attn, default 0 (mute)
+       14 -  left, G destination attn, default 0 (mute)
+       15 -  left, H destination attn, default 0 (mute)
+       16 - right, A destination attn, default 0 (mute)
+       17 - right, B destination attn, default 255 (no attenuation)
+       18 - right, C destination attn, default 0 (mute)
+       19 - right, D destination attn, default 0 (mute)
+       20 - right, E destination attn, default 0 (mute)
+       21 - right, F destination attn, default 0 (mute)
+       22 - right, G destination attn, default 0 (mute)
+       23 - right, H destination attn, default 0 (mute)
+
+
+
+4) MANUALS/PATENTS:
+-------------------
+
+ftp://opensource.creative.com/pub/doc
+-------------------------------------
+
+        Files:
+        LM4545.pdf      AC97 Codec
+
+        m2049.pdf       The EMU10K1 Digital Audio Processor
+
+        hog63.ps        FX8010 - A DSP Chip Architecture for Audio Effects
+
+
+WIPO Patents
+------------
+        Patent numbers:
+        WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
+                        streams
+
+        WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+
+        WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
+                        Execution and Audio Data Sequencing (Jan. 14, 1999)
+
+
+US Patents (http://www.uspto.gov/)
+----------------------------------
+
+        US 5925841      Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+        US 5928342      Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
+                        with a multiport memory onto which multiple asynchronous
+                        digital sound samples can be concurrently loaded
+
+        US 5930158      Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+        US 6032235      Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+        US 6138207      Interpolation looping of audio samples in cache connected to    (Oct. 24, 2000)
+                        system bus with prioritization and modification of bus transfers
+                        in accordance with loop ends and minimum block sizes
+
+        US 6151670      Method for conserving memory storage using a (Nov. 21, 2000)
+                        pool of  short term memory registers
+
+        US 6195715      Interrupt control for multiple programs communicating with      (Feb. 27, 2001)
+                        a common interrupt by associating programs to GP registers,
+                        defining interrupt register, polling GP registers, and invoking
+                        callback routine associated with defined interrupt register
diff --git a/ld10k1/doc/AudigyTRAM.txt b/ld10k1/doc/AudigyTRAM.txt
new file mode 100644 (file)
index 0000000..4bb2095
--- /dev/null
@@ -0,0 +1,39 @@
+TRAM setup:
+
+TCBS (0x44) and TCB (0x41) has same meaning as on SB Live
+
+Internal TRAM size is 0x4000
+Max external TRAM size is 0x100000 - as on SB Live
+
+Register description:
+
+0xdb - Internal TRAM Delay Base Address Counter
+0xde - External TRAM Delay Base Address Counter
+
+0x100 - 0x1ff - tram access control registers (?)
+       - only 5 bit valid 
+               bit :  4 - 0 - use log. compresion on write and read
+                          1 - use raw access - data from/to tram are read/wrote
+                              as 16 bit samples
+               bits : 321 - ???
+                      001 - read from tram
+                      010 - read from tram
+                      011 - write to tram + 0111, 1001
+                      100 - read from tram
+                      101 - read from tram
+                      110 - read from tram
+                      others - ?????
+               bit:   0 - 0 - normal mode
+                          1 - clear tram - set to data register valid address
+                              until TRAM counter reaches this address, reads from
+                              tram will return 0, then this flag is zeroed and
+                              tram is working in normal mode, working for read
+0x200 - 0x2ff - tram access data registers
+       - same as on SB Live
+0x300 - 0x3ff - tram access address registers
+       - address format - host: 32 bit offset 20 bit integer part + 12 bit fractional part
+         to set offset to 0x123(SB Live) - 0x123 << 11 (Audigy)
+       - address format - DSP: same as SB Live ???
+
+internal TRAM has index 0x00 - 0xbf
+external TRAM has index 0xc0 - 0xff
\ No newline at end of file
diff --git a/ld10k1/doc/Makefile.am b/ld10k1/doc/Makefile.am
new file mode 100644 (file)
index 0000000..20b3d22
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST = ld10k1_usage lo10k1_usage dl10k1_usage AudigyTRAM.txt README Audigy-mixer.txt
diff --git a/ld10k1/doc/README b/ld10k1/doc/README
new file mode 100644 (file)
index 0000000..c0d0017
--- /dev/null
@@ -0,0 +1,5 @@
+ld10k1_usage   - short command line help for ld10k1
+lo10k1_usage   - short command line help for lo10k1
+dl10k1_usage   - short command line help for dl10k1
+AudigyTRAM.txt - everythink what I know about TRAM on Audigy
+Audigy-mixer.txt - some info on audigy 1,2 mixer
\ No newline at end of file
diff --git a/ld10k1/doc/dl10k1_usage b/ld10k1/doc/dl10k1_usage
new file mode 100644 (file)
index 0000000..deddf85
--- /dev/null
@@ -0,0 +1,19 @@
+dl10k1 is dump loader
+You can load config  with ld10k1, lo10k1 and then make dump. This dum can be loaded without usage
+of ld10k1
+
+Parameters:
+
+-h or --help
+    Prints short help message
+
+-c num or --card num
+    Use card number num - dl10k1 will use device with name hw:0
+
+    example:
+       dl10k1 -c 1
+       Use card 1
+
+-d or --dump
+    File with dump
+
diff --git a/ld10k1/doc/ld10k1_usage b/ld10k1/doc/ld10k1_usage
new file mode 100644 (file)
index 0000000..58493c3
--- /dev/null
@@ -0,0 +1,36 @@
+ld10k1 is server part - linker - it must run to use loader
+There must be exactly one instance for one emu10k1 based card wich you want use.
+
+Parameters:
+
+-h or --help
+    Prints short help message
+    
+-c num or --card num
+    Use card number num - ld10k1 will use device with name hw:0
+    
+    example:
+       ld10k1 -c 1
+       Use card 1 
+       
+-p name or --pipe_name name
+    ld10k1 will listen on named socked name. This socket is used for communication with lo10k1.
+    Default is /tmp/.ld10k1_port
+
+-t size or --tram_size size
+    Initialize initial TRAM size to size size. Size is rounded up to next valid value. Size is in samples and
+    can be one of 0 - external tram is disabled, 1 - 16384, 2 - 32768, 3 - 65536, 4 - 131072, 5 - 262144,
+       6 -524288, 7 - 1048576, 8 - 1048576. For Audigy 1, Audigy 2 you need patch from patch directory,
+       because current ALSA version doesn't supports TRAM on these cards.
+
+    example:
+       ld10k1 -t 7
+
+-n or --network
+       ld10k1 default uses named socket, this switch to use network socket. You can use --port options to
+       define port to listen
+
+--port portnum
+       listen on port portnum.
+-d or --daemon
+       ld10k1 runs as daemon.
\ No newline at end of file
diff --git a/ld10k1/doc/lo10k1_usage b/ld10k1/doc/lo10k1_usage
new file mode 100644 (file)
index 0000000..69791ff
--- /dev/null
@@ -0,0 +1,245 @@
+lo10k1 is loader.
+
+Parameters:
+
+-h or --help
+    Prints short help message
+    
+-l patch_name or --list path_name
+    List some usefull informations about patch in file patch_name. lo10k1 uses patch produced by as10k1 from
+    alsatools package.
+    
+-p name or --pipe_name name
+    lo10k1 will use local named pipe with name name to communication with linker. Default is /tmp/.ld10k1_port
+
+-i or --info
+    Prints some info about card - not wery usefull
+    
+-a patch_name or --add patch_name
+    Loads patch from file patch_name to DSP
+
+-d num or --del num
+    Unloads patch with number num from DSP. Use option --debug 4 to obtain patch numbers.
+    
+--conadd conn_string
+    Connects patches between each others or to inputs or outputs.
+    Format of conn_string:
+       FX buses:
+       FX(f1, ...) - specify fx bus register f1 can be number or fx bus register name
+               Names can be optained by lo10k1 --debug 7
+           FX(1)
+           FX(1,2)
+           FX(FX_PCM_Left,FX_PCM_Right)
+           
+       Inputs:
+       IN(i1, ...) - specify input register i1 can be number or input register name
+               Names can be optained by lo10k1 --debug 8
+           IN(1)
+           IN(1,2)
+           IN(IN_AC97_Left,IN_AC97_Right)
+
+       Outputs:
+       OUT(o1, ...) - specify input register o1 can be number or input register name
+               Names can be optained by lo10k1 --debug 9
+           OUT(1)
+           OUT(1,2)
+           OUT(OUT_AC97_Front_Left,OUT_AC97_Front_Right)
+           
+       Patch inputs:
+       PIN(p, i1, ...) - p is patch number or patch name, i1 is input register i1 can be number or input register name
+               Patch numbers and names can be optained by lo10k1 --debug 5
+               Names can be optained by lo10k1 --debug patch_num
+           PIN(1) - all patch inputs for patch 1
+           PIN(Volume,IL,IL) - inputs IL and IR for patch Volume
+           PIN(2,0,1,2,3,4,5) - inputs 0,1,2,3,4,5 patch 2
+           
+       Patch outputs:
+       POUT(p, o1, ...) - p is patch number or patch name, o1 is output register o1 can be number or outpur register name
+               Patch numbers and names can be optained by lo10k1 --debug 5
+               Names can be optained by lo10k1 --debug patch_num
+           POUT(1) - all patch outputs for patch 1
+           POUT(Volume,OL,OL) - outputs OL and OR for patch Volume
+           POUT(2,0,1,2,3,4,5) - outputs 0,1,2,3,4,5 patch 2
+
+       
+       - connecting two patches:
+           something1=something2
+           or
+               something1:something2
+           or
+           something1>something2
+               something1,something2 - strings specify fx bus, input, output, patch input or patch output
+               something1 - must be patch input or output
+
+           Difference between = and > is that = connect only two patches > enables connecting more
+           patches together. If you have three patches p1,p2,p3 - p1 with output o1, p2 with input i2,
+           and p3 with input i3.
+           PIN(p2,i2)=POUT(p1,o1) - will connect p1 with p2
+           then next connect
+           PIN(p3,i3)=POUT(p1,o1) - will disconnect p1 and p2 and connect p1 with p2
+           but
+           PIN(p3,i3)>POUT(p1,o1) - will connect p1 and p2 - p2 input i2 and p3 input i3 will be connected
+           to p1 output o1
+
+               Diffrence between = and : is that = allocate extra instructions and register to properly add
+               sources. : uses same register for all sources and patches must care about this register.
+
+           Counts of connected inputs and outputs must be same.
+
+           FX busses, inputs and outputs can have multiple patches connected to them.
+           Examples:
+           lo10k1 --conadd "PIN(1)=FX(0,1)"
+               - connect to patch 1 input to fx bus 0 and 1
+
+           lo10k1 --conadd "PIN(2)=POUT(PCM)"
+               - connect to all patch 2 inputs all outputs from patch PCM
+
+
+--condel conndel_string
+    Disconnects patch register.
+    Format of conndel_string:
+       something
+               something - strings specify patch input or patch output
+               
+       Examples:
+           lo10k1 --condel "PIN(1)"
+               - disconnect all inputs of patch 1
+               
+           lo10k1 --condel "POUT(PCM1,1,Center))"
+               - disconnect output 1 and Center from patch PCM
+
+--debug num
+    Prints on console some debug information. 
+    mum = 1 - prints registers information
+    mum = 2 - prints consts information
+    mum = 3 - prints instruction information
+    mum = 4 - prints information about TRAM
+    mum = 5 - prints loaded patch names and numbers
+    mum = 6 - prints patch order in DSP instruction memory
+    mum = 7 - prints fx information
+    mum = 8 - prints input information
+    mum = 9 - prints output information
+    mum = 100 and more - prints informations about loaded patches (--debug 100 - about patch number 0,
+       -- debug 101 about patch number 1, and so on)
+       
+--defionames
+    When patch is loaded, this assign default names for patch input and output registers.
+    Input/Output count:
+       1/1 - In/Out
+       2/2 - IL,IR/OL,OR
+       4/4 - IL,IR,IRL,IRR/OL,OR,ORL,ORR
+       6/6 - IL,IR,IRL,IRR,IC,ILFE/OL,OR,ORL,ORR,OC,OLFE
+    where:
+       In = Input
+       On = Output
+       IL = Input Left
+       OL = Output Left
+       IR = Input Right
+       OR = Output Right
+       IRL = Input Rear Left
+       ORL = Output Rear Left
+       IRR = Input Rear Right
+       ORR = Output Rear Right
+       IC = Input Center
+       OC = Output Center
+       ILFE = Input LFE
+       OLFE = Output LFE
+       
+--ctrl string
+    This options is used to concate, rename controls and sets various parameters for controls
+    String format:
+
+       c-name1,name2,...namen:outname
+
+       This concate controls with names name1, name2, ..namen to one control with name outname
+       Input controls must have same range and are single channel (this is limitation of as10k1).
+       Output control has n channes. This can be used only for as10k1 file format.
+
+       example:
+           c-masterl,masterr:master,t-master:1
+
+           Concate two controls masterl and masterr into one stereo control master with translaton table100
+
+       t-name:type
+
+       This sets translate function whitch translate range and current value from mixer value to gpr
+       value for control with name name. This can be used only for as10k1 file format.
+       Type can be:
+           0 - no translation is used
+           1 - table 100 - range 0-100 in mixer is translated to range 0-2^31
+           2 - bass - range 0-40 in mixer is translated to range 0-2^31 - used for bass control
+           3 - treble - range 0-40 in mixer is translated to range 0-2^31 - used for treble control
+           4 - on/off - control uses range 0-1
+
+       v-name:count
+
+       This sets number off visible channel in mixer. This can be used only for as10k1 file format.
+       
+       example:
+            v-bass:1
+
+            for bass control which has 5 channels is in mixer visible only one
+
+       s-name:value1#value2# ...
+
+       This sets initial value for control.
+       
+       i-name:value
+
+       Sets control index value to control
+       
+       r-name:outname
+
+       This rename control with name name to control with name outname. This can be used only for native file format.
+       
+       example:
+           r-master:PCM Master
+
+           Rename control master to control PCM Master
+           
+--patch_name name
+    Sets name for actualy loaded patch (it is used with -a option). Dafault name comes from patch file.
+
+--where num
+    Used with -a option. Actualy loaded path will by loaded before patch with order num.
+    You can get patch order with --debug 5
+    
+--setup
+    When this option is used DSP on card is cleared.
+       
+--renam something=new_name
+    Same string as in connection add and plus PATCH(p) - specify patch with name p or number p
+    
+    Examples:
+    lo10k1 --renam "IN(5)=CD Left"
+       - renames input 5 to CD Left
+       
+    lo10k1 --renam "PATCH(Volume)=Mic Volume"
+       - renames patch Volume to Mic Volume
+       
+    lo10k1 --renam "PIN(Volume,IC)=Center IN"
+       - renames patch Volume input IL to Center IN
+
+--dump file
+       This will dump dsp instructions and register to file. This file can be loaded with dl10k1 without
+       ld10k1.
+
+--host machine:port
+       ld10k1 default uses named socket, this switch to use network socket.
+
+-P or --path add effect search paths (default will lo10k1 search in effects dir)
+
+--store file.ld10k1
+       Stores DSP config to native ld10k1 file file.ld10k1
+
+--restore file.ld10k1
+       Restores DSP config from native ld10k1 file file.ld10k1
+       
+--save_patch file.ld10k1
+       Saves patch specified with --where option to file file.ld10k1
+       
+--load_patch file.ld10k1
+       Loads patch to dsp on position specified with --where option from file file.ld10k1
+       
+--wait msec
+       Wait for ld10k1 for msec mili second.
\ No newline at end of file
diff --git a/ld10k1/dump/Makefile.am b/ld10k1/dump/Makefile.am
new file mode 100644 (file)
index 0000000..4970035
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST = README audigy.dl10k1 audigy_ms.dl10k1
diff --git a/ld10k1/dump/README b/ld10k1/dump/README
new file mode 100644 (file)
index 0000000..c80aa06
--- /dev/null
@@ -0,0 +1,4 @@
+audigy_ms.dl10k1 - dump with default configuration + mute switches + capture switches + headphone
+               You can load this with dl10k1 -d audigy_ms.dl10k1
+audigy.dl10k1 - dump with default configuration + headphone
+               You can load this with dl10k1 -d audigy_p.dl10k1
diff --git a/ld10k1/dump/audigy.dl10k1 b/ld10k1/dump/audigy.dl10k1
new file mode 100644 (file)
index 0000000..a3ff9f1
Binary files /dev/null and b/ld10k1/dump/audigy.dl10k1 differ
diff --git a/ld10k1/dump/audigy_ms.dl10k1 b/ld10k1/dump/audigy_ms.dl10k1
new file mode 100644 (file)
index 0000000..b49cffd
Binary files /dev/null and b/ld10k1/dump/audigy_ms.dl10k1 differ
diff --git a/ld10k1/include/Makefile.am b/ld10k1/include/Makefile.am
new file mode 100644 (file)
index 0000000..f9e8bc9
--- /dev/null
@@ -0,0 +1,33 @@
+lo10k1includedir = $(includedir)/lo10k1
+lo10k1include_HEADERS = version.h comm.h liblo10k1.h liblo10k1ef.h ld10k1_error.h ld10k1_fnc.h liblo10k1lf.h lo10k1.h
+
+INCLUDES = -I$(top_srcdir)/include
+
+#taken from alsa-lib - start
+CLEANFILES = stamp-vh version.h lo10k1
+
+version.h: stamp-vh
+       @:
+
+stamp-vh: $(top_builddir)/configure.in
+       @echo "/*" > ver.tmp
+       @echo " *  version.h" >> ver.tmp
+       @echo " */" >> ver.tmp
+       @echo "" >> ver.tmp
+       @echo "#define LD10K1_LIB_MAJOR         $(LD10K1_LIB_MAJOR) /**< major number of library version */" >> ver.tmp
+       @echo "#define LD10K1_LIB_MINOR         $(LD10K1_LIB_MINOR) /**< minor number of library version */" >> ver.tmp
+       @echo "#define LD10K1_LIB_SUBMINOR      $(LD10K1_LIB_SUBMINOR) /**< subminor number of library version */" >> ver.tmp
+       @echo "/** library version */" >> ver.tmp
+       @echo "#define LD10K1_LIB_VERSION               ((LD10K1_LIB_MAJOR<<16)|\\" >> ver.tmp
+       @echo "                                  (LD10K1_LIB_MINOR<<8)|\\" >> ver.tmp
+       @echo "                                  LD10K1_LIB_SUBMINOR)" >> ver.tmp
+       @echo "/** library version (string) */" >> ver.tmp
+       @echo "#define LD10K1_LIB_VERSION_STR   \"$(LD10K1_LIB_VERSION)\"" >> ver.tmp
+       @echo >> ver.tmp
+       @cmp -s version.h ver.tmp \
+          || (echo "Updating version.h"; \
+              cp ver.tmp version.h; \
+              echo timestamp > stamp-vh)
+       -@rm -f ver.tmp
+
+#taken from alsa-lib - end
\ No newline at end of file
diff --git a/ld10k1/include/comm.h b/ld10k1/include/comm.h
new file mode 100644 (file)
index 0000000..2293aaa
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef __COMM_H
+#define __COMM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct msg_req
+{
+       int op;
+       int size;
+};
+
+struct msg_resp
+{
+       int op;
+       int err;
+       int size;
+};
+
+#define COMM_TYPE_LOCAL 0
+#define COMM_TYPE_IP 1
+
+typedef struct
+{
+       int type;
+       int server;
+       char *name;
+       unsigned short port;
+       int wfc;
+} comm_param;
+
+int setup_comm(comm_param *param);
+int connect_comm(int conn_num, comm_param *param);
+int listen_comm(int conn_num);
+int accept_comm(int conn_num);
+int free_comm(int conn_num);
+int send_request(int conn_num, int op, void *data, int data_size);
+int send_response(int conn_num, int op, int err, void *data, int data_size);
+int send_msg_data(int conn_num, void *data, int data_size);
+int receive_request(int conn_num, int *op, int *data_size);
+int receive_response(int conn_num, int *op, int *data_size);
+int receive_msg_data(int conn_num, void *data, int data_size);
+void *receive_msg_data_malloc(int conn_num, int data_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __COMM_H */
diff --git a/ld10k1/include/ld10k1_error.h b/ld10k1/include/ld10k1_error.h
new file mode 100644 (file)
index 0000000..a36ba78
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __LD10K1_ERROR_H
+#define __LD10K1_ERROR_H
+
+#define LD10K1_ERR_UNKNOWN -1 /* unknown error */
+#define LD10K1_ERR_COMM_READ -2 /* errorn in read from socket */
+#define LD10K1_ERR_COMM_WRITE -3 /* error in write to socket */
+#define LD10K1_ERR_UNKNOWN_PATCH_NUM -4 /* wrong parameter - patch with this num doesn't exists */
+#define LD10K1_ERR_PROTOCOL -5 /* ld10k1 is expecting more or less data as it got */
+#define LD10K1_ERR_COMM_CONN -29 /*  */
+
+#define LD10K1_ERR_PROTOCOL_IN_COUNT -6 /* */
+#define LD10K1_ERR_PROTOCOL_OUT_COUNT -7 /* */
+#define LD10K1_ERR_PROTOCOL_CONST_COUNT -8 /* */
+#define LD10K1_ERR_PROTOCOL_STATIC_COUNT -9 /* */
+#define LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT -10 /* */
+#define LD10K1_ERR_PROTOCOL_HW_COUNT -11 /* */
+#define LD10K1_ERR_PROTOCOL_TRAM_COUNT -12 /* */
+#define LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT -13 /* */
+#define LD10K1_ERR_PROTOCOL_CTL_COUNT -14 /* */
+#define LD10K1_ERR_PROTOCOL_INSTR_COUNT -15 /* */
+
+/* driver */
+#define LD10K1_ERR_DRIVER_CODE_POKE -16 /* unable to poke code */
+#define LD10K1_ERR_DRIVER_INFO -17 /* unable to get info */
+#define LD10K1_ERR_DRIVER_CODE_PEEK -18 /* unable to peek code */
+#define LD10K1_ERR_DRIVER_PCM_POKE -19 /* unable to poke pcm */
+
+/* tram */
+#define LD10K1_ERR_ITRAM_FULL -20 /* not enought free itram */
+#define LD10K1_ERR_ETRAM_FULL -21 /* not enought free etram */
+#define LD10K1_ERR_TRAM_FULL -22 /* not enought free tram */
+#define LD10K1_ERR_TRAM_FULL_GRP -23 /* not enought free tram group */
+
+#define LD10K1_ERR_ITRAM_FULL_ACC -25 /* not enought free itram acc */
+#define LD10K1_ERR_ETRAM_FULL_ACC -26 /* not enought free etram acc */
+#define LD10K1_ERR_TRAM_FULL_ACC -27 /* not enought free tram acc */
+
+#define LD10K1_ERR_MAX_CON_PER_POINT -28 /* maximum connections per point reached */
+
+/* others */
+#define LD10K1_ERR_NO_MEM -30 /* not enought free mem */
+#define LD10K1_ERR_MAX_PATCH_COUNT -31 /* max patch count excesed */
+#define LD10K1_ERR_NOT_FREE_REG -32 /* there is not free reg */
+#define LD10K1_ERR_NOT_FREE_INSTR -34 /* there is no free instruction slot */
+
+/* patch chceck */
+#define LD10K1_ERR_WRONG_REG_HW_INDEX -36 /*  */
+#define LD10K1_ERR_WRONG_TRAM_POS -37 /*  */
+
+#define LD10K1_ERR_WRONG_TRAM_TYPE -39 /*  */
+#define LD10K1_ERR_WRONG_TRAM_SIZE -40 /*  */
+#define LD10K1_ERR_WRONG_TRAM_ACC_TYPE -41 /*  */
+
+#define LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE -42 /*  */
+#define LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE -43 /*  */
+
+#define LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE -48 /*  */
+#define LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE -49 /*  */
+
+#define LD10K1_ERR_CTL_MIN_MAX_RANGE -50 /*  */
+#define LD10K1_ERR_CTL_TRANLSLATION -51 /*  */
+#define LD10K1_ERR_CTL_REG_INDEX -52 /*  */
+#define LD10K1_ERR_CTL_REG_VALUE -53 /*  */
+
+#define LD10K1_ERR_INSTR_OPCODE -54 /*  */
+#define LD10K1_ERR_INSTR_ARG_INDEX -56 /*  */
+
+#define LD10K1_ERR_UNKNOWN_REG_NUM -57 /* */
+#define LD10K1_ERR_UNKNOWN_PATCH_REG_NUM -58 /* */
+
+#define LD10K1_ERR_CONNECTION -59 /* can't connect */
+#define LD10K1_ERR_CONNECTION_FNC -60 /* wrong connection funcion requested */
+
+#define LD10K1_ERR_CTL_EXISTS -61 /*  */
+
+#define LD10K1_ERR_PATCH_RENAME -62 /*  */
+#define LD10K1_ERR_PATCH_REG_RENAME -63 /*  */
+#define LD10K1_ERR_REG_RENAME -64 /*  */
+#define LD10K1_ERR_WRONG_VER -65 /* wrong ld10k1 <=> lo10k1 version */
+
+#define LD10K1_ERR_UNKNOWN_POINT -66 /*  */
+
+#endif /* __LD10K1_ERROR_H */
diff --git a/ld10k1/include/ld10k1_fnc.h b/ld10k1/include/ld10k1_fnc.h
new file mode 100644 (file)
index 0000000..b027336
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __LD10K1_FNC_H
+#define __LD10K1_FNC_H
+
+#define MAX_NAME_LEN 256
+#define MAX_CTL_GPR_COUNT 32
+#define EMU10K1_GPR_TRANSLATION_LAST EMU10K1_GPR_TRANSLATION_ONOFF
+
+#define EMU10K1_REG_TYPE_NONE 0
+#define EMU10K1_REG_TYPE_FX 1
+#define EMU10K1_REG_TYPE_INPUT 2
+#define EMU10K1_REG_TYPE_OUTPUT 3
+#define EMU10K1_REG_TYPE_HW 4
+#define EMU10K1_REG_TYPE_TRAM_CTL 5 /* only on Audigy */
+#define EMU10K1_REG_TYPE_TRAM_DATA 6
+#define EMU10K1_REG_TYPE_TRAM_ADDR 7
+#define EMU10K1_REG_TYPE_NORMAL 8
+#define EMU10K1_REG_TYPE_CONST 9
+#define EMU10K1_REG_TYPE_ALL 10
+#define EMU10K1_REG_TYPE_NAMED 11
+
+#define EMU10K1_REG_TYPE_MASK 0xF0000000
+
+/* access macros */
+#define EMU10K1_REG_TYPE(type) (((type) << 28) & EMU10K1_REG_TYPE_MASK)
+#define EMU10K1_REG_TYPE_B(type) (((type) & EMU10K1_REG_TYPE_MASK) >> 28)
+#define EMU10K1_REG_FX(fxnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_FX) | ((fxnum) & 0x3F))
+#define EMU10K1_REG_IN(innum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_INPUT) | ((innum) & 0x1F))
+#define EMU10K1_REG_OUT(outnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_OUTPUT) | ((outnum) & 0x3F))
+#define EMU10K1_REG_HW(hwnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_HW) | ((hwnum) & 0x3F))
+#define EMU10K1_REG_TRAM_CTL(ctlnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_CTL) | ((ctlnum) & 0xFF))
+#define EMU10K1_REG_TRAM_DATA(datanum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_DATA) | ((datanum) & 0xFF))
+#define EMU10K1_REG_TRAM_ADDR(addrnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_ADDR) | ((addrnum) & 0xFF))
+#define EMU10K1_REG_NORMAL(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_NORMAL) | ((num) & 0x1FF))
+#define EMU10K1_REG_CONST(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_CONST) | ((num) & 0x2ff))
+#define EMU10K1_REG_ALL(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_ALL) | ((num) & 0x7FF))
+#define EMU10K1_REG_NAMED(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_ALL) | ((num) & 0xFFFFFFF))
+
+/* this will not be changed */
+/* FX buses */
+#define EMU10K1_NREG_FXBUS_PCM_LEFT                    EMU10K1_REG_NAMED(0x0000)
+#define EMU10K1_NREG_FXBUS_PCM_RIGHT           EMU10K1_REG_NAMED(0x0001)
+#define EMU10K1_NREG_FXBUS_PCM_FRONT_LEFT      EMU10K1_REG_NAMED(0x0002)
+#define EMU10K1_NREG_FXBUS_PCM_FRONT_RIGHT     EMU10K1_REG_NAMED(0x0003)
+#define EMU10K1_NREG_FXBUS_PCM_REAR_LEFT       EMU10K1_REG_NAMED(0x0004)
+#define EMU10K1_NREG_FXBUS_PCM_REAR_RIGHT      EMU10K1_REG_NAMED(0x0005)
+#define EMU10K1_NREG_FXBUS_PCM_CENTER          EMU10K1_REG_NAMED(0x0006)
+#define EMU10K1_NREG_FXBUS_PCM_LFE                     EMU10K1_REG_NAMED(0x0007)
+#define EMU10K1_NREG_FXBUS_MIDI_LEFT           EMU10K1_REG_NAMED(0x0008)
+#define EMU10K1_NREG_FXBUS_MIDI_RIGHT          EMU10K1_REG_NAMED(0x0009)
+#define EMU10K1_NREG_FXBUS_MIDI_REVERB         EMU10K1_REG_NAMED(0x000A)
+#define EMU10K1_NREG_FXBUS_MIDI_CHORUS         EMU10K1_REG_NAMED(0x000B)
+
+#define EMU10K1_A_NREG_FXBUS_PT_LEFT           EMU10K1_REG_NAMED(0x000C)
+#define EMU10K1_A_NREG_FXBUS_PT_RIGHT          EMU10K1_REG_NAMED(0x000D)
+
+/* inputs */
+#define EMU10K1_NREG_IN_AC97_LEFT                      EMU10K1_REG_NAMED(0x0100)
+#define EMU10K1_NREG_IN_AC97_RIGHT                     EMU10K1_REG_NAMED(0x0101)
+#define EMU10K1_NREG_IN_SPDIF_CD_LEFT          EMU10K1_REG_NAMED(0x0102)
+#define EMU10K1_NREG_IN_SPDIF_CD_RIGHT         EMU10K1_REG_NAMED(0x0103)
+#define EMU10K1_NREG_IN_SPDIF_OPT_LEFT         EMU10K1_REG_NAMED(0x0104)
+#define EMU10K1_NREG_IN_SPDIF_OPT_RIGHT                EMU10K1_REG_NAMED(0x0105)
+#define EMU10K1_NREG_IN_I2S_1_LEFT                     EMU10K1_REG_NAMED(0x0106)
+#define EMU10K1_NREG_IN_I2S_1_RIGHT                    EMU10K1_REG_NAMED(0x0107)
+#define EMU10K1_NREG_IN_I2S_2_LEFT                     EMU10K1_REG_NAMED(0x0108)
+#define EMU10K1_NREG_IN_I2S_2_RIGHT                    EMU10K1_REG_NAMED(0x0109)
+
+#define EMU10K1_L_NREG_IN_SPDIF_COAX_LEFT      EMU10K1_REG_NAMED(0x010A)
+#define EMU10K1_L_NREG_IN_SPDIF_COAX_RIGHT     EMU10K1_REG_NAMED(0x010B)
+#define EMU10K1_L_NREG_IN_ZOOM_LEFT                    EMU10K1_REG_NAMED(0x010C)
+#define EMU10K1_L_NREG_IN_ZOOM_RIGHT           EMU10K1_REG_NAMED(0x010D)
+#define EMU10K1_L_NREG_IN_LINE_1_LEFT          EMU10K1_REG_NAMED(0x010E)
+#define EMU10K1_L_NREG_IN_LINE_1_RIGHT         EMU10K1_REG_NAMED(0x010F)
+#define EMU10K1_L_NREG_IN_LINE_2_LEFT          EMU10K1_REG_NAMED(0x0110)
+#define EMU10K1_L_NREG_IN_LINE_2_RIGHT         EMU10K1_REG_NAMED(0x0111)
+
+#define EMU10K1_A_NREG_IN_LINE_1_LEFT          EMU10K1_REG_NAMED(0x0112)
+#define EMU10K1_A_NREG_IN_LINE_1_RIGHT         EMU10K1_REG_NAMED(0x0113)
+#define EMU10K1_A_NREG_IN_LINE_2_LEFT          EMU10K1_REG_NAMED(0x0114)
+#define EMU10K1_A_NREG_IN_LINE_2_RIGHT         EMU10K1_REG_NAMED(0x0115)
+#define EMU10K1_A_NREG_IN_LINE_3_LEFT          EMU10K1_REG_NAMED(0x0116)
+#define EMU10K1_A_NREG_IN_LINE_3_RIGHT         EMU10K1_REG_NAMED(0x0117)
+/* outputs */
+#define EMU10K1_NREG_OUT_FRONT_LEFT                    EMU10K1_REG_NAMED(0x0200)
+#define EMU10K1_NREG_OUT_FRONT_RIGHT           EMU10K1_REG_NAMED(0x0201)
+#define EMU10K1_NREG_OUT_REAR_LEFT                     EMU10K1_REG_NAMED(0x0202)
+#define EMU10K1_NREG_OUT_REAR_RIGHT                    EMU10K1_REG_NAMED(0x0203)
+#define EMU10K1_NREG_OUT_CENTER                                EMU10K1_REG_NAMED(0x0204)
+#define EMU10K1_NREG_OUT_LFE                           EMU10K1_REG_NAMED(0x0205)
+#define EMU10K1_NREG_OUT_AC97_LEFT                     EMU10K1_REG_NAMED(0x0206)
+#define EMU10K1_NREG_OUT_AC97_RIGHT                    EMU10K1_REG_NAMED(0x0207)
+#define EMU10K1_NREG_OUT_ADC_LEFT                      EMU10K1_REG_NAMED(0x0208)
+#define EMU10K1_NREG_OUT_ADC_RIGHT                     EMU10K1_REG_NAMED(0x0209)
+#define EMU10K1_NREG_OUT_MIC                           EMU10K1_REG_NAMED(0x020A)
+#define EMU10K1_NREG_OUT_HEADPHONE_LEFT                EMU10K1_REG_NAMED(0x020B)
+#define EMU10K1_NREG_OUT_HEADPHONE_RIGHT       EMU10K1_REG_NAMED(0x020C)
+
+#define EMU10K1_L_NREG_OUT_OPT_LEFT                    EMU10K1_REG_NAMED(0x020D)
+#define EMU10K1_L_NREG_OUT_OPT_RIGHT           EMU10K1_REG_NAMED(0x020E)
+
+#define EMU10K1_A_NREG_OUT_D_FRONT_LEFT                EMU10K1_REG_NAMED(0x020F)
+#define EMU10K1_A_NREG_OUT_D_FRONT_RIGHT       EMU10K1_REG_NAMED(0x0210)
+#define EMU10K1_A_NREG_OUT_D_REAR_LEFT         EMU10K1_REG_NAMED(0x0211)
+#define EMU10K1_A_NREG_OUT_D_REAR_RIGHT                EMU10K1_REG_NAMED(0x0212)
+#define EMU10K1_A_NREG_OUT_D_CENTER                    EMU10K1_REG_NAMED(0x0213)
+#define EMU10K1_A_NREG_OUT_D_LFE                       EMU10K1_REG_NAMED(0x0214)
+
+/* hardware */
+#define EMU10K1_NREG_CONST_00000000                    EMU10K1_REG_NAMED(0x0300)
+#define EMU10K1_NREG_CONST_00000001                    EMU10K1_REG_NAMED(0x0301)
+#define EMU10K1_NREG_CONST_00000002                    EMU10K1_REG_NAMED(0x0302)
+#define EMU10K1_NREG_CONST_00000003                    EMU10K1_REG_NAMED(0x0303)
+#define EMU10K1_NREG_CONST_00000004                    EMU10K1_REG_NAMED(0x0304)
+#define EMU10K1_NREG_CONST_00000008                    EMU10K1_REG_NAMED(0x0305)
+#define EMU10K1_NREG_CONST_00000010                    EMU10K1_REG_NAMED(0x0306)
+#define EMU10K1_NREG_CONST_00000020                    EMU10K1_REG_NAMED(0x0307)
+#define EMU10K1_NREG_CONST_00000100                    EMU10K1_REG_NAMED(0x0308)
+#define EMU10K1_NREG_CONST_00010000                    EMU10K1_REG_NAMED(0x0309)
+#define EMU10K1_L_NREG_CONST_00080000          EMU10K1_REG_NAMED(0x030A)
+#define EMU10K1_A_NREG_CONST_00000800          EMU10K1_REG_NAMED(0x030B)
+#define EMU10K1_NREG_CONST_10000000                    EMU10K1_REG_NAMED(0x030C)
+#define EMU10K1_NREG_CONST_20000000                    EMU10K1_REG_NAMED(0x030D)
+#define EMU10K1_NREG_CONST_40000000                    EMU10K1_REG_NAMED(0x030E)
+#define EMU10K1_NREG_CONST_80000000                    EMU10K1_REG_NAMED(0x030F)
+#define EMU10K1_NREG_CONST_7FFFFFFF                    EMU10K1_REG_NAMED(0x0310)
+#define EMU10K1_NREG_CONST_FFFFFFFF                    EMU10K1_REG_NAMED(0x0311)
+#define EMU10K1_NREG_CONST_FFFFFFFE                    EMU10K1_REG_NAMED(0x0312)
+#define EMU10K1_NREG_CONST_C0000000                    EMU10K1_REG_NAMED(0x0313)
+#define EMU10K1_NREG_CONST_4F1BBCDC                    EMU10K1_REG_NAMED(0x0314)
+#define EMU10K1_NREG_CONST_5A7EF9DB                    EMU10K1_REG_NAMED(0x0315)
+#define EMU10K1_NREG_CONST_00100000                    EMU10K1_REG_NAMED(0x0316)
+
+#define EMU10K1_NREG_HW_ACCUM                          EMU10K1_REG_NAMED(0x0317)
+#define EMU10K1_NREG_HW_CCR                                    EMU10K1_REG_NAMED(0x0318)
+#define EMU10K1_NREG_HW_NOISE1                         EMU10K1_REG_NAMED(0x0319)
+#define EMU10K1_NREG_HW_NOISE2                         EMU10K1_REG_NAMED(0x031A)
+#define EMU10K1_NREG_HW_IRQ                                    EMU10K1_REG_NAMED(0x031B)
+#define EMU10K1_NREG_HW_DBAC                           EMU10K1_REG_NAMED(0x031C)
+#define EMU10K1_A_NREG_HW_DBACE                                EMU10K1_REG_NAMED(0x031D)
+
+/* patch registers */
+#define EMU10K1_PREG_TYPE_IN 1
+#define EMU10K1_PREG_TYPE_OUT 2
+#define EMU10K1_PREG_TYPE_CONST 3
+#define EMU10K1_PREG_TYPE_STA 4
+#define EMU10K1_PREG_TYPE_DYN 5
+#define EMU10K1_PREG_TYPE_HW 6
+#define EMU10K1_PREG_TYPE_CTL 7
+#define EMU10K1_PREG_TYPE_TRAM_DATA 8
+#define EMU10K1_PREG_TYPE_TRAM_ADDR 9
+
+#define EMU10K1_PREG_TYPE_MASK 0xF0000000
+
+/* access macros */
+#define EMU10K1_PREG_TYPE(type) (((type) << 28) & EMU10K1_PREG_TYPE_MASK)
+#define EMU10K1_PREG_TYPE_B(type) (((type) & EMU10K1_PREG_TYPE_MASK) >> 28)
+#define EMU10K1_PREG_IN(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_IN) | ((num) & 0x1F))
+#define EMU10K1_PREG_OUT(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_OUT) | ((num) & 0x1F))
+#define EMU10K1_PREG_CONST(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_CONST) | ((num) & 0xFF))
+#define EMU10K1_PREG_STA(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_STA) | ((num) & 0xFF))
+#define EMU10K1_PREG_DYN(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_DYN) | ((num) & 0xFF))
+#define EMU10K1_PREG_HW(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_HW) | ((num) & 0xFF))
+#define EMU10K1_PREG_CTL(ctlnum, num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_CTL) | (((ctlnum) & 0xFF) << 8) | ((num) & 0xFF))
+#define EMU10K1_PREG_TRAM_DATA(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_TRAM_DATA) | ((num) & 0xFF))
+#define EMU10K1_PREG_TRAM_ADDR(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_TRAM_ADDR) | ((num) & 0xFF))
+
+typedef struct {
+       char name[MAX_NAME_LEN];
+} ld10k1_dsp_p_in_out_t;
+
+typedef struct {
+       unsigned int const_val;
+} ld10k1_dsp_p_const_static_t;
+
+typedef struct {
+       unsigned int hw_val;
+} ld10k1_dsp_p_hw_t;
+
+
+#define EMU10K1_GPR_TRANSLATION_NONE           0
+#define EMU10K1_GPR_TRANSLATION_TABLE100       1
+#define EMU10K1_GPR_TRANSLATION_BASS           2
+#define EMU10K1_GPR_TRANSLATION_TREBLE         3
+#define EMU10K1_GPR_TRANSLATION_ONOFF          4
+
+typedef struct {
+       char name[44];
+       int index;                      /* -1 - auto choose index */
+       unsigned int vcount;            /* count of GPR (1..32) */
+       unsigned int count;                     /* count of GPR (1..32) */
+       unsigned int value[MAX_CTL_GPR_COUNT];
+       unsigned int min;                       /* minimum range */
+       unsigned int max;                       /* maximum range */
+       unsigned int translation;
+} ld10k1_dsp_ctl_t;
+
+typedef struct {
+       unsigned int op_code;
+       unsigned int arg[4];
+} ld10k1_dsp_instr_t;
+
+#define TRAM_GRP_DELAY 1
+#define TRAM_GRP_TABLE 2
+
+#define TRAM_POS_NONE 0
+#define TRAM_POS_AUTO 1
+#define TRAM_POS_INTERNAL 2
+#define TRAM_POS_EXTERNAL 3
+
+typedef struct {
+       unsigned int grp_type;
+       unsigned int grp_size;
+       unsigned int grp_pos;
+} ld10k1_dsp_tram_grp_t;
+
+#define TRAM_ACC_READ 1
+#define TRAM_ACC_WRITE 2
+#define TRAM_ACC_ZERO 4
+
+typedef struct {
+       unsigned int acc_type;
+       unsigned int acc_offset;
+       unsigned int grp;
+} ld10k1_dsp_tram_acc_t;
+
+typedef struct {
+       char patch_name[MAX_NAME_LEN];
+       int id;
+       unsigned int in_count;
+       unsigned int out_count;
+       unsigned int const_count;
+       unsigned int static_count;
+       unsigned int dynamic_count;
+       unsigned int hw_count;
+       unsigned int tram_count;
+       unsigned int tram_acc_count;
+       unsigned int ctl_count;
+       unsigned int instr_count;
+} ld10k1_dsp_patch_t;
+
+
+#define CON_IO_FX 'F'
+#define CON_IO_IN 'I'
+#define CON_IO_OUT 'O'
+#define CON_IO_PIN 'A'
+#define CON_IO_POUT 'B'
+#define CON_IO_NORMAL '\0'
+
+/* must be changed in ld10k1.h too */
+#define POINT_MAX_CONN_PER_POINT 15
+typedef struct {
+       int id;
+       int type;
+       int io_idx;
+       int simple;
+       int multi;
+       unsigned int conn_count;
+       int io_type[POINT_MAX_CONN_PER_POINT];
+       int patch[POINT_MAX_CONN_PER_POINT];
+       int io[POINT_MAX_CONN_PER_POINT];
+} ld10k1_dsp_point_t;
+
+typedef struct {
+       int where;
+       ld10k1_dsp_patch_t patch;
+} ld10k1_fnc_patch_add_t;
+
+typedef struct {
+       int where;
+} ld10k1_fnc_patch_del_t;
+
+typedef struct {
+       int what;
+       int multi;
+       int simple;
+       int from_type;
+       int from_patch;
+       int from_io;
+       int to_type;
+       int to_patch;
+       int to_io;
+} ld10k1_fnc_connection_t;
+
+typedef struct {
+       int patch_num;
+       int gpr;
+       char name[MAX_NAME_LEN];
+} ld10k1_fnc_name_t;
+
+typedef struct {
+       char name[MAX_NAME_LEN];
+} ld10k1_fnc_get_io_t;
+
+typedef struct {
+       int patch_num;
+       int id;
+       char patch_name[MAX_NAME_LEN];
+} ld10k1_fnc_patches_info_t;
+
+typedef struct {
+       char ld10k1_version[MAX_NAME_LEN];
+} ld10k1_fnc_version_t;
+
+#define CHIP_LIVE 0
+#define CHIP_AUDIGY 1
+
+typedef struct {
+       unsigned int chip_type;
+} ld10k1_fnc_dsp_info_t;
+
+#define FNC_PATCH_ADD 1
+#define FNC_PATCH_DEL 2
+
+#define FNC_CONNECTION_ADD 3
+#define FNC_CONNECTION_DEL 4
+
+#define FNC_PATCH_RENAME 5
+#define FNC_PATCH_FIND 6
+
+#define FNC_GET_FX 11
+#define FNC_GET_IN 12
+#define FNC_GET_OUT 13
+#define FNC_GET_PIN 14
+#define FNC_GET_POUT 15
+
+#define FNC_GET_FX_COUNT 21
+#define FNC_GET_IN_COUNT 22
+#define FNC_GET_OUT_COUNT 23
+#define FNC_GET_PIN_COUNT 24
+#define FNC_GET_POUT_COUNT 25
+
+#define FNC_FX_RENAME 30
+#define FNC_IN_RENAME 31
+#define FNC_OUT_RENAME 32
+#define FNC_PATCH_IN_RENAME 33
+#define FNC_PATCH_OUT_RENAME 34
+
+
+#define FNC_GET_PATCHES_INFO 40
+#define FNC_GET_PATCH 41
+
+#define FNC_FX_FIND 50
+#define FNC_IN_FIND 51
+#define FNC_OUT_FIND 52
+#define FNC_PATCH_IN_FIND 53
+#define FNC_PATCH_OUT_FIND 54
+
+#define FNC_DUMP 60
+
+#define FNC_GET_POINTS_INFO 70
+#define FNC_GET_POINT_INFO 71
+
+#define FNC_GET_DSP_INFO 97
+
+#define FNC_VERSION 98
+#define FNC_DSP_INIT 99
+
+#define FNC_OK 100
+#define FNC_ERR 101
+#define FNC_CONTINUE 102
+#define FNC_CLOSE_CONN 103
+
+#define FNC_DEBUG 200
+
+#endif /* __LD10K1_FNC_H */
diff --git a/ld10k1/include/liblo10k1.h b/ld10k1/include/liblo10k1.h
new file mode 100644 (file)
index 0000000..9f57850
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef __LIBLO10K1_H
+#define __LIBLO10K1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBLO10K1_ERR_DEBUG -10000
+
+typedef ld10k1_dsp_p_in_out_t liblo10k1_dsp_pio_t;
+typedef ld10k1_dsp_p_const_static_t liblo10k1_dsp_cs_t;
+typedef ld10k1_dsp_p_hw_t liblo10k1_dsp_hw_t;
+typedef ld10k1_dsp_ctl_t liblo10k1_dsp_ctl_t;
+typedef ld10k1_dsp_instr_t liblo10k1_dsp_instr_t;
+typedef ld10k1_dsp_tram_grp_t liblo10k1_dsp_tram_grp_t;
+typedef ld10k1_dsp_tram_acc_t liblo10k1_dsp_tram_acc_t;
+typedef ld10k1_fnc_get_io_t liblo10k1_get_io_t;
+
+typedef struct {
+       char patch_name[MAX_NAME_LEN];
+       unsigned int in_count;
+       liblo10k1_dsp_pio_t *ins;
+       unsigned int out_count;
+       liblo10k1_dsp_pio_t *outs;
+       unsigned int const_count;
+       liblo10k1_dsp_cs_t *consts;
+       unsigned int sta_count;
+       liblo10k1_dsp_cs_t *stas;
+       unsigned int dyn_count;
+       unsigned int hw_count;
+       liblo10k1_dsp_hw_t *hws;
+       unsigned int tram_count;
+       liblo10k1_dsp_tram_grp_t *tram;
+       unsigned int tram_acc_count;
+       liblo10k1_dsp_tram_acc_t *tram_acc;
+       unsigned int ctl_count;
+       liblo10k1_dsp_ctl_t *ctl;
+       unsigned int instr_count;
+       liblo10k1_dsp_instr_t *instr;
+} liblo10k1_dsp_patch_t;
+
+typedef int liblo10k1_connection_t;
+typedef ld10k1_fnc_patches_info_t liblo10k1_patches_info_t;
+
+typedef ld10k1_fnc_dsp_info_t liblo10k1_dsp_info_t;
+
+typedef ld10k1_dsp_point_t liblo10k1_point_info_t;
+
+typedef comm_param liblo10k1_param;
+
+void liblo10k1_connection_init(liblo10k1_connection_t *conn);
+int liblo10k1_connect(liblo10k1_param *param, liblo10k1_connection_t *conn);
+int liblo10k1_is_open(liblo10k1_connection_t *conn);
+int liblo10k1_disconnect(liblo10k1_connection_t *conn);
+
+liblo10k1_dsp_patch_t *liblo10k1_patch_alloc(int in_count, int out_count, int const_count, int sta_count, int dyn_count, int hw_count, int tram_count, int tram_acc_count, int ctl_count, int instr_count);
+void liblo10k1_patch_free(liblo10k1_dsp_patch_t *patch);
+
+int liblo10k1_patch_set_in_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_out_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_const_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_sta_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_dyn_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_hw_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_tram_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_tram_acc_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_ctl_count(liblo10k1_dsp_patch_t *p, int count);
+int liblo10k1_patch_set_instr_count(liblo10k1_dsp_patch_t *p, int count);
+
+int liblo10k1_patch_load(liblo10k1_connection_t *conn, liblo10k1_dsp_patch_t *patch, int before, int *loaded, int *loaded_id);
+int liblo10k1_patch_unload(liblo10k1_connection_t *conn, int patch_num);
+int liblo10k1_patch_get(liblo10k1_connection_t *conn, int patch_num, liblo10k1_dsp_patch_t **patch);
+
+int liblo10k1_debug(liblo10k1_connection_t *conn, int deb, void (*prn_fnc)(char *));
+
+int liblo10k1_dsp_init(liblo10k1_connection_t *conn);
+
+int liblo10k1_find_patch(liblo10k1_connection_t *conn, char *patch_name, int *out);
+int liblo10k1_find_fx(liblo10k1_connection_t *conn, char *fx_name, int *out);
+int liblo10k1_find_in(liblo10k1_connection_t *conn, char *in_name, int *out);
+int liblo10k1_find_out(liblo10k1_connection_t *conn, char *out_name, int *out);
+int liblo10k1_find_patch_in(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out);
+int liblo10k1_find_patch_out(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out);
+
+int liblo10k1_rename_patch(liblo10k1_connection_t *conn, int patch_num, char *patch_name);
+int liblo10k1_rename_fx(liblo10k1_connection_t *conn, int fx, char *fx_name);
+int liblo10k1_rename_in(liblo10k1_connection_t *conn, int in, char *in_name);
+int liblo10k1_rename_out(liblo10k1_connection_t *conn, int out, char *out_name);
+int liblo10k1_rename_patch_in(liblo10k1_connection_t *conn, int patch_num, int in, char *patch_in_name);
+int liblo10k1_rename_patch_out(liblo10k1_connection_t *conn, int patch_num, int out, char *patch_out_name);
+
+int liblo10k1_con_add(liblo10k1_connection_t *conn, int multi, int simple, int from_type, int from_patch, int from_io, int to_type, int to_patch, int to_io, int *ci);
+int liblo10k1_con_del(liblo10k1_connection_t *conn, int type, int patch, int io, int *ci);
+
+int liblo10k1_get_fx(liblo10k1_connection_t *conn, int fx_num, liblo10k1_get_io_t *out);
+int liblo10k1_get_in(liblo10k1_connection_t *conn, int in_num, liblo10k1_get_io_t *out);
+int liblo10k1_get_out(liblo10k1_connection_t *conn, int out_num, liblo10k1_get_io_t *out);
+int liblo10k1_get_pin(liblo10k1_connection_t *conn, int patch_num, int in_num, liblo10k1_get_io_t *out);
+int liblo10k1_get_pout(liblo10k1_connection_t *conn, int patch_num, int out_num, liblo10k1_get_io_t *out);
+
+int liblo10k1_get_fx_count(liblo10k1_connection_t *conn, int *count);
+int liblo10k1_get_in_count(liblo10k1_connection_t *conn, int *count);
+int liblo10k1_get_out_count(liblo10k1_connection_t *conn, int *count);
+int liblo10k1_get_pin_count(liblo10k1_connection_t *conn, int patch_num, int *count);
+int liblo10k1_get_pout_count(liblo10k1_connection_t *conn, int patch_num, int *count);
+
+int liblo10k1_get_patches_info(liblo10k1_connection_t *conn, liblo10k1_patches_info_t **out, int *count);
+int liblo10k1_get_points_info(liblo10k1_connection_t *conn, int **out, int *count);
+int liblo10k1_get_point_info(liblo10k1_connection_t *conn, int point_id, liblo10k1_point_info_t *out);
+int liblo10k1_dump(liblo10k1_connection_t *conn, void **out, int *size);
+int liblo10k1_check_version(liblo10k1_connection_t *conn);
+
+int liblo10k1_get_dsp_info(liblo10k1_connection_t *conn, liblo10k1_dsp_info_t *info);
+
+char *liblo10k1_error_str(int error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBLO10K1_H */
diff --git a/ld10k1/include/liblo10k1ef.h b/ld10k1/include/liblo10k1ef.h
new file mode 100644 (file)
index 0000000..fb95025
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef __LIBLO10K1EF_H
+#define __LIBLO10K1EF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       unsigned int sc;
+       unsigned int sc_val;
+} liblo10k1_emu_sc_t;
+
+typedef struct {
+       unsigned int ctl;
+       unsigned int ctl_val;
+       unsigned int ctl_val_min;
+       unsigned int ctl_val_max;
+       char ctl_name[32];
+} liblo10k1_emu_ctl_t;
+
+typedef struct {
+       unsigned int line;
+       unsigned int line_size;
+} liblo10k1_emu_tram_line_t;
+
+typedef struct {
+       unsigned int size;
+       unsigned int read_line_count;
+       liblo10k1_emu_tram_line_t *read_lines;
+       unsigned int write_line_count;
+       liblo10k1_emu_tram_line_t *write_lines;
+} liblo10k1_emu_tram_t;
+
+typedef struct {
+       unsigned int op;
+       unsigned int arg[4];
+} liblo10k1_emu_instr_t;
+
+typedef struct {
+       char patch_name[32];
+       unsigned int in_count;
+       unsigned int *ins;
+       unsigned int out_count;
+       unsigned int *outs;
+       unsigned int dyn_count;
+       unsigned int *dyns;
+       unsigned int sta_count;
+       liblo10k1_emu_sc_t *stas;
+       unsigned int ctl_count;
+       liblo10k1_emu_ctl_t *ctls;
+       unsigned int con_count;
+       liblo10k1_emu_sc_t *cons;
+       unsigned int tram_lookup_count;
+       liblo10k1_emu_tram_t *tram_lookups;
+       unsigned int tram_delay_count;
+       liblo10k1_emu_tram_t *tram_delays;
+       unsigned int instr_count;
+       liblo10k1_emu_instr_t *instrs;
+} liblo10k1_emu_patch_t;
+
+liblo10k1_emu_patch_t *liblo10k1_emu_new_patch();
+void liblo10k1_emu_free_patch(liblo10k1_emu_patch_t *p);
+
+int liblo10k1_emu_patch_set_in_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_out_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_dyn_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_sta_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_ctl_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_con_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_lookup_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_delay_count(liblo10k1_emu_patch_t *p, int count);
+int liblo10k1_emu_patch_set_instr_count(liblo10k1_emu_patch_t *p, int count);
+
+int liblo10k1_emu_patch_set_line_count(liblo10k1_emu_tram_t *t, int write, int count);
+int liblo10k1_emu_load_patch(char *file_name, liblo10k1_emu_patch_t **p);
+
+typedef struct
+{
+       int emu_ctls[32];
+       int emu_ctl_count;
+       char ctl_name[44];
+} liblo10k1_ctl_transform_t;
+
+int liblo10k1_emu_transform_patch(liblo10k1_emu_patch_t *ep,  liblo10k1_ctl_transform_t *tctl, int tctl_count, liblo10k1_dsp_patch_t **lp);
+int liblo10k1_patch_find_ctl_by_name(liblo10k1_dsp_patch_t *p, char *ctl_name);
+int liblo10k1_patch_ctl_set_trans(liblo10k1_dsp_patch_t *p, int idx, int trans);
+int liblo10k1_patch_ctl_set_vcount(liblo10k1_dsp_patch_t *p, int idx, int vc);
+int liblo10k1_patch_ctl_set_index(liblo10k1_dsp_patch_t *p, int idx, int i);
+int liblo10k1_patch_ctl_set_value(liblo10k1_dsp_patch_t *p, int idx, int vi, int val);
+
+
+#define LD10K1_EF_ERR_OPEN -1000 /* error at file open */
+#define LD10K1_EF_ERR_STAT -1001 /* error at file stat */
+#define LD10K1_EF_ERR_SIZE -1002 /* wrong file size */
+#define LD10K1_EF_ERR_READ -1003 /* error at file read */
+#define LD10K1_EF_ERR_SIGNATURE -1004 /* wrong file signature */
+#define LD10K1_EF_ERR_FORMAT -1005 /* wrong file format */
+
+#define LD10K1_EF_ERR_TRANSFORM_CTL -1100 /* wrong ctl transformation */
+#define LD10K1_EF_ERR_TRANSFORM -1101 /* wrong transformation */
+#define LD10K1_EF_ERR_TRANSFORM_TRANS -1102 /* wrong ctl translation */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBLO10K1EF_H */
diff --git a/ld10k1/include/liblo10k1lf.h b/ld10k1/include/liblo10k1lf.h
new file mode 100644 (file)
index 0000000..c51bb44
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef __LIBLO10K1LF_H
+#define __LIBLO10K1LF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* description of structures used in native ld10k1 files */
+
+typedef struct {
+       /* asciz string with signature - have to be 
+       "LD10K1 NATIVE EFFECT FILE      "
+        01234567890123456789012345678901 */
+       char signature[32];
+       /* don't use this */
+       char reserved[32];
+} liblo10k1_file_header_t;
+
+/* don't use this */
+#define LD10K1_FP_TYPE_RESERVED 0
+/* normal part type, part_length is valid */
+#define LD10K1_FP_TYPE_NORMAL 1
+/* part start type, part_length have to be 0 */
+#define LD10K1_FP_TYPE_START 2
+/* part end type, part_length have to be 0 */
+#define LD10K1_FP_TYPE_END 3
+
+/* parts can be nested */
+typedef struct {
+       /* don't use this */
+       unsigned int reserved : 2,
+       /* part type definition
+               - normal
+               - part content start
+               - part content end */
+               part_type : 6,
+               part_id : 24;
+       /* part data length */
+       unsigned int part_length;
+} liblo10k1_file_part_t;
+
+#define LD10K1_FP_INFO 0
+#define LD10K1_FP_DSP_SETUP 1
+#define LD10K1_FP_FX 2
+#define LD10K1_FP_FX_LIST 3
+#define LD10K1_FP_IN 4
+#define LD10K1_FP_IN_LIST 5
+#define LD10K1_FP_OUT 6
+#define LD10K1_FP_OUT_LIST 7
+#define LD10K1_FP_PATCH 8
+#define LD10K1_FP_PATCH_LIST 9
+#define LD10K1_FP_PATCH_INFO 10
+#define LD10K1_FP_PIO 11
+#define LD10K1_FP_PIN_LIST 12
+#define LD10K1_FP_POUT_LIST 13
+#define LD10K1_FP_CS 14
+#define LD10K1_FP_CONST_LIST 15
+#define LD10K1_FP_STA_LIST 16
+#define LD10K1_FP_DYN_LIST 17
+#define LD10K1_FP_HW 18
+#define LD10K1_FP_HW_LIST 19
+#define LD10K1_FP_TRAM 20
+#define LD10K1_FP_TRAM_LIST 21
+#define LD10K1_FP_TRAM_ACC 22
+#define LD10K1_FP_TRAM_ACC_LIST 23
+#define LD10K1_FP_CTL 24
+#define LD10K1_FP_CTL_LIST 25
+#define LD10K1_FP_INSTR 26
+#define LD10K1_FP_INSTR_LIST 27
+#define LD10K1_FP_POINT 28
+#define LD10K1_FP_POINT_LIST 29
+
+#define LD10K1_FP_FILE_INFO_NAME 30
+#define LD10K1_FP_FILE_INFO_DESC 31
+#define LD10K1_FP_FILE_INFO_CREATER 32
+#define LD10K1_FP_FILE_INFO_AUTHOR 33
+#define LD10K1_FP_FILE_INFO_COPYRIGHT 34
+#define LD10K1_FP_FILE_INFO_LICENCE 35
+
+/* file contains whole dsp config */
+#define LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP 0
+/* file contains only 1 patch */
+#define LD10K1_FP_INFO_FILE_TYPE_PATCH 1
+
+
+typedef struct {
+       unsigned int file_type;
+       /* file version 
+          application can ignore this version and read file, 
+          but must be prepared to ignore unknown parts */
+       unsigned int file_version_major : 8,
+               file_version_minor : 8,
+               file_version_subminor : 8,
+               file_version_pad : 8;
+       /* minimal version of lo10k1/ld10k1 which will load file
+          application must be prepared to ignore unknown parts */
+       unsigned int minimal_reader_version_major : 8,
+               minimal_reader_version_minor : 8,
+               minimal_reader_version_subminor : 8,
+               minimal_reader_version_pad : 8;
+       /* version of lo10k1/ld10k1 which which created file */
+       unsigned int creater_version_major : 8,
+               creater_version_minor : 8,
+               creater_version_subminor : 8,
+               creater_version_pad : 8;
+} liblo10k1_file_part_info_t;
+
+#define LD10K1_FP_INFO_DSP_TYPE_EMU10K1 0
+#define LD10K1_FP_INFO_DSP_TYPE_EMU10K2 1
+typedef struct {
+       unsigned int dsp_type;
+       /* tram size to setup */
+       /* unsigned int externa_tram_size; */
+       /* used to restore io names */
+       unsigned int fx_count;
+       unsigned int in_count;
+       unsigned int out_count;
+       /* patch count contained in this file */
+       unsigned int patch_count;
+       /* point count contained in this file */
+       unsigned int point_count;
+} liblo10k1_file_part_dsp_setup_t;
+
+
+/* structure used to store and restore config */
+typedef struct {
+       unsigned int dsp_type;
+       /* used to restore io names */
+       unsigned int fx_count;
+       liblo10k1_get_io_t *fxs;
+       unsigned int in_count;
+       liblo10k1_get_io_t *ins;
+       unsigned int out_count;
+       liblo10k1_get_io_t *outs;
+       /* patch count contained in this file */
+       unsigned int patch_count;
+       liblo10k1_dsp_patch_t **patches;
+       /* point count contained in this file */
+       unsigned int point_count;
+       liblo10k1_point_info_t *points;
+} liblo10k1_file_dsp_setup_t;
+
+typedef struct {
+       char patch_name[MAX_NAME_LEN];
+       unsigned int in_count;
+       unsigned int out_count;
+       unsigned int const_count;
+       unsigned int sta_count;
+       unsigned int dyn_count;
+       unsigned int hw_count;
+       unsigned int tram_count;
+       unsigned int tram_acc_count;
+       unsigned int ctl_count;
+       unsigned int instr_count;
+} liblo10k1_file_patch_info_t;
+
+int liblo10k1lf_get_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t **setup);
+int liblo10k1lf_put_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t *setup);
+
+liblo10k1_file_dsp_setup_t *liblo10k1lf_dsp_config_alloc();
+void liblo10k1lf_dsp_config_free(liblo10k1_file_dsp_setup_t *c);
+
+typedef struct {
+       /* file name */
+       char *name;
+       /* file description */
+       char *desc;
+       /* description of creater application - can be anything */
+       char *creater;
+       /* author */
+       char *author;
+       /* copyright string */
+       char *copyright;
+       /* licence use for this file */
+       char *license;
+} liblo10k1_file_info_t;
+
+liblo10k1_file_info_t *liblo10k1lf_file_info_alloc();
+void liblo10k1lf_file_info_free(liblo10k1_file_info_t *fi);
+
+int liblo10k1lf_save_dsp_config(liblo10k1_file_dsp_setup_t *c, char *file_name, liblo10k1_file_info_t *fi);
+int liblo10k1lf_load_dsp_config(liblo10k1_file_dsp_setup_t **c, char *file_name, liblo10k1_file_info_t **fi);
+
+int liblo10k1lf_save_dsp_patch(liblo10k1_dsp_patch_t *p, char *file_name, liblo10k1_file_info_t *fi);
+int liblo10k1lf_load_dsp_patch(liblo10k1_dsp_patch_t **p, char *file_name, liblo10k1_file_info_t **fi);
+
+#define LD10K1_LF_ERR_OPEN -2000
+#define LD10K1_LF_ERR_WRITE -2001
+#define LD10K1_LF_ERR_READ -2002
+#define LD10K1_LF_ERR_SIGNATURE -2003
+#define LD10K1_LF_ERR_PART_TYPE -2004
+#define LD10K1_LF_ERR_PART_SIZE -2005
+#define LD10K1_LF_ERR_VERSION -2006
+#define LD10K1_LF_ERR_FILE_TYPE -2007
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBLO10K1LF_H */
diff --git a/ld10k1/include/lo10k1.h b/ld10k1/include/lo10k1.h
new file mode 100644 (file)
index 0000000..67a8af1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LO10K1_H
+#define __LO10K1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <lo10k1/version.h>
+
+#include <lo10k1/ld10k1_error.h>
+#include <lo10k1/ld10k1_fnc.h>
+#include <lo10k1/comm.h>
+#include <lo10k1/liblo10k1.h>
+#include <lo10k1/liblo10k1ef.h>
+#include <lo10k1/liblo10k1lf.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LO10K1_H */
diff --git a/ld10k1/include/version.h b/ld10k1/include/version.h
new file mode 100644 (file)
index 0000000..1ab5f70
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *  version.h
+ */
+
+#define LD10K1_LIB_MAJOR               0 /**< major number of library version */
+#define LD10K1_LIB_MINOR               1 /**< minor number of library version */
+#define LD10K1_LIB_SUBMINOR    8 /**< subminor number of library version */
+/** library version */
+#define LD10K1_LIB_VERSION             ((LD10K1_LIB_MAJOR<<16)|\
+                                        (LD10K1_LIB_MINOR<<8)|\
+                                        LD10K1_LIB_SUBMINOR)
+/** library version (string) */
+#define LD10K1_LIB_VERSION_STR "0.1.8"
+
diff --git a/ld10k1/ld10k1.m4 b/ld10k1/ld10k1.m4
new file mode 100644 (file)
index 0000000..9b51dc1
--- /dev/null
@@ -0,0 +1,135 @@
+dnl Configure Paths for ld10k1 - stolen from ASLA (1.0.5a)
+dnl Configure Paths for Alsa
+dnl Some modifications by Richard Boulton <richard-alsa@tartarus.org>
+dnl Christopher Lansdown <lansdoct@cs.alfred.edu>
+dnl Jaroslav Kysela <perex@suse.cz>
+dnl AM_PATH_LD10K1([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for liblo10k1, and define LD10K1_CFLAGS and LD10K1_LIBS as appropriate.
+dnl enables arguments --with-ld10k1-prefix=
+dnl                   --with-ld10k1-enc-prefix=
+dnl                   --disable-ld10k1test
+dnl
+dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
+dnl and the ld10k1 libraries are not found, a fatal AC_MSG_ERROR() will result.
+dnl
+AC_DEFUN([AM_PATH_LD10K1],
+[dnl Save the original CFLAGS, LDFLAGS, and LIBS
+ld10k1_save_CFLAGS="$CFLAGS"
+ld10k1_save_LDFLAGS="$LDFLAGS"
+ld10k1_save_LIBS="$LIBS"
+ld10k1_found=yes
+
+dnl
+dnl Get the cflags and libraries for ld10k1
+dnl
+AC_ARG_WITH(ld10k1-prefix,
+[  --with-ld10k1-prefix=PFX  Prefix where ld10k1 library is installed(optional)],
+[ld10k1_prefix="$withval"], [ld10k1_prefix=""])
+
+AC_ARG_WITH(ld10k1-inc-prefix,
+[  --with-ld10k1-inc-prefix=PFX  Prefix where include libraries are (optional)],
+[ld10k1_inc_prefix="$withval"], [ld10k1_inc_prefix=""])
+
+dnl FIXME: this is not yet implemented
+AC_ARG_ENABLE(ld10k1test,
+[  --disable-ld10k1test      Do not try to compile and run a test ld10k1 program],
+[enable_ld10k1test="$enableval"],
+[enable_ld10k1test=yes])
+
+dnl Add any special include directories
+AC_MSG_CHECKING(for ld10k1 CFLAGS)
+if test "$ld10k1_inc_prefix" != "" ; then
+       LD10K1_CFLAGS="$LD10K1_CFLAGS -I$ld10k1_inc_prefix"
+       CFLAGS="$CFLAGS -I$ld10k1_inc_prefix"
+fi
+AC_MSG_RESULT($LD10K1_CFLAGS)
+
+dnl add any special lib dirs
+AC_MSG_CHECKING(for ld10l1 LDFLAGS)
+if test "$ld10k1_prefix" != "" ; then
+       LD10K1_LIBS="$LD10K1_LIBS -L$ld10k1_prefix"
+       LDFLAGS="$LDFLAGS $LD10K1_LIBS"
+fi
+
+dnl add the ld10k1 library
+LD10K1_LIBS="$LD10K1_LIBS -llo10k1"
+dnl LIBS=`echo $LIBS | sed 's/-lm//'`
+dnl LIBS=`echo $LIBS | sed 's/-ldl//'`
+dnl LIBS=`echo $LIBS | sed 's/-lpthread//'`
+LIBS=`echo $LIBS | sed 's/  //'`
+LIBS="$LD10K1_LIBS $LIBS"
+AC_MSG_RESULT($LD10K1_LIBS)
+
+dnl Check for a working version of liblo10k1 that is of the right version.
+min_ld10k1_version=ifelse([$1], ,0.1.5,$1)
+AC_MSG_CHECKING(for liblo10k1 headers version >= $min_ld10k1_version)
+no_ld10k1=""
+    ld10k1_min_major_version=`echo $min_ld10k1_version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    ld10k1_min_minor_version=`echo $min_ld10k1_version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    ld10k1_min_micro_version=`echo $min_ld10k1_version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+AC_LANG_SAVE
+AC_LANG_C
+AC_TRY_COMPILE([
+#include <lo10k1/lo10k1.h>
+], [
+/* ensure backward compatibility */
+#  if(LD10K1_LIB_MAJOR > $ld10k1_min_major_version)
+  exit(0);
+#  else
+#    if(LD10K1_LIB_MAJOR < $ld10k1_min_major_version)
+#       error not present
+#    endif
+
+#   if(LD10K1_LIB_MINOR > $ld10k1_min_minor_version)
+  exit(0);
+#   else
+#     if(LD10K1_LIB_MINOR < $ld10k1_min_minor_version)
+#          error not present
+#      endif
+
+#      if(LD10K1_LIB_SUBMINOR < $ld10k1_min_micro_version)
+#        error not present
+#      endif
+#    endif
+#  endif
+exit(0);
+],
+  [AC_MSG_RESULT(found.)],
+  [AC_MSG_RESULT(not present.)
+   ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of liblo10k1 not found.)])
+   ld10k1_found=no]
+)
+AC_LANG_RESTORE
+
+dnl Now that we know that we have the right version, let's see if we have the library and not just the headers.
+if test "x$enable_ld10k1test" = "xyes"; then
+AC_CHECK_LIB([lo10k1], [liblo10k1_connection_init],,
+       [ifelse([$3], , [AC_MSG_ERROR(No linkable liblo10k1 was found.)])
+        ld10k1_found=no]
+)
+fi
+
+if test "x$ld10k1_found" = "xyes" ; then
+   ifelse([$2], , :, [$2])
+   LIBS=`echo $LIBS | sed 's/-llo10k1//g'`
+   LIBS=`echo $LIBS | sed 's/  //'`
+   LIBS="-llo10k1 $LIBS"
+fi
+if test "x$ld10k1_found" = "xno" ; then
+   ifelse([$3], , :, [$3])
+   CFLAGS="$ld10k1_save_CFLAGS"
+   LDFLAGS="$ld10k1_save_LDFLAGS"
+   LIBS="$ld10k1_save_LIBS"
+   LD10K1_CFLAGS=""
+   LD10K1_LIBS=""
+fi
+
+dnl That should be it.  Now just export out symbols:
+AC_SUBST(LD10K1_CFLAGS)
+AC_SUBST(LD10K1_LIBS)
+])
+
diff --git a/ld10k1/ld10k1d.in b/ld10k1/ld10k1d.in
new file mode 100644 (file)
index 0000000..28d10e2
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+test -x@sbindir@/ld10k1 || exit 0
+
+card=$2
+socket=/tmp/.ld10k1_port
+
+if [ -z "$card" ]; then
+    card=0
+elif [ "$card" = "0" ] ; then
+    card=0
+else
+    socket=$socket"_"$card
+fi
+
+pidfile=/var/run/ld10k1_$card.pid
+dspsetup=/etc/dspstate_$card.ld10k1
+
+start() {
+    if [ ! -f $pidfile ] ; then
+       echo $"Starting ld10k1"
+       @sbindir@/ld10k1 -d -c $card -p $socket -i $pidfile >/dev/null 2>&1
+       if [ -f $dspsetup ]; then
+           echo $"Restoring DSP setup"
+           @binarydir@/lo10k1 -p $socket --restore $dspsetup >/dev/null 2>&1
+       fi
+    else
+       echo $"ld10k1 running"
+    fi
+    return 0
+}
+
+stop() {
+    if [ -f $pidfile ] ; then
+       echo $"Storing DSP setup"
+       @binarydir@/lo10k1 -p $socket --store $dspsetup >/dev/null 2>&1
+       echo $"Stoping ld10k1"
+       pid=
+       local line p
+       read line < $pidfile
+       for p in $line ; do
+           [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p"
+       done
+       kill -s 9 $pid >/dev/null 2>&1
+       
+       if [ -f $pidfile ] ; then
+           rm -f $pidfile >/dev/null 2>&1
+       fi
+    else
+       echo $"ld10k1 not runing"
+    fi
+    return 0
+}
+
+save() {
+    if [ -f $pidfile ] ; then
+       echo $"Storing DSP setup"
+       @binarydir@/lo10k1 -p $socket --store $dspsetup >/dev/null 2>&1
+    else
+       echo $"ld10k1 not runing"
+    fi
+    return 0
+}
+
+
+case "$1" in
+start)
+    start
+    ;;
+stop)
+    stop
+    ;;
+save)
+    save
+    ;;
+*)
+    echo $"Usage $0 {start|stop}"
+    exit 1
+esac
diff --git a/ld10k1/patch/Makefile.am b/ld10k1/patch/Makefile.am
new file mode 100644 (file)
index 0000000..952fde6
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST = README
diff --git a/ld10k1/patch/README b/ld10k1/patch/README
new file mode 100644 (file)
index 0000000..808044b
--- /dev/null
@@ -0,0 +1 @@
+For alsa 1.0.7rc1 and higher no patches are needed.
\ No newline at end of file
diff --git a/ld10k1/setup/Makefile.am b/ld10k1/setup/Makefile.am
new file mode 100644 (file)
index 0000000..e89502c
--- /dev/null
@@ -0,0 +1,18 @@
+SUBDIRS = effects
+
+EXTRA_DIST = init_audigy.in init_live.in
+bin_SCRIPTS = init_audigy init_live
+
+do_subst = sed -e 's,[@]datadir[@],$(datadir),g' \
+ -e 's,[@]PERL[@],$(PERL),g' \
+ -e 's,[@]PACKAGE[@],$(PACKAGE),g' \
+ -e 's,[@]VERSION[@],$(VERSION),g' \
+ -e 's,[@]bindir[@],$(bindir),g'
+
+init_live: init_live.in
+       $(do_subst) $(srcdir)/init_live.in > init_live
+
+init_audigy: init_audigy.in
+       $(do_subst) $(srcdir)/init_audigy.in > init_audigy
+
+CLEANFILES = init_live init_audigy
\ No newline at end of file
diff --git a/ld10k1/setup/effects/Makefile.am b/ld10k1/setup/effects/Makefile.am
new file mode 100644 (file)
index 0000000..14cd60c
--- /dev/null
@@ -0,0 +1,18 @@
+EXTRA_DIST = README emu_constants.asm \
+       simple.asm vol_master.asm tone.asm \
+       vol_2.asm output.asm switch_2.asm \
+       sto51.asm switch_6.asm copy_2.asm \
+       prologic.asm fxbus.asm
+
+
+dist_effects_DATA = simple.emu10k1 vol_master.emu10k1 tone.emu10k1 \
+       vol_2.emu10k1 output.emu10k1 switch_2.emu10k1 \
+       sto51.emu10k1 switch_6.emu10k1 copy_2.emu10k1 \
+       prologic.emu10k1 fxbus.emu10k1
+
+CLEANFILES = $(dist_effects_DATA)
+
+SUFFIXEC = .asm .emu10k1
+
+.asm.emu10k1:
+       as10k1 -o $@ $<
diff --git a/ld10k1/setup/effects/README b/ld10k1/setup/effects/README
new file mode 100644 (file)
index 0000000..2185537
--- /dev/null
@@ -0,0 +1 @@
+Most of files in this directory is taken from emu10k1 OSS driver see opensource.creative.com
\ No newline at end of file
diff --git a/ld10k1/setup/effects/copy_2.asm b/ld10k1/setup/effects/copy_2.asm
new file mode 100644 (file)
index 0000000..9f3b240
--- /dev/null
@@ -0,0 +1,13 @@
+;PZU
+       name "2-channel copy"
+
+left   IO
+right  IO
+       
+       macs  left,left,$40,$40
+       macs  right,right,$40,$40
+
+               end
+       
+
+       
diff --git a/ld10k1/setup/effects/emu_constants.asm b/ld10k1/setup/effects/emu_constants.asm
new file mode 100644 (file)
index 0000000..f215604
--- /dev/null
@@ -0,0 +1,151 @@
+;some hardware constants C_[n]<DecimalValue>, 'n' indicates negative value
+;              
+;these are in 2's complement representation
+C_0    equ $040        ;;00000000
+C_1    equ $041        ;;00000001
+C_2    equ $042        ;;00000002
+C_3    equ $043        ;;00000003
+C_4    equ $044        ;;00000004      
+C_8    equ $045        ;;00000008
+C_16   equ $046        ;;00000010
+C_32   equ $047        ;;00000020
+C_256  equ $048        ;;00000100
+C_65536 equ $049       ;;00010000
+C_2^23         equ $04A        ;;00080000
+C_2^28 equ $04b        ;;10000000
+C_2^29 equ $04c        ;;20000000 (C_max /4) +1
+C_2^30 equ $04d        ;;40000000 ( C_max / 2 ) + 1 (almost half)      
+C_nmax equ $04e        ;;80000000 most negative number
+C_max  equ $04f        ;;7fffffff most positive number 
+C_n1   equ $050        ;;ffffffff -1
+C_n2   equ $051        ;;fffffffe -2
+C_n2^30        equ $052        ;;c0000000 C_nmax /2
+
+C_LSshift equ $55      ;;to left shift an address by using macsints
+                       ;;for fractional addresses
+
+
+ZERO equ C_0;
+ONE equ        C_1;
+       
+;;; Hardware Registers:        
+               
+ACCUM  equ $56
+CCR    equ $57 
+NOISE1 equ $58
+NOISE2 equ $59 
+IRQ    equ $5A 
+DBAC   equ $5B 
+       
+and    macro   dest,srcA,srcB
+       andxor  dest,srcA,srcB,C_0
+       endm
+       
+xor    macro   dest,srcA,srcB
+       andxor  dest,C_n1,srcA,srcB
+       endm
+       
+not    macro    dest,src
+       andxor   dest,src,C_n1,C_n1             
+       endm
+
+nand   macro   dest,srcA,srcB  
+       andxor  dest,srcA,srcB,C_n1
+       endm
+       
+or     macro    dest,srcA,srcB
+       not      C_0,srcA
+       andxor   dest,ACCUM,srcA,srcB   
+       endm    
+
+nor    macro   dest,srcA,scrB
+       not     dest,srcA
+       andxor  dest,srcB,dest,srcA     
+       not     dest,dest
+       endm
+
+
+neg     macro   dest,src
+       macs1   dest,C_0,C_1,C_nmax     
+       endm    
+       
+;;; branch on:
+;;; ==0
+beq    macro   count
+       skip    CCR,CCR,C_8,count       
+       endm
+;;; !=0
+bne    macro   count
+       skip    CCR,CCR,C_256,count
+       endm
+;;; <0
+blt    macro   count
+       skip    CCR,CCR,C_4,count
+       endm
+;;; <=0 
+ble    macro count
+C___1008 con $1008
+    skip CCR,CCR,C___1008,count
+    endm
+;;; always branch
+bra    macro   count
+       skip    C_0,C_max,C_max,count
+       endm
+;;; on saturation- for now - as10k1 can not handle more than 25 macros
+;bsa     macro count
+;      skip CCR,CCR,C_16,count
+;      endm
+bge    macro  count
+C___80 con $80
+       skip CCR,CCR,C___80,count       
+       endm
+               
+bgt    macro   count
+C___180        con $180
+       skip CCR,CCR,C___180,count
+       endm
+       
+move   macro dest,src
+       macs  dest,src,C_0,C_0
+       endm            
+fracmult macro dest, src1, src2 
+       macs  dest,$40, src1, src2
+       endm
+intmult macro dest, src1, src2
+       macints  dest, $40, src1, src2
+       endm
+add    macro dest, src1, src2
+       acc3 dest, $40, src1, src2 
+       endm
+               
+;;; usefull for testing values before a skip
+test   macro test
+       macs C_0,test,C_0,C_0
+       endm
+
+cmp    macro src1,scr2
+       macints C_0,src1,C_n1,src2
+       endm
+
+       
+;----------------------------------------
+;      dest = src1 - src2      
+sub    macro dest, src1, src2 
+       macints  dest, src1, src2, C_n1
+       endm
+
+;----------------------------------------
+;          LowPassFilter
+lpf    macro yy, mm, xx
+       interp yy, yy, mm, xx
+       endm
+
+;----------------------------------------
+;          HighPassFilter
+hpf    macro yy, ss, mm, xx
+       interp ss, ss, mm, xx
+       sub   yy, xx, ss
+       endm
+
+       end
\ No newline at end of file
diff --git a/ld10k1/setup/effects/fxbus.asm b/ld10k1/setup/effects/fxbus.asm
new file mode 100644 (file)
index 0000000..3f1a1a6
--- /dev/null
@@ -0,0 +1,30 @@
+       name "FXBUS"
+       include "emu_constants.asm"
+
+       ;; From alsa driver pci/emu10k1/emufx.c _volume_add
+       
+pcm_l  io
+pcm_r  io
+pcm_lr io
+pcm_rr io
+midi_l io
+midi_r io
+pcm_c  io
+pcm_lf io
+spdif_l io
+spdif_r io
+
+       ;; Process FX Buses
+
+       macints pcm_l, C_0, pcm_l, C_4
+       macints pcm_r, C_0, pcm_r, C_4
+       macints pcm_lr, C_0, pcm_lr, C_4
+       macints pcm_rr, C_0, pcm_rr, C_4
+       macints midi_l, C_0, midi_l, C_4
+       macints midi_r, C_0, midi_r, C_4
+       macints pcm_c, C_0, pcm_c, C_4
+       macints pcm_lf, C_0, pcm_lf, C_4
+       macints spdif_l, C_0, spdif_l, C_4
+       macints spdif_r, C_0, spdif_r, C_4
+
+       end
diff --git a/ld10k1/setup/effects/output.asm b/ld10k1/setup/effects/output.asm
new file mode 100644 (file)
index 0000000..61b74b0
--- /dev/null
@@ -0,0 +1,61 @@
+;PZU
+;parts are taken from passthrough-audigy
+
+       name "Output patch"
+       include "emu_constants.asm"
+
+;inputs - and analog outputs
+Left           IO
+Right          IO
+LeftSurr       IO
+RightSurr      IO
+Center         IO
+LFE            IO
+; these are used for digital output
+DLeft          IO
+DRight         IO
+DLeftSurr      IO
+DRightSurr     IO
+DCenter                IO
+DLFE           IO
+
+enableL                control 0,0,1
+enableR                control 0,0,1
+
+tmp_a          dyn
+tmp_b          dyn
+mask           con $ffff0000
+
+
+;simple copy to analog output
+    macs Left, Left, C_0, C_0
+    macs Right, Right, C_0, C_0
+    macs LeftSurr, LeftSurr, C_0, C_0
+    macs RightSurr, RightSurr, C_0, C_0
+    macs Center, Center, C_0, C_0
+    macs LFE, LFE, C_0, C_0
+;
+    macs DLeft, Left, C_0, C_0
+    macs DRight, Right, C_0, C_0
+    macs C_0, enableL, C_0, C_0
+    beq .endL
+    macs tmp_a, DLeft, C_0, C_0
+    ble .next_a
+    acc3 tmp_a, C_0, C_65536, tmp_a
+.next_a
+    and DLeft, tmp_a, mask
+.endL
+    macs C_0, enableR, C_0, C_0
+    beq .end
+    macs tmp_b, DRight, C_0, C_0
+    ble .next_b
+    acc3 tmp_b, C_0, C_65536, tmp_b
+.next_b
+    and DRight, tmp_b, mask
+.end
+    macs DLeftSurr, LeftSurr, C_0, C_0
+    macs DRightSurr, RightSurr, C_0, C_0
+    macs DCenter, Center, C_0, C_0
+    macs DLFE, LFE, C_0, C_0
+
+    end
\ No newline at end of file
diff --git a/ld10k1/setup/effects/prologic.asm b/ld10k1/setup/effects/prologic.asm
new file mode 100644 (file)
index 0000000..9fc2d6e
--- /dev/null
@@ -0,0 +1,115 @@
+; Surround Active Matrix for Emu10k1
+; Author: Robert Mazur <robertmazur@yahoo.com>
+; Date: Jan 14, 2002
+; Version 1.1
+
+; 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.
+
+;========================================
+
+       name    "ProLogic"
+
+       include "emu_constants.asm"
+
+
+;========================================
+
+delline                delay   &0.02           ; 0.02 sec delay
+write          twrite  delline,&0      ; write at 0 sec
+read           tread   delline,&0.02   ; read at 0.02 sec
+
+;----------------------------------------
+ml             con     #0.575997       ; lpf 7000Hz
+yl             sta     0
+
+mlp            con     #0.277015       ; lpf 2500Hz
+mhp            con     #3.7076e-2      ; hpf 300Hz
+ylp            sta     0
+shp            sta     0
+
+;----------------------------------------
+Lt             io                      ; Stereo Left  In
+Rt             io                      ; Stereo Right In
+L              equ Lt                  ; Front  Left  Out
+R              equ Rt                  ; Front  Right Out
+Ls             io
+Rs             io
+C              io                      ; Center
+
+;----------------------------------------
+tmp            dyn
+
+ll             dyn
+rr             dyn
+
+vcal           sta     #0.5
+vcar           sta     #0.5
+
+fl             sta     0
+fr             sta     0
+mf             con     #0.013  ; ~ 100Hz
+
+;----------------------------------------
+;           abs(x)
+tmp_abs        dyn
+abs    macro ret, xx
+       sub     tmp_abs, C_0, xx
+       limit   ret, C_0, tmp_abs, xx
+       endm
+
+       
+;========================================
+;              Start
+;========================================
+
+;;     Servo
+
+       fracmult ll, vcal, Lt           ; ll = vcal * Lt
+       abs     tmp, ll                 ; tmp = abs(ll)
+       lpf     fl, mf, tmp             ; fl = LowPass((n)Hz, tmp);
+
+       fracmult rr, vcar, Rt           ; rr = vcar * Rt
+       abs     tmp, rr                 ; tmp = abs(rr)
+       lpf     fr, mf, tmp             ; fr = LowPass((n)Hz, tmp);
+       
+       intmult ll, C_2, ll             ; vca0 = 0.5 so we must multiply 'll' and 'rr' by 2
+       intmult rr, C_2, rr
+
+       sub     tmp, fr, fl             ; serv = fr - fl
+       
+       macints vcal, C_2^30, C_2, tmp  ;vcal = vca0 + 2*serv
+       macints vcar, C_2^30, C_n2, tmp ;vcar = vca0 - 2*serv
+       
+;;     Suround
+       
+       sub     tmp, ll, rr             ; delay.in = L - R
+       
+       lpf     yl, ml, tmp             ; yl = LowPass(7kHz, delay.out) = rear
+       
+;      macs    L, Lt, vcar, yl         ; L = Lt - vcar * S  Remove Surround from front speakers
+;      macs1   R, Rt, vcal, yl         ; R = Rt + vcal * S     
+       
+       move    write, yl               ; delay surround
+
+       fracmult tmp, vcar, read        ; Ls = 2 * vcar * rear ( 2* becouse vca0 = 0.5)
+       intmult Ls,C_2,tmp
+       fracmult tmp, vcal, read        ; Rs = 2 * vcal * rear
+       intmult Rs,C_2,tmp
+       
+;;     Center
+
+       add     tmp, ll, rr             ; tmp = L + R
+
+       hpf     tmp, shp, mhp, tmp      ; tmp = HighPass(300Hz, tmp)
+       lpf     ylp, mlp, tmp           ; ylp = LowPass(2.5kHz, tmp) = center
+
+       move    C, ylp                  ; Center
+
+       sub     R, Rt, read             ; R = R - rear
+       sub     L, Lt, read             ; L = L - rear
+
+       end
+;========================================
diff --git a/ld10k1/setup/effects/simple.asm b/ld10k1/setup/effects/simple.asm
new file mode 100644 (file)
index 0000000..b16eb6f
--- /dev/null
@@ -0,0 +1,39 @@
+       name "Simple 5.1 volume"
+       include "emu_constants.asm"
+
+inl    io
+outl   equ  inl
+inr    io
+outr   equ  inr
+inrl   io
+outrl  equ  inrl
+inrr   io
+outrr  equ  inrr
+inc    io
+outc   equ  inc
+inlfe  io
+outlfe equ  inlfe
+
+Left control 0,0,100
+Right control 0,0,100
+LeftSurr control 0,0,100
+RightSurr control 0,0,100
+Center control 0,0,100
+LFE control 0,0,100
+
+       macs  outl,C_0, Left, inl
+       macs  outr,C_0, Right, inr
+       macs  outc,C_0, Center, inc
+       macs  outrl,C_0, LeftSurr, inrl
+       macs  outrr,C_0, RightSurr, inrr
+       macs  outlfe,C_0, LFE, inlfe
+       
+       end
+
+
+
+
+
+
+
+
diff --git a/ld10k1/setup/effects/sto51.asm b/ld10k1/setup/effects/sto51.asm
new file mode 100644 (file)
index 0000000..4564f9a
--- /dev/null
@@ -0,0 +1,60 @@
+;PZU
+       name "Simple 5.1 for Wave"
+       include "emu_constants.asm"
+
+inl    io
+outl   equ  inl
+inr    io
+outr   equ  inr
+inrl   io
+outrl  equ  inrl
+inrr   io
+outrr  equ  inrr
+inc    io
+outc   equ  inc
+inlfe  io
+outlfe equ  inlfe
+
+Left control 0,0,100
+Right control 0,0,100
+LeftSurr control 0,0,100
+RightSurr control 0,0,100
+Center control 0,0,100
+LFE control 0,0,100
+
+tmp dyn
+c40 con $40000000
+
+
+tmpl dyn
+tmpr dyn
+
+;5.1 playback
+       macs  tmpl, inl, C_0, C_0
+       macs  tmpr, inr, C_0, C_0
+
+;      macs  outl, inl.o, Left, tmpl
+;      macs  outr, inr.o, Right, tmpr
+;      macs  outrl, inrl.o, LeftSurr, tmpl
+;      macs  outrr, inrr.o, RightSurr, tmpr
+;      interp tmp, tmpl, c40, tmpr
+;      macs  outc, inc.o, Center, tmp
+;      macs  outlfe, inlfe.o, LFE, tmp
+
+       macs  outl, $40, Left, tmpl
+       macs  outr, $40, Right, tmpr
+       macs  outrl, $40, LeftSurr, tmpl
+       macs  outrr, $40, RightSurr, tmpr
+       interp tmp, tmpl, c40, tmpr
+       macs  outc, $40, Center, tmp
+       macs  outlfe, $40, LFE, tmp
+
+       end
+
+
+
+
+
+
+
+
diff --git a/ld10k1/setup/effects/switch_2.asm b/ld10k1/setup/effects/switch_2.asm
new file mode 100644 (file)
index 0000000..1c66a77
--- /dev/null
@@ -0,0 +1,21 @@
+;PZU
+    name "Switch 2 - channel"
+    include "emu_constants.asm"
+    
+Left   IO
+Right  IO
+
+switchL control 0,0,1
+switchR control 0,0,1
+
+    macints Left, C_0, Left, switchL
+    macints Right, C_0, Right, switchR
+;    macs C_0, switchL, C_0, C_0
+;    beq .left
+;    macs Left, Left, C_0, C_0
+;.left
+;    macs C_0, switchR, C_0, C_0
+;    beq .end
+;    macs Right, Right, C_0, C_0
+;.end
+    end
\ No newline at end of file
diff --git a/ld10k1/setup/effects/switch_6.asm b/ld10k1/setup/effects/switch_6.asm
new file mode 100644 (file)
index 0000000..f46f16f
--- /dev/null
@@ -0,0 +1,29 @@
+;PZU
+    name "Switch 6 - channel"
+    include "emu_constants.asm"
+    
+Left           IO
+Right          IO
+LeftSurr       IO
+RightSurr      IO
+Center         IO
+LFE            IO
+
+switch control 0,0,1
+
+    macints Left, C_0, Left, switch
+    macints Right, C_0, Right, switch
+    macints LeftSurr, C_0, LeftSurr, switch
+    macints RightSurr, C_0, RightSurr, switch
+    macints Center, C_0, Center, switch
+    macints LFE, C_0, LFE, switch
+;    macs C_0, switch, C_0, C_0
+;    beq .end
+;    macs Left, Left, C_0, C_0
+;    macs Right, Right, C_0, C_0
+;    macs LeftSurr, LeftSurr, C_0, C_0
+;    macs RightSurr, RightSurr, C_0, C_0
+;    macs Center, Center, C_0, C_0
+;    macs LFE, LFE, C_0, C_0
+;.end
+    end
\ No newline at end of file
diff --git a/ld10k1/setup/effects/tone.asm b/ld10k1/setup/effects/tone.asm
new file mode 100644 (file)
index 0000000..6c74962
--- /dev/null
@@ -0,0 +1,110 @@
+; stolen from alsa-driver
+
+       name "Tone - Bass, Treble"
+       include "emu_constants.asm"
+
+inl    io
+toutl  equ inl
+inr    io
+toutr  equ inr
+inrl   io
+toutrl equ inrl
+inrr   io
+toutrr equ inrr
+inc    io
+toutc  equ inc
+inlfe  io
+toutlfe        equ inlfe
+
+; Tone Control - Bass
+bass0  control 20, 0, 40
+bass1  control 20, 0, 40
+bass2  control 20, 0, 40
+bass3  control 20, 0, 40
+bass4  control 20, 0, 40
+
+; Tone Control - Treble
+treble0        control 20, 0, 40
+treble1        control 20, 0, 40
+treble2        control 20, 0, 40
+treble3        control 20, 0, 40
+treble4        control 20, 0, 40
+
+; Tone Control - Switch
+toneonoff      control 0, 0, 1
+
+; temporary
+templb sta 0, 0, 0, 0, 0
+templt sta 0, 0, 0, 0, 0
+temprb sta 0, 0, 0, 0, 0
+temprt sta 0, 0, 0, 0, 0
+temprlb        sta 0, 0, 0, 0, 0
+temprlt        sta 0, 0, 0, 0, 0
+temprrb        sta 0, 0, 0, 0, 0
+temprrt        sta 0, 0, 0, 0, 0
+tempcb sta 0, 0, 0, 0, 0
+tempct sta 0, 0, 0, 0, 0
+
+outl   dyn
+outr   dyn
+outrl  dyn
+outrr  dyn
+outc   dyn
+outlfe dyn
+
+tmp    sta 0, 0
+
+BT     macro   tempb, tempt, chn
+       macs C_0, C_0, chn, bass0
+       macmv tempb+1, tempb, tempb+1, bass2
+       macmv tempb, chn, tempb, bass1
+       macmv tempb+3, tempb+2, tempb+3, bass4
+       macs tempb+2, ACCUM, tempb+2, bass3
+       acc3 tempb+2, tempb+2, tempb+2, C_0
+
+       macs C_0, C_0, tempb+2, treble0
+       macmv tempt+1, tempt, tempt+1, treble2
+       macmv tempt, tempb+2, tempt, treble1
+       macmv tempt+3, tempt+2, tempt+3, treble4
+       macs tempt+2, ACCUM, tempt+2, treble3
+       macints tempt+2, C_0, tempt+ 2, C_16
+
+       acc3 chn, tempt+2, C_0, C_0
+       endm
+
+SONOFF macro out, in
+       macints tmp, C_0, out, toneonoff
+       andxor tmp+1, toneonoff, C_1, C_1
+       macints tmp+1, C_0, in, tmp+1
+       acc3 out, tmp, tmp+1, C_0
+       endm
+
+;Process tone control
+       macs outl, inl, C_0, C_0
+       macs outr, inr, C_0, C_0
+       macs outrl, inrl, C_0, C_0
+       macs outrr, inrr, C_0, C_0
+       macs outc, inc, C_0, C_0
+       macs outlfe, inlfe, C_0, C_0
+
+       BT templb, templt, outl
+       BT temprb, temprt, outr
+       BT temprlb, temprlt, outrl
+       BT temprrb, temprrt, outrr
+       BT tempcb, tempct, outc
+
+       SONOFF outl, inl
+       SONOFF outr, inr
+       SONOFF outrl, inrl
+       SONOFF outrr, inrr
+       SONOFF outc, inc
+       SONOFF outlfe, inlfe
+       
+       macs toutl, outl, C_0, C_0
+       macs toutr, outr, C_0, C_0
+       macs toutrl, outrl, C_0, C_0
+       macs toutrr, outrr, C_0, C_0
+       macs toutc, outc, C_0, C_0
+       macs toutlfe, outlfe, C_0, C_0
+
+       end
\ No newline at end of file
diff --git a/ld10k1/setup/effects/vol_2.asm b/ld10k1/setup/effects/vol_2.asm
new file mode 100644 (file)
index 0000000..8676d1e
--- /dev/null
@@ -0,0 +1,15 @@
+       name "2-channel Vol"
+
+Left control  0,0,100
+Right control  0,0,100
+       
+signal_l       IO
+signal_r       IO
+       
+       macs  signal_l,$40,signal_l,Left
+       macs  signal_r,$40,signal_r,Right
+
+               end
+       
+
+       
diff --git a/ld10k1/setup/effects/vol_master.asm b/ld10k1/setup/effects/vol_master.asm
new file mode 100644 (file)
index 0000000..9673e00
--- /dev/null
@@ -0,0 +1,23 @@
+       name "Master Vol"
+
+VolM control  0,0,100
+;VolM control  100,0,#1
+       
+left   IO
+right  IO
+rleft  IO
+rright IO
+center IO
+lfe    IO
+       
+       macs  left.o,$40,left,VolM
+       macs  right.o,$40,right,VolM
+       macs  rleft.o,$40,rleft,VolM
+       macs  rright.o,$40,rright,VolM
+       macs  center.o,$40,center,VolM
+       macs  lfe.o,$40,lfe,VolM
+
+       end
+       
+
+       
diff --git a/ld10k1/setup/init_audigy.in b/ld10k1/setup/init_audigy.in
new file mode 100644 (file)
index 0000000..eaa32df
--- /dev/null
@@ -0,0 +1,246 @@
+#!/bin/sh
+
+LO10K1=@bindir@/lo10k1
+
+#PCM Multi
+$LO10K1 -s -n --ctrl c-Left,Right:PCM\ Front\ Playback\ Volume,t-PCM\ Front\ Playback\ Volume:1,c-LeftSurr,RightSurr:PCM\ Surround\ Playback\ Volume,t-PCM\ Surround\ Playback\ Volume:1,c-Center:PCM\ Center\ Playback\ Volume,t-PCM\ Center\ Playback\ Volume:1,c-LFE:PCM\ LFE\ Playback\ Volume,t-PCM\ LFE\ Playback\ Volume:1 --patch_name PCM\ Multi\ Volume -a simple.emu10k1
+#Input
+$LO10K1 --conadd "PIN(PCM Multi Volume)=FX(8,9,2,3,6,7)"
+
+#PCM switch
+#$LO10K1 -n --ctrl c-switchL,switchR:PCM\ Playback\ Switch,t-PCM\ Playback\ Switch:4 --patch_name PCM\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(PCM Switch,0,1)=FX(0,1)"
+#PCM
+$LO10K1 -n --ctrl c-Left,Right:PCM\ Playback\ Volume,t-PCM\ Playback\ Volume:1 --patch_name PCM\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(PCM Switch,0,1)=PIN(PCM Volume,0,1)"
+$LO10K1 --conadd "PIN(PCM Volume,0,1)=FX(0,1)"
+#PCM Capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:PCM\ Capture\ Switch,t-PCM\ Capture\ Switch:4 --patch_name PCM\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(PCM Cap Switch,0,1)=FX(0,1)"
+# PCM Capture
+$LO10K1 -n --ctrl c-Left,Right:PCM\ Capture\ Volume,t-PCM\ Capture\ Volume:1 --patch_name PCM\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(PCM Cap Switch,0,1)=PIN(PCM Cap Volume,0,1)"
+$LO10K1 --conadd "PIN(PCM Cap Volume,0,1)=FX(0,1)"
+
+#Analog Mix switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Analog\ Mix\ Playback\ Switch,t-Analog\ Mix\ Playback\ Switch:4 --patch_name Analog\ Mix\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Analog Mix Switch)=IN(10,11)"
+#Analog Mix
+$LO10K1 -n --ctrl c-Left,Right:Analog\ Mix\ Playback\ Volume,t-Analog\ Mix\ Playback\ Volume:1,s-Analog\ Mix\ Playback\ Volume:100#100 --patch_name Analog\ Mix\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Analog Mix Switch)=PIN(Analog Mix Volume)"
+$LO10K1 --conadd "PIN(Analog Mix Volume)=IN(10,11)"
+#Analog Mix capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Analog\ Mix\ Capture\ Switch,t-Analog\ Mix\ Capture\ Switch:4 --patch_name Analog\ Mix\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Analog Mix Cap Switch)=IN(10,11)"
+#Analog Mix Capture
+$LO10K1 -n --ctrl c-Left,Right:Analog\ Mix\ Capture\ Volume,t-Analog\ Mix\ Capture\ Volume:1 --patch_name Analog\ Mix\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Analog Mix Cap Switch)=PIN(Analog Mix Cap Volume)"
+$LO10K1 --conadd "PIN(Analog Mix Cap Volume)=IN(10,11)"
+
+#Music switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Music\ Playback\ Switch,t-Music\ Playback\ Switch:4 --patch_name Music\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Music Switch)=FX(4,5)"
+#Music
+$LO10K1 -n --ctrl c-Left,Right:Music\ Playback\ Volume,t-Music\ Playback\ Volume:1 --patch_name Music\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Music Switch)=PIN(Music Volume)"
+$LO10K1 --conadd "PIN(Music Volume)=FX(4,5)"
+#Music capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Music\ Capture\ Switch,t-Music\ Capture\ Switch:4 --patch_name Music\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Music Cap Switch)=FX(4,5)"
+#Music Capture
+$LO10K1 -n --ctrl c-Left,Right:Music\ Capture\ Volume,t-Music\ Capture\ Volume:1 --patch_name Music\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Music Cap Switch)=PIN(Music Cap Volume)"
+$LO10K1 --conadd "PIN(Music Cap Volume)=FX(4,5)"
+
+#Mic switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Mic\ Playback\ Switch,t-Mic\ Playback\ Switch:4 --patch_name Mic\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Mic Switch)=IN(0,1)"
+#Mic
+$LO10K1 -n --ctrl c-Left,Right:Mic\ Playback\ Volume,t-Mic\ Playback\ Volume:1 --patch_name Mic\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Mic Switch)=PIN(Mic Volume)"
+$LO10K1 --conadd "PIN(Mic Volume)=IN(0,1)"
+#Mic capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Mic\ Capture\ Switch,t-Mic\ Capture\ Switch:4 --patch_name Mic\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Mic Cap Switch)=IN(0,1)"
+#Mic Capture
+$LO10K1 -n --ctrl c-Left,Right:Mic\ Capture\ Volume,t-Mic\ Capture\ Volume:1 --patch_name Mic\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Mic Cap Switch)=PIN(Mic Cap Volume)"
+$LO10K1 --conadd "PIN(Mic Cap Volume)=IN(0,1)"
+
+#Audigy CD switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Audigy\ CD\ Playback\ Switch,t-Audigy\ CD\ Playback\ Switch:4 --patch_name Audigy\ CD\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Audigy CD Switch)=IN(2,3)"
+#Audigy CD
+$LO10K1 -n --ctrl c-Left,Right:Audigy\ CD\ Playback\ Volume,t-Audigy\ CD\ Playback\ Volume:1 --patch_name Audigy\ CD\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Audigy CD Switch)=PIN(Audigy CD Volume)"
+$LO10K1 --conadd "PIN(Audigy CD Volume)=IN(2,3)"
+#Audigy CD capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Audigy\ CD\ Capture\ Switch,t-Audigy\ CD\ Capture\ Switch:4 --patch_name Audigy\ CD\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Audigy CD Cap Switch)=IN(2,3)"
+#Audigy CD Capture
+$LO10K1 -n --ctrl c-Left,Right:Audigy\ CD\ Capture\ Volume,t-Audigy\ CD\ Capture\ Volume:1 --patch_name Audigy\ CD\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Audigy CD Cap Switch)=PIN(Audigy CD Cap Volume)"
+$LO10K1 --conadd "PIN(Audigy CD Cap Volume)=IN(2,3)"
+
+#Optical & Coaxial IN switch
+#$LO10K1 -n --ctrl c-switchL,switchR:IEC958\ Opt\ and\ Coax\ Playback\ Switch,t-IEC958\ Opt\ and\ Coax\ Playback\ Switch:4 --patch_name Opt\ and\ Coax\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Opt and Coax Switch)=IN(4,5)"
+#Optical & Coaxial IN
+$LO10K1 -n --ctrl c-Left,Right:IEC958\ Opt\ and\ Coax\ Playback\ Volume,t-IEC958\ Opt\ and\ Coax\ Playback\ Volume:1 --patch_name Opt\ and\ Coax\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Opt and Coax Switch)=PIN(Opt and Coax Volume)"
+$LO10K1 --conadd "PIN(Opt and Coax Volume)=IN(4,5)"
+#Optical & Coaxial IN capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:IEC958\ Opt\ and\ Coax\ Capture\ Switch,t-IEC958\ Opt\ and\ Coax\ Capture\ Switch:4 --patch_name Opt\ and\ Coax\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Opt and Coax Cap Switch)=IN(4,5)"
+#Optical & Coaxial IN Capture
+$LO10K1 -n --ctrl c-Left,Right:IEC958\ Opt\ and\ Coax\ Capture\ Volume,t-IEC958\ Opt\ and\ Coax\ Capture\ Volume:1 --patch_name Opt\ and\ Coax\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Opt and Coax Cap Switch)=PIN(Opt and Coax Cap Volume)"
+$LO10K1 --conadd "PIN(Opt and Coax Cap Volume)=IN(4,5)"
+
+#Line2 switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Line2\ Playback\ Switch,t-Line2\ Playback\ Switch:4 --patch_name Line2\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Line2 Switch)=IN(8,9)"
+#Line2
+$LO10K1 -n --ctrl c-Left,Right:Line2\ Playback\ Volume,t-Line2\ Playback\ Volume:1 --patch_name Line2\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Line2 Switch)=PIN(Line2 Volume)"
+$LO10K1 --conadd "PIN(Line2 Volume)=IN(8,9)"
+#Line2 capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Line2\ Capture\ Switch,t-Line2\ Capture\ Switch:4 --patch_name Line2\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Line2 Cap Switch)=IN(8,9)"
+#Line2 Capture
+$LO10K1 -n --ctrl c-Left,Right:Line2\ Capture\ Volume,t-Line2\ Capture\ Volume:1 --patch_name Line2\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Line2 Cap Switch)=PIN(Line2 Cap Volume)"
+$LO10K1 --conadd "PIN(Line2 Cap Volume)=IN(8,9)"
+
+#Aux2 switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Aux2\ Playback\ Switch,t-Aux2\ Playback\ Switch:4 --patch_name Aux2\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Aux2 Switch)=IN(12,13)"
+#Aux2
+$LO10K1 -n --ctrl c-Left,Right:Aux2\ Playback\ Volume,t-Aux2\ Playback\ Volume:1 --patch_name Aux2\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Aux2 Switch)=PIN(Aux2 Volume)"
+$LO10K1 --conadd "PIN(Aux2 Volume)=IN(12,13)"
+#Aux2 capture switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Aux2\ Capture\ Switch,t-Aux2\ Capture\ Switch:4 --patch_name Aux2\ Cap\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "PIN(Aux2 Cap Switch)=IN(12,13)"
+#Aux2 Capture
+$LO10K1 -n --ctrl c-Left,Right:Aux2\ Capture\ Volume,t-Aux2\ Capture\ Volume:1 --patch_name Aux2\ Cap\ Volume -a vol_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Aux2 Cap Switch)=PIN(Aux2 Cap Volume)"
+$LO10K1 --conadd "PIN(Aux2 Cap Volume)=IN(12,13)"
+
+#1
+#Stereo to 5.1
+$LO10K1 -n --ctrl c-Left,Right:Front\ Playback\ Volume,t-Front\ Playback\ Volume:1,s-Front\ Playback\ Volume:100#100,c-LeftSurr,RightSurr:Surround\ Playback\ Volume,t-Surround\ Playback\ Volume:1,c-Center:Center\ Playback\ Volume,t-Center\ Playback\ Volume:1,c-LFE:LFE\ Playback\ Volume,t-LFE\ Playback\ Volume:1 --patch_name Stereo\ To\ 51 -a sto51.emu10k1
+#Input
+$LO10K1 --conadd "POUT(PCM Volume)=PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Analog Mix Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Music Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Mic Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Audigy CD Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Opt and Coax Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Line2 Volume)>PIN(Stereo To 51,0,1)"
+$LO10K1 --conadd "POUT(Aux2 Volume)>PIN(Stereo To 51,0,1)"
+
+
+#Capture
+#$LO10K1 -n --patch_name Capture\ Copy -a copy_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(PCM Cap Volume)=PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Analog Mix Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Music Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Mic Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Audigy CD Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Opt and Coax Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Line2 Cap Volume)>PIN(Capture Copy)"
+#$LO10K1 --conadd "POUT(Aux2 Cap Volume)>PIN(Capture Copy)"
+#Output
+#$LO10K1 --conadd "POUT(Capture Copy)=OUT(22,23)"
+
+$LO10K1 --conadd "POUT(PCM Cap Volume)=OUT(22,23)"
+$LO10K1 --conadd "POUT(Analog Mix Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Music Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Mic Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Audigy CD Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Opt and Coax Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Line2 Cap Volume)>OUT(22,23)"
+$LO10K1 --conadd "POUT(Aux2 Cap Volume)>OUT(22,23)"
+
+
+#Tone
+$LO10K1 -n --ctrl c-bass0,bass1,bass2,bass3,bass4:Tone\ Control\ -\ Bass,t-Tone\ Control\ -\ Bass:2,v-Tone\ Control\ -\ Bass:1,c-treble0,treble1,treble2,treble3,treble4:Tone\ Control\ -\ Treble,t-Tone\ Control\ -\ Treble:3,v-Tone\ Control\ -\ Treble:1,c-toneonoff:Tone\ Control\ -\ Switch,t-Tone\ Control\ -\ Switch:4 --patch_name Tone\ Controls -a tone.emu10k1
+#Input
+$LO10K1 --conadd "POUT(PCM Multi Volume)=PIN(Tone Controls)"
+$LO10K1 --conadd "POUT(Stereo To 51)>PIN(Tone Controls)"
+
+#Master
+$LO10K1 -n --ctrl c-VolM:Master\ Playback\ Volume,t-Master\ Playback\ Volume:1 --patch_name Master\ Volume -a vol_master.emu10k1
+#Inputs
+$LO10K1 --conadd "POUT(Tone Controls)>PIN(Master Volume)"
+
+#Master switch
+#$LO10K1 -n --ctrl c-switch:Master\ Playback\ Switch,t-Master\ Playback\ Switch:4 --patch_name Master\ Switch -a switch_6.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Master Volume)=PIN(Master Switch)"
+
+#Output
+$LO10K1 -n --ctrl c-enableL,enableR:IEC958\ Optical\ Raw\ Playback\ Switch,t-IEC958\ Optical\ Raw\ Playback\ Switch:4 --patch_name Output -a output.emu10k1
+#Inputs
+#$LO10K1 --conadd "POUT(Master Switch)=PIN(Output,0,1,2,3,4,5)"
+$LO10K1 --conadd "POUT(Master Volume)=PIN(Output,0,1,2,3,4,5)"
+$LO10K1 --conadd "PIN(Output,6,7)=FX(20,21)"
+#Output
+$LO10K1 --conadd "POUT(Output,0,1,2,3,4,5)=OUT(8,9,14,15,10,11)"
+#$LO10K1 --conadd "POUT(Output,2,3,4,5)=OUT(14,15,10,11)"
+$LO10K1 --conadd "POUT(Output,6,7,8,9,10,11)=OUT(0,1,6,7,2,3)"
+
+#$LO10K1 -n --patch_name delay1 -a delay.emu10k1
+#$LO10K1 --conadd "POUT(delay1,0)=OUT(8)"
+#$LO10K1 --conadd "PIN(delay1,0)=POUT(Output,0)"
+
+#$LO10K1 -n --patch_name delay2 -a delay.emu10k1
+#$LO10K1 --conadd "POUT(delay2,0)=OUT(9)"
+#$LO10K1 --conadd "PIN(delay2,0)=POUT(Output,1)"
+
+#Headphone
+$LO10K1 -n --ctrl c-Left,Right:Headphone\ Playback\ Volume,t-Headphone\ Playback\ Volume:1 --patch_name Headphone\ Volume -a vol_2.emu10k1
+#Input
+$LO10K1 --conadd "PIN(Headphone Volume,0,1)>PIN(Stereo To 51,0,1)"
+
+#Headphone switch
+#$LO10K1 -n --ctrl c-switchL,switchR:Headphone\ Playback\ Switch,t-Headphone\ Playback\ Switch:4 --patch_name Headphone\ Switch -a switch_2.emu10k1
+#Input
+#$LO10K1 --conadd "POUT(Headphone Volume)=PIN(Headphone Switch)"
+#Output
+#$LO10K1 --conadd "POUT(Headphone Switch,0,1)=OUT(4,5)"
+$LO10K1 --conadd "POUT(Headphone Volume,0,1)=OUT(4,5)"
diff --git a/ld10k1/setup/init_live.in b/ld10k1/setup/init_live.in
new file mode 100644 (file)
index 0000000..9b83059
--- /dev/null
@@ -0,0 +1,390 @@
+#!/bin/sh
+#
+# Copyright (c) 2004 Mikael Magnusson <mikma@users.sourceforge.net>
+#
+
+LO10K1=@bindir@/lo10k1
+
+#LO10K1="valgrind --num-callers=6 ../lo10k1"
+
+DEBUG=0
+
+function runlo10k1
+{
+    if test $DEBUG -gt 2 ; then
+       echo $LO10K1 "$@"
+    fi
+
+    $LO10K1 "$@"
+
+    res=$?
+    
+
+    if test $res -ne 0 ; then
+       echo Failed $LO10K1 "$@"
+    fi
+}
+
+function connect
+{
+    from=$1
+    op=$2
+    to=$3
+
+    if test $DEBUG -gt 1 ; then
+       echo "connect  $from $op $to"
+    fi
+
+    runlo10k1 --conadd "$from$op$to"
+}
+
+function copy
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "copy              \"$name\" $port"
+    fi
+
+    # Copy
+    runlo10k1 -n --patch_name "$name Copy" -a copy_2.emu10k1
+    # Input
+    connect "PIN($name Copy)" '=' "$port"
+}
+
+function volume
+{
+    local name=$1
+    local port=$2
+    local default=$3
+
+    if test $DEBUG -gt 1 ; then
+       echo "volume            \"$name\" $port default=$default"
+    fi
+
+    # Volume
+    runlo10k1 -n --ctrl "c-Left,Right:$name Volume,t-$name Volume:1,s-$name Volume:$default" --patch_name "$name Volume" -a vol_2.emu10k1
+    # Input
+    connect "PIN($name Volume)" '=' "$port"
+}
+
+function master_volume
+{
+    local name=$1
+    local port=$2
+    local default=$3
+
+    if test $DEBUG -gt 1 ; then
+       echo "master volume \"$name\" $port default=$default"
+    fi
+
+    # Master
+    runlo10k1 -n --ctrl "c-VolM:$name Volume,t-$name Volume:1,s-$name Volume:$default" --patch_name "$name Volume" -a vol_master.emu10k1
+    # Input
+    connect "$port" '=' "PIN($name Volume)"
+}
+
+function switch
+{
+    local name=$1
+    local port=$2
+    local default=$3
+
+    if test $DEBUG -gt 1 ; then
+       echo "switch            \"$name\" $port default=$default"
+    fi
+
+    # Switch
+    runlo10k1 -n --ctrl "c-switchL,switchR:$name Switch,t-$name Switch:4,s-$name Switch:$default" --patch_name "$name Switch" -a switch_2.emu10k1
+    # Input
+    connect "PIN($name Switch)" '>' "$port"
+}
+
+function master_switch
+{
+    local name=$1
+    local port=$2
+    local default=$3
+
+    if test $DEBUG -gt 1 ; then
+       echo "master_switch \"$name\" $port default=$default"
+    fi
+
+    # Master switch
+    runlo10k1 -n --ctrl "c-switch:$name Switch,t-$name Switch:4,s-$name Switch:$default" --patch_name "$name Switch" -a switch_6.emu10k1
+    # Input
+    connect "PIN($name Switch)" '=' "$port"
+}
+
+function playback
+{
+    name=$1
+    port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "playback          \"$name\" $port"
+    fi
+
+    # Switch
+    switch "$name Playback" "$port" "1#1"
+    volume "$name Playback" "POUT($name Playback Switch)" "0#0"
+    # Output
+    connect "POUT($name Playback Volume)" '>' "PIN(Wave Stereo To 51,0,1)"
+}
+
+function playback_noswitch
+{
+    name=$1
+    port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "playback_noswitch \"$name\" $port"
+    fi
+
+    # Switch
+    volume "$name Playback" "$port" "0#0"
+    # Output
+    connect "POUT($name Playback Volume)" '>' "PIN(Wave Stereo To 51,0,1)"
+}
+
+function capture
+{
+    name=$1
+    port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "capture           \"$name\" $port"
+    fi
+
+    # Capture switch
+    switch "$name Capture" "$port" "0#0"
+    volume "$name Capture" "POUT($name Capture Switch)" "100#100"
+    # Output
+    connect "POUT($name Capture Volume)" '>' "OUT(OUT_PCM_Capture_Left,OUT_PCM_Capture_Right)"
+}
+
+function capture_noswitch
+{
+    name=$1
+    port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "capture_noswitch  \"$name\" $port"
+    fi
+
+    # Capture switch
+    volume "$name Capture" "$port" "100#100"
+    # Output
+    connect "POUT($name Capture Volume)" '>' "OUT(OUT_PCM_Capture_Left,OUT_PCM_Capture_Right)"
+}
+
+function master
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "master \"$name\" $port"
+    fi
+
+    # Switch
+    master_volume "$name Playback" "$port" "100"
+    master_switch "$name Playback" "POUT($name Playback Volume)" "1"
+}
+
+function dump_patches
+{
+    num=$1
+
+    for (( i=0; $i < $num; i=$i+1 )); do
+       p=$(( $i + 100))
+       runlo10k1 --debug $p
+    done
+
+
+    exit
+}
+
+
+function simple_stereo_to_51
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 1 ; then
+       echo "simple_stereo_to_51 \"$name\" $port"
+    fi
+
+# Stereo to 5.1
+    runlo10k1 -n --ctrl "c-Left,Right:$name Playback Volume,t-$name Playback Volume:1,s-$name Playback Volume:100#100,c-LeftSurr,RightSurr:$name Surround Playback Volume,t-$name Surround Playback Volume:1,c-Center:$name Center Playback Volume,t-$name Center Playback Volume:1,c-LFE:$name LFE Playback Volume,t-$name LFE Playback Volume:1" --patch_name "$name Stereo To 51" -a sto51.emu10k1
+# Input
+    connect "$port" '>' "PIN($name Stereo To 51,0,1)"
+
+# Output
+    connect "POUT($name Stereo To 51,0,1,2,3,4)" '>' "PIN(Tone Control,0,1,2,3,4)"
+}
+
+function prologic
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 1 ; then
+       echo "prologic \"$name\" $port"
+    fi
+
+# Stereo to 5.1
+    runlo10k1 -n --ctrl "" --patch_name "$name Stereo To 51" -a prologic.emu10k1
+# Input
+    connect "PIN($name Stereo To 51,0,1)" '>' "$port"
+
+# PCM Multi
+    runlo10k1 -n --ctrl "c-Left,Right:$name Playback Volume,t-$name Playback Volume:1,c-LeftSurr,RightSurr:$name Surround Playback Volume,t-$name Surround Playback Volume:1,c-Center:$name Center Playback Volume,t-$name Center Playback Volume:1,c-LFE:$name LFE Playback Volume,t-LFE Playback Volume:1" --patch_name "$name Multi Volume" -a simple.emu10k1
+# Input
+    connect "POUT($name Stereo To 51)" '=' "PIN($name Multi Volume,0,1,2,3,4)"
+
+# Output
+    connect "POUT($name Multi Volume,0,1,2,3,4)" '>' "PIN(Tone Control,0,1,2,3,4)"
+}
+
+function stereo_to_51
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "stereo_to_51 \"$name\" $port"
+    fi
+
+#    simple_stereo_to_51 "$name" "$port"
+    prologic "$name" "$port"
+
+}
+
+function tone
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "tone \"$name\" $port"
+    fi
+
+#
+# Tone
+#
+    runlo10k1 -n --ctrl "c-bass0,bass1,bass2,bass3,bass4:$name - Bass,t-$name - Bass:2,v-$name - Bass:1,c-treble0,treble1,treble2,treble3,treble4:$name - Treble,t-$name - Treble:3,v-$name - Treble:1,c-toneonoff:$name - Switch,t-$name - Switch:4" --patch_name "${name}" -a tone.emu10k1
+}
+
+function multi_playback
+{
+    local name=$1
+    local port=$2
+
+    if test $DEBUG -gt 0 ; then
+       echo "multi_playback \"$name\" $port"
+    fi
+
+# PCM Multi
+    runlo10k1 -n --ctrl "c-Left,Right:PCM Front Playback Volume,t-PCM Front Playback Volume:1,c-LeftSurr,RightSurr:Surround Playback Volume,t-Surround Playback Volume:1,c-Center:Center Playback Volume,t-Center Playback Volume:1,c-LFE:LFE Playback Volume,t-LFE Playback Volume:1" --patch_name "$name Multi Volume" -a simple.emu10k1
+# Input
+    connect "PIN($name Multi Volume)" '>' "$port"
+# Output
+    connect "POUT($name Multi Volume)" '>' "PIN(Tone Control)"
+}
+
+function fxbus
+{
+    runlo10k1 --patch_name "FX Bus" -a fxbus.emu10k1
+    connect "PIN(FX Bus)" '=' "FX(FX_PCM_Left,FX_PCM_Right,FX_PCM_Surr_Left,FX_PCM_Surr_Right,FX_MIDI_Left,FX_MIDI_Right,FX_Center,FX_LFE,8,9)"
+
+    fx_multi="POUT(FX Bus,0,1,2,3,6,7)"
+    fx_front="POUT(FX Bus,0,1)"
+    fx_rear="POUT(FX Bus,2,3)"
+    fx_midi="POUT(FX Bus,4,5)"
+    fx_pcm="POUT(FX Bus,8,9)"
+}
+
+#dump_patches 16
+
+runlo10k1 -s 
+
+tone "Tone Control"
+
+fxbus
+
+#copy "FX89" "FX(8,9)"
+stereo_to_51 "Wave" "$fx_pcm"
+
+#
+# FXBUS
+#
+multi_playback "PCM" "$fx_multi"
+
+capture "PCM Front" "$fx_front"
+capture "Wave" "$fx_pcm"
+capture "Surround" "$fx_rear"
+
+playback "Music" "$fx_midi"
+capture "Music" "$fx_midi"
+
+
+#
+# INPUTS
+#
+playback "AC97" "IN(IN_AC97_Left,IN_AC97_Right)"
+capture_noswitch "AC97" "IN(IN_AC97_Left,IN_AC97_Right)"
+
+# playback "IEC958 TTL" "IN(IN_TTL_IEC958_Left,IN_TTL_IEC958_Right)"
+# capture "IEC958 TTL" "IN(IN_TTL_IEC958_Left,IN_TTL_IEC958_Right)"
+
+# playback "Zoom Video" "IN(IN_Zoom_Video_Left,IN_Zoom_Video_Right)"
+# capture "Zoom Video" "IN(IN_Zoom_Video_Left,IN_Zoom_Video_Right)"
+
+# playback "IEC958 LiveDrive" "IN(IN_Optical_IEC958_Left,IN_Optical_IEC958_Right)"
+# capture "IEC958 LiveDrive" "IN(IN_Optical_IEC958_Left,IN_Optical_IEC958_Right)"
+
+# playback "Line LiveDrive" "IN(IN_Line_Mic_1_Left,IN_Line_Mic_1_Right)"
+# capture "Line LiveDrive" "IN(IN_Line_Mic_1_Left,IN_Line_Mic_1_Right)"
+
+# playback "IEC958 Coaxial" "IN(IN_Coax_IEC958_Left,IN_Coax_IEC958_Right)"
+# capture "IEC958 Coaxial" "IN(IN_Coax_IEC958_Left,IN_Coax_IEC958_Right)"
+
+# playback "Line2 LiveDrive" "IN(IN_Line_Mic_2_Left,IN_Line_Mic_2_Right)"
+# capture "Line2 LiveDrive" "IN(IN_Line_Mic_2_Left,IN_Line_Mic_2_Right)"
+
+
+master_volume="Master_2 Playback Volume"
+master_switch="Master_2 Playback Switch"
+
+master "Master_2" "POUT(Tone Control)"
+connect "POUT($master_switch)" '>' "OUT(OUT_AC97_Left,OUT_AC97_Right,OUT_Analog_Surr_Left,OUT_Analog_Surr_Right,OUT_AC97_Center,OUT_AC97_LFE)"
+
+exit
+# Headphone
+
+# Headphone Switch
+runlo10k1 -n --ctrl "c-switchL:Headphone Center Playback Switch,c-switchR:Headphone LFE Playback Switch,t-Headphone Center Playback Switch:4,t-Headphone LFE Playback Switch:4,i-Headphone Center Playback Switch:1,i-Headphone LFE P\
+layback Switch:1" --patch_name "Headphone Center Playback Switch" -a switch_2.emu10k1
+#Input
+#connect "POUT(Headphone Playback Volume)" '' "PIN(Headphone Center Playback Switch)"
+#Output
+#connect "POUT(Headphone Center Playback Switch,0,1)" '' "OUT(OUT_Headphone_Left,OUT_Headphone_Right)"
+
+# Headphone Volume
+runlo10k1 -n --ctrl "c-Left,Right:Headphone Playback Volume,t-Headphone Playback Volume#1:1,i-Headphone Playback Volume:1" --patch_name "Headphone Playback Volume" -a vol_2.emu10k1
+#Input
+#runlo10k1 --conadd "PIN(Headphone Playback Volume,0,1)>PIN(Wave Stereo To 51,0,1)"
+#connect "POUT(Headphone Playback Volume,0,1)" '>' "PIN(Wave Stereo To 51,0,1)"
+#connect "POUT(Tone Control,0,1)" '=' "PIN(Headphone Playback Volume,0,1)"
+#connect "POUT(Headphone Playback SwitchTone Control,0,1)" '=' "PIN(Headphone Playback Volume,0,1)"
+
+#Output
+runlo10k1 -n --ctrl "c-enableL,enableR:IEC958 Optical Raw Playback Switch,t-IEC958 Optical Raw Playback Switch:4" --patch_name "Output" -a output.emu10k1
+#Inputs
+runlo10k1 --conadd "POUT(Master Switch)=PIN(Output,0,1,2,3,4,5)"
+#runlo10k1 --conadd "PIN(Output,6,7)=FX(20,21)"
+#Output
+runlo10k1 --conadd "POUT(Output,0,1,2,3,4,5)=OUT(0,1,8,9,17,18)"
+runlo10k1 --conadd "POUT(Output,6,7,8,9,10,11)=OUT(0,1,2,3,4,5)"
diff --git a/ld10k1/src/Makefile.am b/ld10k1/src/Makefile.am
new file mode 100644 (file)
index 0000000..243011c
--- /dev/null
@@ -0,0 +1,25 @@
+bin_PROGRAMS = lo10k1
+sbin_PROGRAMS = ld10k1 dl10k1
+ld10k1_SOURCES = ld10k1.c ld10k1_fnc.c ld10k1_fnc1.c ld10k1_debug.c \
+       ld10k1_driver.c comm.c ld10k1_tram.c \
+       ld10k1_dump.c ld10k1_mixer.c\
+       ld10k1.h ld10k1_fnc_int.h ld10k1_fnc1.h ld10k1_debug.h \
+       ld10k1_driver.h bitops.h ld10k1_tram.h \
+       ld10k1_dump.h ld10k1_dump_file.h ld10k1_mixer.h
+ld10k1_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS)
+ld10k1_LDADD = $(ALSA_LIBS)
+
+#liblo10k1_ladir = $(includedir)/lo10k1
+lib_LTLIBRARIES = liblo10k1.la
+liblo10k1_la_SOURCES = comm.c liblo10k1.c liblo10k1ef.c liblo10k1lf.c
+#liblo10k1_la_HEADERS = comm.h liblo10k1.h liblo10k1ef.h ld10k1_error.h ld10k1_fnc.h liblo10k1lf.h
+
+lo10k1_SOURCES = lo10k1.c
+lo10k1_CFLAGS = $(ALSA_CFLAGS) -DEFFECTSDIR='"$(effectsdir)"'
+lo10k1_LDADD = liblo10k1.la
+
+dl10k1_SOURCES = dl10k1.c ld10k1_dump_file.h
+dl10k1_CFLAGS = $(ALSA_CFLAGS)
+dl10k1_LDADD = $(ALSA_LIBS)
+
+INCLUDES=-I$(top_srcdir)/include
\ No newline at end of file
diff --git a/ld10k1/src/bitops.h b/ld10k1/src/bitops.h
new file mode 100644 (file)
index 0000000..03f106f
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _PZ_GENERIC_BITOPS_H_
+#define _PZ_GENERIC_BITOPS_H_
+/* this is from linux kernel header */
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents.  You should
+ * recode these in the native assembly language, if at all possible.
+ * To guarantee atomicity, these routines call cli() and sti() to
+ * disable interrupts while they operate.  (You have to provide inline
+ * routines to cli() and sti().)
+ *
+ * Also note, these routines assume that you have 32 bit longs.
+ * You will have to change this if you are trying to port Linux to the
+ * Alpha architecture or to a Cray.  :-)
+ * 
+ * C language equivalents written by Theodore Ts'o, 9/26/92
+ */
+
+__inline__ int set_bit(int nr, unsigned long * addr)
+{
+       int     mask, retval;
+
+       addr += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       retval = (mask & *addr) != 0;
+       *addr |= mask;
+       return retval;
+}
+
+__inline__ int clear_bit(int nr, unsigned long * addr)
+{
+       int     mask, retval;
+
+       addr += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       retval = (mask & *addr) != 0;
+       *addr &= ~mask;
+       return retval;
+}
+
+__inline__ int test_bit(int nr, unsigned long * addr)
+{
+       int     mask;
+
+       addr += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       return ((mask & *addr) != 0);
+}
+
+#endif /* _PZ_GENERIC_BITOPS_H */
diff --git a/ld10k1/src/comm.c b/ld10k1/src/comm.c
new file mode 100644 (file)
index 0000000..f010e20
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "comm.h"
+#include "ld10k1_error.h"
+
+/* taken from glibc example */
+int setup_comm(comm_param *param)
+{
+       int sock;
+       struct sockaddr_un lname;
+       struct sockaddr_in iname;
+       size_t size;
+
+       /* Create the socket. */
+       if (param->type == COMM_TYPE_LOCAL)
+               sock = socket (PF_LOCAL, SOCK_STREAM, 0);
+       else
+               sock = socket (PF_INET, SOCK_STREAM, 0);
+       if (sock < 0)
+               return -1;
+
+       if (param->server)      {
+               if (param->type == COMM_TYPE_LOCAL) {
+                       unlink(param->name);
+
+                       /* Bind a name to the socket. */
+                       memset(&lname, 0, sizeof(struct sockaddr_un));
+                       lname.sun_family = AF_LOCAL;
+                       strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
+                       lname.sun_path[sizeof (lname.sun_path) - 1] = '\0';
+
+                       /* The size of the address is
+                       the offset of the start of the filename,
+                       plus its length,
+                       plus one for the terminating null byte.
+                       Alternatively you can just do:
+                       size = SUN_LEN (&name);
+                       */
+                       size = (offsetof (struct sockaddr_un, sun_path) + strlen (lname.sun_path) + 1);
+
+                       if (bind (sock, (struct sockaddr *) &lname, size) < 0)
+                               return -1;
+
+                       chmod(param->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+               } else {
+                       /* Give the socket a name. */
+                       memset(&iname, 0, sizeof(struct sockaddr_in));
+                       iname.sin_family = AF_INET;
+                       iname.sin_port = htons (param->port);
+                       iname.sin_addr.s_addr = htonl(INADDR_ANY);
+                       if (bind(sock, (struct sockaddr *) &iname, sizeof (iname)) < 0)
+                               return -1;
+               }
+       }
+
+       return sock;
+}
+
+int connect_comm(int conn_num, comm_param *param)
+{
+       struct sockaddr_un lname;
+       struct sockaddr_in iname;
+       struct hostent *hostinfo;
+       size_t size;
+       
+       int attempt;
+       int max_attempt;
+       int not_connected;
+       
+       attempt = 0;
+       if (param->wfc)
+               max_attempt = param->wfc / 10;
+       else
+               max_attempt = 0;
+
+       if (param->type == COMM_TYPE_LOCAL) {
+               memset(&lname, 0, sizeof(struct sockaddr_un));
+               lname.sun_family = AF_LOCAL;
+               strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
+               lname.sun_path[sizeof(lname.sun_path) - 1] = '\0';
+
+               size = (offsetof(struct sockaddr_un, sun_path)) + strlen(lname.sun_path) + 1;
+
+               while (1)
+               {
+                       not_connected = connect(conn_num, (struct sockaddr *) &lname, size);
+                       if (!not_connected)
+                               break;
+                       if (attempt >= max_attempt)
+                               return -1;
+                       attempt++;
+                       usleep(10000);
+               }
+       } else {
+               memset(&iname, 0, sizeof(struct sockaddr_in));
+               iname.sin_family = AF_INET;
+               iname.sin_port = htons(param->port);
+               hostinfo = gethostbyname(param->name);
+               if (hostinfo == NULL)
+                       return -1;
+               iname.sin_addr = *(struct in_addr *)hostinfo->h_addr;
+               
+               while (1)
+               {
+                       not_connected = connect(conn_num, (struct sockaddr *) &iname, sizeof(struct sockaddr_in));
+                       if (!not_connected)
+                               break;
+                       if (attempt >= max_attempt)
+                               return -1;
+                       attempt++;
+                       usleep(10000);
+               }
+       }
+       return 0;
+}
+
+int listen_comm(int conn_num)
+{
+       if (listen(conn_num, 1) < 0)
+               return -1;
+       return 0;
+}
+
+int accept_comm(int conn_num)
+{
+       struct sockaddr addr;
+       socklen_t addr_len;
+       int sock;
+
+       addr_len = sizeof(addr);
+       
+       sock = accept(conn_num, &addr, &addr_len);
+       
+       if (sock < 0)
+               return -1;
+
+       return sock;
+}
+
+int free_comm(int conn_num)
+{      
+       if (shutdown(conn_num, 2))
+               return -1;
+       if (close(conn_num) < 0)
+               return -1;
+
+       return 0;
+}
+
+#define MAX_ATEMPT 5
+
+int read_all(int conn_num, void *data, int data_size)
+{
+       int offset = 0;
+       int how_much = data_size;
+       int atempt = 0;
+       int readed = 0;
+       
+       while (atempt < MAX_ATEMPT && how_much > 0)     {
+               readed = read(conn_num, ((char *)data) + offset, how_much);
+               if (readed < 0)
+                       return LD10K1_ERR_COMM_READ;
+               offset += readed;
+               how_much -= readed;
+               atempt++;
+               if (how_much > 0)
+                       usleep(10000);
+       }
+       
+       if (how_much > 0)
+               return LD10K1_ERR_COMM_READ;
+       else
+               return data_size;
+}
+
+int write_all(int conn_num, void *data, int data_size)
+{
+       int offset = 0;
+       int how_much = data_size;
+       int atempt = 0;
+       int writed = 0;
+       
+       while (atempt < MAX_ATEMPT && how_much > 0)     {
+               writed = write(conn_num, ((char *)data) + offset, how_much);
+               if (writed < 0)
+                       return LD10K1_ERR_COMM_WRITE;
+               offset += writed;
+               how_much -= writed;
+               atempt++;
+               if (how_much > 0)
+                       usleep(50000);
+       }
+       
+       if (how_much > 0)
+               return LD10K1_ERR_COMM_WRITE;
+       else
+               return data_size;
+}
+
+int send_request(int conn_num, int op, void *data, int data_size)
+{
+       int nbytes;
+       struct msg_req header;
+
+       header.op = op;
+       header.size = data_size;
+
+       /* header */
+       nbytes = write_all(conn_num, &header, sizeof(header));
+       if (nbytes < 0)
+               return nbytes;
+
+       if (data_size > 0) {
+               /* data */
+               nbytes = write_all(conn_num, data, data_size);
+               if (nbytes < 0)
+                       return nbytes;
+       }
+       return 0;
+}
+
+int send_response(int conn_num, int op, int err, void *data, int data_size)
+{
+       int nbytes;
+       struct msg_resp header;
+
+       header.op = op;
+       header.err = err;
+       header.size = data_size;
+
+       /* header */
+       nbytes = write_all(conn_num, &header, sizeof(header));
+       if (nbytes < 0)
+               return nbytes;
+
+       if (data_size > 0) {
+               /* data */
+               nbytes = write_all(conn_num, data, data_size);
+               if (nbytes < 0)
+                       return nbytes;
+       }
+       return 0;
+}
+
+int send_msg_data(int conn_num, void *data, int data_size)
+{
+       int nbytes;
+
+       if (data_size > 0) {
+               /* data */
+               nbytes = write_all(conn_num, data, data_size);
+               if (nbytes < 0)
+                       return nbytes;
+       }
+       return 0;
+}
+
+int receive_request(int conn_num, int *op, int *data_size)
+{
+       struct msg_req header;
+       int nbytes;
+       
+       nbytes = read_all(conn_num, &header, sizeof(header));
+       if (nbytes < 0)
+               return nbytes;
+       if (nbytes == 0) {
+               *op = -1;
+               *data_size = 0;
+               return 0;
+       }
+       *op = header.op;
+       *data_size = header.size;
+       return 0;
+}
+
+int receive_response(int conn_num, int *op, int *data_size)
+{
+       struct msg_resp header;
+       int nbytes;
+       
+       nbytes = read_all(conn_num, &header, sizeof(header));
+       if (nbytes < 0)
+               return nbytes;
+       if (nbytes == 0) {
+               *op = -1;
+               *data_size = 0;
+               return 0;
+       }
+       *op = header.op;
+       *data_size = header.size;
+       if (header.err < 0)
+               return header.err;
+       return 0;
+}
+
+int receive_msg_data(int conn_num, void *data, int data_size)
+{
+       int nbytes;
+       nbytes = read_all(conn_num, data, data_size);
+       if (nbytes < 0)
+               return nbytes;
+       return 0;
+}
+
+void *receive_msg_data_malloc(int conn_num, int data_size)
+{
+       void *tmp;
+       
+       tmp = malloc(data_size);
+       if (!tmp)
+               return NULL;
+               
+       if (receive_msg_data(conn_num, tmp, data_size)) {
+               free(tmp);
+               return NULL;    
+       }
+       return tmp;
+}
diff --git a/ld10k1/src/dl10k1.c b/ld10k1/src/dl10k1.c
new file mode 100644 (file)
index 0000000..7ca3f43
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ *  EMU10k1 dump loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   Hwdep usage based on sb16_csp
+ *
+ *   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
+ *
+ */
+
+/* TODO - kontrola dat, ktore nahravam */
+
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <alsa/asoundlib.h>
+#include <alsa/sound/emu10k1.h>
+
+#include <getopt.h>
+#include <bitops.h>
+
+#include "ld10k1_dump_file.h"
+
+#define DL10K1_SIGNATURE "DUMP Image (dl10k1)"
+int card = 0;
+snd_hwdep_t *handle;
+const char *card_proc_id;
+
+void error(const char *fmt,...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       fprintf(stderr, "Error: ");
+       vfprintf(stderr, fmt, va);
+       fprintf(stderr, "\n");
+       va_end(va);
+}
+
+static void help(char *command)
+{
+       fprintf(stderr,
+               "Usage: %s [-options]\n"
+               "\nAvailable options:\n"
+               "  -h, --help        this help\n"
+               "  -c, --card        select card number, default = 0\n"
+               "  -d, --dump        file with dump\n"
+               , command);
+}
+
+int driver_set_tram_size(int tram_size)
+{
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
+               error("unable to setup tram");
+               return 1;
+       }
+       return 0;
+}
+
+void free_code_struct(emu10k1_fx8010_code_t *code)
+{
+       if (code->gpr_map)
+               free(code->gpr_map);
+       if (code->tram_data_map)
+               free(code->tram_data_map);
+       if (code->tram_addr_map)
+               free(code->tram_addr_map);
+       if (code->code)
+               free(code->code);
+}
+
+int alloc_code_struct(emu10k1_fx8010_code_t *code)
+{
+       /* alloc code structure */
+       code->gpr_map = NULL;
+       code->tram_data_map = NULL;
+       code->tram_addr_map = NULL;
+       code->code = NULL;
+       
+       code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
+       if (!code->gpr_map)
+               goto err;
+       memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
+
+       code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
+       if (!code->tram_data_map)
+               goto err;
+       memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
+
+       code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
+       if (!code->tram_addr_map)
+               goto err;
+       memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
+
+       code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
+       if (!code->code)
+               goto err;
+       memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
+
+        return 0;
+err:
+       free_code_struct(code);
+       return -1;
+}
+
+int driver_init_dsp(int audigy)
+{
+       int i;
+       emu10k1_fx8010_code_t code;
+       emu10k1_fx8010_control_gpr_t *ctrl;
+       emu10k1_ctl_elem_id_t *ids;
+       emu10k1_fx8010_pcm_t ipcm;
+       unsigned int *iptr;
+
+       if (alloc_code_struct(&code) < 0) {
+               error("no mem");
+               return 1;
+       }
+
+       /* get count of controls */
+       code.gpr_list_control_count = 0;
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
+               error("unable to peek code");
+               free_code_struct(&code);
+               return 1;
+       }
+
+       ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total);
+       if (!ctrl) {
+               error("no mem");
+               free_code_struct(&code);
+               return 1;
+       }
+
+       code.gpr_list_control_count = code.gpr_list_control_total;
+       code.gpr_list_controls = ctrl;
+
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = 0x0;
+       for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
+               code.tram_valid[i] = 0x0;
+       for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
+               code.code_valid[i] = 0x0;;
+
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
+               error("unable to peek code");
+               free_code_struct(&code);
+               free(ctrl);
+               return 1;
+       }
+
+       
+       /* new name */
+       strcpy(code.name, DL10K1_SIGNATURE);
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = ~0;
+
+       for (i = 0; i < sizeof(code.gpr_valid) * 8; i++)
+               code.gpr_map[i] = 0;
+
+       ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total);
+       if (!ids) {
+               free_code_struct(&code);
+               free(ctrl);
+               error("no mem");
+               return 1;
+       }
+
+       code.gpr_del_control_count = code.gpr_list_control_total;
+       if (code.gpr_del_control_count) {
+               for (i = 0; i < code.gpr_del_control_count; i++) {
+                       memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
+               }
+       }
+
+       free(ctrl);
+
+       code.gpr_del_controls = ids;
+       code.gpr_list_control_count = 0;
+       code.gpr_add_control_count = 0;
+       code.gpr_list_control_count = 0;
+
+       for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
+               code.tram_valid[i] = ~0;
+       for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
+               code.code_valid[i] = ~0;
+
+       for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
+               code.tram_addr_map[i] = 0;
+               code.tram_data_map[i] = 0;
+       }
+
+       for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
+               if (audigy) {
+                       *iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
+                       *(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
+               } else {
+                       *iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
+                       *(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
+               }
+
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
+               error("unable to poke code");
+               free_code_struct(&code);
+               free(ids);
+               return 1;
+       }
+
+       free(ids);
+
+       /* delete tram pcm dsp part */
+       if (!audigy) {
+               for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
+                       ipcm.substream = i;
+                       ipcm.channels = 0;
+                       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
+                               error("unable to poke code");
+                               free_code_struct(&code);
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+int dump_load(int audigy, char *file_name)
+{
+       struct stat dump_stat;
+       void *dump_data, *ptr;
+       FILE *dump_file;
+       emu10k1_fx8010_control_gpr_t *ctrl = NULL;
+       ld10k1_ctl_dump_t *fctrl = NULL;
+       unsigned int *fgpr = NULL;
+       ld10k1_tram_dump_t *ftram = NULL;
+       ld10k1_instr_dump_t *finstr = NULL;
+       int i, j;
+       unsigned int vaddr, addr;
+       int op;
+       
+       unsigned int *iptr;
+
+       emu10k1_fx8010_code_t code;
+
+       ld10k1_dump_t *header = NULL;
+
+       /* first load patch to mem */
+       if (stat(file_name, &dump_stat)) {
+               error("unable to load patch %s", file_name);
+               return 1;
+       }
+
+       /* minimal dump len is size of header */
+       if (dump_stat.st_size < sizeof(ld10k1_dump_t)) {
+               error("unable to load dump %s (wrong file size)", file_name);
+               return 1;
+       }
+
+
+       dump_data = malloc(dump_stat.st_size);
+       if (!dump_data) {
+               error("no mem");
+               return 1;
+       }
+
+       dump_file = fopen(file_name, "r");
+       if (!dump_file) {
+               error("unable to open file %s", file_name);
+               goto err;
+       }
+
+       if (fread(dump_data, dump_stat.st_size, 1, dump_file) != 1) {
+               error("unable to read data from file %s", file_name);
+               goto err;
+       } else
+               fclose(dump_file);
+
+       /* signature check */
+
+       header = (ld10k1_dump_t *)dump_data;
+       if (strncmp(header->signature, "LD10K1 DUMP 001", 16) != 0) {
+               error("wrong dump file %s (wrong signature)", file_name);
+               goto err;
+       }
+       
+       /*printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t),
+               header->ctl_count, sizeof(ld10k1_ctl_dump_t),
+               header->gpr_count, sizeof(unsigned int),
+               header->tram_count, sizeof(ld10k1_tram_dump_t),
+               header->instr_count, sizeof(ld10k1_instr_dump_t));*/
+
+       /*check size */
+       if (sizeof(ld10k1_dump_t) +
+               header->ctl_count * sizeof(ld10k1_ctl_dump_t) +
+               header->gpr_count * sizeof(unsigned int) +
+               header->tram_count * sizeof(ld10k1_tram_dump_t) +
+               header->instr_count * sizeof(ld10k1_instr_dump_t) != dump_stat.st_size)
+               goto err;
+
+       /* check dump type */
+       if (header->dump_type == DUMP_TYPE_LIVE && audigy) {
+               error("can't load dump from Live to Audigy");
+               goto err1;
+       } else if ((header->dump_type == DUMP_TYPE_AUDIGY_OLD ||
+                       header->dump_type == DUMP_TYPE_AUDIGY) &&
+                       !audigy) {
+               error("can't load dump from Audigy to Live");
+               goto err1;
+       } else if (header->dump_type == DUMP_TYPE_AUDIGY_OLD) {
+               error("can't load dump from Audigy (not patched drivers) to Audigy (current drivers)");
+               goto err1;
+       }
+
+       ptr = dump_data;
+       ptr += sizeof(ld10k1_dump_t);
+
+       ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
+       if (!ctrl) {
+               error("no mem");
+               goto err1;
+       }
+
+       if (alloc_code_struct(&code) < 0) {
+               error("no mem");
+               return 1;
+       }
+       
+
+       strcpy(code.name, DL10K1_SIGNATURE);
+
+       /* copy ctls */
+       fctrl = (ld10k1_ctl_dump_t *)ptr;
+       memset(ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
+       for (i = 0; i < header->ctl_count; i++) {
+               strcpy(ctrl[i].id.name, fctrl[i].name);
+               ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
+               ctrl[i].id.index = fctrl[i].index;
+               ctrl[i].vcount = fctrl[i].vcount;
+               ctrl[i].count = fctrl[i].count;
+               for (j = 0; j < 32; j++) {
+                       ctrl[i].gpr[j] = fctrl[i].gpr_idx[j];
+                       ctrl[i].value[j] = fctrl[i].value[j];
+               }
+               ctrl[i].min = fctrl[i].min;
+               ctrl[i].max = fctrl[i].max;
+               ctrl[i].translation = fctrl[i].translation;
+       }
+       code.gpr_add_control_count = header->ctl_count;
+       code.gpr_add_controls = ctrl;
+
+       code.gpr_del_control_count = 0;
+       code.gpr_del_controls = NULL;
+
+       code.gpr_list_control_count = 0;
+       code.gpr_list_controls = NULL;
+
+       /* copy gprs */
+       ptr += sizeof(ld10k1_ctl_dump_t) * header->ctl_count;
+       fgpr = (unsigned int *)ptr;
+
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = ~0;
+
+       for (i = 0; i < header->gpr_count; i++)
+               code.gpr_map[i] = fgpr[i];
+
+       ptr += sizeof(unsigned int) * header->gpr_count;
+       ftram = (ld10k1_tram_dump_t *)ptr;
+       /* tram addr + data */
+       for (i = 0; i < header->tram_count; i++) {
+               addr = ftram[i].addr;
+               vaddr = addr & 0xFFFFF;
+               op = ftram[i].type;
+
+               set_bit(i, code.tram_valid);
+               switch(op) {
+                       case DUMP_TRAM_READ:
+                               if (audigy)
+                                       vaddr = vaddr | 0x2 << 20;
+                               else
+                                       vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
+                               break;
+                       case DUMP_TRAM_WRITE:
+                               if (audigy)
+                                       vaddr = vaddr | 0x6 << 20;
+                               else
+                                       vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
+                               break;
+                       case DUMP_TRAM_NULL:
+                       default:
+                               vaddr = 0;
+                               break;
+               }
+
+               code.tram_addr_map[i] = vaddr;
+               code.tram_data_map[i] = ftram[i].data;
+       }
+
+       ptr += sizeof(ld10k1_tram_dump_t) * header->tram_count;
+       finstr = (ld10k1_instr_dump_t *)ptr;
+       for (iptr = code.code, i = 0; i < header->instr_count; i++, iptr += 2) {
+               set_bit(i, code.code_valid);
+               if (finstr[i].used) {
+                       if (audigy) {
+                               *iptr = ((finstr[i].arg[2] & 0x7ff) << 12) | (finstr[i].arg[3] & 0x7ff);
+                               *(iptr + 1) = ((finstr[i].op & 0x0f) << 24) | ((finstr[i].arg[0] & 0x7ff) << 12) | (finstr[i].arg[1] & 0x7ff);
+                       } else {
+                               if (i < 0x200) {
+                                       *iptr = ((finstr[i].arg[2] & 0x3ff) << 10) | (finstr[i].arg[3] & 0x3ff);
+                                       *(iptr + 1) = ((finstr[i].op & 0x0f) << 20) | ((finstr[i].arg[0] & 0x3ff) << 10) | (finstr[i].arg[1] & 0x3ff);
+                               }
+                       }
+               } else {
+                       if (audigy) {
+                               *iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
+                               *(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
+                       } else {
+                               if (i < 0x200) {
+                                       *iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
+                                       *(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
+                               }
+                       }
+               }
+       }
+
+       if (header->dump_type != DUMP_TYPE_AUDIGY_OLD && 
+               driver_set_tram_size(header->tram_size))
+               goto err1;
+
+       if (driver_init_dsp(audigy))
+               goto err1;
+
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
+               error("unable to poke code");
+               goto err1;
+       }
+
+       if (dump_data)
+               free(dump_data);
+
+       if (ctrl)
+               free(ctrl);
+
+       return 0;
+
+err:
+       error("wrong dump file format %s", file_name);
+err1:
+       free_code_struct(&code);
+       if (dump_data)
+               free(dump_data);
+       if (ctrl)
+               free(ctrl);
+
+       return 1;
+}
+
+int main(int argc, char *argv[])
+{
+       int dev;
+       int c;
+       int err;
+       int audigy;
+       
+       int opt_help = 0;
+       char *opt_dump_file = NULL;
+
+       char card_id[32];
+       snd_ctl_t *ctl_handle;
+       snd_ctl_card_info_t *card_info;
+       snd_hwdep_info_t *hwdep_info;
+
+       char name[16];
+
+       snd_ctl_card_info_alloca(&card_info);
+       snd_hwdep_info_alloca(&hwdep_info);
+
+       static struct option long_options[] = {
+                                  {"help", 0, 0, 'h'},
+                                  {"card", 1, 0, 'c'},
+                                  {"dump", 1, 0, 'd'},
+                                  {0, 0, 0, 0}
+               };
+
+       int option_index = 0;
+       while ((c = getopt_long(argc, argv, "hc:d:",
+               long_options, &option_index)) != EOF) {
+               switch (c) {
+/*             case 0: */
+/*                     break; */
+               case 'h':
+                       opt_help = 1;
+                       break;
+               case 'd':
+                       opt_dump_file = optarg;
+                       break;
+               case 'c':
+                       card = snd_card_get_index(optarg);
+                       if (card < 0 || card > 31) {
+                               error("wrong -c argument '%s'\n", optarg);
+                               return 1;
+                       }
+                       break;
+               default:
+                       return 1;
+               }
+       }
+
+       if (opt_help) {
+               help(argv[0]);
+               return 0;
+       }
+
+       if (!opt_dump_file) {
+               error("dump file not specified");
+               return 1;
+       }
+
+       if (getuid() != 0 )
+       {
+               error("You are not running dl10k1 as root.");
+               return 1;
+       }
+       
+       /* Get control handle for selected card */
+       sprintf(card_id, "hw:%i", card);
+       if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {
+               error("control open (%s): %s", card_id, snd_strerror(err));
+               return 1;
+       }
+
+       /* Read control hardware info from card */
+       if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {
+               error("control hardware info (%s): %s", card_id, snd_strerror(err));
+               exit(1);
+       }
+
+       if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) {
+               error("card id (%s): %s", card_id, snd_strerror(err));
+               exit(1);
+       }
+
+
+       /* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */
+       if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 &&
+           strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 &&
+               strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 &&
+               strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) {
+               error("not a EMU10K1/EMU10K2 based card");
+               exit(1);
+       }
+
+       if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 ||
+               strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0)
+               audigy = 1;
+       else
+               audigy = 0;
+
+       /* find EMU10k1 hardware dependant device and execute command */
+       dev = -1;
+       err = 1;
+       while (1) {
+               if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)
+                       error("hwdep next device (%s): %s", card_id, snd_strerror(err));
+               if (dev < 0)
+                       break;
+               snd_hwdep_info_set_device(hwdep_info, dev);
+               if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {
+                       if (err != -ENOENT)
+                               error("control hwdep info (%s): %s", card_id, snd_strerror(err));
+                       continue;
+               }
+               if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) {
+                       sprintf(name, "hw:%i,%i", card, dev);
+
+                       /* open EMU10k1 hwdep device */
+                       if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) {
+                               error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err));
+                               exit(1);
+                       }
+                       
+                       err = dump_load(audigy, opt_dump_file);
+
+                       snd_hwdep_close(handle);
+
+                       break;
+               }
+       }
+
+       snd_ctl_close(ctl_handle);
+
+       return 0;
+}
diff --git a/ld10k1/src/ld10k1.c b/ld10k1/src/ld10k1.c
new file mode 100644 (file)
index 0000000..7359f13
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   Hwdep usage based on sb16_csp
+ *
+ *   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 <limits.h>
+#include <sys/stat.h>
+#include <alsa/asoundlib.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/ioctl.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+
+#include "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_fnc1.h"
+
+int card = 0;
+snd_hwdep_t *handle;
+char comm_pipe[256];
+FILE *comm;
+char pidpath[256];
+FILE *logfile=NULL;
+
+static void vlog(const char *label, const char *fmt, va_list va)
+{
+       FILE *out = stderr;
+
+       if (logfile)
+               out = logfile;
+
+       if (logfile) {
+               char timestr[20];
+               time_t tp;
+
+               tp = time(NULL);
+               strftime(timestr, sizeof(timestr), "%b %d %H:%M:%S",
+                        localtime(&tp));
+               fprintf(out, "%s %s", timestr, label);
+       } else 
+               fprintf(out, label);
+       vfprintf(out, fmt, va);
+       fprintf(out, "\n");
+       fflush(out);
+}
+
+void error(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       vlog("Error: ", fmt, va);
+       va_end(va);
+}
+
+static void log(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       vlog("", fmt, va);
+       va_end(va);
+}
+
+static void help(char *command)
+{
+       fprintf(stderr,
+               "Usage: %s [-options]\n"
+               "\nAvailable options:\n"
+               "  -h, --help        this help\n"
+               "  -c, --card        select card number, default = 0\n"
+               "  -p, --pipe_name   connect to this, default = /tmp/.ld10k1_port\n"
+               "  -n, --network     listen on port\n"
+               "      --port        port number, default = 20480\n"
+               "  -d  --daemon      start in background\n"
+               "  -i  --pidfile     print daemon process id to file, default /var/run/ld10k1.pid\n"
+               "  -l  --logfile     \n"
+               "  -t, --tram_size   initialize tram with given size\n"
+               "               0 -    0 KB\n"
+               "               1 -   16 KB\n"
+               "               2 -   32 KB\n"
+               "               3 -   64 KB\n"
+               "               4 -  128 KB\n"
+               "               5 -  256 KB\n"
+               "               6 -  512 KB\n"
+               "               7 - 1024 KB\n"
+               "               8 - 2048 KB\n"
+               , command);
+}
+
+static void cleanup()
+{
+       if (pidpath[0])
+               unlink(pidpath);
+       log("Exiting daemon");
+}
+
+static void term_handler(int i)
+{
+       exit(1);
+}
+
+int tram_size_table[] = {0, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576};
+
+int main(int argc, char *argv[])
+{
+       int dev;
+       int c;
+       int err;
+       int audigy;
+
+       int opt_help = 0;
+       int tram_size = 0;
+       int opt_daemon = 0;
+       unsigned short opt_port = 20480;
+       int uses_pipe = 1;
+       char logpath[255];
+
+       char card_id[32];
+       const char *card_proc_id;
+
+       snd_ctl_t *ctl_handle;
+       snd_ctl_card_info_t *card_info;
+       snd_hwdep_info_t *hwdep_info;
+       
+       char name[16];
+
+       comm_param params;
+       
+       int option_index;
+       
+       static struct option long_options[] = {
+                                  {"help", 0, 0, 'h'},
+                                  {"card", 1, 0, 'c'},
+                                  {"pipe_name", 1, 0, 'p'},
+                                  {"network", 0, 0, 'n'},
+                                  {"port", 1, 0, 0},
+                                  {"daemon", 0, 0, 'd'},
+                                  {"tram_size", 1, 0, 't'},
+                                  {"pidfile", 1, 0, 'i'},
+                                  {"logfile", 1, 0, 'l'},
+                   {0, 0, 0, 0}
+               };
+
+       snd_ctl_card_info_alloca(&card_info);
+       snd_hwdep_info_alloca(&hwdep_info);
+
+       strcpy(comm_pipe,"/tmp/.ld10k1_port");
+       strcpy(pidpath, "/var/run/ld10k1.pid");
+       memset(logpath, 0, sizeof(logpath));
+
+       option_index = 0;
+       while ((c = getopt_long(argc, argv, "hc:p:t:ndl:i:",
+               long_options, &option_index)) != EOF) {
+               switch (c) {
+               case 0:
+                       if (strcmp(long_options[option_index].name, "port") == 0) {
+                               opt_port = atoi(optarg);
+                       }
+                       break;
+               case 'h':
+                       opt_help = 1;
+                       break;
+               case 'c':
+                       card = snd_card_get_index(optarg);
+                       if (card < 0 || card > 31) {
+                               error ("wrong -c argument '%s'\n", optarg);
+                               return 1;
+                       }
+                       break;
+               case 'p':
+                       uses_pipe = 1;
+                       strncpy(comm_pipe, optarg, sizeof(comm_pipe) - 1);
+                       comm_pipe[sizeof(comm_pipe) - 1] = '\0';
+                       break;
+               case 'n':
+                       uses_pipe = 0;
+                       break;
+               case 'd':
+                       opt_daemon = 1;
+                       break;
+               case 't':
+                       tram_size = atoi(optarg);
+                       if (tram_size < 0)
+                               tram_size = 0;
+                       else if (tram_size > 8)
+                               tram_size = 8;
+                       tram_size = tram_size_table[tram_size];
+                       break;
+               case 'i':
+                       strncpy(pidpath, optarg, sizeof(pidpath) - 1);
+                       pidpath[sizeof(pidpath) - 1] = '\0';
+                       break;
+               case 'l':
+                       strncpy(logpath, optarg, sizeof(logpath) - 1);
+                       logpath[sizeof(logpath) - 1] = '\0';
+                       break;
+               default:
+                       return 1;
+               }
+       }
+
+       if (opt_help) {
+               help(argv[0]);
+               return 0;
+       }
+       
+       if (getuid() != 0 ) {
+               error("You are not running ld10k1 as root.");
+               return 1;
+       }
+       
+       if (logpath[0])
+               logfile = fopen(logpath, "at");
+
+       if (opt_daemon) {
+               FILE *pidfile;
+
+               if (daemon(0, 0) < 0) {
+                   error("Unable to run as daemon.");
+                   return 1;
+               }
+               
+               pidfile = fopen(pidpath, "wt");
+               if (!pidfile) {
+                       log("%s: pidfile (%s)\n", strerror(errno), pidpath);
+                       return 1;
+               }
+               
+               fprintf(pidfile, "%d\n", getpid());
+               fflush(pidfile);
+               fclose(pidfile);
+               
+               atexit(cleanup);
+               signal(SIGTERM, term_handler);
+
+               if (logfile) {
+                       dup2(fileno(logfile), fileno(stderr));
+                       dup2(fileno(logfile), fileno(stdout));
+               }
+               
+               log("Starting daemon");
+       }
+
+       params.type = uses_pipe ? COMM_TYPE_LOCAL : COMM_TYPE_IP;
+       params.name = comm_pipe;
+       params.server = 1;
+       params.port = opt_port;
+       params.wfc = 0;
+
+       /* Get control handle for selected card */
+       sprintf(card_id, "hw:%i", card);
+       if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {
+               error("control open (%s): %s", card_id, snd_strerror(err));
+               return 1;
+       }
+
+       /* Read control hardware info from card */
+       if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {
+               error("control hardware info (%s): %s", card_id, snd_strerror(err));
+               exit(1);
+       }
+
+       if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) {
+               error("card id (%s): %s", card_id, snd_strerror(err));
+               exit(1);
+       }
+
+
+       /* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */
+       if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 &&
+           strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 &&
+               strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 &&
+               strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) {
+               error("not a EMU10K1/EMU10K2 based card");
+               exit(1);
+       }
+
+       if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 ||
+               strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0)
+               audigy = 1;
+       else
+               audigy = 0;
+               
+       /* find EMU10k1 hardware dependant device and execute command */
+       dev = -1;
+       err = 1;
+       while (1) {
+               if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)
+                       error("hwdep next device (%s): %s", card_id, snd_strerror(err));
+               if (dev < 0)
+                       break;
+               snd_hwdep_info_set_device(hwdep_info, dev);
+               if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {
+                       if (err != -ENOENT)
+                               error("control hwdep info (%s): %s", card_id, snd_strerror(err));
+                       continue;
+               }
+               if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) {
+                       sprintf(name, "hw:%i,%i", card, dev);
+
+                       /* open EMU10k1 hwdep device */
+                       if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) {
+                               error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err));
+                               exit(1);
+                       }
+
+                       while (1)
+                               if (main_loop(&params, audigy, card_proc_id, tram_size, ctl_handle)) {
+                                       error("error in main loop");
+                                       break;
+                               }
+                       
+                       snd_hwdep_close(handle);
+
+                       break;
+               }
+       }
+
+       snd_ctl_close(ctl_handle);
+
+       return 0;
+}
diff --git a/ld10k1/src/ld10k1.h b/ld10k1/src/ld10k1.h
new file mode 100644 (file)
index 0000000..aa10304
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_H
+#define __LD10K1_H
+
+#define MAX_CONST_COUNT 0x220
+#define MAX_GPR_COUNT 0x200
+#define MAX_TRAM_COUNT 0x100
+
+/* instructions */
+typedef struct {
+       unsigned int used: 1,
+               modified: 1;
+       unsigned int op_code;
+       unsigned int arg[4];
+} ld10k1_instr_t;
+
+/* tram */
+typedef struct {
+       unsigned int used: 1,
+               type: 2,
+               req_pos: 2,
+               pos: 2;
+       unsigned int size;
+       unsigned int offset;
+       int acc_count;
+} ld10k1_tram_grp_t;
+
+#define TRAM_OP_NULL 0
+#define TRAM_OP_READ 1
+#define TRAM_OP_WRITE 2
+
+typedef struct {
+       unsigned int used: 1,
+               modified: 1;
+       unsigned int op;
+       unsigned int addr_val;
+       unsigned int data_val;
+} ld10k1_tram_hwacc_t;
+
+typedef struct {
+       unsigned int used: 1,
+               type: 2;
+       unsigned int offset;
+       unsigned int hwacc;
+       unsigned int grp;
+} ld10k1_tram_acc_t;
+
+typedef struct {
+       unsigned int size;
+       unsigned int max_hwacc;
+       ld10k1_tram_hwacc_t *hwacc;
+       unsigned int used_hwacc;
+} ld10k1_tram_t;
+
+#define MAX_CONN_PER_POINT 15
+#define MAX_INSTR_PER_POINT 7
+
+#define INSERT_BEFORE_OWNER 0
+#define INSERT_AFTER_OWNER 1
+
+typedef struct ld10k1_conn_point_tag
+{
+       struct ld10k1_conn_point_tag *next;
+
+       int id;
+       int con_count; /* count of io connected to this point */
+       unsigned int con_gpr_idx;
+       int type[MAX_CONN_PER_POINT];
+       struct ld10k1_patch_tag *patch[MAX_CONN_PER_POINT];
+       int io[MAX_CONN_PER_POINT];
+       unsigned int out_gpr_idx[MAX_CONN_PER_POINT];
+
+       int simple;
+
+       int reserved_gpr;
+       int reserved_instr;
+
+       struct ld10k1_patch_tag *owner;
+       int position;
+
+       unsigned int out_instr_offset;
+       ld10k1_instr_t out_instr[MAX_INSTR_PER_POINT];
+} ld10k1_conn_point_t;
+
+typedef struct {
+       char *name;
+       ld10k1_conn_point_t *point;
+} ld10k1_p_in_out_t;
+
+typedef struct {
+       unsigned int gpr_idx;
+       unsigned int const_val;
+} ld10k1_p_const_sta_t;
+
+typedef struct {
+       unsigned int gpr_idx;
+} ld10k1_p_dyn_t;
+
+typedef struct {
+       unsigned int reg_idx;
+       unsigned int gpr_idx;
+} ld10k1_p_hw_t;
+
+typedef struct {
+       unsigned int grp_type;
+       unsigned int grp_size;
+       unsigned int grp_pos;
+       unsigned int grp_idx;
+} ld10k1_p_tram_grp_t;
+
+typedef struct {
+       unsigned int acc_type;
+       unsigned int acc_offset;
+       unsigned int acc_idx;
+       unsigned int grp;
+} ld10k1_p_tram_acc_t;
+
+typedef struct {
+       char name[44];
+       int index;
+       int want_index;
+       unsigned int vcount;            /* count of GPR (1..32) */
+       unsigned int count;                     /* count of GPR (1..32) */
+       unsigned int gpr_idx[32];       /* GPR number(s) */
+       unsigned int value[32];
+       unsigned int min;                       /* minimum range */
+       unsigned int max;                       /* maximum range */
+       unsigned int translation;       /* typ - 0 - bool, num 1 - enum */
+} ld10k1_ctl_t;
+
+typedef struct ld10k1_ctl_list_item_tag {
+       struct ld10k1_ctl_list_item_tag *next;
+       ld10k1_ctl_t ctl;
+} ld10k1_ctl_list_item_t;
+
+typedef struct ld10k1_patch_tag {
+       char *patch_name;
+       int order;
+       int id;
+
+       unsigned int in_count;
+       ld10k1_p_in_out_t *ins;
+
+       unsigned int out_count;
+       ld10k1_p_in_out_t *outs;
+
+       unsigned int const_count;
+       ld10k1_p_const_sta_t *consts;
+
+       unsigned int sta_count;
+       ld10k1_p_const_sta_t *stas;
+
+       unsigned int dyn_count;
+       ld10k1_p_dyn_t *dyns;
+
+       unsigned int hw_count;
+       ld10k1_p_hw_t *hws;
+
+       unsigned int tram_count;
+       ld10k1_p_tram_grp_t *tram_grp;
+
+       unsigned int tram_acc_count;
+       ld10k1_p_tram_acc_t *tram_acc;
+
+       unsigned int ctl_count;
+       ld10k1_ctl_t *ctl;
+
+       unsigned int instr_count;
+       unsigned int instr_offset;
+       ld10k1_instr_t *instr;
+} ld10k1_patch_t;
+
+#define EMU10K1_PATCH_MAX 128
+
+typedef struct {
+       unsigned int gpr_idx;
+       unsigned int const_val;
+       unsigned int hw;
+       unsigned int ref;
+       unsigned int used: 1;
+} ld10k1_dsp_const_t;
+
+#define GPR_USAGE_NONE 0
+#define GPR_USAGE_NORMAL 1
+#define GPR_USAGE_CONST 2
+#define GPR_USAGE_DYNAMIC 3
+
+typedef struct {
+       unsigned int gpr_usage;
+       unsigned int val;
+       unsigned int ref;
+       unsigned int modified: 1,
+               used: 1;
+} ld10k1_dsp_gpr_t;
+
+/* reserved ctls - for example AC97 */
+
+typedef struct {
+       char name[44];
+       unsigned int index;
+} ld10k1_reserved_ctl_t;
+
+typedef struct ld10k1_reserved_ctl_list_item_tag {
+       struct ld10k1_reserved_ctl_list_item_tag *next;
+       ld10k1_reserved_ctl_t res_ctl;
+} ld10k1_reserved_ctl_list_item_t;
+
+typedef struct {
+       int audigy;
+       const char *card_id;
+
+       /* registers */
+       unsigned int fx_count;
+       ld10k1_p_in_out_t fxs[0x40];
+
+       unsigned int in_count;
+       ld10k1_p_in_out_t ins[0x20];
+
+       unsigned int out_count;
+       ld10k1_p_in_out_t outs[0x40];
+
+       unsigned int consts_max_count;
+       ld10k1_dsp_const_t consts[MAX_CONST_COUNT];
+
+       unsigned int regs_max_count;
+       ld10k1_dsp_gpr_t regs[MAX_GPR_COUNT];
+
+       /* instructions */
+       unsigned int instr_count;
+       ld10k1_instr_t instr[1024];
+
+       unsigned int instr_free;
+
+       /* internal tram */
+       ld10k1_tram_t i_tram;
+
+       /* external tram */
+       ld10k1_tram_t e_tram;
+
+       unsigned int max_tram_grp;
+       ld10k1_tram_grp_t tram_grp[MAX_TRAM_COUNT];
+
+       unsigned int max_tram_acc;
+       ld10k1_tram_acc_t tram_acc[MAX_TRAM_COUNT];
+
+       unsigned int max_itram_hwacc;
+       ld10k1_tram_hwacc_t itram_hwacc[0xC0];
+       unsigned int max_etram_hwacc;
+       ld10k1_tram_hwacc_t etram_hwacc[0x40];
+
+       unsigned int patch_count;
+       ld10k1_patch_t *patch_ptr[EMU10K1_PATCH_MAX];
+       unsigned int patch_order[EMU10K1_PATCH_MAX];
+
+       unsigned short patch_id_gens[EMU10K1_PATCH_MAX];
+
+       ld10k1_ctl_list_item_t *add_ctl_list;
+       int add_list_count;
+
+       ld10k1_ctl_list_item_t *del_ctl_list;
+       int del_list_count;
+
+       ld10k1_ctl_list_item_t *ctl_list;
+       int ctl_list_count;
+       
+       ld10k1_reserved_ctl_list_item_t *reserved_ctl_list;
+
+       ld10k1_conn_point_t *point_list;
+} ld10k1_dsp_mgr_t;
+
+void error(const char *fmt,...);
+#endif /* __LD10K1_H */
diff --git a/ld10k1/src/ld10k1_debug.c b/ld10k1/src/ld10k1_debug.c
new file mode 100644 (file)
index 0000000..6ba0ec6
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 <alsa/asoundlib.h>
+#include "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_fnc1.h"
+#include "ld10k1_debug.h"
+#include "ld10k1_error.h"
+#include "ld10k1_tram.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static char *usage_str[] = {
+       "NONE",
+       "NORMAL",
+       "CONST",
+       "DYNAMIC"
+};
+
+char debug_line[1000];
+int send_debug_line(int data_conn)
+{
+       return send_response(data_conn, FNC_CONTINUE, 0, debug_line, strlen(debug_line) + 1);
+}
+
+int ld10k1_debug_new_gpr_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx)
+{
+       int usage;
+       int value;
+       int ref_count;
+       int modified;
+
+       modified = dsp_mgr->regs[idx].modified;
+       usage = dsp_mgr->regs[idx].gpr_usage;
+       value = dsp_mgr->regs[idx].val;
+       ref_count = dsp_mgr->regs[idx].ref;
+
+       sprintf(debug_line, "%c 0x%03x : %-12s  0x%08x  %3d\n",
+                       modified ? '*' : ' ',
+                       idx,
+                       usage_str[usage],
+                       value,
+                       ref_count);
+       return send_debug_line(data_conn);
+}
+
+int ld10k1_debug_new_gpr_read_hdr(int data_conn)
+{
+       sprintf(debug_line, "M Idx     Usage         Value         Ref\n");
+       return send_debug_line(data_conn);
+}
+
+static int ld10k1_debug_new_gpr_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+
+       sprintf(debug_line, "FX8010 GPR List\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       if ((err = ld10k1_debug_new_gpr_read_hdr(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->regs_max_count; i++)
+               if (dsp_mgr->regs[i].used)
+                       if ((err = ld10k1_debug_new_gpr_read_one(data_conn, dsp_mgr, i)) < 0)
+                               return err;
+       return 0;
+}
+
+static int ld10k1_debug_new_fx_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+
+       sprintf(debug_line, "FX8010 FX List\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->fx_count; i++) {
+               sprintf(debug_line, "%03x : %-20s\n",
+                       i,
+                       dsp_mgr->fxs[i].name ? dsp_mgr->fxs[i].name : "");
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int ld10k1_debug_new_in_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+
+       sprintf(debug_line, "FX8010 IN List\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->in_count; i++) {
+               sprintf(debug_line, "%03x : %-20s\n",
+                       i,
+                       dsp_mgr->ins[i].name ? dsp_mgr->ins[i].name : "");
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int ld10k1_debug_new_out_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+
+       sprintf(debug_line, "FX8010 OUT List\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->out_count; i++) {
+               sprintf(debug_line, "%03x : %-20s\n",
+                       i,
+                       dsp_mgr->outs[i].name ? dsp_mgr->outs[i].name : "");
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+       return 0;
+}
+
+int ld10k1_debug_new_const_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx)
+{
+       int hw;
+       int value;
+       int ref_count;
+
+       hw = dsp_mgr->consts[idx].hw;
+       value = dsp_mgr->consts[idx].const_val;
+       ref_count = dsp_mgr->consts[idx].ref;
+
+       sprintf(debug_line, "0x%03x : 0x%08x  %c  %3d\n",
+                       idx,
+                       value,
+                       hw ? '*' : ' ',
+                       ref_count);
+       return send_debug_line(data_conn);
+}
+
+int ld10k1_debug_new_const_read_hdr(int data_conn)
+{
+       sprintf(debug_line, "Idx     Value       HW   Ref\n");
+       return send_debug_line(data_conn);
+}
+
+static int ld10k1_debug_new_const_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+
+       sprintf(debug_line, "CONST List\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       if ((err = ld10k1_debug_new_const_read_hdr(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->consts_max_count; i++)
+               if (dsp_mgr->consts[i].used)
+                       if ((err = ld10k1_debug_new_const_read_one(data_conn, dsp_mgr, i)) < 0)
+                               return err;
+       return 0;
+}
+
+char *instr_name[] = {
+       "MACS",
+       "MACS1",
+       "MACW",
+       "MACW1",
+       "MACINTS",
+       "MACINTW",
+       "ACC3",
+       "MACMV",
+       "ANDXOR",
+       "TSTNEG",
+       "LIMIT",
+       "LIMIT1",
+       "LOG",
+       "EXP",
+       "INTERP",
+       "SKIP",
+};
+
+static void ld10k1_debug_decode_preg_idx(char *type, unsigned int reg)
+{
+       switch ((reg & EMU10K1_PREG_TYPE_MASK) >> 28) {
+               case EMU10K1_PREG_TYPE_IN:
+                       sprintf(type, "IN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_OUT:
+                       sprintf(type, "OUT(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_CONST:
+                       sprintf(type, "CON(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_STA:
+                       sprintf(type, "STA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_DYN:
+                       sprintf(type, "DYN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_HW:
+                       sprintf(type, "HW(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_CTL:
+                       sprintf(type, "CTL(%03d, %03d)", (reg & ~EMU10K1_PREG_TYPE_MASK) >> 8, reg & ~EMU10K1_PREG_TYPE_MASK & 0xFF);
+                       break;
+               case EMU10K1_PREG_TYPE_TRAM_DATA:
+                       sprintf(type, "TD(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               case EMU10K1_PREG_TYPE_TRAM_ADDR:
+                       sprintf(type, "TA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
+                       break;
+               default:
+                       sprintf(type, "??? 0x%08x", reg);
+       }
+}
+
+int ld10k1_debug_new_code_read_one(int data_conn, int preg, ld10k1_instr_t *instr, unsigned int idx)
+{
+       char type1[100];
+       char type2[100];
+       char type3[100];
+       char type4[100];
+
+       if (instr->used) {
+               if (preg) {
+                       ld10k1_debug_decode_preg_idx(type1, instr->arg[0]);
+                       ld10k1_debug_decode_preg_idx(type2, instr->arg[1]);
+                       ld10k1_debug_decode_preg_idx(type3, instr->arg[2]);
+                       ld10k1_debug_decode_preg_idx(type4, instr->arg[3]);
+
+                       sprintf(debug_line, "%c 0x%03x : %-10s %s, %s, %s, %s\n",
+                               instr->modified ? '*' : ' ',
+                               idx,
+                               instr_name[instr->op_code],
+                               type1,
+                               type2,
+                               type3,
+                               type4);
+               } else {
+                       sprintf(debug_line, "%c 0x%03x : %-10s 0x%03x, 0x%03x, 0x%03x, 0x%03x\n",
+                               instr->modified ? '*' : ' ',
+                               idx,
+                               instr_name[instr->op_code],
+                               instr->arg[0],
+                               instr->arg[1],
+                               instr->arg[2],
+                               instr->arg[3]);
+               }
+
+               return send_debug_line(data_conn);
+       } else {
+               sprintf(debug_line, "%c 0x%03x : NOT USED\n",
+                       instr->modified ? '*' : ' ',
+                       idx);
+               return send_debug_line(data_conn);
+       }
+}
+
+int ld10k1_debug_new_code_read_hdr(int data_conn)
+{
+       sprintf(debug_line, "M Idx     OPCODE\n");
+       return send_debug_line(data_conn);
+}
+
+static int ld10k1_debug_new_code_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       int err;
+       ld10k1_instr_t *instr;
+
+       sprintf(debug_line, "FX8010 Code\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->instr_count; i++) {
+               instr = &(dsp_mgr->instr[i]);
+               if (instr->used)
+                       if ((err = ld10k1_debug_new_code_read_one(data_conn, 0, instr, i)) < 0)
+                               return err;
+       }
+       return 0;
+}
+
+static int ld10k1_debug_new_tram_info_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i, j;
+       int err;
+
+       char *req_pos_str;
+       char *pos_str;
+
+       ld10k1_tram_acc_t *tram_acc;
+       unsigned int data, addr;
+
+       int ifree = dsp_mgr->i_tram.size;
+       int efree = dsp_mgr->e_tram.size;
+
+       sprintf(debug_line, "TRAM\n\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+
+       sprintf(debug_line, "Internal tram size: 0x%08x\n", dsp_mgr->i_tram.size);
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       sprintf(debug_line, "External tram size: 0x%08x\n", dsp_mgr->e_tram.size);
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+
+       sprintf(debug_line, "\nTram groups:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+
+       for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
+               if (dsp_mgr->tram_grp[i].used) {
+                       sprintf(debug_line, "%03d  %10s  ", i, dsp_mgr->tram_grp[i].type == TRAM_GRP_DELAY ? "DELAY" : "TABLE");
+                       if ((err = send_debug_line(data_conn)) < 0)
+                               return err;
+
+                       req_pos_str = "NONE";
+                       if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_AUTO)
+                               req_pos_str = "AUTO";
+                       else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_INTERNAL)
+                               req_pos_str = "INTERNAL";
+                       else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_EXTERNAL)
+                               req_pos_str = "EXTERNAL";
+
+                       pos_str = "NONE";
+                       if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) {
+                               pos_str = "INTERNAL";
+                               ifree -= dsp_mgr->tram_grp[i].size;
+                       } else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) {
+                               pos_str = "EXTERNAL";
+                               efree -= dsp_mgr->tram_grp[i].size;
+                       }
+
+                       sprintf(debug_line, "%10s  %10s   %08x  %08x  %03d\n", req_pos_str, pos_str,
+                               dsp_mgr->tram_grp[i].size, dsp_mgr->tram_grp[i].offset, dsp_mgr->tram_grp[i].acc_count);
+                       if ((err = send_debug_line(data_conn)) < 0)
+                               return err;
+
+                       for (j = 0; j < dsp_mgr->max_tram_acc; j++) {
+                               tram_acc = &(dsp_mgr->tram_acc[j]);
+
+                               ld10k1_tram_get_hwacc(dsp_mgr, tram_acc->hwacc, &addr, &data);
+                               if ((tram_acc->used) && (tram_acc->grp == i)) {
+                                       sprintf(debug_line, "  %c%c%c  Off:0x%08x  HWacc:%03d  ADDR:0x%08x   DATA:0x%08x\n",
+                                               (tram_acc->type & TRAM_ACC_READ) ? 'R' : '-',
+                                               (tram_acc->type & TRAM_ACC_WRITE) ? 'W' : '-',
+                                               (tram_acc->type & TRAM_ACC_ZERO) ? 'Z' : '-',
+                                               tram_acc->offset,
+                                               tram_acc->hwacc,
+                                               addr,
+                                               data);
+                                       if ((err = send_debug_line(data_conn)) < 0)
+                                               return err;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+int ld10k1_debug_new_patch_read1(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
+{
+       int i, j;
+       int err;
+
+       ld10k1_conn_point_t *point;
+
+       sprintf(debug_line, "Patch name: %s\n\n", patch->patch_name);
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+
+       /* in list */
+       sprintf(debug_line, "IN registers:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->in_count; i++) {
+               sprintf(debug_line, "%03d   %s  ->  0x%08x\n", i,
+                       patch->ins[i].name ? patch->ins[i].name : "",
+                       patch->ins[i].point ? patch->ins[i].point->con_gpr_idx : 0);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+
+               point = patch->ins[i].point;
+               if (point != NULL)
+                       for (j = 0; j < MAX_CONN_PER_POINT; j++) {
+                               if (point->out_gpr_idx[j] != 0) {
+                                       sprintf(debug_line, "   +0x%08x\n", point->out_gpr_idx[j]);
+                                       if ((err = send_debug_line(data_conn)) < 0)
+                                               return err;
+                               }
+                       }
+       }
+
+       /* out list */
+       sprintf(debug_line, "OUT registers:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->out_count; i++) {
+               sprintf(debug_line, "%03d   %s  ->  0x%08x\n", i,
+                       patch->outs[i].name ? patch->outs[i].name : "",
+                       patch->outs[i].point ? patch->outs[i].point->con_gpr_idx : 0);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* const list */
+       sprintf(debug_line, "CONST registers:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->const_count; i++) {
+               sprintf(debug_line, "%03d   0x%08x  ->  0x%08x\n", i,
+                       patch->consts[i].const_val,
+                       patch->consts[i].gpr_idx);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* sta list */
+       sprintf(debug_line, "STA registers:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->sta_count; i++) {
+               sprintf(debug_line, "%03d   0x%08x  ->  0x%08x\n", i,
+                       patch->stas[i].const_val,
+                       patch->stas[i].gpr_idx);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* hw list */
+       sprintf(debug_line, "HW registers:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->hw_count; i++) {
+               sprintf(debug_line, "%03d   0x%08x  ->  0x%08x\n", i,
+                       patch->hws[i].reg_idx,
+                       patch->hws[i].gpr_idx);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* tram list */
+       sprintf(debug_line, "\nUsed tram groups:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->tram_count; i++) {
+               sprintf(debug_line, "%03d  0x%01x 0x%08x 0x%01x ->  %03d\n", i,
+                       patch->tram_grp[i].grp_type,
+                       patch->tram_grp[i].grp_size,
+                       patch->tram_grp[i].grp_pos,
+                       patch->tram_grp[i].grp_idx);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* tram acc list */
+       sprintf(debug_line, "\nUsed tram acc:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->tram_acc_count; i++) {
+               sprintf(debug_line, "%03d   0x%01x  0x%08x  0x%03x ->  0x%03x\n", i,
+                       patch->tram_acc[i].acc_type,
+                       patch->tram_acc[i].acc_offset,
+                       patch->tram_acc[i].grp,
+                       patch->tram_acc[i].acc_idx);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+       }
+
+       /* cotrol list */
+       sprintf(debug_line, "\nUsed controls:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->ctl_count; i++) {
+               sprintf(debug_line, "%03d\n", i);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+               sprintf(debug_line, "  Name:%s\n", patch->ctl[i].name);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+               sprintf(debug_line, "  Min: 0x%08x\n", patch->ctl[i].min);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+               sprintf(debug_line, "  Max: 0x%08x\n", patch->ctl[i].max);
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+               sprintf(debug_line, "  GPRS:\n");
+               if ((err = send_debug_line(data_conn)) < 0)
+                       return err;
+               for (j = 0; j < patch->ctl[i].count; j++) {
+                       sprintf(debug_line, "    %03d  0x%08x ->  0x%08x  %c\n", j,
+                               patch->ctl[i].value[j],
+                               patch->ctl[i].gpr_idx[j],
+                               j < patch->ctl[i].vcount ? 'v' : ' ');
+                       if ((err = send_debug_line(data_conn)) < 0)
+                               return err;
+               }
+       }
+
+       /* instruction list */
+       sprintf(debug_line, "\nCode:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+
+       if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0)
+               return err;
+       for (i = 0; i < patch->instr_count; i++) {
+               ld10k1_instr_t *instr;
+
+               instr = &(patch->instr[i]);
+               if ((err = ld10k1_debug_new_code_read_one(data_conn, 1, instr, i)) < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int ld10k1_debug_new_patch_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, int idx)
+{
+       ld10k1_patch_t *patch;
+       patch = dsp_mgr->patch_ptr[idx];
+       if (!patch)
+               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+       return ld10k1_debug_new_patch_read1(data_conn, dsp_mgr, patch);
+}
+
+static int ld10k1_debug_new_patch_list_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       ld10k1_patch_t *patch;
+       int err;
+
+       sprintf(debug_line, "\nPatch List:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++) {
+               patch = dsp_mgr->patch_ptr[i];
+               if (patch) {
+                       sprintf(debug_line, "%03d  %s\n\n", i, patch->patch_name);
+                       if ((err = send_debug_line(data_conn)) < 0)
+                               return err;
+               }
+       }
+       return 0;
+}
+
+static int ld10k1_debug_new_patch_order_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i, idx;
+       ld10k1_patch_t *patch;
+       int err;
+
+       sprintf(debug_line, "\nPatch order:\n");
+       if ((err = send_debug_line(data_conn)) < 0)
+               return err;
+       for (i = 0; i < dsp_mgr->patch_count; i++) {
+               idx = dsp_mgr->patch_order[i];
+               patch = dsp_mgr->patch_ptr[idx];
+               if (patch) {
+                       sprintf(debug_line, "%03d   %03d %s\n\n", i, idx, patch->patch_name);
+                       if ((err = send_debug_line(data_conn)) < 0)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
+int ld10k1_fnc_debug(int data_conn, int op, int size)
+{
+       ld10k1_fnc_debug_t debug_info;
+       int err;
+
+       if (size != sizeof(ld10k1_fnc_debug_t))
+               return LD10K1_ERR_PROTOCOL;
+
+       if ((err = receive_msg_data(data_conn, &debug_info, sizeof(ld10k1_fnc_debug_t))))
+               return err;
+
+       if (debug_info.what >= 100 && debug_info.what <= 100 + EMU10K1_PATCH_MAX) {
+               if ((err = ld10k1_debug_new_patch_read(data_conn, &dsp_mgr, debug_info.what - 100)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 1) {
+               /* registers */
+               if ((err = ld10k1_debug_new_gpr_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 2) {
+               /* registers */
+               if ((err = ld10k1_debug_new_const_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 3) {
+               /* instruction */
+               if ((err = ld10k1_debug_new_code_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 4) {
+               /* tram */
+               if ((err = ld10k1_debug_new_tram_info_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 5) {
+               if ((err = ld10k1_debug_new_patch_list_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 6) {
+               if ((err = ld10k1_debug_new_patch_order_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 7) {
+               /* fx */
+               if ((err = ld10k1_debug_new_fx_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 8) {
+               /* in */
+               if ((err = ld10k1_debug_new_in_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else if (debug_info.what == 9) {
+               /* out */
+               if ((err = ld10k1_debug_new_out_read(data_conn, &dsp_mgr)) < 0)
+                       return err;
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+       } else
+               if ((err = send_response_ok(data_conn)) < 0)
+                       return err;
+
+       return 0;
+}
diff --git a/ld10k1/src/ld10k1_debug.h b/ld10k1/src/ld10k1_debug.h
new file mode 100644 (file)
index 0000000..519eab3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003 by Peter Zubaj
+ *
+ *   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;
+ *
+ *   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 __LD10K1_DEBUG_H
+#define __LD10K1_DEBUG_H
+
+typedef struct {
+       int what;
+} ld10k1_fnc_debug_t;
+
+int ld10k1_fnc_debug(int data_conn, int op, int size);
+
+#endif /* __LD10K1_DEBUG_H */
diff --git a/ld10k1/src/ld10k1_driver.c b/ld10k1/src/ld10k1_driver.c
new file mode 100644 (file)
index 0000000..3742773
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <alsa/asoundlib.h>
+#include <alsa/sound/emu10k1.h>
+#include <stdint.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "bitops.h"
+#include "ld10k1.h"
+#include "ld10k1_driver.h"
+#include "ld10k1_error.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_fnc_int.h"
+
+//#define DEBUG_DRIVER 1
+
+extern snd_hwdep_t *handle;
+
+void ld10k1_syntetize_instr(int audigy, int op, int arg1, int arg2, int arg3, int arg4, unsigned int *out)
+{
+       if (audigy) {
+               *out = ((arg3 & 0x7ff) << 12) | (arg4 & 0x7ff);
+               *(out + 1) = ((op & 0x0f) << 24) | ((arg1 & 0x7ff) << 12) | (arg2 & 0x7ff);
+       } else {
+               *out = ((arg3 & 0x3ff) << 10) | (arg4 & 0x3ff);
+               *(out + 1) = ((op & 0x0f) << 20) | ((arg1 & 0x3ff) << 10) | (arg2 & 0x3ff);
+       }
+}
+
+void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr);
+void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
+void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code);
+
+/* outputs what must be initialized on audigy */
+static int audigy_must_init_output[] = {
+       0x68, 0,
+       0x69, 0,
+       0x6a, 0,
+       0x6b, 0,
+       0x6e, 0,
+       0x6f, 0,
+       -1};
+
+#define LD10K1_SIGNATURE "LD10K1 ver. " VERSION " managed DSP code"
+
+void ld10k1_free_code_struct(emu10k1_fx8010_code_t *code)
+{
+       if (code->gpr_map)
+               free(code->gpr_map);
+       if (code->tram_data_map)
+               free(code->tram_data_map);
+       if (code->tram_addr_map)
+               free(code->tram_addr_map);
+       if (code->code)
+               free(code->code);
+}
+
+int ld10k1_alloc_code_struct(emu10k1_fx8010_code_t *code)
+{
+       /* alloc code structure */
+       code->gpr_map = NULL;
+       code->tram_data_map = NULL;
+       code->tram_addr_map = NULL;
+       code->code = NULL;
+       
+       code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
+       if (!code->gpr_map)
+               goto err;
+       memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
+
+       code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
+       if (!code->tram_data_map)
+               goto err;
+       memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
+
+       code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
+       if (!code->tram_addr_map)
+               goto err;
+       memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
+
+       code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
+       if (!code->code)
+               goto err;
+       memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
+
+        return 0;
+err:
+       ld10k1_free_code_struct(code);
+       return LD10K1_ERR_NO_MEM;
+}
+
+int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       emu10k1_fx8010_code_t code;
+       emu10k1_fx8010_control_gpr_t *add_ctrl;
+       emu10k1_ctl_elem_id_t *del_ids;
+
+       ld10k1_ctl_list_item_t *item;
+       unsigned int i, j;
+       int max;
+       int modified;
+       unsigned int addr;
+       unsigned int vaddr;
+       unsigned int op;
+       unsigned int idx_offset;
+       unsigned int *iptr;
+       ld10k1_ctl_t gctl;
+       
+       int err;
+       
+       if ((err = ld10k1_alloc_code_struct(&code)) < 0)
+               return err;
+       
+       /* new name */
+       strcpy(code.name, LD10K1_SIGNATURE);
+
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = 0;
+       for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
+               code.tram_valid[i] = 0;
+       for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
+               code.code_valid[i] = 0;
+
+       /* registers */
+       for (i = 0; i < dsp_mgr->regs_max_count; i++)
+               if (dsp_mgr->regs[i].modified) {
+                       set_bit(i, code.gpr_valid);
+                       code.gpr_map[i] = dsp_mgr->regs[i].val;
+               }
+
+       /* tram addr + data */
+       for (j = 0; j < 2; j++) {
+               max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
+               for (i = 0; i < max; i++) {
+                       modified = (j == 0 ? dsp_mgr->itram_hwacc[i].modified : dsp_mgr->etram_hwacc[i].modified);
+                       if (modified) {
+                               addr = (j == 0 ? dsp_mgr->itram_hwacc[i].addr_val : dsp_mgr->etram_hwacc[i].addr_val);
+                               vaddr = addr & 0xFFFFF;
+                               idx_offset = (j == 0 ? 0 : dsp_mgr->max_itram_hwacc);
+                               op = (j == 0 ? dsp_mgr->itram_hwacc[i].op : dsp_mgr->etram_hwacc[i].op);
+
+                               set_bit(i + idx_offset, code.tram_valid);
+                               switch(op) {
+                                       case TRAM_OP_READ:
+                                               if (dsp_mgr->audigy)
+                                                       vaddr = vaddr | 0x2 << 20;
+                                               else
+                                                       vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
+                                               break;
+                                       case TRAM_OP_WRITE:
+                                               if (dsp_mgr->audigy)
+                                                       vaddr = vaddr | 0x6 << 20;
+                                               else
+                                                       vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
+                                               break;
+                                       case TRAM_OP_NULL:
+                                       default:
+                                               vaddr = 0;
+                                               break;
+                               }
+
+                               code.tram_addr_map[i + idx_offset] = vaddr;
+                               code.tram_data_map[i + idx_offset] = (j == 0 ? dsp_mgr->itram_hwacc[i].data_val : dsp_mgr->etram_hwacc[i].data_val);
+                       }
+               }
+       }
+
+       /* controls to add */
+       if (dsp_mgr->add_list_count > 0) {
+               add_ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count);
+               memset(add_ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count);
+               for (i = 0, item = dsp_mgr->add_ctl_list; item != NULL; item = item->next, i++) {
+                       strcpy(add_ctrl[i].id.name, item->ctl.name);
+                       add_ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
+                       add_ctrl[i].id.index = item->ctl.index;
+                       add_ctrl[i].vcount = item->ctl.vcount;
+                       add_ctrl[i].count = item->ctl.count;
+                       for (j = 0; j < 32; j++) {
+                               add_ctrl[i].gpr[j] = item->ctl.gpr_idx[j];
+                               add_ctrl[i].value[j] = item->ctl.value[j];
+                       }
+                       add_ctrl[i].min = item->ctl.min;
+                       add_ctrl[i].max = item->ctl.max;
+                       add_ctrl[i].translation = item->ctl.translation;
+               }
+       } else
+               add_ctrl = NULL;
+
+       code.gpr_add_control_count = dsp_mgr->add_list_count;
+       code.gpr_add_controls = add_ctrl;
+
+       /* controls to del */
+       if (dsp_mgr->del_list_count > 0) {
+               del_ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count);
+               memset(del_ids, 0, sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count);
+               for (i = 0, item = dsp_mgr->del_ctl_list; item != NULL; item = item->next, i++) {
+                       strcpy(del_ids[i].name, item->ctl.name);
+                       del_ids[i].iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
+                       del_ids[i].index = item->ctl.index;
+               }
+       } else
+               del_ids = NULL;
+               
+       code.gpr_del_control_count = dsp_mgr->del_list_count;
+       code.gpr_del_controls = del_ids;
+
+       code.gpr_list_control_count = 0;
+
+       for (iptr = code.code, i = 0; i < dsp_mgr->instr_count; i++, iptr += 2) {
+               if (dsp_mgr->instr[i].modified) {
+                       set_bit(i, code.code_valid);
+                       if (dsp_mgr->instr[i].used) {
+                               if (dsp_mgr->audigy) {
+                                       ld10k1_syntetize_instr(dsp_mgr->audigy,
+                                               dsp_mgr->instr[i].op_code,
+                                               dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
+                               } else {
+                                       if (i < 0x200) {
+                                               ld10k1_syntetize_instr(dsp_mgr->audigy,
+                                                       dsp_mgr->instr[i].op_code,
+                                                       dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
+                                       }
+                               }
+                       } else {
+                               if (dsp_mgr->audigy) {
+                                       ld10k1_syntetize_instr(dsp_mgr->audigy,
+                                               0x0f,
+                                               0xc0, 0xc0, 0xcf, 0xc0, iptr);
+                               } else {
+                                       if (i < 0x200) {
+                                               ld10k1_syntetize_instr(dsp_mgr->audigy,
+                                                       0x06,
+                                                       0x40, 0x40, 0x40, 0x40, iptr);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /* check initialization of i2s outputs on audigy */
+       if (dsp_mgr->audigy)
+               ld10k1_check_must_init_output(dsp_mgr, &code);
+
+
+#ifndef DEBUG_DRIVER
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
+               error("unable to poke code");
+               ld10k1_free_code_struct(&code);
+               if (add_ctrl)
+                       free(add_ctrl);
+               if (del_ids)
+                       free(del_ids);
+               return LD10K1_ERR_DRIVER_CODE_POKE;
+       }
+#endif
+
+       /* update state */
+       for (item = dsp_mgr->del_ctl_list; item != NULL; item = item->next) {
+               strcpy(gctl.name, item->ctl.name);
+               ld10k1_del_control_from_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &gctl);
+       }
+
+       ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count);
+
+       for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next)
+               ld10k1_add_control_to_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &(item->ctl));
+
+       ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count);
+
+       for (i = 0; i < dsp_mgr->regs_max_count; i++)
+               dsp_mgr->regs[i].modified = 0;
+
+       for (i = 0; i < dsp_mgr->instr_count; i++)
+               dsp_mgr->instr[i].modified = 0;
+
+       for (j = 0; j < 2; j++) {
+               max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
+               for (i = 0; i < max; i++) {
+                       if (j == 0)
+                               dsp_mgr->itram_hwacc[i].modified = 0;
+                       else
+                               dsp_mgr->etram_hwacc[i].modified = 0;
+               }
+       }
+       
+       ld10k1_free_code_struct(&code);
+
+       if (add_ctrl)
+               free(add_ctrl);
+       if (del_ids)
+               free(del_ids);
+       return 0;
+}
+
+
+int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size)
+{
+       emu10k1_fx8010_info_t info;
+       int i;
+       emu10k1_fx8010_code_t code;
+       emu10k1_fx8010_control_gpr_t *ctrl;
+       emu10k1_ctl_elem_id_t *ids;
+       emu10k1_fx8010_pcm_t ipcm;
+       
+       unsigned int *iptr;
+       
+       int err;
+       
+       if ((err = ld10k1_alloc_code_struct(&code)) < 0)
+               return err;
+       
+       /* setup tram size */
+       if (tram_size >= 0 && snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
+               error("unable to setup tram");
+               if (dsp_mgr->audigy)
+                       error("You are probably user of audigy, audigy 2 and you not aplyed patch to enable tram");
+               /* this is not fatal, but do not use tram */
+               dsp_mgr->i_tram.size = 0;
+               dsp_mgr->e_tram.size = 0;
+       } else {
+               if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_INFO, &info) < 0) {
+                       error("unable to get info ");
+                       ld10k1_free_code_struct(&code);
+                       return LD10K1_ERR_DRIVER_INFO;
+               }
+
+               dsp_mgr->i_tram.size = info.internal_tram_size;
+               dsp_mgr->e_tram.size = info.external_tram_size;
+       }
+       
+       /* get count of controls */
+       code.gpr_list_control_count = 0;
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
+               error("unable to peek code");
+               ld10k1_free_code_struct(&code);
+               return LD10K1_ERR_DRIVER_CODE_PEEK;
+       }
+
+       ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total);
+       if (!ctrl) {
+               ld10k1_free_code_struct(&code);
+               return LD10K1_ERR_NO_MEM;
+       }
+
+       code.gpr_list_control_count = code.gpr_list_control_total;
+       code.gpr_list_controls = ctrl;
+
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = 0x0;
+       for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
+               code.tram_valid[i] = 0x0;
+       for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
+               code.code_valid[i] = 0x0;;
+
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
+               error("unable to peek code");
+               ld10k1_free_code_struct(&code);
+               free(ctrl);
+               return LD10K1_ERR_DRIVER_CODE_PEEK;
+       }
+       
+       
+
+       /* new name */
+       strcpy(code.name, LD10K1_SIGNATURE);
+       for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
+               code.gpr_valid[i] = ~0;
+
+       for (i = 0; i < sizeof(code.gpr_valid) * 8; i++) {
+               code.gpr_map[i] = 0;
+       }
+
+       ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total);
+       if (!ids) {
+               ld10k1_free_code_struct(&code);
+               free(ctrl);
+               return LD10K1_ERR_NO_MEM;
+       }
+
+       code.gpr_del_control_count = code.gpr_list_control_total;
+       if (code.gpr_del_control_count) {
+               for (i = 0; i < code.gpr_del_control_count; i++) {
+                       memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
+               }
+       }
+
+       free(ctrl);
+
+       code.gpr_del_controls = ids;
+       code.gpr_list_control_count = 0;
+       code.gpr_add_control_count = 0;
+       code.gpr_list_control_count = 0;
+
+       for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
+               code.tram_valid[i] = ~0;
+       for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
+               code.code_valid[i] = ~0;
+
+       for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
+               code.tram_addr_map[i] = 0;
+               code.tram_data_map[i] = 0;
+       }
+
+       for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
+               if (dsp_mgr->audigy) {
+                       ld10k1_syntetize_instr(dsp_mgr->audigy,
+                               0x0f,
+                               0xc0, 0xc0, 0xcf, 0xc0, iptr);
+               } else {
+                       ld10k1_syntetize_instr(dsp_mgr->audigy,
+                               0x06,
+                               0x40, 0x40, 0x40, 0x40, iptr);
+               }
+               
+       /* initialize i2s outputs on audigy */
+       if (dsp_mgr->audigy) {
+               for (iptr = code.code, i = 0; audigy_must_init_output[i] > 0; i += 2, iptr += 2)
+                       ld10k1_syntetize_instr(dsp_mgr->audigy, 0x00,
+                               audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, iptr);
+       }
+       
+#ifndef DEBUG_DRIVER
+       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
+               error("unable to poke code");
+               ld10k1_free_code_struct(&code);
+               free(ids);
+               return LD10K1_ERR_DRIVER_CODE_POKE;
+       }
+#endif
+
+       free(ids);
+
+       /* delete tram pcm dsp part */
+       if (!dsp_mgr->audigy) {
+               for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
+                       ipcm.substream = i;
+                       ipcm.channels = 0;
+#ifndef DEBUG_DRIVER
+                       if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
+                               error("unable to poke code");
+                               ld10k1_free_code_struct(&code);
+                               return LD10K1_ERR_DRIVER_PCM_POKE;
+                       }
+#endif
+               }
+       }
+       
+       ld10k1_free_code_struct(&code);
+       return 0;
+}
+
+void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       if (dsp_mgr->audigy) {
+               for (i = 0; audigy_must_init_output[i] > 0; i += 2)
+                       audigy_must_init_output[i + 1] = 1;
+       }
+}
+       
+void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
+{
+       int i ;
+       if (dsp_mgr->audigy) {
+               for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
+                       if (audigy_must_init_output[i] == reg) {
+                               audigy_must_init_output[i + 1] = 0;
+                               return;                 
+                       }
+               }
+       }
+}
+
+void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code)
+{
+       int j;
+       
+       ld10k1_init_must_init_output(dsp_mgr);
+       for (j = 0; j < dsp_mgr->instr_count; j++) {
+               if (dsp_mgr->instr[j].used)
+                       ld10k1_set_must_init_output(dsp_mgr, dsp_mgr->instr[j].arg[0]);
+       }
+       
+       int i;
+       int l;
+       int ioffset = dsp_mgr->instr_count - 1;
+       if (dsp_mgr->audigy) {
+               for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
+                       if (audigy_must_init_output[i + 1]) {
+                               /* find free instruction slot */
+                               for (;ioffset >= 0; ioffset--) {
+                                       if (!dsp_mgr->instr[ioffset].used) {
+                                               ld10k1_instr_t *instr = &(dsp_mgr->instr[ioffset]);
+                                               ld10k1_syntetize_instr(dsp_mgr->audigy, 
+                                                       0x0, 
+                                                       audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, 
+                                                       code->code + ioffset * 2);
+                                               instr->op_code = 0;
+                                               instr->arg[0] = audigy_must_init_output[i];
+                                               for (l = 1; l < 4; l++)
+                                                       instr->arg[l] = 0xc0;
+                                               set_bit(ioffset, code->code_valid);
+                                               dsp_mgr->instr[ioffset].used = 1;
+                                               ioffset--;
+                                               break;
+                                       }
+                               }
+                                       
+                               if (ioffset < 0)
+                                       return;                         
+                       }               
+               }
+       }
+}
diff --git a/ld10k1/src/ld10k1_driver.h b/ld10k1/src/ld10k1_driver.h
new file mode 100644 (file)
index 0000000..2a3bc4d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_DRIVER_H
+#define __LD10K1_DRIVER_H
+
+int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr);
+int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size);
+
+#endif /* __LD10K1_DRIVER_H */
diff --git a/ld10k1/src/ld10k1_dump.c b/ld10k1/src/ld10k1_dump.c
new file mode 100644 (file)
index 0000000..f2167b0
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <alsa/asoundlib.h>
+
+#include "ld10k1.h"
+#include "ld10k1_dump_file.h"
+#include "ld10k1_dump.h"
+#include "ld10k1_error.h"
+
+int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size)
+{
+       int dump_size = 0;
+       void *dump_file = NULL;
+       void *ptr = NULL;
+       ld10k1_dump_t *header = NULL;
+       ld10k1_ctl_dump_t *ctl = NULL;
+       int i, j;
+       ld10k1_ctl_list_item_t *item;
+       unsigned int *ival = NULL;
+       ld10k1_tram_dump_t *tram = NULL;
+       ld10k1_instr_dump_t *instr = NULL;
+
+       dump_size += sizeof(ld10k1_dump_t);
+       dump_size += sizeof(ld10k1_ctl_dump_t) * dsp_mgr->ctl_list_count;
+       dump_size += sizeof(unsigned int) * dsp_mgr->regs_max_count;
+       dump_size += sizeof(ld10k1_tram_dump_t) * (dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc);
+       dump_size += sizeof(ld10k1_instr_dump_t) * dsp_mgr->instr_count;
+
+       dump_file = malloc(dump_size);
+       if (!dump_file)
+               return LD10K1_ERR_NO_MEM;
+
+       ptr = dump_file;
+       header = (ld10k1_dump_t *)ptr;
+       strcpy(header->signature, "LD10K1 DUMP 001");
+       if (!dsp_mgr->audigy)
+               header->dump_type = DUMP_TYPE_LIVE;
+       else
+               header->dump_type = DUMP_TYPE_AUDIGY;
+       
+       header->tram_size = dsp_mgr->e_tram.size;
+       header->ctl_count = dsp_mgr->ctl_list_count;
+       header->gpr_count = dsp_mgr->regs_max_count;
+       header->tram_count = dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc;
+       header->instr_count = dsp_mgr->instr_count;
+       
+       /*printf("Size header%d\n", dump_size);
+       printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t),
+               header->ctl_count, sizeof(ld10k1_ctl_dump_t),
+               header->gpr_count, sizeof(unsigned int),
+               header->tram_count, sizeof(ld10k1_tram_dump_t),
+               header->instr_count, sizeof(ld10k1_instr_dump_t));*/
+
+       ptr += sizeof(ld10k1_dump_t);
+       /* ctls */
+       for (item = dsp_mgr->ctl_list; item != NULL; item = item->next) {
+               ctl = (ld10k1_ctl_dump_t *)ptr;
+               strcpy(ctl->name, item->ctl.name);
+               ctl->index = item->ctl.index;
+               ctl->vcount = item->ctl.vcount;
+               ctl->count = item->ctl.count;
+               for (j = 0; j < 32; j++) {
+                       ctl->gpr_idx[j] = item->ctl.gpr_idx[j];
+                       ctl->value[j] = item->ctl.value[j];
+               }
+               ctl->min = item->ctl.min;
+               ctl->max = item->ctl.max;
+               ctl->translation = item->ctl.translation;
+
+               ptr += sizeof(ld10k1_ctl_dump_t);
+       }
+
+       /* regs */
+       for (i = 0; i < dsp_mgr->regs_max_count; i++) {
+               ival = (unsigned int *) ptr;
+               *ival = dsp_mgr->regs[i].val;
+               ptr += sizeof(unsigned int);
+       }
+
+       /* tram */
+       for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) {
+               tram = (ld10k1_tram_dump_t *) ptr;
+               if (dsp_mgr->itram_hwacc[i].used) {
+                       tram->type = dsp_mgr->itram_hwacc[i].op;
+                       tram->addr = dsp_mgr->itram_hwacc[i].addr_val;
+                       tram->data = dsp_mgr->itram_hwacc[i].data_val;
+               } else {
+                       tram->type = 0;
+                       tram->addr = 0;
+                       tram->data = 0;
+               }
+               ptr += sizeof(ld10k1_tram_dump_t);
+       }
+
+       for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) {
+               tram = (ld10k1_tram_dump_t *) ptr;
+               if (dsp_mgr->etram_hwacc[i].used) {
+                       if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_READ)
+                               tram->type = DUMP_TRAM_READ;
+                       else if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_WRITE)
+                               tram->type = DUMP_TRAM_WRITE;
+                       else
+                               tram->type = DUMP_TRAM_NULL;
+                       tram->addr = dsp_mgr->etram_hwacc[i].addr_val;
+                       tram->data = dsp_mgr->etram_hwacc[i].data_val;
+               } else {
+                       tram->type = 0;
+                       tram->addr = 0;
+                       tram->data = 0;
+               }
+               ptr += sizeof(ld10k1_tram_dump_t);
+       }
+
+       /* instr */
+       for (i = 0; i < dsp_mgr->instr_count; i++) {
+               instr = (ld10k1_instr_dump_t *) ptr;
+               instr->used = dsp_mgr->instr[i].used;
+               instr->op = dsp_mgr->instr[i].op_code;
+               instr->arg[0] = dsp_mgr->instr[i].arg[0];
+               instr->arg[1] = dsp_mgr->instr[i].arg[1];
+               instr->arg[2] = dsp_mgr->instr[i].arg[2];
+               instr->arg[3] = dsp_mgr->instr[i].arg[3];
+               ptr += sizeof(ld10k1_instr_dump_t);
+       }
+
+       *dump = dump_file;
+       *size = dump_size;
+
+       return 0;
+}
diff --git a/ld10k1/src/ld10k1_dump.h b/ld10k1/src/ld10k1_dump.h
new file mode 100644 (file)
index 0000000..f5e50ef
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_DUMP_H
+#define __LD10K1_DUMP_H
+
+int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size);
+
+#endif /* __LD10K1_DUMP_H */
diff --git a/ld10k1/src/ld10k1_dump_file.h b/ld10k1/src/ld10k1_dump_file.h
new file mode 100644 (file)
index 0000000..6a2a5fb
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_DUMP_FILE_H
+#define __LD10K1_DUMP_FILE_H
+
+#define DUMP_TYPE_LIVE 0
+#define DUMP_TYPE_AUDIGY_OLD 1
+#define DUMP_TYPE_AUDIGY 2
+
+typedef struct {
+       char signature[16]; /* LD10K1 DUMP 001 */
+       int dump_type;
+       int tram_size;
+       int ctl_count;
+       int gpr_count;
+       int tram_count;
+       int instr_count;
+} ld10k1_dump_t;
+
+#define DUMP_TRAM_NULL 0
+#define DUMP_TRAM_READ 1
+#define DUMP_TRAM_WRITE 2
+
+typedef struct {
+       int type;
+       unsigned int addr;
+       unsigned int data;
+} ld10k1_tram_dump_t;
+
+typedef struct {
+       int used;
+       unsigned int op;
+       unsigned int arg[4];
+} ld10k1_instr_dump_t;
+
+typedef struct {
+       char name[44];
+       int index;
+       unsigned int vcount;            /* count of GPR (1..32) */
+       unsigned int count;                     /* count of GPR (1..32) */
+       unsigned int gpr_idx[32];       /* GPR number(s) */
+       unsigned int value[32];
+       unsigned int min;                       /* minimum range */
+       unsigned int max;                       /* maximum range */
+       unsigned int translation;       /* typ - 0 - bool, num 1 - enum */
+} ld10k1_ctl_dump_t;
+
+#endif /* __LD10K1_DUMP_FILE_H */
diff --git a/ld10k1/src/ld10k1_fnc.c b/ld10k1/src/ld10k1_fnc.c
new file mode 100644 (file)
index 0000000..4bc1f55
--- /dev/null
@@ -0,0 +1,2373 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 <malloc.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <alsa/asoundlib.h>
+#include <alsa/sound/emu10k1.h>
+
+#include "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_fnc_int.h"
+#include "ld10k1_driver.h"
+#include "ld10k1_tram.h"
+#include "ld10k1_error.h"
+
+char *ld10k1_dsp_mgr_name_new(char **where, const char *from);
+int ld10k1_add_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl);
+void ld10k1_del_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl);
+int ld10k1_dsp_mgr_patch_unload(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int idx);
+int ld10k1_get_used_index_for_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl, int **idxs, int *cnt);
+
+unsigned int ld10k1_resolve_named_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg);
+unsigned int ld10k1_gpr_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res,
+       unsigned int usage, unsigned int val);
+unsigned int ld10k1_gpr_dyn_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res);
+unsigned int ld10k1_const_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_const_count, int *res_const_count, int *res_const,
+       int max_res_count, int *res_count, int *res, int const_val);
+
+void ld10k1_const_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
+void ld10k1_const_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
+void ld10k1_gpr_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
+void ld10k1_gpr_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
+
+ld10k1_conn_point_t *ld10k1_conn_point_alloc(int simple);
+void ld10k1_conn_point_free(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point);
+int ld10k1_conn_point_set_to(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, int io);
+void ld10k1_conn_point_unset(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point);
+int ld10k1_conn_point_add(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io);
+int ld10k1_conn_point_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io);
+
+int ld10k1_conn_point_get_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io);
+
+void ld10k1_conn_point_add_to_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point);
+void ld10k1_conn_point_del_from_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point);
+int ld10k1_gen_patch_id(ld10k1_dsp_mgr_t *dsp_mgr, int pnum);
+
+/*
+ *  Tables
+ */
+
+unsigned int hw_const[22 * 2] =
+{
+       0x00000000, EMU10K1_REG_HW(0),
+       0x00000001, EMU10K1_REG_HW(1),
+       0x00000002, EMU10K1_REG_HW(2),
+       0x00000003, EMU10K1_REG_HW(3),
+       0x00000004, EMU10K1_REG_HW(4),
+       0x00000008, EMU10K1_REG_HW(5),
+       0x00000010, EMU10K1_REG_HW(6),
+       0x00000020, EMU10K1_REG_HW(7),
+       0x00000100, EMU10K1_REG_HW(8),
+       0x00010000, EMU10K1_REG_HW(9),
+       0x10000000, EMU10K1_REG_HW(11),
+       0x20000000, EMU10K1_REG_HW(12),
+       0x40000000, EMU10K1_REG_HW(13),
+       0x80000000, EMU10K1_REG_HW(14),
+       0x7fffffff, EMU10K1_REG_HW(15),
+       0xffffffff, EMU10K1_REG_HW(16),
+       0xfffffffe, EMU10K1_REG_HW(17),
+       0xc0000000, EMU10K1_REG_HW(18),
+       0x4f1bbcde, EMU10K1_REG_HW(19),
+       0x5a7ef9db, EMU10K1_REG_HW(20),
+       0x00100000, EMU10K1_REG_HW(21)
+};
+
+int ld10k1_dsp_mgr_init(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int tmp_gpr_count = 0;
+       int tmp_a_gpr_count = 0;
+       int tmp_itram_count = 0;
+       int tmp_etram_count = 0;
+       int tmp_op_count = 0;
+       int i, j;
+
+       dsp_mgr->add_ctl_list = NULL;
+       dsp_mgr->add_list_count = 0;
+
+       dsp_mgr->del_ctl_list = NULL;
+       dsp_mgr->del_list_count = 0;
+
+       dsp_mgr->ctl_list = NULL;
+       dsp_mgr->ctl_list_count = 0;
+       
+       dsp_mgr->point_list = 0;
+
+       if (dsp_mgr->audigy) {
+               tmp_itram_count = 0xC0;
+               tmp_etram_count = 0x100 - 0xC0;
+               tmp_op_count = 0x400;
+               tmp_a_gpr_count = 0x200;
+       } else {
+               tmp_itram_count = 0x80;
+               tmp_etram_count = 0xA0 - 0x80;
+               tmp_op_count = 0x200;
+               tmp_gpr_count = 0x100;
+       }
+
+       dsp_mgr->instr_count = tmp_op_count;
+       dsp_mgr->instr_free = tmp_op_count;
+
+       for (i = 0; i < tmp_op_count; i++) {
+               dsp_mgr->instr[i].used = 0;
+               dsp_mgr->instr[i].modified = 1;
+               dsp_mgr->instr[i].op_code = 0;
+               for (j = 0; j < 4; j++)
+                   dsp_mgr->instr[i].arg[j] = 0;
+       }
+
+       /* fx */
+       for (i = 0; i < (dsp_mgr->audigy ? 0x40 : 0x10); i++) {
+               dsp_mgr->fxs[i].name = NULL;
+               dsp_mgr->fxs[i].point = NULL;
+       }
+       dsp_mgr->fx_count = dsp_mgr->audigy ? 0x40 : 0x10;
+
+       /* input */
+       for (i = 0; i < (dsp_mgr->audigy ? 0x20 : 0x10); i++) {
+               dsp_mgr->ins[i].name = NULL;
+               dsp_mgr->ins[i].point = NULL;
+       }
+
+       dsp_mgr->in_count = dsp_mgr->audigy ? 0x20 : 0x10;
+
+       /* output */
+       for (i = 0; i < (dsp_mgr->audigy ? 0x40 : 0x20); i++) {
+               dsp_mgr->outs[i].name = NULL;
+               dsp_mgr->outs[i].point = NULL;
+       }
+
+       dsp_mgr->out_count = dsp_mgr->audigy ? 0x40 : 0x20;
+
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x00].name), "FX_PCM_Left");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x01].name), "FX_PCM_Right");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x02].name), "FX_PCM_Surr_Left");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x03].name), "FX_PCM_Surr_Right");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x04].name), "FX_MIDI_Left");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x05].name), "FX_MIDI_Right");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x06].name), "FX_Center");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x07].name), "FX_LFE");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x0c].name), "FX_MIDI_Reverb");
+       ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x0d].name), "FX_MIDI_Chorus");
+
+       if (dsp_mgr->audigy) {
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x08].name), "FX_PCM_Front_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x09].name), "FX_PCM_Front_Right");
+
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x14].name), "FX_Passthrough_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x15].name), "FX_Passthrough_Right");
+
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x00].name), "IN_AC97_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x01].name), "IN_AC97_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x02].name), "IN_Audigy_CD_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x03].name), "IN_Audigy_CD_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x04].name), "IN_Opt_IEC958_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x05].name), "IN_Opt_IEC958_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x08].name), "IN_Line_Mic_2_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x09].name), "IN_Line_Mic_2_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0a].name), "IN_ADC_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0b].name), "IN_ADC_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0c].name), "IN_Aux2_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0d].name), "IN_Aux2_Right");
+
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x00].name), "OUT_Dig_Front_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x01].name), "OUT_Dig_Front_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x02].name), "OUT_Dig_Center");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x03].name), "OUT_Dig_LEF");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x04].name), "OUT_Headphone_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x05].name), "OUT_Headphone_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x06].name), "OUT_Dig_Rear_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x07].name), "OUT_Dig_Rear_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x08].name), "OUT_Front_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x09].name), "OUT_Front_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0a].name), "OUT_Center");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0b].name), "OUT_LFE");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0e].name), "OUT_Rear_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0f].name), "OUT_Rear_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x10].name), "OUT_AC97_Front_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x11].name), "OUT_AC97_Front_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x16].name), "OUT_ADC_Caputre_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x17].name), "OUT_ADC_Capture_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x18].name), "OUT_Mic_Capture");
+       } else {
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x00].name), "IN_AC97_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x01].name), "IN_AC97_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x02].name), "IN_TTL_IEC958_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x03].name), "IN_TTL_IEC958_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x04].name), "IN_Zoom_Video_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x05].name), "IN_Zoom_Video_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x06].name), "IN_Optical_IEC958_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x07].name), "IN_Optical_IEC958_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x08].name), "IN_Line_Mic_1_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x09].name), "IN_Line_Mic_1_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0a].name), "IN_Coax_IEC958_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0b].name), "IN_Coax_IEC958_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0c].name), "IN_Line_Mic_2_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0d].name), "IN_Line_Mic_2_Right");
+
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x00].name), "OUT_AC97_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x01].name), "OUT_AC97_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x02].name), "OUT_Opt_IEC958_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x03].name), "OUT_Opt_IEC958_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x04].name), "OUT_Center");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x05].name), "OUT_LFE");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x06].name), "OUT_Headphone_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x07].name), "OUT_Headphone_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x08].name), "OUT_Analog_Surr_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x09].name), "OUT_Analog_Surr_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0a].name), "OUT_PCM_Capture_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0b].name), "OUT_PCM_Capture_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0c].name), "OUT_MIC_Capture");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0d].name), "OUT_AC97_Surr_Left");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0e].name), "OUT_AC97_Surr_Right");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x11].name), "OUT_AC97_Center");
+               ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x12].name), "OUT_AC97_LFE");
+       }
+
+       dsp_mgr->regs_max_count = dsp_mgr->audigy ? tmp_a_gpr_count : tmp_gpr_count;
+
+       /* constants */
+       for (i = 0; i < 21; i++) {
+               dsp_mgr->consts[i].const_val = hw_const[i * 2];
+               dsp_mgr->consts[i].gpr_idx = hw_const[i * 2 + 1];
+               dsp_mgr->consts[i].hw = 1;
+               dsp_mgr->consts[i].ref = 1;
+               dsp_mgr->consts[i].used = 1;
+       }
+
+       dsp_mgr->consts[21].const_val = dsp_mgr->audigy ? 0x00000800 : 0x00080000;
+       dsp_mgr->consts[21].gpr_idx = EMU10K1_REG_HW(10);
+       dsp_mgr->consts[21].hw = 1;
+       dsp_mgr->consts[21].used = 1;
+       dsp_mgr->consts[21].ref = 1;
+       dsp_mgr->consts_max_count = 22 + dsp_mgr->regs_max_count;
+
+       /* gprs */
+       for (i = 0; i < dsp_mgr->regs_max_count; i++) {
+               dsp_mgr->regs[i].used = 0;
+               dsp_mgr->regs[i].gpr_usage = GPR_USAGE_NONE;
+               dsp_mgr->regs[i].val = 0;
+               dsp_mgr->regs[i].ref = 0;
+               dsp_mgr->regs[i].modified = 1;
+       }
+
+       dsp_mgr->patch_count = 0;
+
+       for (i = 0; i < 0x100; i++) {
+               dsp_mgr->tram_acc[i].used = 0;
+               dsp_mgr->tram_acc[i].type = 0;
+               dsp_mgr->tram_acc[i].offset = 0;
+               dsp_mgr->tram_acc[i].hwacc = 0xFFFFFFFF;
+               dsp_mgr->tram_acc[i].grp = 0xFFFFFFFF;
+
+               dsp_mgr->tram_grp[i].used = 0;
+               dsp_mgr->tram_grp[i].type = 0;
+               dsp_mgr->tram_grp[i].size = 0;
+               dsp_mgr->tram_grp[i].offset = 0;
+               dsp_mgr->tram_grp[i].req_pos = TRAM_POS_NONE;
+               dsp_mgr->tram_grp[i].pos = TRAM_POS_NONE;
+       }
+
+       for (i = 0; i < 0x40; i++) {
+               dsp_mgr->etram_hwacc[i].used = 0;
+               dsp_mgr->etram_hwacc[i].op = 0;
+               dsp_mgr->etram_hwacc[i].modified = 1;
+               dsp_mgr->etram_hwacc[i].data_val = 0;
+               dsp_mgr->etram_hwacc[i].addr_val = 0;
+       }
+
+       for (i = 0; i < 0xC0; i++) {
+               dsp_mgr->itram_hwacc[i].used = 0;
+               dsp_mgr->itram_hwacc[i].modified = 1;
+               dsp_mgr->itram_hwacc[i].data_val = 0;
+               dsp_mgr->itram_hwacc[i].addr_val = 0;
+       }
+
+       dsp_mgr->max_tram_grp = dsp_mgr->max_tram_acc = tmp_itram_count + tmp_etram_count;
+       dsp_mgr->max_itram_hwacc = tmp_itram_count;
+       dsp_mgr->max_etram_hwacc = tmp_etram_count;
+
+       dsp_mgr->i_tram.size = 0;
+       dsp_mgr->i_tram.max_hwacc = tmp_itram_count;
+       dsp_mgr->i_tram.hwacc = dsp_mgr->itram_hwacc;
+       dsp_mgr->i_tram.used_hwacc = 0;
+
+       dsp_mgr->e_tram.size = 0;
+       dsp_mgr->e_tram.max_hwacc = tmp_etram_count;
+       dsp_mgr->e_tram.hwacc = dsp_mgr->etram_hwacc;
+       dsp_mgr->e_tram.used_hwacc = 0;
+
+       dsp_mgr->patch_count = 0;
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++) {
+               dsp_mgr->patch_ptr[i] = NULL;
+               dsp_mgr->patch_order[i] = 0xFFFFFFFF;
+       }
+
+       return 0;
+}
+
+void ld10k1_dsp_mgr_init_id_gen(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++)
+               dsp_mgr->patch_id_gens[i] = 0;
+}
+
+void ld10k1_dsp_mgr_free(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       unsigned int i;
+
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++) {
+               if (dsp_mgr->patch_ptr[i])
+                   ld10k1_dsp_mgr_patch_unload(dsp_mgr, dsp_mgr->patch_ptr[i], i);
+       }
+
+       ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count);
+       ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count);
+       ld10k1_del_all_controls_from_list(&(dsp_mgr->ctl_list), &dsp_mgr->ctl_list_count);
+
+       /* FIXME - uvolnovanie point - asi netreba - su uvolnovane pri patch */
+       for (i = 0; i < dsp_mgr->fx_count; i++)
+               if (dsp_mgr->fxs[i].name)
+                       free(dsp_mgr->fxs[i].name);
+
+       for (i = 0; i < dsp_mgr->in_count; i++)
+               if (dsp_mgr->ins[i].name)
+                       free(dsp_mgr->ins[i].name);
+
+       for (i = 0; i < dsp_mgr->out_count; i++)
+               if (dsp_mgr->outs[i].name)
+                       free(dsp_mgr->outs[i].name);
+}
+
+ld10k1_patch_t *ld10k1_dsp_mgr_patch_new(void)
+{
+       ld10k1_patch_t *np;
+
+       np = (ld10k1_patch_t *)malloc(sizeof(ld10k1_patch_t));
+       if (!np)
+               return NULL;
+
+       np->patch_name = NULL;
+       np->id = 0;
+
+       np->in_count = 0;
+       np->ins = NULL;
+
+       np->out_count = 0;
+       np->outs = NULL;
+
+       np->const_count = 0;
+       np->consts = NULL;
+
+       np->sta_count = 0;
+       np->stas = NULL;
+
+       np->dyn_count = 0;
+       np->dyns = NULL;
+
+       np->hw_count = 0;
+       np->hws = NULL;
+
+       np->tram_count = 0;
+       np->tram_grp = NULL;
+
+       np->tram_acc_count = 0;
+       np->tram_acc = NULL;
+
+       np->ctl_count = 0;
+       np->ctl = NULL;
+
+       np->instr_count = 0;
+       np->instr_offset = 0;
+       np->instr = NULL;
+
+       return np;
+}
+
+void ld10k1_dsp_mgr_patch_free(ld10k1_patch_t *patch)
+{
+       int i;
+
+       if (patch->patch_name)
+               free(patch->patch_name);
+
+       for (i = 0; i < patch->in_count; i++)
+               if (patch->ins[i].name)
+                       free(patch->ins[i].name);
+
+       for (i = 0; i < patch->out_count; i++)
+               if (patch->outs[i].name)
+                       free(patch->outs[i].name);
+
+       if (patch->ins)
+               free(patch->ins);
+
+       if (patch->outs)
+               free(patch->outs);
+
+       if (patch->consts)
+               free(patch->consts);
+
+       if (patch->stas)
+               free(patch->stas);
+
+       if (patch->dyns)
+               free(patch->dyns);
+
+       if (patch->hws)
+               free(patch->hws);
+
+       if (patch->tram_grp)
+               free(patch->tram_grp);
+
+       if (patch->tram_acc)
+               free(patch->tram_acc);
+
+       if (patch->ctl)
+               free(patch->ctl);
+
+       if (patch->instr)
+               free(patch->instr);
+
+       free(patch);
+}
+
+ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_in_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_in_out_t *ins;
+
+       ins = (ld10k1_p_in_out_t *)malloc(sizeof(ld10k1_p_in_out_t) * count);
+       if (!ins)
+               return NULL;
+
+       if (patch->ins)
+               free(patch->ins);
+
+       memset(ins, 0, sizeof(ld10k1_p_in_out_t) * count);
+
+       patch->ins = ins;
+       patch->in_count = count;
+       return ins;
+}
+
+ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_out_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_in_out_t *outs;
+
+       outs = (ld10k1_p_in_out_t *)malloc(sizeof(ld10k1_p_in_out_t) * count);
+       if (!outs)
+               return NULL;
+
+       if (patch->outs)
+               free(patch->outs);
+
+       memset(outs, 0, sizeof(ld10k1_p_in_out_t) * count);
+
+       patch->outs = outs;
+       patch->out_count = count;
+       return outs;
+}
+
+ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_const_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_const_sta_t *consts;
+
+       consts = (ld10k1_p_const_sta_t *)malloc(sizeof(ld10k1_p_const_sta_t) * count);
+       if (!consts)
+               return NULL;
+
+       if (patch->consts)
+               free(patch->consts);
+
+       memset(consts, 0, sizeof(ld10k1_p_const_sta_t) * count);
+
+       patch->consts = consts;
+       patch->const_count = count;
+       return consts;
+}
+
+ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_sta_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_const_sta_t *stas;
+
+       stas = (ld10k1_p_const_sta_t *)malloc(sizeof(ld10k1_p_const_sta_t) * count);
+       if (!stas)
+               return NULL;
+
+       if (patch->stas)
+               free(patch->stas);
+
+       memset(stas, 0, sizeof(ld10k1_p_const_sta_t) * count);
+
+       patch->stas = stas;
+       patch->sta_count = count;
+       return stas;
+}
+
+ld10k1_p_dyn_t *ld10k1_dsp_mgr_patch_dyn_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_dyn_t *dyns;
+
+       dyns = (ld10k1_p_dyn_t *)malloc(sizeof(ld10k1_p_dyn_t) * count);
+       if (!dyns)
+               return NULL;
+
+       if (patch->dyns)
+               free(patch->dyns);
+
+       memset(dyns, 0, sizeof(ld10k1_p_dyn_t) * count);
+
+       patch->dyns = dyns;
+       patch->dyn_count = count;
+       return dyns;
+}
+
+ld10k1_p_hw_t *ld10k1_dsp_mgr_patch_hw_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_hw_t *hws;
+
+       hws = (ld10k1_p_hw_t *)malloc(sizeof(ld10k1_p_hw_t) * count);
+       if (!hws)
+               return NULL;
+
+       if (patch->hws)
+               free(patch->hws);
+
+       memset(hws, 0, sizeof(ld10k1_p_hw_t) * count);
+
+       patch->hws = hws;
+       patch->hw_count = count;
+       return hws;
+}
+
+ld10k1_p_tram_grp_t *ld10k1_dsp_mgr_patch_tram_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_tram_grp_t *tram;
+
+       tram = (ld10k1_p_tram_grp_t *)malloc(sizeof(ld10k1_p_tram_grp_t) * count);
+       if (!tram)
+               return NULL;
+
+       if (patch->tram_grp)
+               free(patch->tram_grp);
+
+       memset(tram, 0, sizeof(ld10k1_p_tram_grp_t) * count);
+
+       patch->tram_grp = tram;
+       patch->tram_count = count;
+       return tram;
+}
+
+ld10k1_p_tram_acc_t *ld10k1_dsp_mgr_patch_tram_acc_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_p_tram_acc_t *tram_acc;
+       
+       tram_acc = (ld10k1_p_tram_acc_t *)malloc(sizeof(ld10k1_p_tram_acc_t) * count);
+       if (!tram_acc)
+               return NULL;
+
+       if (patch->tram_acc)
+               free(patch->tram_acc);
+               
+       memset(tram_acc, 0, sizeof(ld10k1_p_tram_acc_t) * count);
+       
+       patch->tram_acc = tram_acc;
+       patch->tram_acc_count = count;
+       return tram_acc;
+}
+
+ld10k1_instr_t *ld10k1_dsp_mgr_patch_instr_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_instr_t *instr;
+       
+       instr = (ld10k1_instr_t *)malloc(sizeof(ld10k1_instr_t) * count);
+       if (!instr)
+               return NULL;
+               
+       if (patch->instr)
+               free(patch->instr);
+
+       memset(instr, 0, sizeof(ld10k1_instr_t) * count);
+
+       patch->instr = instr;
+       patch->instr_count = count;
+       return instr;
+}
+
+ld10k1_ctl_t *ld10k1_dsp_mgr_patch_ctl_new(ld10k1_patch_t *patch, unsigned int count)
+{
+       ld10k1_ctl_t *ctl;
+       
+       ctl = (ld10k1_ctl_t *)malloc(sizeof(ld10k1_ctl_t) * count);
+       if (!ctl)
+               return NULL;
+               
+       if (patch->ctl)
+               free(patch->ctl);
+
+       memset(ctl, 0, sizeof(ld10k1_ctl_t) * count);
+
+       patch->ctl = ctl;
+       patch->ctl_count = count;
+       return ctl;
+}
+
+char *ld10k1_dsp_mgr_name_new(char **where, const char *from)
+{
+       char *ns;
+
+       ns = (char *)malloc(strlen(from) + 1);
+       if (!ns)
+               return NULL;
+
+       if (*where)
+               free(*where);
+
+       *where = ns;
+       strcpy(ns, from);
+       return ns;
+}
+
+void ld10k1_dsp_mgr_op(ld10k1_instr_t *instr, unsigned int op, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4)
+{
+       instr->used = 1;
+       instr->modified = 1;
+       instr->op_code = op;
+       instr->arg[0] = arg1;
+       instr->arg[1] = arg2;
+       instr->arg[2] = arg3;
+       instr->arg[3] = arg4;
+}
+
+int ld10k1_dsp_mgr_get_phys_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg)
+{
+       int idx = reg & 0xFFFFFFF;
+
+       switch(EMU10K1_REG_TYPE_B(reg)) {
+               case EMU10K1_REG_TYPE_FX:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0x3F)
+                                       return -1;
+                               else
+                                       return idx;
+                       } else {
+                               if (idx > 0x0F)
+                                       return -1;
+                               else
+                                       return idx;
+                       }
+                       break;
+               case EMU10K1_REG_TYPE_INPUT:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0x1F)
+                                       return -1;
+                               else
+                                       return idx + 0x40;
+                       } else {
+                               if (idx > 0x0F)
+                                       return -1;
+                               else
+                                       return idx + 0x10;
+                       }
+                       break;
+               case EMU10K1_REG_TYPE_OUTPUT:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0x3F)
+                                       return -1;
+                               else
+                                       return idx + 0x60;
+                       } else {
+                               if (idx > 0x1F)
+                                       return -1;
+                               else
+                                       return idx + 0x20;
+                       }
+               case EMU10K1_REG_TYPE_HW:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0x1F)
+                                       return -1;
+                               else
+                                       return idx + 0xC0;
+                       } else {
+                               if (idx > 0x1F)
+                                       return -1;
+                               else
+                                       return idx + 0x40;
+                       }
+               case EMU10K1_REG_TYPE_TRAM_CTL:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0xFF)
+                                       return -1;
+                               else
+                                       return idx + 0x10;
+                       } else {
+                                       return -1;
+                       }
+               case EMU10K1_REG_TYPE_TRAM_DATA:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0xFF)
+                                       return -1;
+                               else
+                                       return idx + 0x200;
+                       } else {
+                               if (idx > 0xBF)
+                                       return -1;
+                               else
+                                       return idx + 0x200;
+                       }
+               case EMU10K1_REG_TYPE_TRAM_ADDR:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0xFF)
+                                       return -1;
+                               else
+                                       return idx + 0x300;
+                       } else {
+                               if (idx > 0xBF)
+                                       return -1;
+                               else
+                                       return idx + 0x300;
+                       }
+               case EMU10K1_REG_TYPE_NORMAL:
+                       if (dsp_mgr->audigy) {
+                               if (idx > 0x1FF)
+                                       return -1;
+                               else
+                                       return idx + 0x400;
+                       } else {
+                               if (idx > 0xFF)
+                                       return -1;
+                               else
+                                       return idx + 0x100;
+                       }
+               case EMU10K1_REG_TYPE_CONST:
+                       if (idx > MAX_CONST_COUNT)
+                               return -1;
+                       else
+                               return ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, dsp_mgr->consts[idx].gpr_idx);
+               default:
+                       return -1;
+       }
+}
+
+int ld10k1_dsp_mgr_get_phys_reg_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int reg)
+{
+       unsigned int ind_reg = 0;
+       unsigned int acc_idx = 0;
+
+       ld10k1_conn_point_t *point;
+
+       switch (EMU10K1_PREG_TYPE_B(reg)) {
+               case EMU10K1_PREG_TYPE_IN:
+                       /*if (patch->ins[reg & 0xFFFFFFF].point)
+                               ind_reg = patch->ins[reg & 0xFFFFFFF].point->con_gpr_idx;
+                       else
+                               ind_reg = EMU10K1_REG_HW(0);
+                       break;*/
+                       if (patch->ins[reg & 0xFFFFFFF].point) {
+                               point = patch->ins[reg & 0xFFFFFFF].point;
+                               ind_reg = ld10k1_conn_point_get_reg(dsp_mgr, point, CON_IO_PIN, patch, reg & 0xFFFFFFF);
+                       } else
+                               ind_reg = EMU10K1_REG_HW(0);
+                       break;
+               case EMU10K1_PREG_TYPE_OUT:
+                       if (patch->outs[reg & 0xFFFFFFF].point) {
+                               point = patch->outs[reg & 0xFFFFFFF].point;
+
+                               ind_reg = ld10k1_conn_point_get_reg(dsp_mgr, point, CON_IO_POUT, patch, reg & 0xFFFFFFF);
+                       } else
+                               ind_reg = EMU10K1_REG_HW(0); /* const 0 */
+                       break;
+               case EMU10K1_PREG_TYPE_CONST:
+                       ind_reg = patch->consts[reg & 0xFFFFFFF].gpr_idx;
+                       break;
+               case EMU10K1_PREG_TYPE_STA:
+                       ind_reg = patch->stas[reg & 0xFFFFFFF].gpr_idx;
+                       break;
+               case EMU10K1_PREG_TYPE_DYN:
+                       ind_reg = patch->dyns[reg & 0xFFFFFFF].gpr_idx;
+                       break;
+               case EMU10K1_PREG_TYPE_HW:
+                       ind_reg = patch->hws[reg & 0xFFFFFFF].gpr_idx;
+                       break;
+               case EMU10K1_PREG_TYPE_CTL:
+                       ind_reg = patch->ctl[(reg & 0xFF00) >> 8].gpr_idx[reg & 0xFF];
+                       break;
+               case EMU10K1_PREG_TYPE_TRAM_DATA:
+                       acc_idx = patch->tram_acc[reg & 0xFFFFFFF].acc_idx;
+                       ind_reg = EMU10K1_REG_TRAM_DATA(dsp_mgr->tram_acc[acc_idx].hwacc);
+                       break;
+               case EMU10K1_PREG_TYPE_TRAM_ADDR:
+                       acc_idx = patch->tram_acc[reg & 0xFFFFFFF].acc_idx;
+                       ind_reg = EMU10K1_REG_TRAM_ADDR(dsp_mgr->tram_acc[acc_idx].hwacc);
+                       break;
+               default:
+                       return -1;
+       }
+
+       if (ind_reg)
+               return ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, ind_reg);
+       return -1;
+}
+
+int ld10k1_dsp_mgr_actualize_instr(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       unsigned int i, j, k, l, m, z;
+       unsigned int instr_offset;
+       ld10k1_patch_t *tmpp;
+       ld10k1_instr_t *instr;
+       ld10k1_conn_point_t *tmp_point;
+       int allmodified = 0;
+       int found;
+       
+       instr_offset = 0;
+
+       /* intruction actualization */
+       for (i = 0; i < dsp_mgr->patch_count; i++) {
+               tmpp = dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]];
+
+
+               for (m = 0; m < 3; m++) {
+                       if (m == 0 || m == 2) {
+                               /* get all owned points */
+                               for (j = 0; j < (m == 0 ? tmpp->in_count : tmpp->out_count); j++) {
+                                       allmodified = 0;
+                                       if (m == 0)
+                                               tmp_point = tmpp->ins[j].point;
+                                       else
+                                               tmp_point = tmpp->outs[j].point;
+                                       if (tmp_point && tmp_point->owner == tmpp &&
+                                               ((m == 0 && tmp_point->position == INSERT_BEFORE_OWNER) ||
+                                               (m == 2 && tmp_point->position == INSERT_AFTER_OWNER)))
+                                       {
+                                               /* check if not generated before */
+                                               found = 0;
+                                               for (z = 0; z < j; z++)
+                                                       if ((m == 0 && tmpp->ins[z].point == tmp_point) ||
+                                                               (m == 2 && tmpp->outs[z].point == tmp_point)) {
+                                                               found = 1;
+                                                               break;
+                                                       }
+                                               /* if generated - continue */
+                                               if (found)
+                                                       continue;
+                                                               
+                                               if (tmp_point->reserved_instr > 0 && tmp_point->out_instr_offset != instr_offset)
+                                                       allmodified = 1;
+
+                                               tmp_point->out_instr_offset = instr_offset;
+                                               /* copy instructions */
+                                               for (k = 0; k < tmp_point->reserved_instr; k++)
+                                                       if (allmodified || tmp_point->out_instr[k].modified) {
+                                                               instr = &(dsp_mgr->instr[k + tmp_point->out_instr_offset]);
+
+                                                               instr->used = 1;
+                                                               instr->modified = 1;
+                                                               instr->op_code = tmp_point->out_instr[k].op_code;
+                                                               for (l = 0; l < 4; l++)
+                                                                       instr->arg[l] = ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, tmp_point->out_instr[k].arg[l]);
+                                                               tmp_point->out_instr[k].modified = 0;
+                                                       }
+                                               instr_offset += tmp_point->reserved_instr;
+                                       }
+                               }
+                       } else {
+                               /* patch*/
+                               allmodified = 0;
+                               if (tmpp->instr_offset != instr_offset)
+                                       allmodified = 1;
+
+                               tmpp->instr_offset = instr_offset;
+
+                               for (j = 0; j < tmpp->instr_count; j++)
+                                       if (allmodified || tmpp->instr[j].modified) {
+                                               instr = &(dsp_mgr->instr[j + tmpp->instr_offset]);
+
+                                               instr->used = 1;
+                                               instr->modified = 1;
+                                               instr->op_code = tmpp->instr[j].op_code;
+                                               for (k = 0; k < 4; k++)
+                                                       instr->arg[k] = ld10k1_dsp_mgr_get_phys_reg_for_patch(dsp_mgr, tmpp, tmpp->instr[j].arg[k]);
+                                               tmpp->instr[j].modified = 0;
+                                       }
+                               instr_offset += tmpp->instr_count;
+                       }
+               }
+       }
+
+       for (j = instr_offset; j < dsp_mgr->instr_count; j++) {
+               if (dsp_mgr->instr[j].used) {
+                       dsp_mgr->instr[j].modified = 1;
+                       dsp_mgr->instr[j].used = 0;
+               }
+       }
+       return ld10k1_update_driver(dsp_mgr);
+}
+
+int ld10k1_dsp_mgr_actualize_instr_for_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int reg)
+{
+       int j, k;
+
+       for (j = 0; j < patch->instr_count; j++)
+               for (k = 0; k < 4; k++)
+                       if (patch->instr[j].arg[k] == reg) {
+                               patch->instr[j].modified = 1;
+                       }
+       return 0;
+}
+
+void ld10k1_dsp_mgr_actualize_order(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+
+       for (i = 0; i < dsp_mgr->patch_count; i++)
+               dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]]->order = i;
+}
+
+int ld10k1_dsp_mgr_patch_load(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, int before, int *loaded)
+{
+       /* check if i can add patch */
+       int pp, i, j;
+       int err;
+
+       int res[MAX_GPR_COUNT];
+       int res_count = 0;
+       int max_res_count = MAX_GPR_COUNT;
+       int const_res[MAX_CONST_COUNT];
+       int const_res_count = 0;
+       int max_const_res_count = MAX_CONST_COUNT;
+
+       unsigned int reserved;
+       
+       ld10k1_ctl_t tmp_ctl;
+
+       ld10k1_dsp_tram_resolve_t tram_res;
+
+       ld10k1_patch_t *tpatch;
+
+       if (dsp_mgr->patch_count >= EMU10K1_PATCH_MAX)
+               return LD10K1_ERR_MAX_PATCH_COUNT;
+
+       /* get patch number */
+       for (i = 0, pp = -1; i < dsp_mgr->patch_count; i++)
+               if (dsp_mgr->patch_ptr[i] == NULL)
+                       pp = i;
+
+       if (pp < 0)
+               pp = dsp_mgr->patch_count;
+
+       if (before > dsp_mgr->patch_count)
+               before =  dsp_mgr->patch_count;
+
+       /* static */
+       for (i = 0; i < patch->sta_count; i++) {
+               reserved = ld10k1_gpr_reserve(dsp_mgr, max_res_count, &res_count, res, GPR_USAGE_NORMAL, patch->stas[i].const_val);
+               if (!reserved)
+                       return LD10K1_ERR_NOT_FREE_REG;
+               patch->stas[i].gpr_idx = reserved;
+       }
+
+       /* constant */
+       for (i = 0; i < patch->const_count; i++) {
+               
+               /* try allocate */
+               reserved = ld10k1_const_reserve(dsp_mgr, max_const_res_count, &const_res_count, const_res,
+                       max_res_count, &res_count, res, patch->consts[i].const_val);
+               if (reserved == 0)
+                       return LD10K1_ERR_NOT_FREE_REG;
+               patch->consts[i].gpr_idx = reserved;
+       }
+
+       /* dynamic */
+       for (i = 0; i < patch->dyn_count; i++) {
+               reserved = ld10k1_gpr_dyn_reserve(dsp_mgr, max_res_count, &res_count, res);
+               if (!reserved)
+                       return LD10K1_ERR_NOT_FREE_REG;
+               patch->dyns[i].gpr_idx = reserved;
+       }
+
+       /* hw */
+       for (i = 0; i < patch->hw_count; i++)
+               patch->hws[i].gpr_idx = ld10k1_resolve_named_reg(dsp_mgr, patch->hws[i].reg_idx);
+
+       /* ctl regs */
+       for (i = 0; i < patch->ctl_count; i++) {
+               for (j = 0; j < patch->ctl[i].count; j++) {
+                       reserved = ld10k1_gpr_reserve(dsp_mgr, max_res_count, &res_count, res,
+                               GPR_USAGE_NORMAL, patch->ctl[i].value[j]);
+                       if (!reserved)
+                               return LD10K1_ERR_NOT_FREE_REG;
+                       patch->ctl[i].gpr_idx[j] = reserved;
+               }
+       }
+
+       if (dsp_mgr->instr_free < patch->instr_count)
+               return LD10K1_ERR_NOT_FREE_INSTR;
+
+       /* tram */
+       if (patch->tram_count > 0)
+               if ((err = ld10k1_tram_reserve_for_patch(dsp_mgr, patch, &tram_res)) < 0)
+                       return err;
+
+       for (i = 0; i < patch->ctl_count; i++) {
+               memcpy(&tmp_ctl, &(patch->ctl[i]), sizeof(ld10k1_ctl_t));
+               /* resolve gpr_idx */
+               for (j = 0; j < tmp_ctl.count; j++)
+                       tmp_ctl.gpr_idx[j] = tmp_ctl.gpr_idx[j] & ~EMU10K1_REG_TYPE_MASK;
+               if ((err = ld10k1_add_control(dsp_mgr, &tmp_ctl)) < 0) {
+                       for (j = 0; j < i - 1; j++)
+                               ld10k1_del_control(dsp_mgr, &(patch->ctl[j]));
+                       return err;
+               }
+               
+               /* copy index back */
+               patch->ctl[i].index = tmp_ctl.index;
+       }
+
+       if (patch->tram_count > 0)
+               if ((err = ld10k1_tram_alloc_for_patch(dsp_mgr, patch, &tram_res)) < 0)
+                       return err;
+
+       for (i = dsp_mgr->patch_count - 1; i >= before ; i--)
+               dsp_mgr->patch_order[i + 1] = dsp_mgr->patch_order[i];
+
+       dsp_mgr->patch_order[before] = pp;
+       dsp_mgr->patch_count++;
+
+       dsp_mgr->patch_ptr[pp] = patch;
+       loaded[0] = pp;
+
+       patch->id = ld10k1_gen_patch_id(dsp_mgr, pp);
+       loaded[1] = patch->id;
+
+       /* allocate registers */
+       for (i = 0; i < const_res_count; i++)
+               ld10k1_const_alloc(dsp_mgr, const_res[i]);
+
+       for (i = 0; i < res_count; i++)
+               ld10k1_gpr_alloc(dsp_mgr, res[i]);
+
+       /* actualize tram */
+       if (patch->tram_count > 0)
+               for (i = 0; i < dsp_mgr->patch_count; i++) {
+                       tpatch = dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]];
+                       if (tpatch->tram_count)
+                               ld10k1_tram_actualize_tram_for_patch(dsp_mgr, tpatch);
+               }
+
+       dsp_mgr->instr_free -= patch->instr_count;
+
+       ld10k1_dsp_mgr_actualize_order(dsp_mgr);
+       return ld10k1_dsp_mgr_actualize_instr(dsp_mgr);
+}
+
+int ld10k1_dsp_mgr_patch_unload(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int idx)
+{
+       unsigned int i,j ;
+
+       /* free in registers */
+       for (i = 0; i < patch->in_count; i++)
+               if (patch->ins[i].point)
+                       ld10k1_conn_point_del(dsp_mgr, patch->ins[i].point, CON_IO_PIN, patch, i);
+
+       /* free out registers */
+       for (i = 0; i < patch->out_count; i++)
+               if (patch->outs[i].point)
+                       ld10k1_conn_point_del(dsp_mgr, patch->outs[i].point, CON_IO_POUT, patch, i);
+
+       /* free dyn registers */
+       for (i = 0; i < patch->dyn_count; i++)
+               ld10k1_gpr_free(dsp_mgr, patch->dyns[i].gpr_idx);
+
+       /* free sta registers */
+       for (i = 0; i < patch->sta_count; i++)
+               ld10k1_gpr_free(dsp_mgr, patch->stas[i].gpr_idx);
+
+       /* free const registers */
+       for (i = 0; i < patch->const_count; i++)
+               ld10k1_const_free(dsp_mgr, patch->consts[i].gpr_idx);
+
+       /* free ctl regs */
+       for (i = 0; i < patch->ctl_count; i++) {
+               for (j = 0; j < patch->ctl[i].count; j++) {
+                       ld10k1_gpr_free(dsp_mgr, patch->ctl[i].gpr_idx[j]);
+               }
+       }
+
+       /* free controls */
+       for (i = 0; i < patch->ctl_count; i++)
+               ld10k1_del_control(dsp_mgr, &(patch->ctl[i]));
+
+       /* free tram */
+       if (patch->tram_count > 0)
+               ld10k1_tram_free_tram_for_patch(dsp_mgr, patch);
+
+       /* free from registers */
+       for (i = 0; i < dsp_mgr->patch_count; i++)
+               if (dsp_mgr->patch_order[i] == idx)
+                       for (;i < dsp_mgr->patch_count; i++)
+                               dsp_mgr->patch_order[i] = dsp_mgr->patch_order[i + 1];
+       dsp_mgr->patch_ptr[idx] = NULL;
+
+       /* free from mem */
+       ld10k1_dsp_mgr_patch_free(patch);
+
+       /* decrement patch count */
+       dsp_mgr->patch_count--;
+       dsp_mgr->instr_free += patch->instr_count;
+
+       ld10k1_dsp_mgr_actualize_order(dsp_mgr);
+       /* actualize instructons */
+       return ld10k1_dsp_mgr_actualize_instr(dsp_mgr);
+}
+
+int ld10k1_patch_fnc_check_patch(ld10k1_dsp_mgr_t *dsp_mgr,
+       ld10k1_patch_t *new_patch)
+{
+       int i, j, k;
+
+       /* check hw registers */
+       for (i = 0; i < new_patch->hw_count; i++) {
+               if (!ld10k1_resolve_named_reg(dsp_mgr, new_patch->hws[i].reg_idx))
+                       return LD10K1_ERR_WRONG_REG_HW_INDEX;
+       }
+
+       /* tram check */
+       for (i = 0; i < new_patch->tram_count; i++) {
+               if (new_patch->tram_grp[i].grp_type != TRAM_GRP_DELAY && new_patch->tram_grp[i].grp_type != TRAM_GRP_TABLE)
+                       return LD10K1_ERR_WRONG_TRAM_TYPE;
+               if (new_patch->tram_grp[i].grp_size < 0)
+                       return LD10K1_ERR_WRONG_TRAM_SIZE;
+               if (new_patch->tram_grp[i].grp_pos != TRAM_POS_AUTO &&
+                       new_patch->tram_grp[i].grp_pos != TRAM_POS_INTERNAL &&
+                       new_patch->tram_grp[i].grp_pos != TRAM_POS_EXTERNAL)
+                       return LD10K1_ERR_WRONG_TRAM_POS;
+       }
+
+       /* tram access check */
+       for (i = 0; i < new_patch->tram_acc_count; i++) {
+               /* type */
+               if ((new_patch->tram_acc[i].acc_type & ~(TRAM_ACC_READ | TRAM_ACC_WRITE | TRAM_ACC_ZERO)) != 0)
+                       return LD10K1_ERR_WRONG_TRAM_ACC_TYPE;
+
+               if (((new_patch->tram_acc[i].acc_type & (TRAM_ACC_READ | TRAM_ACC_WRITE)) != TRAM_ACC_READ) &&
+                       ((new_patch->tram_acc[i].acc_type & (TRAM_ACC_READ | TRAM_ACC_WRITE)) != TRAM_ACC_WRITE))
+                       return LD10K1_ERR_WRONG_TRAM_ACC_TYPE;
+
+               if (new_patch->tram_acc[i].grp < 0 && new_patch->tram_acc[i].grp >= new_patch->tram_count)
+                       return LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE;
+
+               if (new_patch->tram_acc[i].acc_offset < 0 || new_patch->tram_acc[i].acc_offset >= new_patch->tram_grp[new_patch->tram_acc[i].grp].grp_size)
+                       return LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE;
+       }
+
+       /* control check */
+       for (i = 0; i < new_patch->ctl_count; i++) {
+               new_patch->ctl[i].name[43] = '\0';
+
+               if (new_patch->ctl[i].vcount > new_patch->ctl[i].count)
+                       return LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE;
+               if (new_patch->ctl[i].count > MAX_CTL_GPR_COUNT)
+                       return LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE;
+
+               if (new_patch->ctl[i].min > new_patch->ctl[i].max)
+                       return LD10K1_ERR_CTL_MIN_MAX_RANGE;
+
+               if (new_patch->ctl[i].translation < 0 || new_patch->ctl[i].translation > EMU10K1_GPR_TRANSLATION_LAST)
+                       return LD10K1_ERR_CTL_TRANLSLATION;
+
+               for(j = 0; j < new_patch->ctl[i].count; j++) {
+                       if (new_patch->ctl[i].value[j] < new_patch->ctl[i].min || new_patch->ctl[i].value[j] > new_patch->ctl[i].max)
+                               return LD10K1_ERR_CTL_REG_VALUE;
+               }
+       }
+
+       /* instruction check */
+       for (i = 0; i < new_patch->instr_count; i++) {
+               if (new_patch->instr[i].op_code < 0 || new_patch->instr[i].op_code > iSKIP)
+                       return LD10K1_ERR_INSTR_OPCODE;
+
+               for (k = 0; k < 4; k++) {
+                       int arg = new_patch->instr[i].arg[k];
+                       switch (EMU10K1_PREG_TYPE_B(arg)) {
+                               case EMU10K1_PREG_TYPE_IN:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->in_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_OUT:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->out_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_CONST:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->const_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_STA:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->sta_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_DYN:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->dyn_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_HW:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->hw_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_CTL:
+                                       if ((((arg & 0xFF00) >> 8) >= new_patch->ctl_count) ||
+                                               ((arg & 0xFF) >= new_patch->ctl[(arg & 0xFF00) >> 8].count))
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               case EMU10K1_PREG_TYPE_TRAM_DATA:
+                               case EMU10K1_PREG_TYPE_TRAM_ADDR:
+                                       if ((arg & 0xFFFFFFF) >= new_patch->tram_acc_count)
+                                               return LD10K1_ERR_INSTR_ARG_INDEX;
+                                       break;
+                               default:
+                                       return LD10K1_ERR_INSTR_ARG_INDEX;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int ld10k1_patch_fnc_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_patch_del_t *patch_fnc)
+{
+       int err;
+
+       if (patch_fnc->where >= 0 && patch_fnc->where < EMU10K1_PATCH_MAX) {
+               if (dsp_mgr->patch_ptr[patch_fnc->where]) {
+                       if ((err = ld10k1_dsp_mgr_patch_unload(dsp_mgr,
+                               dsp_mgr->patch_ptr[patch_fnc->where],
+                               patch_fnc->where)) < 0)
+                               return err;
+                       else
+                               return 0;
+               } else
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+       }
+       else
+               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+}
+
+int ld10k1_connection_fnc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_connection_t *connection_fnc, int *conn_id)
+{
+       ld10k1_patch_t *from_patch = NULL;
+       ld10k1_patch_t *to_patch = NULL;
+       ld10k1_conn_point_t *from_point = NULL;
+       ld10k1_conn_point_t *to_point = NULL;
+       ld10k1_conn_point_t *tmp_point = NULL;
+       int err;
+
+       if (connection_fnc->what == FNC_CONNECTION_ADD) {
+               if (connection_fnc->from_type != CON_IO_PIN &&
+                       connection_fnc->from_type != CON_IO_POUT &&
+                       connection_fnc->from_type != CON_IO_FX &&
+                       connection_fnc->from_type != CON_IO_IN &&
+                       connection_fnc->from_type != CON_IO_OUT)
+                       return LD10K1_ERR_CONNECTION;
+               if (connection_fnc->to_type != CON_IO_PIN &&
+                       connection_fnc->to_type != CON_IO_POUT &&
+                       connection_fnc->to_type != CON_IO_FX &&
+                       connection_fnc->to_type != CON_IO_IN &&
+                       connection_fnc->to_type != CON_IO_OUT)
+                       return LD10K1_ERR_CONNECTION;
+
+               /* first must be patch */
+               if (connection_fnc->from_type != CON_IO_PIN && connection_fnc->from_type != CON_IO_POUT)
+                       return LD10K1_ERR_CONNECTION;
+
+               if (connection_fnc->from_type == CON_IO_PIN &&
+                       connection_fnc->to_type == CON_IO_OUT)
+                       return LD10K1_ERR_CONNECTION;
+               if (connection_fnc->from_type == CON_IO_POUT &&
+                       (connection_fnc->to_type == CON_IO_FX ||
+                       connection_fnc->to_type == CON_IO_IN))
+                       return LD10K1_ERR_CONNECTION;
+
+               if (connection_fnc->from_patch < 0 || connection_fnc->from_patch >= EMU10K1_PATCH_MAX)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+               from_patch = dsp_mgr->patch_ptr[connection_fnc->from_patch];
+               if (!from_patch)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+               if (connection_fnc->to_type == CON_IO_PIN ||
+                       connection_fnc->to_type == CON_IO_POUT) {
+                       if (connection_fnc->to_patch < 0 || connection_fnc->to_patch >= EMU10K1_PATCH_MAX)
+                               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       to_patch = dsp_mgr->patch_ptr[connection_fnc->to_patch];
+                       if (!to_patch)
+                               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+               }
+               else
+                       to_patch = NULL;
+                       
+               if (from_patch == to_patch)
+                       return LD10K1_ERR_CONNECTION;
+
+               if (connection_fnc->to_io < 0)
+                       return LD10K1_ERR_CONNECTION;
+               if (connection_fnc->from_io < 0)
+                       return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+               if (connection_fnc->from_type == CON_IO_PIN) {
+                       if (connection_fnc->from_io >= from_patch->in_count)
+                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                       from_point = from_patch->ins[connection_fnc->from_io].point;
+               } else {
+                       if (connection_fnc->from_io >= from_patch->out_count)
+                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                       from_point = from_patch->outs[connection_fnc->from_io].point;
+               }
+
+               switch (connection_fnc->to_type) {
+                       case CON_IO_FX:
+                               if (connection_fnc->to_io >= dsp_mgr->fx_count)
+                                       return LD10K1_ERR_CONNECTION;
+                               to_point = dsp_mgr->fxs[connection_fnc->to_io].point;
+                               break;
+                       case CON_IO_IN:
+                               if (connection_fnc->to_io >= dsp_mgr->in_count)
+                                       return LD10K1_ERR_CONNECTION;
+                               to_point = dsp_mgr->ins[connection_fnc->to_io].point;
+                               break;
+                       case CON_IO_OUT:
+                               if (connection_fnc->to_io >= dsp_mgr->out_count)
+                                       return LD10K1_ERR_CONNECTION;
+                               to_point = dsp_mgr->outs[connection_fnc->to_io].point;
+                               break;
+                       case CON_IO_PIN:
+                               if (connection_fnc->to_io >= to_patch->in_count)
+                                       return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                               to_point = to_patch->ins[connection_fnc->to_io].point;
+                               break;
+                       case CON_IO_POUT:
+                               if (connection_fnc->to_io >= to_patch->out_count)
+                                       return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                               to_point = to_patch->outs[connection_fnc->to_io].point;
+                               break;
+               }
+
+               if (from_patch && to_patch) {
+                       if (from_point == to_point)
+                               if (from_point)
+                                       if (connection_fnc->multi || from_point->con_count == 2)
+                                               return 0;
+                       if (!connection_fnc->multi || !to_point) {
+                               if (!(tmp_point = ld10k1_conn_point_alloc(connection_fnc->simple)))
+                                       return LD10K1_ERR_NO_MEM;
+                               if ((err = ld10k1_conn_point_set_to(dsp_mgr, tmp_point, 0, -1)) < 0) {
+                                       ld10k1_conn_point_free(dsp_mgr, tmp_point);
+                                       return err;
+                               }
+
+                               /* reconnect to patch */
+                               if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->to_type, to_patch, connection_fnc->to_io)) < 0) {
+                                       ld10k1_conn_point_free(dsp_mgr, tmp_point);
+                                       return err;
+                               }
+                       } else
+                               tmp_point = to_point;
+
+                       /* reconnect from patch */
+                       if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->from_type, from_patch, connection_fnc->from_io)) < 0) {
+                               /* if point is allocated now this call can't fail */
+                               /* ld10k1_conn_point_free(dsp_mgr, tmp_point); */
+                               return err;
+                       }
+               } else {
+                       if (from_point == to_point && from_point)
+                               return 0;
+                       if (!to_point) {
+                               if (!(tmp_point = ld10k1_conn_point_alloc(0)))
+                                       return LD10K1_ERR_NO_MEM;
+                               if ((err = ld10k1_conn_point_set_to(dsp_mgr, tmp_point, connection_fnc->to_type, connection_fnc->to_io)) < 0) {
+                                       ld10k1_conn_point_free(dsp_mgr, tmp_point);
+                                       return err;
+                               }
+                       } else
+                               tmp_point = to_point;
+
+                       /* reconnect from patch */
+                       if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->from_type, from_patch, connection_fnc->from_io)) < 0) {
+                               /* if point is allocated now this call can't fail */
+                               /* ld10k1_conn_point_free(dsp_mgr, tmp_point); */
+                               return err;
+                       }
+               }
+
+               if (tmp_point->id <= 0)
+                       tmp_point->id = ld10k1_gen_patch_id(dsp_mgr, connection_fnc->from_patch);
+                       
+               *conn_id = tmp_point->id;
+               
+               ld10k1_dsp_mgr_actualize_instr(dsp_mgr);
+               return 0;
+       } if (connection_fnc->what == FNC_CONNECTION_DEL) {
+               if (connection_fnc->from_type != CON_IO_PIN &&
+                       connection_fnc->from_type != CON_IO_POUT)
+                       return LD10K1_ERR_CONNECTION;
+
+               if (connection_fnc->from_patch < 0 || connection_fnc->from_patch >= EMU10K1_PATCH_MAX)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+               from_patch = dsp_mgr->patch_ptr[connection_fnc->from_patch];
+               if (!from_patch)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+               if (connection_fnc->from_io < 0)
+                       return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+
+               if (connection_fnc->from_type == CON_IO_PIN) {
+                       if (connection_fnc->from_io >= from_patch->in_count)
+                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                       from_point = from_patch->ins[connection_fnc->from_io].point;
+               } else {
+                       if (connection_fnc->from_io >= from_patch->out_count)
+                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                       from_point = from_patch->outs[connection_fnc->from_io].point;
+               }
+               
+               *conn_id = -1;
+
+               if (!from_point)
+                       return 0;
+
+               if ((EMU10K1_REG_TYPE_B(from_point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL && from_point->con_count > 1) ||
+                       from_point->con_count > 0)
+                       *conn_id = from_point->id;                      
+                       
+               ld10k1_conn_point_del(dsp_mgr, from_point, connection_fnc->from_type, from_patch, connection_fnc->from_io);
+
+               ld10k1_dsp_mgr_actualize_instr(dsp_mgr);
+               return 0;
+       } else
+               return LD10K1_ERR_CONNECTION_FNC;
+}
+
+ld10k1_ctl_list_item_t *ld10k1_look_control_from_list(ld10k1_ctl_list_item_t *list, ld10k1_ctl_t *gctl)
+{
+       ld10k1_ctl_list_item_t *item;
+
+       for (item = list; item != NULL; item = item->next)
+               if (strcmp(item->ctl.name, gctl->name) == 0 && item->ctl.index == gctl->index)
+                       return item;
+
+       return NULL;
+}
+
+int ld10k1_add_control_to_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl)
+{
+       ld10k1_ctl_list_item_t *item;
+       
+       item = ld10k1_look_control_from_list(*list, gctl);
+       if (!item) {
+               item = (ld10k1_ctl_list_item_t *)malloc(sizeof(ld10k1_ctl_list_item_t));
+               if (!item)
+                       return LD10K1_ERR_NO_MEM;
+
+               item->next = NULL;
+
+               if (!*list)
+                       /* empty */
+                       *list = item;
+               else {
+                       /* add to begining */
+                       item->next = *list;
+                       *list = item;
+               }
+               (*count)++;
+       }
+
+       memcpy(&(item->ctl), gctl, sizeof(*gctl));
+       
+       return 0;
+}
+
+void ld10k1_del_control_from_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl)
+{
+       ld10k1_ctl_list_item_t *item;
+       ld10k1_ctl_list_item_t *item1;
+
+       if (!*list)
+               return;
+
+       item = ld10k1_look_control_from_list(*list, gctl);
+       if (!item)
+               return;
+               
+       if (*list == item) {
+               *list = item->next;
+       } else {
+               for (item1 = *list; item1->next != NULL; item1 = item1->next)
+                       if (item1->next == item) {
+                               item1->next = item->next;
+                               break;
+                       }
+       }
+
+       free(item);
+       (*count)--;
+}
+
+void ld10k1_del_all_controls_from_list(ld10k1_ctl_list_item_t **list, int *count)
+{
+       ld10k1_ctl_list_item_t *item;
+       ld10k1_ctl_list_item_t *item1;
+       
+       for (item = *list; item != NULL;) {
+               item1 = item->next;
+               free(item);
+               item = item1;
+       }
+       
+       *count = 0;
+       *list = NULL;
+}
+
+int ld10k1_get_used_index_for_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl, int **idxs, int *cnt)
+{
+       int i;
+       ld10k1_ctl_list_item_t *item;
+       ld10k1_reserved_ctl_list_item_t *itemr;
+       int count;
+       int *index_list;
+
+       count = 0;
+       i = 0;
+       
+       /* first get count */
+       for (item = dsp_mgr->ctl_list; item != NULL; item = item->next)
+               if (strcmp(item->ctl.name, gctl->name) == 0)
+                       count++;
+                       
+       for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next)
+               if (strcmp(item->ctl.name, gctl->name) == 0)
+                       count++;
+                       
+       for (itemr = dsp_mgr->reserved_ctl_list; itemr != NULL; itemr = itemr->next)
+               if (strcmp(itemr->res_ctl.name, gctl->name) == 0)
+                       count++;
+                       
+       if (!count) {
+               *idxs = NULL;
+               *cnt = 0;
+               return 0;
+       }
+       
+       /* second get array */
+       index_list = (int *)malloc(sizeof(int) * count);
+       if (!index_list)
+               return LD10K1_ERR_NO_MEM;
+               
+       for (item = dsp_mgr->ctl_list; item != NULL; item = item->next)
+               if (strcmp(item->ctl.name, gctl->name) == 0)
+                       index_list[i++] = item->ctl.index;
+       
+       for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next)
+               if (strcmp(item->ctl.name, gctl->name) == 0)
+                       index_list[i++] = item->ctl.index;
+       
+       for (itemr = dsp_mgr->reserved_ctl_list; itemr != NULL; itemr = itemr->next)
+               if (strcmp(itemr->res_ctl.name, gctl->name) == 0)
+                       index_list[i++] = itemr->res_ctl.index;
+                       
+       *idxs = index_list;
+       *cnt = count;
+
+       return 0;
+}
+
+
+int ld10k1_add_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl)
+{
+       int err;
+       int *idxs;
+       int cnt;
+       int new_idx;
+       int i;
+       int found;
+       
+       new_idx = 0;
+       
+       /* check index */
+       if (gctl->want_index < 0) {
+               /* find free index */
+               if ((err = ld10k1_get_used_index_for_control(dsp_mgr, gctl, &idxs, &cnt)) < 0)
+                       return err;
+       
+               while (new_idx < 1000) {
+                       found = 0;
+                       for (i = 0; i < cnt; i++) {
+                               if (new_idx == idxs[i]) {
+                                       new_idx++;
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found) {
+                               gctl->index = new_idx;
+                               break;
+                       }
+               }       
+               
+               if (idxs)
+                       free(idxs);
+               
+               if (new_idx >= 1000)
+                       return LD10K1_ERR_CTL_EXISTS;
+       }
+       else
+               gctl->index = gctl->want_index;
+       
+       /* is there control ??? */
+       if (ld10k1_look_control_from_list(dsp_mgr->ctl_list, gctl))
+               return LD10K1_ERR_CTL_EXISTS;
+       /* is for add ??? */
+       if (ld10k1_look_control_from_list(dsp_mgr->add_ctl_list, gctl))
+               return 0;
+
+       /* add */
+       return ld10k1_add_control_to_list(&(dsp_mgr->add_ctl_list), &(dsp_mgr->add_list_count), gctl);
+}
+
+void ld10k1_del_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl)
+{
+       /* is for add ??? */
+       if (ld10k1_look_control_from_list(dsp_mgr->add_ctl_list, gctl)) {
+               ld10k1_del_control_from_list(&(dsp_mgr->add_ctl_list), &(dsp_mgr->add_list_count), gctl);
+               return;
+       }
+       
+       /* is for del ??? */
+       if (ld10k1_look_control_from_list(dsp_mgr->del_ctl_list, gctl))
+               return;
+
+       /* delete ??? */
+       if (ld10k1_look_control_from_list(dsp_mgr->ctl_list, gctl)) {
+               ld10k1_add_control_to_list(&(dsp_mgr->del_ctl_list), &(dsp_mgr->del_list_count), gctl);
+               return;
+       }
+       return;
+}
+
+/* this will by usefull with modified as10k1 */
+unsigned int named_to_standard[] =
+{
+       /* FX buses */
+       EMU10K1_NREG_FXBUS_PCM_LEFT,            EMU10K1_REG_FX(0x00),   EMU10K1_REG_FX(0x00),
+       EMU10K1_NREG_FXBUS_PCM_RIGHT,           EMU10K1_REG_FX(0x01),   EMU10K1_REG_FX(0x01),
+       EMU10K1_NREG_FXBUS_PCM_FRONT_LEFT,      EMU10K1_REG_FX(0x08),   EMU10K1_REG_FX(0x08),
+       EMU10K1_NREG_FXBUS_PCM_FRONT_RIGHT,     EMU10K1_REG_FX(0x09),   EMU10K1_REG_FX(0x09),
+       EMU10K1_NREG_FXBUS_PCM_REAR_LEFT,       EMU10K1_REG_FX(0x02),   EMU10K1_REG_FX(0x02),
+       EMU10K1_NREG_FXBUS_PCM_REAR_RIGHT,      EMU10K1_REG_FX(0x03),   EMU10K1_REG_FX(0x03),
+       EMU10K1_NREG_FXBUS_PCM_CENTER,          EMU10K1_REG_FX(0x06),   EMU10K1_REG_FX(0x06),
+       EMU10K1_NREG_FXBUS_PCM_LFE,                     EMU10K1_REG_FX(0x07),   EMU10K1_REG_FX(0x07),
+       EMU10K1_NREG_FXBUS_MIDI_LEFT,           EMU10K1_REG_FX(0x04),   EMU10K1_REG_FX(0x04),
+       EMU10K1_NREG_FXBUS_MIDI_RIGHT,          EMU10K1_REG_FX(0x05),   EMU10K1_REG_FX(0x05),
+       EMU10K1_NREG_FXBUS_MIDI_REVERB,         EMU10K1_REG_FX(0x0C),   EMU10K1_REG_FX(0x0C),
+       EMU10K1_NREG_FXBUS_MIDI_CHORUS,         EMU10K1_REG_FX(0x0D),   EMU10K1_REG_FX(0x0D),
+
+       EMU10K1_A_NREG_FXBUS_PT_LEFT,           0,                                              EMU10K1_REG_FX(0x14),
+       EMU10K1_A_NREG_FXBUS_PT_RIGHT,          0,                                              EMU10K1_REG_FX(0x15),
+
+       /* inputs */
+       EMU10K1_NREG_IN_AC97_LEFT,                      EMU10K1_REG_IN(0x00),   EMU10K1_REG_IN(0x00),
+       EMU10K1_NREG_IN_AC97_RIGHT,                     EMU10K1_REG_IN(0x01),   EMU10K1_REG_IN(0x01),
+       EMU10K1_NREG_IN_SPDIF_CD_LEFT,          EMU10K1_REG_IN(0x02),   EMU10K1_REG_IN(0x02),
+       EMU10K1_NREG_IN_SPDIF_CD_RIGHT,         EMU10K1_REG_IN(0x03),   EMU10K1_REG_IN(0x03),
+       EMU10K1_NREG_IN_SPDIF_OPT_LEFT,         EMU10K1_REG_IN(0x06),   EMU10K1_REG_IN(0x04),
+       EMU10K1_NREG_IN_SPDIF_OPT_RIGHT,        EMU10K1_REG_IN(0x07),   EMU10K1_REG_IN(0x05),
+       EMU10K1_NREG_IN_I2S_1_LEFT,                     EMU10K1_REG_IN(0x08),   EMU10K1_REG_IN(0x08),
+       EMU10K1_NREG_IN_I2S_1_RIGHT,            EMU10K1_REG_IN(0x09),   EMU10K1_REG_IN(0x09),
+       EMU10K1_NREG_IN_I2S_2_LEFT,                     EMU10K1_REG_IN(0x0C),   EMU10K1_REG_IN(0x0C),
+       EMU10K1_NREG_IN_I2S_2_RIGHT,            EMU10K1_REG_IN(0x0D),   EMU10K1_REG_IN(0x0D),
+
+       EMU10K1_L_NREG_IN_SPDIF_COAX_LEFT,      EMU10K1_REG_IN(0x0A),   0,
+       EMU10K1_L_NREG_IN_SPDIF_COAX_RIGHT,     EMU10K1_REG_IN(0x0B),   0,
+       EMU10K1_L_NREG_IN_ZOOM_LEFT,            EMU10K1_REG_IN(0x04),   0,
+       EMU10K1_L_NREG_IN_ZOOM_RIGHT,           EMU10K1_REG_IN(0x05),   0,
+       EMU10K1_L_NREG_IN_LINE_1_LEFT,          EMU10K1_REG_IN(0x08),   0,
+       EMU10K1_L_NREG_IN_LINE_1_RIGHT,         EMU10K1_REG_IN(0x09),   0,
+       EMU10K1_L_NREG_IN_LINE_2_LEFT,          EMU10K1_REG_IN(0x0C),   0,
+       EMU10K1_L_NREG_IN_LINE_2_RIGHT,         EMU10K1_REG_IN(0x0D),   0,
+
+       EMU10K1_A_NREG_IN_LINE_1_LEFT,          0,                                              EMU10K1_REG_IN(0x0A),
+       EMU10K1_A_NREG_IN_LINE_1_RIGHT,         0,                                              EMU10K1_REG_IN(0x0B),
+       EMU10K1_A_NREG_IN_LINE_2_LEFT,          0,                                              EMU10K1_REG_IN(0x08),
+       EMU10K1_A_NREG_IN_LINE_2_RIGHT,         0,                                              EMU10K1_REG_IN(0x09),
+       EMU10K1_A_NREG_IN_LINE_3_LEFT,          0,                                              EMU10K1_REG_IN(0x0C),
+       EMU10K1_A_NREG_IN_LINE_3_RIGHT,         0,                                              EMU10K1_REG_IN(0x0D),
+
+       /* outputs */
+       EMU10K1_NREG_OUT_FRONT_LEFT,            EMU10K1_REG_OUT(0x00),  EMU10K1_REG_OUT(0x08),
+       EMU10K1_NREG_OUT_FRONT_RIGHT,           EMU10K1_REG_OUT(0x01),  EMU10K1_REG_OUT(0x09),
+       EMU10K1_NREG_OUT_REAR_LEFT,                     EMU10K1_REG_OUT(0x08),  EMU10K1_REG_OUT(0x0E),
+       EMU10K1_NREG_OUT_REAR_RIGHT,            EMU10K1_REG_OUT(0x09),  EMU10K1_REG_OUT(0x0F),
+       EMU10K1_NREG_OUT_CENTER,                        EMU10K1_REG_OUT(0x04),  EMU10K1_REG_OUT(0x0A),
+       EMU10K1_NREG_OUT_LFE,                           EMU10K1_REG_OUT(0x05),  EMU10K1_REG_OUT(0x0B),
+       EMU10K1_NREG_OUT_AC97_LEFT,                     EMU10K1_REG_OUT(0x00),  EMU10K1_REG_OUT(0x10),
+       EMU10K1_NREG_OUT_AC97_RIGHT,            EMU10K1_REG_OUT(0x01),  EMU10K1_REG_OUT(0x11),
+       EMU10K1_NREG_OUT_ADC_LEFT,                      EMU10K1_REG_OUT(0x0A),  EMU10K1_REG_OUT(0x16),
+       EMU10K1_NREG_OUT_ADC_RIGHT,                     EMU10K1_REG_OUT(0x0B),  EMU10K1_REG_OUT(0x17),
+       EMU10K1_NREG_OUT_MIC,                           EMU10K1_REG_OUT(0x0C),  EMU10K1_REG_OUT(0x18),
+       EMU10K1_NREG_OUT_HEADPHONE_LEFT,        EMU10K1_REG_OUT(0x06),  EMU10K1_REG_OUT(0x04),
+       EMU10K1_NREG_OUT_HEADPHONE_RIGHT,       EMU10K1_REG_OUT(0x07),  EMU10K1_REG_OUT(0x05),
+
+       EMU10K1_L_NREG_OUT_OPT_LEFT,            EMU10K1_REG_OUT(0x02),  0,
+       EMU10K1_L_NREG_OUT_OPT_RIGHT,           EMU10K1_REG_OUT(0x03),  0,
+
+       EMU10K1_A_NREG_OUT_D_FRONT_LEFT,        0,                                              EMU10K1_REG_OUT(0x00),
+       EMU10K1_A_NREG_OUT_D_FRONT_RIGHT,       0,                                              EMU10K1_REG_OUT(0x01),
+       EMU10K1_A_NREG_OUT_D_REAR_LEFT,         0,                                              EMU10K1_REG_OUT(0x06),
+       EMU10K1_A_NREG_OUT_D_REAR_RIGHT,        0,                                              EMU10K1_REG_OUT(0x07),
+       EMU10K1_A_NREG_OUT_D_CENTER,            0,                                              EMU10K1_REG_OUT(0x02),
+       EMU10K1_A_NREG_OUT_D_LFE,                       0,                                              EMU10K1_REG_OUT(0x03),
+
+       /* hardware */
+       EMU10K1_NREG_CONST_00000000,            EMU10K1_REG_HW(0x00),   EMU10K1_REG_HW(0x00),
+       EMU10K1_NREG_CONST_00000001,            EMU10K1_REG_HW(0x01),   EMU10K1_REG_HW(0x01),
+       EMU10K1_NREG_CONST_00000002,            EMU10K1_REG_HW(0x02),   EMU10K1_REG_HW(0x02),
+       EMU10K1_NREG_CONST_00000003,            EMU10K1_REG_HW(0x03),   EMU10K1_REG_HW(0x03),
+       EMU10K1_NREG_CONST_00000004,            EMU10K1_REG_HW(0x04),   EMU10K1_REG_HW(0x04),
+       EMU10K1_NREG_CONST_00000008,            EMU10K1_REG_HW(0x05),   EMU10K1_REG_HW(0x05),
+       EMU10K1_NREG_CONST_00000010,            EMU10K1_REG_HW(0x06),   EMU10K1_REG_HW(0x06),
+       EMU10K1_NREG_CONST_00000020,            EMU10K1_REG_HW(0x07),   EMU10K1_REG_HW(0x07),
+       EMU10K1_NREG_CONST_00000100,            EMU10K1_REG_HW(0x08),   EMU10K1_REG_HW(0x08),
+       EMU10K1_NREG_CONST_00010000,            EMU10K1_REG_HW(0x09),   EMU10K1_REG_HW(0x09),
+       EMU10K1_L_NREG_CONST_00080000,          EMU10K1_REG_HW(0x0A),   0,
+       EMU10K1_A_NREG_CONST_00000800,          0,                                              EMU10K1_REG_HW(0x0A),
+       EMU10K1_NREG_CONST_10000000,            EMU10K1_REG_HW(0x0B),   EMU10K1_REG_HW(0x0B),
+       EMU10K1_NREG_CONST_20000000,            EMU10K1_REG_HW(0x0C),   EMU10K1_REG_HW(0x0C),
+       EMU10K1_NREG_CONST_40000000,            EMU10K1_REG_HW(0x0D),   EMU10K1_REG_HW(0x0D),
+       EMU10K1_NREG_CONST_80000000,            EMU10K1_REG_HW(0x0E),   EMU10K1_REG_HW(0x0E),
+       EMU10K1_NREG_CONST_7FFFFFFF,            EMU10K1_REG_HW(0x0F),   EMU10K1_REG_HW(0x0F),
+       EMU10K1_NREG_CONST_FFFFFFFF,            EMU10K1_REG_HW(0x10),   EMU10K1_REG_HW(0x10),
+       EMU10K1_NREG_CONST_FFFFFFFE,            EMU10K1_REG_HW(0x11),   EMU10K1_REG_HW(0x11),
+       EMU10K1_NREG_CONST_C0000000,            EMU10K1_REG_HW(0x12),   EMU10K1_REG_HW(0x12),
+       EMU10K1_NREG_CONST_4F1BBCDC,            EMU10K1_REG_HW(0x13),   EMU10K1_REG_HW(0x13),
+       EMU10K1_NREG_CONST_5A7EF9DB,            EMU10K1_REG_HW(0x14),   EMU10K1_REG_HW(0x14),
+       EMU10K1_NREG_CONST_00100000,            EMU10K1_REG_HW(0x15),   EMU10K1_REG_HW(0x15),
+
+       EMU10K1_NREG_HW_ACCUM,                          EMU10K1_REG_HW(0x16),   EMU10K1_REG_HW(0x16),
+       EMU10K1_NREG_HW_CCR,                            EMU10K1_REG_HW(0x17),   EMU10K1_REG_HW(0x17),
+       EMU10K1_NREG_HW_NOISE1,                         EMU10K1_REG_HW(0x18),   EMU10K1_REG_HW(0x18),
+       EMU10K1_NREG_HW_NOISE2,                         EMU10K1_REG_HW(0x19),   EMU10K1_REG_HW(0x19),
+       EMU10K1_NREG_HW_IRQ,                            EMU10K1_REG_HW(0x1A),   EMU10K1_REG_HW(0x1A),
+       EMU10K1_NREG_HW_DBAC,                           EMU10K1_REG_HW(0x1B),   EMU10K1_REG_HW(0x1B),
+       EMU10K1_A_NREG_HW_DBACE,                        0,                                              EMU10K1_REG_HW(0x1D),
+       0
+};
+
+unsigned int ld10k1_resolve_named_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg)
+{
+       /* find named - better will be use of binary search */
+       int i;
+
+       i = 0;
+       while (named_to_standard[i]) {
+               if (named_to_standard[i] == reg)
+                       return dsp_mgr->audigy ? named_to_standard[i + 2] : named_to_standard[i + 1];
+               i += 3;
+       }
+
+       return 0;
+}
+
+unsigned int ld10k1_gpr_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res,
+       unsigned int usage, unsigned int val)
+{
+       int i, j;
+       if (*res_count >= max_res_count)
+               return 0;
+
+       for (i = 0; i < dsp_mgr->regs_max_count; i++) {
+               if (!dsp_mgr->regs[i].used) {
+                       /* check in reserved */
+                       for (j = 0; j < *res_count; j++) {
+                               if (res[j] == i)
+                                       break;
+                       }
+
+                       if (j >= *res_count) {
+                               res[*res_count] = i;
+                               (*res_count)++;
+                               dsp_mgr->regs[i].gpr_usage = usage;
+                               dsp_mgr->regs[i].val = val;
+                               return EMU10K1_REG_NORMAL(i);
+                       }
+               }
+       }
+       return 0;
+}
+
+unsigned int ld10k1_gpr_dyn_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res)
+{
+       int i, j;
+       if (*res_count >= max_res_count)
+               return 0;
+
+       /* try find other dyn not reserved */
+       for (i = 0; i < dsp_mgr->regs_max_count; i++) {
+               if (dsp_mgr->regs[i].used && dsp_mgr->regs[i].gpr_usage == GPR_USAGE_DYNAMIC) {
+                       /* check in reserved */
+                       for (j = 0; j < *res_count; j++) {
+                               if (res[j] == i)
+                                       break;
+                       }
+
+                       if (j >= *res_count) {
+                               res[*res_count] = i;
+                               (*res_count)++;
+                               dsp_mgr->regs[i].gpr_usage = GPR_USAGE_DYNAMIC;
+                               dsp_mgr->regs[i].val = 0;
+                               return EMU10K1_REG_NORMAL(i);
+                       }
+               }
+       }
+
+       /* not found - try normal */
+       return ld10k1_gpr_reserve(dsp_mgr, max_res_count, res_count, res, GPR_USAGE_DYNAMIC, 0);
+}
+
+void ld10k1_gpr_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
+{
+       int i = reg & 0x0FFFFFFF;
+       dsp_mgr->regs[i].ref++;
+       dsp_mgr->regs[i].modified = 1;
+       dsp_mgr->regs[i].used = 1;
+}
+
+void ld10k1_gpr_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
+{
+       int i = reg & 0x0FFFFFFF;
+       dsp_mgr->regs[i].gpr_usage = GPR_USAGE_NONE;
+       dsp_mgr->regs[i].val = 0;
+       dsp_mgr->regs[i].ref--;
+       dsp_mgr->regs[i].modified = 1;
+       dsp_mgr->regs[i].used = 0;
+}
+
+unsigned int ld10k1_const_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_const_count, int *res_const_count, int *res_const,
+       int max_res_count, int *res_count, int *res, int const_val)
+{
+       int i, j;
+       int free_gpr;
+
+       if (*res_const_count >= max_res_const_count)
+               return 0;
+
+       /* check in reserved */
+       for (i = 0; i < *res_const_count; i++) {
+               if (dsp_mgr->consts[res_const[i]].const_val == const_val)
+                       return EMU10K1_REG_CONST(res_const[i]);
+       }
+
+       /* check in all constants */
+       for (i = 0; i < dsp_mgr->consts_max_count; i++)
+               if (dsp_mgr->consts[i].used && dsp_mgr->consts[i].const_val == const_val) {
+                       /* add to reserved */
+                       res_const[*res_const_count] = i;
+                       (*res_const_count)++;
+                       return EMU10K1_REG_CONST(i);
+               }
+
+
+       /* try find other dyn not reserved */
+       for (i = 0; i < dsp_mgr->consts_max_count; i++) {
+               if (!dsp_mgr->consts[i].used) {
+                       /* there is free room */
+                       /* if in reserved continue */
+                       for (j = 0; j < *res_const_count; j++) {
+                               if (res_const[j] == i)
+                                       break;
+                       }
+                       if (j < *res_const_count)
+                               continue;
+
+                       free_gpr = ld10k1_gpr_reserve(dsp_mgr, max_res_count, res_count, res, GPR_USAGE_CONST, const_val);
+                       if (!free_gpr)
+                               return 0;
+                       res_const[*res_const_count] = i;
+                       (*res_const_count)++;
+                       dsp_mgr->consts[i].gpr_idx = free_gpr;
+                       dsp_mgr->consts[i].const_val = const_val;
+                       dsp_mgr->consts[i].hw = 0;
+                       return EMU10K1_REG_CONST(i);
+               }
+       }
+
+       return 0;
+}
+
+void ld10k1_const_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
+{
+       int i = reg & 0x0FFFFFFF;
+       dsp_mgr->consts[i].ref++;
+       if (!dsp_mgr->consts[i].used) {
+               /*ld10k1_gpr_free(dsp_mgr, dsp_mgr->consts[i].gpr_idx);*/
+               dsp_mgr->consts[i].used = 1;
+       }
+}
+
+void ld10k1_const_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
+{
+       int i = reg & 0x0FFFFFFF;
+       dsp_mgr->consts[i].ref--;
+       if (dsp_mgr->consts[i].ref == 0) {
+               if (!dsp_mgr->consts[i].hw)
+                       dsp_mgr->consts[i].used = 0;
+       }
+}
+
+ld10k1_conn_point_t *ld10k1_conn_point_alloc(int simple)
+{
+       ld10k1_conn_point_t *tmp = (ld10k1_conn_point_t *)malloc(sizeof(ld10k1_conn_point_t));
+       int i;
+
+       if (!tmp)
+               return NULL;
+
+       tmp->simple = simple;
+       tmp->id = 0;
+
+       tmp->next = NULL;
+       tmp->con_count = 0;
+       tmp->con_gpr_idx = 0;
+
+       tmp->reserved_gpr = 0;
+       tmp->reserved_instr = 0;
+
+       tmp->out_instr_offset = 0;
+
+       for (i = 0; i < MAX_CONN_PER_POINT; i++) {
+               tmp->type[i] = 0;
+               tmp->patch[i] = NULL;
+               tmp->io[i] = -1;
+               tmp->out_gpr_idx[i] = 0;
+       }
+
+       tmp->owner = NULL;
+       tmp->position = INSERT_BEFORE_OWNER;
+       return tmp;
+}
+
+void ld10k1_conn_point_free(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point)
+{
+       int i;
+
+       point->owner = NULL;
+
+       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+               if (point->type[i] != 0) {
+                   if (point->out_gpr_idx[i]) {
+                               ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[i]);
+                               point->out_gpr_idx[i] = 0;
+                       }
+
+                       if (point->type[i] == CON_IO_PIN) {
+                               point->patch[i]->ins[point->io[i]].point = NULL;
+                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[i], EMU10K1_PREG_IN(point->io[i]));
+                       } else {
+                               point->patch[i]->outs[point->io[i]].point = NULL;
+                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[i], EMU10K1_PREG_OUT(point->io[i]));
+                       }
+
+                       point->con_count--;
+
+                       point->type[i] = 0;
+                       point->patch[i] = NULL;
+                       point->io[i] = -1;
+               }
+
+       dsp_mgr->instr_free += point->reserved_instr;
+       point->reserved_instr = 0;
+
+       ld10k1_conn_point_unset(dsp_mgr, point);
+}
+
+void ld10k1_point_actualize_owner(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point)
+{
+       /* instructions should be alocated */
+       int i;
+       int icount, iarg, iout;
+
+       ld10k1_patch_t *tmp_owner = NULL;
+
+       if (point->simple)
+               return;
+
+       if (point->reserved_gpr > 0) {
+               if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL) {
+                       /* patch reg */
+                       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+                               if (point->type[i] == CON_IO_PIN) {
+                                       if (!tmp_owner)
+                                               tmp_owner = point->patch[i];
+                                       else {
+                                               if (tmp_owner->order > point->patch[i]->order)
+                                                       tmp_owner = point->patch[i];
+                                       }
+                               }
+                       point->owner = tmp_owner;
+                       point->position = INSERT_BEFORE_OWNER;
+               } else {
+                       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+                               if (point->type[i] == CON_IO_POUT) {
+                                       if (!tmp_owner)
+                                               tmp_owner = point->patch[i];
+                                       else {
+                                               if (tmp_owner->order < point->patch[i]->order)
+                                                       tmp_owner = point->patch[i];
+                                       }
+                               }
+                       point->owner = tmp_owner;
+                       point->position = INSERT_AFTER_OWNER;
+               }
+
+               icount = 0;
+               iarg = 0;
+               iout = 0;
+               for (i = 0; i < MAX_CONN_PER_POINT; i++) {
+                       if (point->out_gpr_idx[i] != 0) {
+                               if (iarg == 0) {
+                                       point->out_instr[icount].used = 1;
+                                       point->out_instr[icount].modified = 1;
+                                       point->out_instr[icount].op_code = iACC3;
+                                       point->out_instr[icount].arg[0] = point->con_gpr_idx;
+                                       iarg++;
+                                       if (iout >= 3) {
+                                               point->out_instr[icount].arg[1] = point->con_gpr_idx;
+                                               iarg++;
+                                       }
+                               }
+                               point->out_instr[icount].arg[iarg++] = point->out_gpr_idx[i];
+
+                               iout++;
+                               if (iarg > 3) {
+                                       icount++;
+                                       iarg = 0;
+                               }
+                       }
+               }
+
+               if (iarg > 0/* && iarg <= 3*/)
+                       for (i = iarg; i < 4; i++)
+                               point->out_instr[icount].arg[i] = EMU10K1_REG_HW(0);
+       } else {
+               point->owner = NULL;
+               point->position = INSERT_BEFORE_OWNER;
+       }
+}
+
+int ld10k1_conn_point_set_to(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, int io)
+{
+       int reserved_tmp;
+       int reserved_tmp_count = 0;
+       unsigned int reserved;
+
+       switch (type) {
+               case CON_IO_FX:
+                       dsp_mgr->fxs[io].point = point;
+                       point->con_gpr_idx = EMU10K1_REG_FX(io);
+                       break;
+               case CON_IO_IN:
+                       dsp_mgr->ins[io].point = point;
+                       point->con_gpr_idx = EMU10K1_REG_IN(io);
+                       break;
+               case CON_IO_OUT:
+                       dsp_mgr->outs[io].point = point;
+                       point->con_gpr_idx = EMU10K1_REG_OUT(io);
+                       break;
+               default:
+                       reserved = ld10k1_gpr_reserve(dsp_mgr, 1, &reserved_tmp_count, &reserved_tmp, GPR_USAGE_NORMAL, 0);
+                       if (!reserved)
+                               return LD10K1_ERR_NOT_FREE_REG;
+                       ld10k1_gpr_alloc(dsp_mgr, reserved);
+                       point->con_gpr_idx = reserved;
+       }
+
+       /* FIXME - aktualizacia instrukcii */
+
+
+       ld10k1_conn_point_add_to_list(dsp_mgr, point);
+
+       return 0;
+}
+
+void ld10k1_conn_point_unset(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point)
+{
+       int index = point->con_gpr_idx & ~EMU10K1_REG_TYPE_MASK;
+       switch (EMU10K1_REG_TYPE_B(point->con_gpr_idx)) {
+               case EMU10K1_REG_TYPE_FX:
+                       dsp_mgr->fxs[index].point = NULL;
+                       point->con_gpr_idx = 0;
+                       break;
+               case EMU10K1_REG_TYPE_INPUT:
+                       dsp_mgr->ins[index].point = NULL;
+                       point->con_gpr_idx = 0;
+                       break;
+               case EMU10K1_REG_TYPE_OUTPUT:
+                       dsp_mgr->outs[index].point = NULL;
+                       point->con_gpr_idx = 0;
+                       break;
+               default:
+                       ld10k1_gpr_free(dsp_mgr, point->con_gpr_idx);
+                       point->con_gpr_idx = 0;
+       }
+
+       ld10k1_conn_point_del_from_list(dsp_mgr, point);
+
+       /* FIXME - aktualizacia instrukcii */
+}
+
+int ld10k1_conn_point_add(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io)
+{
+       int i, j;
+       int poutcount;
+       int allocgprcount = 0;
+       int allocinstrcount = 0;
+       unsigned int reserved[2];
+       unsigned int res[2];
+       int reservedcount = 0;
+       int usedreserved = 0;
+
+       if (point->con_count >= MAX_CONN_PER_POINT)
+               return LD10K1_ERR_MAX_CON_PER_POINT;
+
+       /* check pout count */
+       if (!point->simple && type == CON_IO_POUT) {
+               poutcount = 0;
+               for (i = 0; i < MAX_CONN_PER_POINT; i++)
+                       if (point->type[i] == CON_IO_POUT)
+                               poutcount++;
+
+               if (poutcount > 0) {
+                       if (poutcount < 2) {
+                               allocgprcount = 2;
+                               allocinstrcount = 1;
+                       } else if (poutcount >= 2) {
+                               allocgprcount = 1;
+                               if ((poutcount - 3) % 2 == 0) {
+                                       allocinstrcount = 1;
+                               }
+                       }
+
+                       /* allocate instr */
+                       if (dsp_mgr->instr_free < allocinstrcount)
+                               return LD10K1_ERR_NOT_FREE_INSTR;
+
+                       /* allocate gpr */
+                       for (i = 0; i < allocgprcount; i++) {
+                               reserved[i] = ld10k1_gpr_reserve(dsp_mgr, 2, &reservedcount, res, GPR_USAGE_NORMAL, 0);
+                               if (!reserved[i])
+                                       return LD10K1_ERR_NOT_FREE_REG;
+                       }
+
+                       for (i = 0; i < allocgprcount; i++)
+                               ld10k1_gpr_alloc(dsp_mgr, reserved[i]);
+               }
+       }
+
+       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+               if (point->type[i] == 0) {
+                       point->type[i] = type;
+                       point->patch[i] = patch;
+                       point->io[i] = io;
+                       point->out_gpr_idx[i] = 0;
+
+                       if (type == CON_IO_PIN) {
+                               if (patch->ins[io].point)
+                                       ld10k1_conn_point_del(dsp_mgr, patch->ins[io].point, CON_IO_PIN, patch, io);
+                               patch->ins[io].point = point;
+                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_IN(io));
+                       } else {
+                               if (patch->outs[io].point)
+                                       ld10k1_conn_point_del(dsp_mgr, patch->outs[io].point, CON_IO_POUT, patch, io);
+                               patch->outs[io].point = point;
+
+                               if (point->simple)
+                                       ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io));
+                               else {
+                                       /* i is not used anymore */
+                                       /* for all CON_IO_POUT where isn't reg add reserved */
+                                       if (reservedcount > 0) {
+                                               for (j = 0; j < MAX_CONN_PER_POINT; j++) {
+                                                       if (point->type[j] == CON_IO_POUT && point->out_gpr_idx[j] == 0) {
+                                                               point->out_gpr_idx[j] = reserved[usedreserved++];
+                                                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[j], EMU10K1_PREG_OUT(point->io[j]));
+                                                               if (usedreserved >= reservedcount)
+                                                                       break;
+                                                       }
+                                               }
+                                       } else
+                                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io));
+
+                                       dsp_mgr->instr_free -= allocinstrcount;
+                                       point->reserved_gpr += reservedcount;
+                                       point->reserved_instr += allocinstrcount;
+
+                                       if (reservedcount > 0)
+                                               ld10k1_point_actualize_owner(dsp_mgr, point);
+                               }
+                       }
+
+                       point->con_count++;
+
+                       return 0;
+               }
+
+       return LD10K1_ERR_MAX_CON_PER_POINT;
+}
+
+int ld10k1_conn_point_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io)
+{
+       int i, j;
+       int poutcount;
+       int inc, outc;
+
+       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+               if (point->type[i] == type && point->patch[i] == patch && point->io[i] == io) {
+                       point->type[i] = 0;
+                       point->patch[i] = NULL;
+                       point->io[i] = -1;
+                       if (type == CON_IO_PIN) {
+                               patch->ins[io].point = NULL;
+                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_IN(io));
+                       } else {
+                               patch->outs[io].point = NULL;
+                               if (!point->simple && point->out_gpr_idx[i]) {
+                                       ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[i]);
+                                       point->reserved_gpr--;
+                                       point->out_gpr_idx[i] = 0;
+                               }
+                               ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io));
+
+                               if (!point->simple) {
+                                       /* get pout count */
+                                       poutcount = 0;
+                                       for (i = 0; i < MAX_CONN_PER_POINT; i++)
+                                               if (point->type[i] == CON_IO_POUT)
+                                                       poutcount++;
+
+                                       if (poutcount > 0) {
+                                               if (poutcount < 2) {
+                                                       /* free all gpr and instr */
+                                                       for (j = 0; j < MAX_CONN_PER_POINT; j++)
+                                                               if (point->type[j] == CON_IO_POUT && point->out_gpr_idx[j]) {
+                                                                       ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[j], EMU10K1_PREG_OUT(point->io[j]));
+                                                                       ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[j]);
+                                                                       point->reserved_gpr--;
+                                                                       point->out_gpr_idx[j] = 0;
+                                                               }
+                                                       dsp_mgr->instr_free += point->reserved_instr;
+                                                       point->reserved_instr -= point->reserved_instr;
+                                               } else if ((poutcount - 3) % 2 == 0) {
+                                                       /* free 1 instruction */
+                                                       dsp_mgr->instr_free += 1;
+                                                       point->reserved_instr -= 1;
+                                               }
+                                       }
+                                       ld10k1_point_actualize_owner(dsp_mgr, point);
+                               }
+                       }
+                       point->con_count--;
+                       
+                       /* check in out count */
+                       outc = 0;
+                       inc = 0;
+                       for (j = 0; j < MAX_CONN_PER_POINT; j++) {
+                               if (point->type[j] == CON_IO_POUT)
+                                       outc++;
+                               else if (point->type[j] == CON_IO_PIN)
+                                       inc++;
+                       }
+
+                       if ((EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL && point->con_count <= 1) ||
+                               point->con_count <= 0 ||
+                               ((outc <= 0 || inc <= 0) && EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL))
+                               ld10k1_conn_point_free(dsp_mgr, point);
+
+                       return 0;
+               }
+       return 0;
+}
+
+int ld10k1_conn_point_get_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io)
+{
+       unsigned int reg = 0;
+       int i;
+
+       for (i = 0; i < MAX_CONN_PER_POINT; i++) {
+               if (point->patch[i] == patch &&
+                       point->type[i] == type &&
+                       point->io[i] == io) {
+                       reg = point->out_gpr_idx[i];
+                       break;
+               }
+       }
+       if (reg == 0)
+               reg = point->con_gpr_idx;
+       return reg;
+}
+
+int ld10k1_gen_patch_id(ld10k1_dsp_mgr_t *dsp_mgr, int pnum)
+{
+       int nid = 0;
+
+       nid = dsp_mgr->patch_id_gens[pnum]++ | pnum << 16;
+       return nid;
+}
+
+void ld10k1_conn_point_add_to_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point)
+{
+       if (dsp_mgr->point_list)
+               point->next = dsp_mgr->point_list;
+       else
+               point->next = NULL;
+       dsp_mgr->point_list = point;
+}
+
+void ld10k1_conn_point_del_from_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point)
+{
+       ld10k1_conn_point_t *tmp = dsp_mgr->point_list;
+
+       if (tmp == point) {
+               dsp_mgr->point_list = point->next;
+               point->next = NULL;
+               return;
+       }
+
+       while (tmp) {
+               if (tmp->next == point) {
+                       tmp->next = point->next;
+                       point->next = NULL;
+                       return;
+               }
+               tmp = tmp->next;
+       }
+}
diff --git a/ld10k1/src/ld10k1_fnc1.c b/ld10k1/src/ld10k1_fnc1.c
new file mode 100644 (file)
index 0000000..651fcff
--- /dev/null
@@ -0,0 +1,1507 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <alsa/asoundlib.h>
+
+#include <signal.h>
+#include "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_fnc_int.h"
+#include "ld10k1_debug.h"
+#include "ld10k1_error.h"
+#include "ld10k1_dump.h"
+#include "ld10k1_driver.h"
+#include "ld10k1_mixer.h"
+#include "comm.h"
+
+
+void ld10k1_fnc_prepare_free();
+int ld10k1_fnc_patch_add(int data_conn, int op, int size);
+int ld10k1_fnc_patch_del(int data_conn, int op, int size);
+int ld10k1_fnc_patch_conn(int data_conn, int op, int size);
+int ld10k1_fnc_name_find(int data_conn, int op, int size);
+int ld10k1_fnc_name_rename(int data_conn, int op, int size);
+int ld10k1_fnc_dsp_init(int data_conn, int op, int size);
+int ld10k1_fnc_get_io_count(int data_conn, int op, int size);
+int ld10k1_fnc_get_io(int data_conn, int op, int size);
+int ld10k1_fnc_get_pio_count(int data_conn, int op, int size);
+int ld10k1_fnc_get_pio(int data_conn, int op, int size);
+int ld10k1_fnc_get_patches_info(int data_conn, int op, int size);
+int ld10k1_fnc_get_patch(int data_conn, int op, int size);
+int ld10k1_fnc_dump(int data_conn, int op, int size);
+int ld10k1_fnc_version(int data_conn, int op, int size);
+int ld10k1_fnc_get_points_info(int data_conn, int op, int size);
+int ld10k1_fnc_get_point_info(int data_conn, int op, int size);
+int ld10k1_fnc_get_dsp_info(int data_conn, int op, int size);
+
+ld10k1_dsp_mgr_t dsp_mgr;
+
+struct fnc_table_t
+{
+       int fnc;
+       int min_size;
+       int max_size;
+       int (*fnc_code)(int data_conn, int op, int size);
+};
+
+struct fnc_table_t fnc_table[] =
+{
+       {FNC_PATCH_ADD, sizeof(ld10k1_fnc_patch_add_t), sizeof(ld10k1_fnc_patch_add_t), ld10k1_fnc_patch_add},
+       {FNC_PATCH_DEL, sizeof(ld10k1_fnc_patch_del_t), sizeof(ld10k1_fnc_patch_del_t), ld10k1_fnc_patch_del},
+       {FNC_CONNECTION_ADD, sizeof(ld10k1_fnc_connection_t), sizeof(ld10k1_fnc_connection_t), ld10k1_fnc_patch_conn},
+       {FNC_CONNECTION_DEL, sizeof(ld10k1_fnc_connection_t), sizeof(ld10k1_fnc_connection_t), ld10k1_fnc_patch_conn},
+       {FNC_DEBUG, sizeof(ld10k1_fnc_debug_t), sizeof(ld10k1_fnc_debug_t), ld10k1_fnc_debug},
+       {FNC_PATCH_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_PATCH_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_FX_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_IN_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_OUT_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_PATCH_IN_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_PATCH_OUT_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
+       {FNC_FX_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_IN_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_OUT_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_PATCH_IN_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_PATCH_OUT_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
+       {FNC_GET_FX_COUNT, 0, 0, ld10k1_fnc_get_io_count},
+       {FNC_GET_IN_COUNT, 0, 0, ld10k1_fnc_get_io_count},
+       {FNC_GET_OUT_COUNT, 0, 0, ld10k1_fnc_get_io_count},
+       {FNC_GET_PIN_COUNT, sizeof(int), sizeof(int), ld10k1_fnc_get_pio_count},
+       {FNC_GET_POUT_COUNT, sizeof(int), sizeof(int), ld10k1_fnc_get_pio_count},
+       {FNC_GET_FX, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
+       {FNC_GET_IN, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
+       {FNC_GET_OUT, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
+       {FNC_GET_PIN, sizeof(int) * 2, sizeof(int) * 2, ld10k1_fnc_get_pio},
+       {FNC_GET_POUT, sizeof(int) * 2, sizeof(int) * 2, ld10k1_fnc_get_pio},
+       {FNC_GET_PATCHES_INFO, 0, 0, ld10k1_fnc_get_patches_info},
+       {FNC_GET_PATCH, sizeof(int), sizeof(int), ld10k1_fnc_get_patch},
+       {FNC_DSP_INIT, 0, 0, ld10k1_fnc_dsp_init},
+       {FNC_DUMP, 0, 0, ld10k1_fnc_dump},
+       {FNC_VERSION, 0, 0, ld10k1_fnc_version},
+       {FNC_GET_POINTS_INFO, 0, 0, ld10k1_fnc_get_points_info},
+       {FNC_GET_POINT_INFO, sizeof(int), sizeof(int), ld10k1_fnc_get_point_info},
+       {FNC_GET_DSP_INFO, 0, 0, ld10k1_fnc_get_dsp_info},
+       {-1, 0, 0, NULL}
+};
+
+ld10k1_dsp_mgr_t dsp_mgr;
+
+int send_response_ok(int conn_num)
+{
+       return send_response(conn_num, FNC_OK, 0, NULL, 0);
+}
+
+int send_response_err(int conn_num, int err)
+{
+       return send_response(conn_num, FNC_ERR, err, NULL, 0);
+}
+
+int send_response_wd(int conn_num, void *data, int data_size)
+{
+       return send_response(conn_num, FNC_OK, 0, data, data_size);
+}
+
+struct ClientDefTag
+{
+       int used;
+       int socket;
+};
+
+typedef struct ClientDefTag ClientDef;
+
+#define MAX_CLIENTS 10
+ClientDef clients[MAX_CLIENTS];
+int clients_count = 0;
+
+static void client_init()
+{
+       int i;
+       for (i = 0; i < MAX_CLIENTS; i++)
+               clients[i].used = 0;
+
+       clients_count = 0;
+}
+
+static int client_add()
+{
+       int i;
+
+       for (i = 0; i < MAX_CLIENTS; i++)
+               if (clients[i].used == 0) {
+                       clients[i].used = 1;
+                       clients_count++;
+                       return i;
+               }
+       return -1;
+}
+
+static void client_del(int client)
+{
+    if (client >= 0 && client < MAX_CLIENTS && clients[client].used == 1) {
+       clients[client].used = 0;
+       clients_count--;
+    }
+}
+
+static int client_find_by_socket(int socket)
+{
+       int i;
+
+       for (i = 0; i < MAX_CLIENTS; i++)
+               if (clients[i].socket == socket)
+                       return i;
+       return -1;
+}
+
+int main_loop(comm_param *param, int audigy, const char *card_id, int tram_size, snd_ctl_t *ctlp)
+{
+       fd_set active_fd_set/*, read_fd_set*/;
+       int i, j, res = 0;
+       __sighandler_t old_sig_pipe;
+
+       int main_sock = 0;
+       int data_sock = 0;
+       int new_client = 0;
+       int op = 0;
+       int data_size = 0;
+
+       int retval = 0;
+
+       dsp_mgr.audigy = audigy;
+       dsp_mgr.card_id = card_id;
+
+       if (ld10k1_dsp_mgr_init(&dsp_mgr))
+               return -1;
+
+       /* initialize id generators */
+       ld10k1_dsp_mgr_init_id_gen(&dsp_mgr);
+
+
+       if (ld10k1_init_driver(&dsp_mgr, tram_size) < 0) {
+               ld10k1_dsp_mgr_free(&dsp_mgr);
+               return -1;
+       }
+       
+       if (ld10k1_init_reserved_ctls(&dsp_mgr, ctlp) < 0) {
+               ld10k1_dsp_mgr_free(&dsp_mgr);
+               return -1;
+       }
+
+       old_sig_pipe = signal(SIGPIPE, SIG_IGN);
+
+       param->server = 1;
+       if ((main_sock = setup_comm(param)) < 0)
+               goto error;
+
+       if (listen_comm(main_sock))
+               goto error;
+
+       /* Initialize the set of active sockets. */
+       client_init();
+
+       while (1) {
+               /* Block until input arrives on one or more active sockets. */
+               FD_ZERO (&active_fd_set);
+               FD_SET (main_sock, &active_fd_set);
+
+               for (i = 0; i < MAX_CLIENTS; i++)
+                       if (clients[i].used)
+                               FD_SET(clients[i].socket, &active_fd_set);
+
+
+               if (select(FD_SETSIZE, &active_fd_set, NULL, NULL, NULL) < 0)
+                       goto error;
+
+
+               for (i = 0; i < FD_SETSIZE; i++)
+                       if (FD_ISSET (i, &active_fd_set))       {
+                               if (i == main_sock)     {
+                                       /* Connection request on original socket. */
+                                       if ((data_sock = accept_comm(main_sock)) < 0)
+                                               goto error;
+
+                                       new_client = client_add();
+                                       if (new_client < 0)
+                                               free_comm(data_sock);
+                                       else
+                                               clients[new_client].socket = data_sock;
+                                               /*FD_SET(data_sock, &active_fd_set);*/
+                               } else {
+                                       /* Data arriving on an already-connected socket. */
+                                       if (receive_request(i, &op, &data_size))
+                                               /*goto error;*/
+                                               op = -1; /* probably client closes */
+
+                                       if (op == FNC_CLOSE_CONN) {
+                                               /* wait some time */
+                                               usleep(10000);
+                                               goto e_close;
+                                       }
+
+                                       if (op >= 0) {
+                                               /* search in function table */
+                                               res = 1;
+                                               for (j = 0; fnc_table[j].fnc >= 0; j++) {
+                                                       if ((fnc_table[j].fnc == op) &&
+                                                               (data_size >= fnc_table[j].min_size) &&
+                                                               (data_size <= fnc_table[j].max_size)) {
+                                                               res = (*fnc_table[j].fnc_code)(i, op, data_size);
+                                                               break;
+                                                       }
+                                               }
+                                               if (!res) {
+                                                       if (send_response(i, FNC_OK, 0, NULL, 0) < 0)
+                                                               goto e_close;
+                                               } else {
+                                                       if (send_response(i, FNC_ERR, res, NULL, 0) < 0)
+                                                               goto e_close;
+                                               }
+                                       } else {
+e_close:
+                                               if (op != FNC_CLOSE_CONN)
+                                                       printf("error protocol fnc:%d - %d\n", op, res);
+                                               client_del(client_find_by_socket(i));
+                                               /*FD_CLR (i, &active_fd_set);*/
+
+                                               /* close connection */
+                                               if (free_comm(i))
+                                                       data_sock = 0;
+                                       }
+                               }
+                       }
+       }
+end:
+       signal(SIGPIPE, old_sig_pipe);
+       for (i = 0; i < MAX_CLIENTS; i++)
+               if (clients[i].used) {
+                       client_del(i);
+                       free_comm(clients[i].socket);
+               }
+       free_comm(main_sock);
+
+       ld10k1_free_reserved_ctls(&dsp_mgr);
+       ld10k1_dsp_mgr_free(&dsp_mgr);
+
+       return retval;
+
+error:
+       retval = -1;
+       goto end;
+}
+
+int ld10k1_fnc_receive_patch_info(int data_conn, ld10k1_dsp_patch_t *new_patch, int *where)
+{
+       ld10k1_fnc_patch_add_t tmp_info;
+
+       if (receive_msg_data(data_conn, &tmp_info, sizeof(ld10k1_fnc_patch_add_t)) < 0)
+               return LD10K1_ERR_PROTOCOL;
+
+       memcpy(new_patch, &(tmp_info.patch), sizeof(ld10k1_dsp_patch_t));
+       *where = tmp_info.where;
+
+       new_patch->patch_name[MAX_NAME_LEN - 1] = '\n';
+       if (new_patch->in_count < 0 || new_patch->in_count > 32)
+               return LD10K1_ERR_PROTOCOL_IN_COUNT;
+       if (new_patch->out_count < 0 || new_patch->out_count > 32)
+               return LD10K1_ERR_PROTOCOL_OUT_COUNT;
+       if (new_patch->const_count < 0 || new_patch->const_count > 255)
+               return LD10K1_ERR_PROTOCOL_CONST_COUNT;
+       if (new_patch->static_count < 0 || new_patch->static_count > 255)
+               return LD10K1_ERR_PROTOCOL_STATIC_COUNT;
+       if (new_patch->dynamic_count < 0 || new_patch->dynamic_count > 255)
+               return LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT;
+       if (new_patch->hw_count < 0 || new_patch->hw_count > 255)
+               return LD10K1_ERR_PROTOCOL_HW_COUNT;
+       if (new_patch->tram_count < 0 || new_patch->tram_count > 255)
+               return LD10K1_ERR_PROTOCOL_TRAM_COUNT;
+       if (new_patch->tram_acc_count < 0 || new_patch->tram_acc_count > 255)
+               return LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT;
+       if (new_patch->ctl_count < 0 || new_patch->ctl_count > 255)
+               return LD10K1_ERR_PROTOCOL_CTL_COUNT;
+       if (new_patch->instr_count < 0 || new_patch->instr_count > 512)
+               return LD10K1_ERR_PROTOCOL_INSTR_COUNT;
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_in(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_p_in_out_t *new_in = NULL;
+       int i;
+       int err;
+
+       if (!new_patch->in_count)
+               return 0;
+
+       if (!(new_in = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_in_out_t) * new_patch->in_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->in_count; i++) {
+               if (!ld10k1_dsp_mgr_name_new(&(new_patch->ins[i].name), new_in[i].name)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+       }
+
+       return send_response_ok(data_conn);
+error:
+       free(new_in);
+       return err;
+}
+
+int ld10k1_fnc_receive_patch_out(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_p_in_out_t *new_out = NULL;
+       int i;
+       int err;
+
+       if (!new_patch->out_count)
+               return 0;
+
+       if (!(new_out = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_in_out_t) * new_patch->out_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->out_count; i++) {
+               if (!ld10k1_dsp_mgr_name_new(&(new_patch->outs[i].name), new_out[i].name)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+       }
+
+       return send_response_ok(data_conn);
+error:
+       free(new_out);
+       return err;
+}
+
+int ld10k1_fnc_receive_patch_const(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_p_const_static_t *new_const = NULL;
+       int i;
+
+       if (!new_patch->const_count)
+               return 0;
+
+       if (!(new_const = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_const_static_t) * new_patch->const_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->const_count; i++)
+               new_patch->consts[i].const_val = new_const[i].const_val;
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_sta(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_p_const_static_t *new_sta = NULL;
+       int i;
+
+       if (!new_patch->sta_count)
+               return 0;
+
+       if (!(new_sta = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_const_static_t) * new_patch->sta_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->sta_count; i++)
+               new_patch->stas[i].const_val = new_sta[i].const_val;
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_hw(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_p_hw_t *new_hw = NULL;
+       int i;
+
+       if (!new_patch->hw_count)
+               return 0;
+
+       if (!(new_hw = (ld10k1_dsp_p_hw_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_hw_t) * new_patch->hw_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->hw_count; i++)
+               new_patch->hws[i].reg_idx = new_hw[i].hw_val;
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_tram_grp(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_tram_grp_t *new_tram_grp = NULL;
+       int i;
+
+       if (!new_patch->tram_count)
+               return 0;
+
+       if (!(new_tram_grp = (ld10k1_dsp_tram_grp_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_tram_grp_t) * new_patch->tram_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->tram_count; i++) {
+               new_patch->tram_grp[i].grp_type = new_tram_grp[i].grp_type;
+               new_patch->tram_grp[i].grp_size = new_tram_grp[i].grp_size;
+               new_patch->tram_grp[i].grp_pos = new_tram_grp[i].grp_pos;
+       }
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_tram_acc(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_tram_acc_t *new_tram_acc = NULL;
+       int i;
+
+       if (!new_patch->tram_acc_count)
+               return 0;
+
+       if (!(new_tram_acc = (ld10k1_dsp_tram_acc_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_tram_acc_t) * new_patch->tram_acc_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->tram_acc_count; i++) {
+               new_patch->tram_acc[i].acc_type = new_tram_acc[i].acc_type;
+               new_patch->tram_acc[i].acc_offset = new_tram_acc[i].acc_offset;
+               new_patch->tram_acc[i].grp = new_tram_acc[i].grp;
+       }
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_ctl(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_ctl_t *new_ctl = NULL;
+       int i, j;
+
+       if (!new_patch->ctl_count)
+               return 0;
+
+       if (!(new_ctl = (ld10k1_dsp_ctl_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_ctl_t) * new_patch->ctl_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->ctl_count; i++) {
+               strncpy(new_patch->ctl[i].name, new_ctl[i].name, 43);
+               new_patch->ctl[i].name[43] = '\0';
+               new_patch->ctl[i].index = -1;
+               new_patch->ctl[i].want_index = new_ctl[i].index;
+               new_patch->ctl[i].count = new_ctl[i].count;
+               new_patch->ctl[i].vcount = new_ctl[i].vcount;
+               new_patch->ctl[i].min = new_ctl[i].min;
+               new_patch->ctl[i].max = new_ctl[i].max;
+               new_patch->ctl[i].translation = new_ctl[i].translation;
+
+               for (j = 0; j < new_patch->ctl[i].count; j++)
+                       new_patch->ctl[i].value[j] = new_ctl[i].value[j];
+       }
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_receive_patch_instr(int data_conn, ld10k1_patch_t *new_patch)
+{
+       ld10k1_dsp_instr_t *new_instr = NULL;
+       int i, j;
+
+       if (!new_patch->instr_count)
+               return 0;
+
+       if (!(new_instr = (ld10k1_dsp_instr_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_instr_t) * new_patch->instr_count)))
+               return LD10K1_ERR_PROTOCOL;
+
+       /* copy values */
+       for (i = 0; i < new_patch->instr_count; i++) {
+               new_patch->instr[i].op_code = new_instr[i].op_code;
+               for (j = 0; j < 4; j++)
+                       new_patch->instr[i].arg[j] = new_instr[i].arg[j];
+               new_patch->instr[i].used = 1;
+               new_patch->instr[i].modified = 1;
+       }
+
+       return send_response_ok(data_conn);
+}
+
+int ld10k1_fnc_patch_add(int data_conn, int op, int size)
+{
+       int err;
+       int loaded[2];
+       int where;
+
+       ld10k1_dsp_patch_t new_patch_info;
+
+       if ((err = ld10k1_fnc_receive_patch_info(data_conn, &new_patch_info, &where)) < 0)
+               goto error;
+
+       /* alocate new patch */
+       ld10k1_patch_t *new_patch = NULL;
+
+       if (!(new_patch = ld10k1_dsp_mgr_patch_new())) {
+               err = LD10K1_ERR_NO_MEM;
+               goto error;
+       }
+
+       /* name */
+       if (!ld10k1_dsp_mgr_name_new(&(new_patch->patch_name), new_patch_info.patch_name)) {
+               err = LD10K1_ERR_NO_MEM;
+               goto error;
+       }
+
+
+       /* set sizes */
+       if (new_patch_info.in_count)
+               if (!ld10k1_dsp_mgr_patch_in_new(new_patch, new_patch_info.in_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.out_count)
+               if (!ld10k1_dsp_mgr_patch_out_new(new_patch, new_patch_info.out_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.const_count)
+               if (!ld10k1_dsp_mgr_patch_const_new(new_patch, new_patch_info.const_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.static_count)
+               if (!ld10k1_dsp_mgr_patch_sta_new(new_patch, new_patch_info.static_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.dynamic_count)
+               if (!ld10k1_dsp_mgr_patch_dyn_new(new_patch, new_patch_info.dynamic_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.hw_count)
+               if (!ld10k1_dsp_mgr_patch_hw_new(new_patch, new_patch_info.hw_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.tram_count)
+               if (!ld10k1_dsp_mgr_patch_tram_new(new_patch, new_patch_info.tram_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.tram_acc_count)
+               if (!ld10k1_dsp_mgr_patch_tram_acc_new(new_patch, new_patch_info.tram_acc_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (new_patch_info.ctl_count)
+               if (!ld10k1_dsp_mgr_patch_ctl_new(new_patch,new_patch_info.ctl_count)) {
+                       err = LD10K1_ERR_NO_MEM;
+                       goto error;
+               }
+
+       if (!ld10k1_dsp_mgr_patch_instr_new(new_patch, new_patch_info.instr_count)) {
+               err = LD10K1_ERR_NO_MEM;
+               goto error;
+       }
+
+       /* receive next parts */
+       if (new_patch_info.in_count)
+               if ((err = ld10k1_fnc_receive_patch_in(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.out_count)
+               if ((err = ld10k1_fnc_receive_patch_out(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.const_count)
+               if ((err = ld10k1_fnc_receive_patch_const(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.static_count)
+               if ((err = ld10k1_fnc_receive_patch_sta(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.hw_count)
+               if ((err = ld10k1_fnc_receive_patch_hw(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.tram_count)
+               if ((err = ld10k1_fnc_receive_patch_tram_grp(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.tram_acc_count)
+               if ((err = ld10k1_fnc_receive_patch_tram_acc(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if (new_patch_info.ctl_count)
+               if ((err = ld10k1_fnc_receive_patch_ctl(data_conn, new_patch)) < 0)
+                       goto error;
+
+       if ((err = ld10k1_fnc_receive_patch_instr(data_conn, new_patch)) < 0)
+               goto error;
+
+       /* check patch */
+       if ((err = ld10k1_patch_fnc_check_patch(&dsp_mgr, new_patch)) < 0)
+               goto error;
+
+       /* load patch */
+       if ((err = ld10k1_dsp_mgr_patch_load(&dsp_mgr, new_patch, where, loaded)) < 0)
+               goto error;
+
+       if ((err = send_response_wd(data_conn, loaded, sizeof(loaded))) < 0)
+               return err;
+
+       return 0;
+error:
+       if (new_patch)
+               ld10k1_dsp_mgr_patch_free(new_patch);
+       return err;
+}
+
+int ld10k1_fnc_patch_del(int data_conn, int op, int size)
+{
+       ld10k1_fnc_patch_del_t patch_info;
+       int err;
+
+       if ((err = receive_msg_data(data_conn, &patch_info, sizeof(ld10k1_fnc_patch_del_t))) < 0)
+               return err;
+
+       return ld10k1_patch_fnc_del(&dsp_mgr, &patch_info);
+}
+
+int ld10k1_fnc_patch_conn(int data_conn, int op, int size)
+{
+       ld10k1_fnc_connection_t connection_info;
+       int err;
+       int conn_id;
+
+       if ((err = receive_msg_data(data_conn, &connection_info, sizeof(ld10k1_fnc_connection_t))) < 0)
+               return err;
+
+       if ((err = ld10k1_connection_fnc(&dsp_mgr, &connection_info, &conn_id)) < 0)
+               return err;
+               
+       return send_response_wd(data_conn, &conn_id, sizeof(conn_id));
+}
+
+int ld10k1_fnc_name_find(int data_conn, int op, int size)
+{
+       ld10k1_fnc_name_t name_info;
+       int i;
+       static int ret;
+       int err;
+       ld10k1_patch_t *patch;
+
+       ret = -1;
+
+       if ((err = receive_msg_data(data_conn, &name_info, sizeof(ld10k1_fnc_name_t))) < 0)
+               return err;
+
+       name_info.name[MAX_NAME_LEN - 1] = '\0';
+
+       switch (op)     {
+               case FNC_PATCH_FIND:
+                       for (i = 0; i < EMU10K1_PATCH_MAX ; i++)
+                               if (dsp_mgr.patch_ptr[i])
+                                       if (strcmp(dsp_mgr.patch_ptr[i]->patch_name, name_info.name) == 0) {
+                                               ret = i;
+                                               break;
+                                       }
+                       break;
+               case FNC_FX_FIND:
+                       for (i = 0; i < dsp_mgr.fx_count ; i++)
+                               if (dsp_mgr.fxs[i].name)
+                                       if (strcmp(dsp_mgr.fxs[i].name, name_info.name) == 0) {
+                                               ret = i;
+                                               break;
+                                       }
+                       break;
+               case FNC_IN_FIND:
+                       for (i = 0; i < dsp_mgr.in_count ; i++)
+                               if (dsp_mgr.ins[i].name)
+                                       if (strcmp(dsp_mgr.ins[i].name, name_info.name) == 0) {
+                                               ret = i;
+                                               break;
+                                       }
+                       break;
+               case FNC_OUT_FIND:
+                       for (i = 0; i < dsp_mgr.out_count ; i++)
+                               if (dsp_mgr.outs[i].name)
+                                       if (strcmp(dsp_mgr.outs[i].name, name_info.name) == 0) {
+                                               ret = i;
+                                               break;
+                                       }
+                       break;
+               case FNC_PATCH_IN_FIND :
+                       if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
+                               patch = dsp_mgr.patch_ptr[name_info.patch_num];
+                               if (patch)
+                                       for (i = 0; i < patch->in_count ; i++)
+                                               if (patch->ins[i].name)
+                                                       if (strcmp(patch->ins[i].name, name_info.name) == 0) {
+                                                               ret = i;
+                                                               break;
+                                                       }
+                       }
+                       break;
+               case FNC_PATCH_OUT_FIND :
+                       if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
+                               patch = dsp_mgr.patch_ptr[name_info.patch_num];
+                               if (patch)
+                                       for (i = 0; i < patch->out_count ; i++)
+                                               if (patch->outs[i].name)
+                                                       if (strcmp(patch->outs[i].name, name_info.name) == 0) {
+                                                               ret = i;
+                                                               break;
+                                                       }
+                       }
+                       break;
+       }
+
+       return send_response_wd(data_conn, &ret, sizeof(ret));
+}
+
+int ld10k1_fnc_name_rename(int data_conn, int op, int size)
+{
+       ld10k1_fnc_name_t name_info;
+       int ret;
+       int err;
+       ld10k1_patch_t *patch;
+
+       ret = -1;
+
+       if ((err = receive_msg_data(data_conn, &name_info, sizeof(ld10k1_fnc_name_t))) < 0)
+               return err;
+
+       name_info.name[MAX_NAME_LEN - 1] = '\0';
+
+       switch (op)     {
+               case FNC_PATCH_RENAME:
+                       if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
+                               patch = dsp_mgr.patch_ptr[name_info.patch_num];
+                               if (patch) {
+                                       if (!ld10k1_dsp_mgr_name_new(&(patch->patch_name), name_info.name))
+                                               return LD10K1_ERR_PATCH_RENAME;
+                               } else
+                                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       } else
+                               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       break;
+               case FNC_FX_RENAME:
+                       if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.fx_count)
+                               return LD10K1_ERR_UNKNOWN_REG_NUM;
+                       if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.fxs[name_info.gpr].name), name_info.name))
+                               return LD10K1_ERR_REG_RENAME;
+                       break;
+               case FNC_IN_RENAME:
+                       if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.in_count)
+                               return LD10K1_ERR_UNKNOWN_REG_NUM;
+                       if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.ins[name_info.gpr].name), name_info.name))
+                               return LD10K1_ERR_REG_RENAME;
+                       break;
+               case FNC_OUT_RENAME:
+                       if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.out_count)
+                               return LD10K1_ERR_UNKNOWN_REG_NUM;
+                       if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.outs[name_info.gpr].name), name_info.name))
+                               return LD10K1_ERR_REG_RENAME;
+                       break;
+               case FNC_PATCH_IN_RENAME:
+                       if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
+                               patch = dsp_mgr.patch_ptr[name_info.patch_num];
+                               if (patch) {
+                                       if (name_info.gpr < 0 || name_info.gpr >= patch->in_count)
+                                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                                       if (!ld10k1_dsp_mgr_name_new(&(patch->ins[name_info.gpr].name), name_info.name))
+                                               return LD10K1_ERR_PATCH_REG_RENAME;
+                               } else
+                                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       } else
+                               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       break;
+               case FNC_PATCH_OUT_RENAME:
+                       if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
+                               patch = dsp_mgr.patch_ptr[name_info.patch_num];
+                               if (patch) {
+                                       if (name_info.gpr < 0 || name_info.gpr >= patch->out_count)
+                                               return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+                                       if (!ld10k1_dsp_mgr_name_new(&(patch->outs[name_info.gpr].name), name_info.name))
+                                               return LD10K1_ERR_PATCH_REG_RENAME;
+                               } else
+                                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       } else
+                               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                       break;
+       }
+       return 0;
+}
+
+int ld10k1_fnc_dsp_init(int data_conn, int op, int size)
+{
+       int audigy;
+       int err, i;
+       
+       ld10k1_reserved_ctl_list_item_t *rlist;
+       int save_ids[EMU10K1_PATCH_MAX];
+
+       audigy = dsp_mgr.audigy;
+
+       rlist = dsp_mgr.reserved_ctl_list; /* FIXME - hack to save reserved ctls and ids */
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++)
+               save_ids[i] = dsp_mgr.patch_id_gens[i];
+               
+       ld10k1_dsp_mgr_free(&dsp_mgr);
+       memset(&dsp_mgr, 0, sizeof(dsp_mgr));
+
+       dsp_mgr.audigy = audigy;
+
+       if ((err = ld10k1_dsp_mgr_init(&dsp_mgr)) < 0)
+               return err;
+               
+       dsp_mgr.reserved_ctl_list = rlist; /* hack to seve reserved ctls */
+       
+       for (i = 0; i < EMU10K1_PATCH_MAX; i++)
+               dsp_mgr.patch_id_gens[i] = save_ids[i];
+
+       return ld10k1_init_driver(&dsp_mgr, -1);
+}
+
+int ld10k1_fnc_get_io_count(int data_conn, int op, int size)
+{
+       int reg_count;
+       
+       reg_count = 0;
+               
+       if (op == FNC_GET_FX_COUNT)
+               /* fxs */
+               reg_count = dsp_mgr.fx_count;
+       else if (op == FNC_GET_IN_COUNT)
+               /* ins */
+               reg_count = dsp_mgr.in_count;
+       else
+               /* outs */
+               reg_count = dsp_mgr.out_count;
+
+       return send_response_wd(data_conn, &reg_count, sizeof(int));
+}
+
+int ld10k1_fnc_get_io(int data_conn, int op, int size)
+{
+       int err;
+
+       int reg_count;
+       int reg_num;
+       ld10k1_fnc_get_io_t io;
+
+       if ((err = receive_msg_data(data_conn, &reg_num, sizeof(int))) < 0)
+               return err;
+
+       if (op == FNC_GET_FX)
+               /* fx */
+               reg_count = dsp_mgr.fx_count;
+       else if (op == FNC_GET_IN)
+               /* in */
+               reg_count = dsp_mgr.in_count;
+       else
+               /* out */
+               reg_count = dsp_mgr.out_count;
+               
+       if (reg_num < 0 || reg_num >= reg_count)
+               return LD10K1_ERR_UNKNOWN_REG_NUM;
+
+       if (op == FNC_GET_FX) {
+               /* fx */
+               memset(io.name, 0, sizeof(io.name));
+               if (dsp_mgr.fxs[reg_num].name)
+                       strcpy(io.name, dsp_mgr.fxs[reg_num].name);
+       } else if (op == FNC_GET_IN) {
+               /* in */
+               memset(io.name, 0, sizeof(io.name));
+               if (dsp_mgr.ins[reg_num].name)
+                       strcpy(io.name, dsp_mgr.ins[reg_num].name);
+       } else {
+               /* out */
+               memset(io.name, 0, sizeof(io.name));
+               if (dsp_mgr.outs[reg_num].name)
+                       strcpy(io.name, dsp_mgr.outs[reg_num].name);
+       }
+
+       return send_response_wd(data_conn, &io, sizeof(ld10k1_fnc_get_io_t));
+}
+
+int ld10k1_fnc_get_pio_count(int data_conn, int op, int size)
+{
+       int patch_num;
+       int err;
+
+       int reg_count;
+       ld10k1_patch_t *patch;
+
+       if ((err = receive_msg_data(data_conn, &patch_num, sizeof(int))) < 0)
+               return err;
+
+       reg_count = 0;
+       /* patch */
+       if (patch_num >= 0 && patch_num < EMU10K1_PATCH_MAX) {
+               /* patch register */
+               patch = dsp_mgr.patch_ptr[patch_num];
+               if (!patch)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+               if (op == FNC_GET_PIN_COUNT)
+                       /* pin */
+                       reg_count = patch->in_count;
+               else
+                       /* pout */
+                       reg_count = patch->out_count;
+       } else
+               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+       
+       return send_response_wd(data_conn, &reg_count, sizeof(int));
+}
+
+int ld10k1_fnc_get_pio(int data_conn, int op, int size)
+{
+       int patch_num;
+       int reg_num;
+       int err;
+
+       int tmp_num[2];
+       int reg_count;
+       ld10k1_fnc_get_io_t io;
+       ld10k1_patch_t *patch;
+
+       if ((err = receive_msg_data(data_conn, tmp_num, sizeof(int) * 2)) < 0)
+               return err;
+       
+       patch_num = tmp_num[0];
+       reg_num = tmp_num[1];
+               
+       reg_count = 0;
+       
+       /* patch */
+       if (patch_num >= 0 && patch_num < EMU10K1_PATCH_MAX) {
+               /* patch register */
+               patch = dsp_mgr.patch_ptr[patch_num];
+               if (!patch)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+               if (op == FNC_GET_PIN)
+                       /* pin */
+                       reg_count = patch->in_count;
+               else
+                       /* pout */
+                       reg_count = patch->out_count;
+                       
+               if (reg_num < 0 || reg_num >= reg_count)
+                       return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
+
+               if (op == FNC_GET_PIN) {
+                       /* pin */
+                       memset(io.name, 0, sizeof(io.name));
+                       if (patch->ins[reg_num].name)
+                               strcpy(io.name, patch->ins[reg_num].name);
+               } else {
+                       /* pout */
+                       memset(io.name, 0, sizeof(io.name));
+                       if (patch->outs[reg_num].name)
+                               strcpy(io.name, patch->outs[reg_num].name);
+               }
+       } else
+               return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+       return send_response_wd(data_conn, &io, sizeof(ld10k1_fnc_get_io_t));
+}
+
+
+int ld10k1_fnc_get_patches_info(int data_conn, int op, int size)
+{
+       int i, idx, j;
+       ld10k1_fnc_patches_info_t *info;
+       ld10k1_patch_t *patch;
+
+       info = NULL;
+
+       if (dsp_mgr.patch_count >= 0) {
+               /* alloc space */
+               info = (ld10k1_fnc_patches_info_t *)malloc(sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
+               if (!info)
+                       return LD10K1_ERR_NO_MEM;
+               memset(info, 0, sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
+
+               /* copy values */
+               for (i = 0, j = 0; i < dsp_mgr.patch_count; i++) {
+                       idx = dsp_mgr.patch_order[i];
+                       patch = dsp_mgr.patch_ptr[idx];
+                       if (patch) {
+                               info[j].patch_num = idx;
+                               info[j].id = patch->id;
+                               strcpy(info[j].patch_name, patch->patch_name);
+                               j++;
+                       }
+               }
+       }
+
+       return send_response_wd(data_conn, info, sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
+}
+
+int ld10k1_fnc_version(int data_conn, int op, int size)
+{
+
+       ld10k1_fnc_version_t version;
+
+       strcpy(version.ld10k1_version, VERSION);
+       return send_response_wd(data_conn, &version, sizeof(ld10k1_fnc_version_t));
+}
+
+
+int ld10k1_fnc_send_patch_in(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_p_in_out_t *ins = NULL;
+
+       if (patch->in_count) {
+               ins = (ld10k1_dsp_p_in_out_t *)malloc(sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count);
+               if (!ins)
+                       return LD10K1_ERR_NO_MEM;
+               memset(ins, 0, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count);
+
+               for (i = 0; i < patch->in_count; i++) {
+                       if (patch->ins[i].name)
+                               strcpy(ins[i].name, patch->ins[i].name);
+                       else
+                               ins[i].name[0] = '\0';
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, ins, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count)) < 0) {
+                       free(ins);
+                       return err;
+               }
+
+               free(ins);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_out(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_p_in_out_t *outs = NULL;
+
+       if (patch->out_count) {
+               outs = (ld10k1_dsp_p_in_out_t *)malloc(sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count);
+               if (!outs)
+                       return LD10K1_ERR_NO_MEM;
+               memset(outs, 0, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count);
+
+               for (i = 0; i < patch->out_count; i++) {
+                       if (patch->outs[i].name)
+                               strcpy(outs[i].name, patch->outs[i].name);
+                       else
+                               outs[i].name[0] = '\0';
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, outs, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count)) < 0) {
+                       free(outs);
+                       return err;
+               }
+
+               free(outs);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_const(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_p_const_static_t *consts = NULL;
+
+       if (patch->const_count) {
+               consts = (ld10k1_dsp_p_const_static_t *)malloc(sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count);
+               if (!consts)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->const_count; i++)
+                       consts[i].const_val = patch->consts[i].const_val;
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, consts, sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count)) < 0) {
+                       free(consts);
+                       return err;
+               }
+
+               free(consts);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_sta(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_p_const_static_t *stas = NULL;
+
+       if (patch->sta_count) {
+               stas = (ld10k1_dsp_p_const_static_t *)malloc(sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count);
+               if (!stas)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->sta_count; i++)
+                       stas[i].const_val = patch->stas[i].const_val;
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, stas, sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count)) < 0) {
+                       free(stas);
+                       return err;
+               }
+
+               free(stas);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_hw(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_p_hw_t *hws = NULL;
+
+       if (patch->hw_count) {
+               hws = (ld10k1_dsp_p_hw_t *)malloc(sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count);
+               if (!hws)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->hw_count; i++)
+                       hws[i].hw_val = patch->hws[i].reg_idx;
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, hws, sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count)) < 0) {
+                       free(hws);
+                       return err;
+               }
+
+               free(hws);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_tram_grp(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_tram_grp_t *grps = NULL;
+
+       if (patch->tram_count) {
+               grps = (ld10k1_dsp_tram_grp_t *)malloc(sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count);
+               if (!grps)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->tram_count; i++) {
+                       grps[i].grp_type = patch->tram_grp[i].grp_type;
+                       grps[i].grp_size = patch->tram_grp[i].grp_size;
+                       grps[i].grp_pos = patch->tram_grp[i].grp_pos;
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, grps, sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count)) < 0) {
+                       free(grps);
+                       return err;
+               }
+
+               free(grps);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_tram_acc(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, err;
+       ld10k1_dsp_tram_acc_t *accs = NULL;
+
+       if (patch->tram_acc_count) {
+               accs = (ld10k1_dsp_tram_acc_t *)malloc(sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count);
+               if (!accs)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->tram_acc_count; i++) {
+                       accs[i].acc_type = patch->tram_acc[i].acc_type;
+                       accs[i].acc_offset = patch->tram_acc[i].acc_offset;
+                       accs[i].grp = patch->tram_acc[i].grp;
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, accs, sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count)) < 0) {
+                       free(accs);
+                       return err;
+               }
+
+               free(accs);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_ctl(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, j, err;
+       ld10k1_dsp_ctl_t *ctls = NULL;
+
+       if (patch->ctl_count) {
+               ctls = (ld10k1_dsp_ctl_t *)malloc(sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count);
+               if (!ctls)
+                       return LD10K1_ERR_NO_MEM;
+               memset(ctls, 0, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count);
+
+               for (i = 0; i < patch->ctl_count; i++) {
+                       strncpy(ctls[i].name, patch->ctl[i].name, 43);
+                       ctls[i].name[43] = '\0';
+                       ctls[i].index = patch->ctl[i].want_index;
+                       ctls[i].count = patch->ctl[i].count;
+                       ctls[i].vcount = patch->ctl[i].vcount;
+                       ctls[i].min = patch->ctl[i].min;
+                       ctls[i].max = patch->ctl[i].max;
+                       ctls[i].translation = patch->ctl[i].translation;
+
+                       for (j = 0; j < ctls[i].count; j++)
+                               ctls[i].value[j] = patch->ctl[i].value[j];
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, ctls, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count)) < 0) {
+                       free(ctls);
+                       return err;
+               }
+
+               free(ctls);
+       }
+       return 0;
+}
+
+int ld10k1_fnc_send_patch_instr(int data_conn, ld10k1_patch_t *patch)
+{
+       int i, j, err;
+       ld10k1_dsp_instr_t *instrs = NULL;
+
+       if (patch->instr_count) {
+               instrs = (ld10k1_dsp_instr_t *)malloc(sizeof(ld10k1_dsp_instr_t) * patch->instr_count);
+               if (!instrs)
+                       return LD10K1_ERR_NO_MEM;
+
+               for (i = 0; i < patch->instr_count; i++) {
+                       instrs[i].op_code = patch->instr[i].op_code;
+                       for (j = 0; j < 4; j++)
+                               instrs[i].arg[j] = patch->instr[i].arg[j];
+               }
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, instrs, sizeof(ld10k1_dsp_instr_t) * patch->instr_count)) < 0) {
+                       free(instrs);
+                       return err;
+               }
+
+               free(instrs);
+       }
+       return 0;
+}
+
+
+int ld10k1_fnc_get_patch(int data_conn, int op, int size)
+{
+       int err;
+
+       ld10k1_dsp_patch_t patch_info;
+       int patch_num = -1;
+       ld10k1_patch_t *patch;
+
+       if ((err = receive_msg_data(data_conn, &patch_num, sizeof(patch_num))) < 0)
+               return err;
+
+       if (dsp_mgr.patch_count >= 0) {
+
+               if (patch_num > EMU10K1_PATCH_MAX)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+               patch = dsp_mgr.patch_ptr[patch_num];
+               if (!patch)
+                       return LD10K1_ERR_UNKNOWN_PATCH_NUM;
+
+               strcpy(patch_info.patch_name, patch->patch_name);
+               patch_info.id = patch->id;
+               patch_info.in_count = patch->in_count;
+               patch_info.out_count = patch->out_count;
+               patch_info.const_count = patch->const_count;
+               patch_info.static_count = patch->sta_count;
+               patch_info.dynamic_count = patch->dyn_count;
+               patch_info.hw_count = patch->hw_count;
+               patch_info.tram_count = patch->tram_count;
+               patch_info.tram_acc_count = patch->tram_acc_count;
+               patch_info.ctl_count = patch->ctl_count;
+               patch_info.instr_count = patch->instr_count;
+
+               if ((err = send_response(data_conn, FNC_CONTINUE, 0, &patch_info, sizeof(ld10k1_dsp_patch_t))) < 0)
+                       return err;
+
+               /* send next parts */
+               if ((err = ld10k1_fnc_send_patch_in(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_out(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_const(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_sta(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_hw(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_tram_grp(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_tram_acc(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_ctl(data_conn, patch)) < 0)
+                       return err;
+
+               if ((err = ld10k1_fnc_send_patch_instr(data_conn, patch)) < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+int ld10k1_fnc_dump(int data_conn, int op, int size)
+{
+       int err;
+       void *dump = NULL;
+       int dump_size = 0;
+
+
+       if ((err = ld10k1_make_dump(&dsp_mgr, &dump, &dump_size)) < 0)
+               return err;
+
+       if ((err = send_response(data_conn, FNC_CONTINUE, 0, dump, dump_size)) < 0)
+               return err;
+
+       free(dump);
+       return 0;
+}
+
+int ld10k1_fnc_get_points_info(int data_conn, int op, int size)
+{
+       int point_count;
+       int i, j = 0;
+       int *info = NULL;
+       ld10k1_conn_point_t *point;
+       
+       point_count = 0;
+       for (i = 0; i < 2; i++) {
+               if (i) {
+                       if (!point_count)
+                               break;
+                       info = (int *)malloc(sizeof(int) * point_count);
+                       if (!info)
+                               return LD10K1_ERR_NO_MEM;
+                       j = 0;
+               }
+               point = dsp_mgr.point_list;
+               while (point) {
+                       if (!i)
+                               point_count++;
+                       else
+                               info[j++] = point->id;
+
+                       point = point->next;
+               }
+       }
+
+       return send_response_wd(data_conn, info, sizeof(int) * point_count);
+}
+
+int ld10k1_fnc_get_point_info(int data_conn, int op, int size)
+{
+       int err;
+
+       int k, l;
+       ld10k1_dsp_point_t info;
+       ld10k1_conn_point_t *point;
+       ld10k1_conn_point_t *found_point;
+       int what_point_id;
+
+       /*info = NULL;*/
+
+       if ((err = receive_msg_data(data_conn, &what_point_id, sizeof(int))) < 0)
+               return err;
+
+       found_point = NULL;
+       
+       point = dsp_mgr.point_list;
+       while (point) {
+               if (point->id == what_point_id) {
+                       found_point = point;
+                       break;
+               }
+               point = point->next;
+       }
+       
+       if (!found_point)
+               return LD10K1_ERR_UNKNOWN_POINT;
+       
+       info.id = point->id;
+                       
+       if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL)
+               info.type = CON_IO_NORMAL;
+       else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_INPUT)
+               info.type = CON_IO_IN;
+       else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_OUTPUT)
+               info.type = CON_IO_OUT;
+       else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_FX)
+               info.type = CON_IO_FX;
+       info.io_idx = point->con_gpr_idx & ~EMU10K1_REG_TYPE_MASK;
+       info.simple = point->simple;
+       info.conn_count = point->con_count;
+       if (info.conn_count > 2 && info.type == CON_IO_NORMAL)
+               info.multi = 1;
+       else if (info.conn_count > 1 && info.type != CON_IO_NORMAL)
+               info.multi = 1;
+       else
+               info.multi = 0;
+       for (k = 0, l = 0; k < POINT_MAX_CONN_PER_POINT; k++) {
+               if (point->type[k]) {
+                       info.io_type[l] = point->type[k] == CON_IO_PIN ? 0 : 1;
+                       info.patch[l] = point->patch[k] ? point->patch[k]->id : -1;
+                       info.io[l] = point->io[k];
+                       l++;
+               }
+       }
+
+       return send_response_wd(data_conn, &info, sizeof(ld10k1_dsp_point_t));
+}
+
+int ld10k1_fnc_get_dsp_info(int data_conn, int op, int size)
+{
+       ld10k1_fnc_dsp_info_t info;
+       
+       info.chip_type = dsp_mgr.audigy;
+       
+       return send_response_wd(data_conn, &info, sizeof(ld10k1_fnc_dsp_info_t));
+}
diff --git a/ld10k1/src/ld10k1_fnc1.h b/ld10k1/src/ld10k1_fnc1.h
new file mode 100644 (file)
index 0000000..696abc8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_FNC1_H
+#define __LD10K1_FNC1_H
+
+#include "comm.h"
+
+extern ld10k1_dsp_mgr_t dsp_mgr;
+
+int main_loop(comm_param *param, int audigy, const char *card_id, int tram_size, snd_ctl_t *ctlp);
+
+int send_response_ok(int conn_num);
+int send_response_err(int conn_num, int err);
+int send_response_wd(int conn_num, void *data, int data_size);
+
+#endif /* __LD10K1_FNC1_H */
diff --git a/ld10k1/src/ld10k1_fnc_int.h b/ld10k1/src/ld10k1_fnc_int.h
new file mode 100644 (file)
index 0000000..b7e4af7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_FNC_INT_H
+#define __LD10K1_FNC_INT_H
+
+int ld10k1_dsp_mgr_init(ld10k1_dsp_mgr_t *dsp_mgr);
+void ld10k1_dsp_mgr_init_id_gen(ld10k1_dsp_mgr_t *dsp_mgr);
+void ld10k1_dsp_mgr_free(ld10k1_dsp_mgr_t *dsp_mgr);
+
+ld10k1_patch_t *ld10k1_dsp_mgr_patch_new(void);
+void ld10k1_dsp_mgr_patch_free(ld10k1_patch_t *patch);
+ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_in_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_out_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_const_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_sta_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_dyn_t *ld10k1_dsp_mgr_patch_dyn_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_hw_t *ld10k1_dsp_mgr_patch_hw_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_tram_grp_t *ld10k1_dsp_mgr_patch_tram_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_p_tram_acc_t *ld10k1_dsp_mgr_patch_tram_acc_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_instr_t *ld10k1_dsp_mgr_patch_instr_new(ld10k1_patch_t *patch, unsigned int count);
+ld10k1_ctl_t *ld10k1_dsp_mgr_patch_ctl_new(ld10k1_patch_t *patch, unsigned int count);
+char *ld10k1_dsp_mgr_name_new(char **where, const char *from);
+
+int ld10k1_dsp_mgr_patch_load(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, int before, int *loaded);
+int ld10k1_patch_fnc_check_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *new_patch);
+int ld10k1_patch_fnc_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_patch_del_t *patch_fnc);
+int ld10k1_connection_fnc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_connection_t *connection_fnc, int *conn_id);
+
+void ld10k1_del_control_from_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl);
+void ld10k1_del_all_controls_from_list(ld10k1_ctl_list_item_t **list, int *count);
+int ld10k1_add_control_to_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl);
+
+#endif /* __LD10K1_FNC_INT_H */
diff --git a/ld10k1/src/ld10k1_mixer.c b/ld10k1/src/ld10k1_mixer.c
new file mode 100644 (file)
index 0000000..772b98c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 <alsa/asoundlib.h>
+
+#include "ld10k1.h"
+#include "ld10k1_mixer.h"
+#include "ld10k1_error.h"
+
+int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp)
+{
+       snd_ctl_elem_list_t *clist;
+       int count;
+       int i;
+       const char *ctl_name;
+       unsigned int ctl_index;
+       
+       ld10k1_reserved_ctl_list_item_t *res_ctl;
+       
+       dsp_mgr->reserved_ctl_list = NULL;
+       
+       snd_ctl_elem_list_alloca(&clist);
+       
+       if (snd_ctl_elem_list(ctlp, clist) < 0)
+               return LD10K1_ERR_NO_MEM;
+               
+       if ((count = snd_ctl_elem_list_get_count(clist)) < 0)
+               return LD10K1_ERR_NO_MEM;
+               
+       snd_ctl_elem_list_set_offset(clist, 0);
+       
+       if (snd_ctl_elem_list_alloc_space(clist, count) < 0)
+               return LD10K1_ERR_NO_MEM;
+               
+       if (snd_ctl_elem_list(ctlp, clist) < 0) {
+               snd_ctl_elem_list_free_space(clist);
+               return LD10K1_ERR_NO_MEM;
+       }
+               
+       for (i = 0; i < count; i++) {
+               snd_ctl_elem_id_t *id;
+               snd_ctl_elem_id_alloca(&id);
+               snd_ctl_elem_list_get_id(clist, i, id);
+               
+               ctl_name = snd_ctl_elem_id_get_name(id);
+               ctl_index = snd_ctl_elem_id_get_index(id);
+               
+               res_ctl = (ld10k1_reserved_ctl_list_item_t *)malloc(sizeof(ld10k1_reserved_ctl_list_item_t));
+               if (!res_ctl) {
+                       snd_ctl_elem_list_free_space(clist);
+                       return LD10K1_ERR_NO_MEM;
+               }
+                       
+               res_ctl->next = dsp_mgr->reserved_ctl_list;
+               dsp_mgr->reserved_ctl_list = res_ctl;
+               strncpy(res_ctl->res_ctl.name, ctl_name, 43);
+               res_ctl->res_ctl.name[43] = '\0';
+               res_ctl->res_ctl.index = ctl_index;
+       }
+       
+       snd_ctl_elem_list_free_space(clist);
+       return 0;
+}
+
+int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       ld10k1_reserved_ctl_list_item_t *item;
+       ld10k1_reserved_ctl_list_item_t *item1;
+       
+       for (item = dsp_mgr->reserved_ctl_list; item != NULL;) {
+               item1 = item->next;
+               free(item);
+               item = item1;
+       }
+       
+       dsp_mgr->reserved_ctl_list = NULL;
+       return 0;
+}
+
diff --git a/ld10k1/src/ld10k1_mixer.h b/ld10k1/src/ld10k1_mixer.h
new file mode 100644 (file)
index 0000000..e1251bc
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_MIXER_H
+#define __LD10K1_MIXER_H
+
+int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp);
+int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr);
+
+#endif /* __LD10K1_MIXER_H */
diff --git a/ld10k1/src/ld10k1_tram.c b/ld10k1/src/ld10k1_tram.c
new file mode 100644 (file)
index 0000000..840f552
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_tram.h"
+#include "ld10k1_error.h"
+#include <stdlib.h>
+
+int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res);
+int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res);
+
+void ld10k1_tram_init_res(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
+{
+       res->isize = dsp_mgr->i_tram.size;
+       res->ifree = dsp_mgr->i_tram.size;
+       res->iacc_count = dsp_mgr->i_tram.max_hwacc;
+       res->iacc_free_count = dsp_mgr->i_tram.max_hwacc;
+
+       res->esize = dsp_mgr->e_tram.size;
+       res->efree = dsp_mgr->e_tram.size;
+       res->eacc_count = dsp_mgr->e_tram.max_hwacc;
+       res->eacc_free_count = dsp_mgr->e_tram.max_hwacc;
+
+       res->grp_free = res->iacc_free_count + res->eacc_free_count;
+
+       res->item_count = 0;
+}
+
+void ld10k1_tram_init_res_from_dsp_mgr(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
+{
+       /* throught all groups */
+       int i;
+       for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
+               if (dsp_mgr->tram_grp[i].used) {
+                       /* get position */
+                       res->grp_free--;
+                       switch (dsp_mgr->tram_grp[i].req_pos) {
+                               case TRAM_POS_NONE:
+                               case TRAM_POS_AUTO:
+                                       /* add to res */
+                                       res->items[res->item_count].grp_idx = i;
+                                       res->items[res->item_count].grp_size = dsp_mgr->tram_grp[i].size;
+                                       res->items[res->item_count].grp_acc_count = dsp_mgr->tram_grp[i].acc_count;
+                                       res->items[res->item_count].res_value = 0;
+                                       res->items[res->item_count].pos = TRAM_POS_NONE;
+                                       res->item_count++;
+                                       break;
+                               case TRAM_POS_INTERNAL:
+                                       /* decrease resources */
+                                       res->ifree -= dsp_mgr->tram_grp[i].size;
+                                       res->iacc_free_count -= dsp_mgr->tram_grp[i].acc_count;
+                                       break;
+                               case TRAM_POS_EXTERNAL:
+                                       res->efree -= dsp_mgr->tram_grp[i].size;
+                                       res->eacc_free_count -= dsp_mgr->tram_grp[i].acc_count;
+                                       break;
+                       }
+               }
+       }
+}
+
+int ld10k1_tram_acc_count_from_patch(ld10k1_patch_t *patch, int grp)
+{
+       int i, count;
+
+       for (count = 0, i = 0; i < patch->tram_acc_count; i++)
+               if (patch->tram_acc[i].grp == grp)
+                       count++;
+
+       return count;
+}
+
+int ld10k1_tram_init_res_from_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch)
+{
+       int i;
+       int acc_count;
+
+       /* through all groups */
+       for (i = 0; i < patch->tram_count; i++) {
+               if (res->grp_free <= 0)
+                       return LD10K1_ERR_TRAM_FULL_GRP;
+               /* get acc count */
+               acc_count = ld10k1_tram_acc_count_from_patch(patch, i);
+               if (acc_count <= 0)
+                       continue;
+                       /* get position */
+               switch (patch->tram_grp[i].grp_pos) {
+                       case TRAM_POS_NONE:
+                       case TRAM_POS_AUTO:
+                               /* add to res */
+                               res->items[res->item_count].grp_idx = -i - 1;
+                               res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size;
+                               res->items[res->item_count].grp_acc_count = acc_count;
+                               res->items[res->item_count].res_value = 0;
+                               res->items[res->item_count].pos = TRAM_POS_NONE;
+                               res->item_count++;
+                               break;
+                       case TRAM_POS_INTERNAL:
+                               /* decrease resources */
+                               if (res->ifree < patch->tram_grp[i].grp_size)
+                                       return LD10K1_ERR_ITRAM_FULL;
+                               if (res->iacc_free_count < acc_count)
+                                       return LD10K1_ERR_ITRAM_FULL_ACC;
+                               res->ifree -= patch->tram_grp[i].grp_size;
+                               res->iacc_free_count -= acc_count;
+                               break;
+                       case TRAM_POS_EXTERNAL:
+                               /* decrease resources */
+                               if (res->efree < patch->tram_grp[i].grp_size)
+                                       return LD10K1_ERR_ETRAM_FULL;
+                               if (res->eacc_free_count < acc_count)
+                                       return LD10K1_ERR_ETRAM_FULL_ACC;
+                               res->efree -= patch->tram_grp[i].grp_size;
+                               res->eacc_free_count -= acc_count;
+                               break;
+               }
+       }
+       return 0;
+}
+
+int ld10k1_tram_init_res_from_patch_copy(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch)
+{
+       /* throught all groups */
+       int i;
+       int acc_count;
+
+       for (i = 0; i < patch->tram_count; i++) {
+               /* get acc count */
+               acc_count = ld10k1_tram_acc_count_from_patch(patch, i);
+                       /* get position */
+               if (patch->tram_grp[i].grp_pos == TRAM_POS_INTERNAL ||
+                       patch->tram_grp[i].grp_pos == TRAM_POS_EXTERNAL) {
+
+                       res->items[res->item_count].grp_idx = -i - 1;
+                       res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size;
+                       res->items[res->item_count].grp_acc_count = acc_count;
+                       res->items[res->item_count].pos = patch->tram_grp[i].grp_pos;
+                       res->items[res->item_count].res_value = 0;
+                       res->item_count++;
+               }
+       }
+       return 0;
+}
+
+int ld10k1_tram_calc_res_value(ld10k1_dsp_tram_resolve_t *res)
+{
+       /* res_value is calculated as grp_size / acc_count */
+       int i;
+       for (i = 0; i < res->item_count; i++)
+               res->items[i].res_value = res->items[i].grp_size / res->items[i].grp_acc_count;
+       return 0;
+}
+
+static int ld10k1_tram_sort_res_compare(const void *item1, const void *item2)
+{
+       ld10k1_dsp_tram_resolve_item_t *i1 = (ld10k1_dsp_tram_resolve_item_t *)item1;
+       ld10k1_dsp_tram_resolve_item_t *i2 = (ld10k1_dsp_tram_resolve_item_t *)item2;
+
+       if (i1->res_value == i2->res_value)
+               return 0;
+       else if (i1->res_value > i2->res_value)
+               return 1;
+       else
+               return -1;
+}
+
+int ld10k1_tram_sort_res(ld10k1_dsp_tram_resolve_t *res)
+{
+       qsort(res->items, res->item_count, sizeof(ld10k1_dsp_tram_resolve_item_t), ld10k1_tram_sort_res_compare);
+       return 0;
+}
+
+int ld10k1_tram_resolve_res(ld10k1_dsp_tram_resolve_t *res)
+{
+       int i;
+       for (i = 0; i < res->item_count; i++) {
+               /* first try internal tram then external tram */
+               if (res->items[i].grp_size <= res->ifree &&
+                       res->items[i].grp_acc_count <= res->iacc_free_count) {
+                       /* put it into itram */
+                       res->ifree -= res->items[i].grp_size;
+                       res->iacc_free_count -= res->items[i].grp_acc_count;
+                       res->items[i].pos = TRAM_POS_INTERNAL;
+               } else if (res->items[i].grp_size <= res->efree &&
+                       res->items[i].grp_acc_count <= res->eacc_free_count) {
+                       /* put it into etram */
+                       res->efree -= res->items[i].grp_size;
+                       res->eacc_free_count -= res->items[i].grp_acc_count;
+                       res->items[i].pos = TRAM_POS_EXTERNAL;
+               } else
+                       return LD10K1_ERR_TRAM_FULL;
+       }
+       return 0;
+}
+
+int ld10k1_tram_grp_alloc(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
+               if (!dsp_mgr->tram_grp[i].used) {
+                       dsp_mgr->tram_grp[i].used = 1;
+                       return i;
+               }
+       }
+       return LD10K1_ERR_TRAM_FULL_GRP;
+}
+
+void ld10k1_tram_grp_free(ld10k1_dsp_mgr_t *dsp_mgr, int grp)
+{
+       dsp_mgr->tram_grp[grp].used = 0;
+}
+
+int ld10k1_tram_acc_alloc(ld10k1_dsp_mgr_t *dsp_mgr)
+{
+       int i;
+       for (i = 0; i < dsp_mgr->max_tram_acc; i++) {
+               if (!dsp_mgr->tram_acc[i].used) {
+                       dsp_mgr->tram_acc[i].used = 1;
+                       return i;
+               }
+       }
+       return LD10K1_ERR_TRAM_FULL_ACC;
+}
+
+void ld10k1_tram_acc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc)
+{
+       dsp_mgr->tram_acc[acc].used = 0;
+}
+
+int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res)
+{
+       int err;
+
+       ld10k1_tram_init_res(dsp_mgr, res);
+       ld10k1_tram_init_res_from_dsp_mgr(dsp_mgr, res);
+
+       if ((err = ld10k1_tram_init_res_from_patch(dsp_mgr, res, patch)) < 0)
+               return err;
+
+       ld10k1_tram_calc_res_value(res);
+       ld10k1_tram_sort_res(res);
+
+       if ((err = ld10k1_tram_resolve_res(res)) < 0)
+               return err;
+
+       ld10k1_tram_init_res_from_patch_copy(dsp_mgr, res, patch);
+
+       return 0;
+}
+
+int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res)
+{
+       int i;
+       int grp;
+       int acc;
+
+       /* allocate tram grp and acc for patch */
+       for (i = 0; i < patch->tram_count; i++) {
+               grp = ld10k1_tram_grp_alloc(dsp_mgr);
+               patch->tram_grp[i].grp_idx = grp;
+               dsp_mgr->tram_grp[grp].type = patch->tram_grp[i].grp_type;
+               dsp_mgr->tram_grp[grp].size = patch->tram_grp[i].grp_size;
+       }
+
+       for (i = 0; i < res->item_count; i++) {
+               if (res->items[i].grp_idx < 0) {
+                       res->items[i].grp_idx = patch->tram_grp[-(res->items[i].grp_idx + 1)].grp_idx;
+                       dsp_mgr->tram_grp[res->items[i].grp_idx].pos = TRAM_POS_NONE;
+                       dsp_mgr->tram_grp[res->items[i].grp_idx].acc_count = res->items[i].grp_acc_count;
+               }
+       }
+
+       for (i = 0; i < patch->tram_acc_count; i++) {
+               acc = ld10k1_tram_acc_alloc(dsp_mgr);
+               patch->tram_acc[i].acc_idx = acc;
+               dsp_mgr->tram_acc[acc].type = patch->tram_acc[i].acc_type;
+               dsp_mgr->tram_acc[acc].offset = patch->tram_acc[i].acc_offset;
+               dsp_mgr->tram_acc[acc].grp = patch->tram_grp[patch->tram_acc[i].grp].grp_idx;
+       }
+
+       ld10k1_tram_res_alloc_hwacc(dsp_mgr, res);
+       ld10k1_tram_realloc_space(dsp_mgr, res);
+       return 0;
+}
+
+int ld10k1_tram_hwacc_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int external)
+{
+       int i;
+
+       if (!external) {
+               for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) {
+                       if (!dsp_mgr->itram_hwacc[i].used) {
+                               dsp_mgr->itram_hwacc[i].used = 1;
+                               dsp_mgr->i_tram.used_hwacc++;
+                               return i;
+                       }
+               }
+       } else {
+               for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) {
+                       if (!dsp_mgr->etram_hwacc[i].used) {
+                               dsp_mgr->etram_hwacc[i].used = 1;
+                               dsp_mgr->e_tram.used_hwacc++;
+                               return i + dsp_mgr->max_itram_hwacc;
+                       }
+               }
+       }
+       return LD10K1_ERR_TRAM_FULL_ACC;
+}
+
+void ld10k1_tram_hwacc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc)
+{
+       if (acc < dsp_mgr->max_itram_hwacc) {
+               dsp_mgr->itram_hwacc[acc].used = 0;
+               dsp_mgr->itram_hwacc[acc].addr_val = 0;
+               dsp_mgr->itram_hwacc[acc].data_val = 0;
+               dsp_mgr->itram_hwacc[acc].modified = 1;
+               dsp_mgr->i_tram.used_hwacc--;
+       } else {
+               int nacc = acc - dsp_mgr->max_itram_hwacc;
+               dsp_mgr->etram_hwacc[nacc].used = 0;
+               dsp_mgr->etram_hwacc[nacc].used = 0;
+               dsp_mgr->etram_hwacc[nacc].addr_val = 0;
+               dsp_mgr->etram_hwacc[nacc].data_val = 0;
+               dsp_mgr->etram_hwacc[nacc].modified = 1;
+               dsp_mgr->e_tram.used_hwacc--;
+       }
+}
+
+void ld10k1_tram_actualize_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int op, unsigned int addr, unsigned int data)
+{
+       if (acc < dsp_mgr->max_itram_hwacc) {
+               dsp_mgr->itram_hwacc[acc].op = op;
+               dsp_mgr->itram_hwacc[acc].addr_val = addr;
+               dsp_mgr->itram_hwacc[acc].data_val = data;
+               dsp_mgr->itram_hwacc[acc].modified = 1;
+       } else {
+               int nacc = acc - dsp_mgr->max_itram_hwacc;
+               dsp_mgr->etram_hwacc[nacc].op = op;
+               dsp_mgr->etram_hwacc[nacc].addr_val = addr;
+               dsp_mgr->etram_hwacc[nacc].data_val = data;
+               dsp_mgr->etram_hwacc[nacc].modified = 1;
+       }
+}
+
+void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data)
+{
+       int nacc;
+
+       if (acc < dsp_mgr->max_itram_hwacc) {
+               *addr = dsp_mgr->itram_hwacc[acc].addr_val;
+               *data = dsp_mgr->itram_hwacc[acc].data_val;
+       } else {
+               nacc = acc - dsp_mgr->max_itram_hwacc;
+               *addr = dsp_mgr->etram_hwacc[nacc].addr_val;
+               *data = dsp_mgr->etram_hwacc[nacc].data_val;
+       }
+}
+
+int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
+{
+       int i, j;
+       int grp_idx;
+       int hwacc;
+
+       /* free hw acc - where pos changed */
+       for (i = 0; i < res->item_count; i++) {
+               grp_idx = res->items[i].grp_idx;
+               if (dsp_mgr->tram_grp[grp_idx].pos != TRAM_POS_NONE &&
+                       dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) {
+                       for (j = 0; j < dsp_mgr->max_tram_acc; j++)
+                               if (dsp_mgr->tram_acc[j].used &&
+                                       dsp_mgr->tram_acc[j].grp == grp_idx)
+                                       ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[j].hwacc);
+                       dsp_mgr->tram_grp[grp_idx].pos = TRAM_POS_NONE;
+               }
+       }
+
+       /* now allocate */
+       for (i = 0; i < res->item_count; i++) {
+               grp_idx = res->items[i].grp_idx;
+               if (dsp_mgr->tram_grp[grp_idx].pos == TRAM_POS_NONE &&
+                       dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) {
+                       dsp_mgr->tram_grp[grp_idx].pos = res->items[i].pos;
+                       for (j = 0; j < dsp_mgr->max_tram_acc; j++)
+                               if (dsp_mgr->tram_acc[j].used &&
+                                       dsp_mgr->tram_acc[j].grp == grp_idx) {
+                                       hwacc = ld10k1_tram_hwacc_alloc(dsp_mgr, res->items[i].pos == TRAM_POS_EXTERNAL ? 1 : 0);
+                                       dsp_mgr->tram_acc[j].hwacc = hwacc;
+                               }
+               }
+       }
+       return 0;
+}
+
+int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
+{
+       int itram_size = res->isize;
+       int etram_size = res->esize;
+       int i;
+
+       /* allocate from end */
+       for (i = 0; i < dsp_mgr->max_tram_grp; i++)
+               if (dsp_mgr->tram_grp[i].used) {
+                       if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) {
+                               itram_size -= dsp_mgr->tram_grp[i].size;
+                               dsp_mgr->tram_grp[i].offset = itram_size;
+                       } else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) {
+                               etram_size -= dsp_mgr->tram_grp[i].size;
+                               dsp_mgr->tram_grp[i].offset = etram_size;
+                       }
+               }
+       
+       return 0;
+}
+
+
+int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
+{
+       int i;
+       int grp_idx;
+       int acc_idx;
+       int tram_op;
+
+       /* for all patch accs */
+       for (i = 0; i < patch->tram_acc_count; i++) {
+               grp_idx = patch->tram_grp[patch->tram_acc[i].grp].grp_idx;
+               acc_idx = patch->tram_acc[i].acc_idx;
+               tram_op = 0;
+
+               if (dsp_mgr->tram_acc[acc_idx].type == TRAM_ACC_WRITE)
+                       tram_op = TRAM_OP_WRITE;
+               else
+                       tram_op = TRAM_OP_READ;
+
+               ld10k1_tram_actualize_hwacc(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc,
+                       tram_op, dsp_mgr->tram_grp[grp_idx].offset + patch->tram_acc[i].acc_offset, 0);
+       }
+       return 0;
+}
+
+int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
+{
+       int i;
+       int acc_idx;
+       int grp_idx;
+       
+       /* free all patch accs */
+       for (i = 0; i < patch->tram_acc_count; i++) {
+               acc_idx = patch->tram_acc[i].acc_idx;
+               ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc);
+               ld10k1_tram_acc_free(dsp_mgr, acc_idx);
+       }
+
+       /* free all patch grps */
+       for (i = 0; i < patch->tram_count; i++) {
+               grp_idx = patch->tram_grp[i].grp_idx;
+               ld10k1_tram_grp_free(dsp_mgr, grp_idx);
+       }
+       
+       return 0;
+}
+
diff --git a/ld10k1/src/ld10k1_tram.h b/ld10k1/src/ld10k1_tram.h
new file mode 100644 (file)
index 0000000..380f8e0
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 __LD10K1_TRAM_H
+#define __LD10K1_TRAM_H
+
+typedef struct {
+       int grp_idx;
+       unsigned int grp_size;
+       unsigned int grp_acc_count;
+       unsigned int res_value;
+       unsigned int pos;
+} ld10k1_dsp_tram_resolve_item_t;
+
+typedef struct {
+       int isize;
+       int ifree;
+       int iacc_count;
+       int iacc_free_count;
+       int esize;
+       int efree;
+       int eacc_count;
+       int eacc_free_count;
+       int grp_free;
+       int item_count;
+       ld10k1_dsp_tram_resolve_item_t items[MAX_TRAM_COUNT];
+} ld10k1_dsp_tram_resolve_t;
+
+int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res);
+int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res);
+int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch);
+void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data);
+int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch);
+
+#endif /* __LD10K1_TRAM_H */
diff --git a/ld10k1/src/liblo10k1.c b/ld10k1/src/liblo10k1.c
new file mode 100644 (file)
index 0000000..c8e0f94
--- /dev/null
@@ -0,0 +1,1168 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "comm.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_error.h"
+#include "liblo10k1.h"
+#include "liblo10k1ef.h"
+#include "liblo10k1lf.h"
+#include "ld10k1_debug.h"
+#include "config.h"
+
+int send_request_check(int conn_num, int op, void *data, int data_size)
+{
+       int opr, sizer;
+       int err;
+
+       if ((err = send_request(conn_num, op, data, data_size)) < 0)
+               return err;
+
+       if ((err = receive_response(conn_num, &opr, &sizer)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int send_msg_data_check(int conn_num, void *data, int data_size)
+{
+       int opr, sizer;
+       int err;
+
+       if ((err = send_msg_data(conn_num, data, data_size)) < 0)
+               return err;
+
+       if ((err = receive_response(conn_num, &opr, &sizer)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int receive_response_data_check(int conn_num, void *data, int idata_size)
+{
+       int err;
+       int op, data_size;
+
+       if ((err = receive_response(conn_num, &op, &data_size)) < 0)
+               return err;
+               
+       if (op == FNC_ERR)
+               return LD10K1_ERR_PROTOCOL;
+       if (data_size != idata_size)
+               return LD10K1_ERR_PROTOCOL;
+               
+       if ((err = receive_msg_data(conn_num, data, data_size)) < 0)
+               return err;
+               
+       /* receive check */
+       if ((err = receive_response(conn_num, &op, &data_size)) < 0)
+               return err;
+       
+       return 0;
+}
+
+void liblo10k1_connection_init(liblo10k1_connection_t *conn)
+{
+       *conn = 0;
+}
+
+int liblo10k1_connect(liblo10k1_param *param, liblo10k1_connection_t *conn)
+{
+       int err;
+
+       param->server = 0;
+       *conn = setup_comm(param);
+       if (*conn < 0)
+               return LD10K1_ERR_COMM_CONN;
+       if ((err = connect_comm(*conn, param)) < 0) {
+               free_comm(*conn);
+               *conn = 0;
+               return err;
+       }
+       return 0;
+}
+
+int liblo10k1_disconnect(liblo10k1_connection_t *conn)
+{
+       send_request(*conn, FNC_CLOSE_CONN, NULL, 0);
+       free_comm(*conn);
+       *conn = 0;
+       return 0;
+}
+
+int liblo10k1_is_open(liblo10k1_connection_t *conn)
+{
+       return *conn != 0;
+}
+
+int liblo10k1_patch_set_in_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_pio_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_pio_t *)malloc(sizeof(liblo10k1_dsp_pio_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_pio_t) * count);
+       }
+       
+       p->in_count = count;
+       if (p->ins)
+               free(p->ins);
+       p->ins = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_out_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_pio_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_pio_t *)malloc(sizeof(liblo10k1_dsp_pio_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_pio_t) * count);
+       }
+       
+       p->out_count = count;
+       if (p->outs)
+               free(p->outs);
+       p->outs = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_const_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_cs_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_cs_t *)malloc(sizeof(liblo10k1_dsp_cs_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_cs_t) * count);
+       }
+       
+       p->const_count = count;
+       if (p->consts)
+               free(p->consts);
+       p->consts = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_sta_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_cs_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_cs_t *)malloc(sizeof(liblo10k1_dsp_cs_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_cs_t) * count);
+       }
+       
+       p->sta_count = count;
+       if (p->stas)
+               free(p->stas);
+       p->stas = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_dyn_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       p->dyn_count = count;
+       return 0;
+}
+
+int liblo10k1_patch_set_hw_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_hw_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_hw_t *)malloc(sizeof(liblo10k1_dsp_hw_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_hw_t) * count);
+       }
+       
+       p->hw_count = count;
+       if (p->hws)
+               free(p->hws);
+       p->hws = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_tram_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_tram_grp_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_tram_grp_t *)malloc(sizeof(liblo10k1_dsp_tram_grp_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_tram_grp_t) * count);
+       }
+       
+       p->tram_count = count;
+       if (p->tram)
+               free(p->tram);
+       p->tram = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_tram_acc_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_tram_acc_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_tram_acc_t *)malloc(sizeof(liblo10k1_dsp_tram_acc_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_tram_acc_t) * count);
+       }
+       
+       p->tram_acc_count = count;
+       if (p->tram_acc)
+               free(p->tram_acc);
+       p->tram_acc = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_ctl_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_ctl_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_ctl_t *)malloc(sizeof(liblo10k1_dsp_ctl_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_ctl_t) * count);
+       }
+       
+       p->ctl_count = count;
+       if (p->ctl)
+               free(p->ctl);
+       p->ctl = tmp;
+       return 0;
+}
+
+int liblo10k1_patch_set_instr_count(liblo10k1_dsp_patch_t *p, int count)
+{
+       liblo10k1_dsp_instr_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_instr_t *)malloc(sizeof(liblo10k1_dsp_instr_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_dsp_instr_t) * count);
+       }
+       
+       p->instr_count = count;
+       if (p->instr)
+               free(p->instr);
+       p->instr = tmp;
+       return 0;
+}
+
+liblo10k1_dsp_patch_t *liblo10k1_patch_alloc(int in_count, int out_count, int const_count, int sta_count, int dyn_count, int hw_count, int tram_count, int tram_acc_count, int ctl_count, int instr_count)
+{
+       liblo10k1_dsp_patch_t *np;
+       int en = 0;
+
+       np = (liblo10k1_dsp_patch_t *)malloc(sizeof(liblo10k1_dsp_patch_t));
+       if (!np)
+               return NULL;
+
+       np->patch_name[0] ='\0';
+       np->ins = NULL;
+       np->outs = NULL;
+       np->consts = NULL;
+       np->stas = NULL;
+       np->hws = NULL;
+       np->tram = NULL;
+       np->tram_acc = NULL;
+       np->ctl = NULL;
+       np->instr = NULL;
+
+       if ((en = liblo10k1_patch_set_dyn_count(np, dyn_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_in_count(np, in_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_out_count(np, out_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_const_count(np, const_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_sta_count(np, sta_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_hw_count(np, hw_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_tram_count(np, tram_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_tram_acc_count(np, tram_acc_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_ctl_count(np, ctl_count)) < 0)
+               goto error;
+       if ((en = liblo10k1_patch_set_instr_count(np, instr_count)) < 0)
+               goto error;
+       return np;
+error:
+       liblo10k1_patch_free(np);
+       return NULL;
+}
+
+void liblo10k1_patch_free(liblo10k1_dsp_patch_t *patch)
+{
+       liblo10k1_patch_set_in_count(patch, 0);
+       liblo10k1_patch_set_out_count(patch, 0);
+       liblo10k1_patch_set_const_count(patch, 0);
+       liblo10k1_patch_set_dyn_count(patch, 0);
+       liblo10k1_patch_set_sta_count(patch, 0);
+       liblo10k1_patch_set_hw_count(patch, 0);
+       liblo10k1_patch_set_tram_count(patch, 0);
+       liblo10k1_patch_set_tram_acc_count(patch, 0);
+       liblo10k1_patch_set_ctl_count(patch, 0);
+       liblo10k1_patch_set_instr_count(patch, 0);
+               
+       free(patch);
+}
+
+int liblo10k1_patch_load(liblo10k1_connection_t *conn, liblo10k1_dsp_patch_t *patch, int before, int *loaded, int *loaded_id)
+{
+       int err;
+       ld10k1_fnc_patch_add_t patch_fnc;
+       int tmpres[2];
+
+       strncpy(patch_fnc.patch.patch_name, patch->patch_name, sizeof(patch_fnc.patch.patch_name) - 1);
+       patch_fnc.patch.patch_name[sizeof(patch_fnc.patch.patch_name) - 1] = '\0';
+       
+       patch_fnc.patch.in_count = patch->in_count;
+       patch_fnc.patch.out_count = patch->out_count;
+       patch_fnc.patch.const_count = patch->const_count;
+       patch_fnc.patch.static_count = patch->sta_count;
+       patch_fnc.patch.dynamic_count = patch->dyn_count;
+       patch_fnc.patch.hw_count = patch->hw_count;
+       patch_fnc.patch.tram_count = patch->tram_count;
+       patch_fnc.patch.tram_acc_count = patch->tram_acc_count;
+       patch_fnc.patch.ctl_count = patch->ctl_count;
+       patch_fnc.patch.instr_count = patch->instr_count;
+
+       /* patch */
+       /* add */
+       patch_fnc.where = before;
+       if ((err = send_request_check(*conn, FNC_PATCH_ADD, &patch_fnc, sizeof(ld10k1_fnc_patch_add_t))) < 0)
+               return err;
+
+       /* in */
+       if (patch->in_count)
+               if ((err = send_msg_data_check(*conn, patch->ins, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count)) < 0)
+                       return err;
+
+       /* out */
+       if (patch->out_count)
+               if ((err = send_msg_data_check(*conn, patch->outs, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count)) < 0)
+                       return err;
+
+       /* const */
+       if (patch->const_count)
+               if ((err = send_msg_data_check(*conn, patch->consts, sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count)) < 0)
+                       return err;
+
+       /* sta */
+       if (patch->sta_count)
+               if ((err = send_msg_data_check(*conn, patch->stas, sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count)) < 0)
+                       return err;
+
+       /* hw */
+       if (patch->hw_count)
+               if ((err = send_msg_data_check(*conn, patch->hws, sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count)) < 0)
+                       return err;
+
+       if (patch->tram_count)
+               /* tram groups */
+               if ((err = send_msg_data_check(*conn, patch->tram, sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count)) < 0)
+                       return err;
+
+       if (patch->tram_acc_count)
+               /* tram access */
+               if ((err = send_msg_data_check(*conn, patch->tram_acc, sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count)) < 0)
+                       return err;
+
+       if (patch->ctl_count)
+               /* ctls */
+               if ((err = send_msg_data_check(*conn, patch->ctl, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count)) < 0)
+                       return err;
+
+       /* instr */
+       if ((err = send_msg_data_check(*conn, patch->instr, sizeof(ld10k1_dsp_instr_t) * patch->instr_count)) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, tmpres, sizeof(tmpres))) < 0)
+               return err;
+
+       if (loaded)
+               *loaded = tmpres[0];
+       if (loaded_id)
+               *loaded_id = tmpres[1];
+
+       return 0;
+}
+
+int liblo10k1_debug(liblo10k1_connection_t *conn, int deb, void (*prn_fnc)(char *))
+{
+       int err;
+       ld10k1_fnc_debug_t debug_info;
+       char debug_line[1000];
+       int opr, sizer;
+
+       /* add */
+       debug_info.what = deb;
+
+       if ((err = send_request(*conn, FNC_DEBUG, &debug_info, sizeof(ld10k1_fnc_debug_t))) < 0)
+               return err;
+
+       while (1) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE)
+                       break;
+
+               if (sizer < (int)sizeof(debug_line)) {
+                       if ((err = receive_msg_data(*conn, &debug_line, sizer)) < 0)
+                               return err;
+               } else
+                       return LIBLO10K1_ERR_DEBUG;
+               (*prn_fnc)(debug_line);
+       }
+
+       /* not checked */
+       return receive_response(*conn, &opr, &sizer);
+}
+
+int liblo10k1_patch_unload(liblo10k1_connection_t *conn, int patch_num)
+{
+       ld10k1_fnc_patch_del_t patch_fnc;
+
+       patch_fnc.where = patch_num;
+
+       return send_request_check(*conn, FNC_PATCH_DEL, &patch_fnc, sizeof(ld10k1_fnc_patch_del_t));
+}
+
+int liblo10k1_dsp_init(liblo10k1_connection_t *conn)
+{
+       return send_request_check(*conn, FNC_DSP_INIT, NULL, 0);
+}
+
+static int liblo10k1_find_any(liblo10k1_connection_t *conn, int op, int patch, char *name, int *out)
+{
+       ld10k1_fnc_name_t name_info;
+       int err;
+       int idx = -1;
+
+       name_info.patch_num = patch;
+       name_info.gpr = -1;
+       
+       strncpy(name_info.name, name, sizeof(name_info.name) - 1);
+       name_info.name[sizeof(name_info.name) - 1] = '\0';
+
+       if ((err = send_request(*conn, op, &name_info, sizeof(ld10k1_fnc_name_t))) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, &idx, sizeof(idx))) < 0)
+               return err;
+       
+       *out = idx;
+       return 0;
+}
+
+int liblo10k1_find_patch(liblo10k1_connection_t *conn, char *patch_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_PATCH_FIND, -1, patch_name, out);
+}
+
+int liblo10k1_find_fx(liblo10k1_connection_t *conn, char *fx_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_FX_FIND, -1, fx_name, out);
+}
+
+int liblo10k1_find_in(liblo10k1_connection_t *conn, char *in_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_IN_FIND, -1, in_name, out);
+}
+
+int liblo10k1_find_out(liblo10k1_connection_t *conn, char *out_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_OUT_FIND, -1, out_name, out);
+}
+
+int liblo10k1_find_patch_in(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_PATCH_IN_FIND, patch_num, patch_in_name, out);
+}
+
+int liblo10k1_find_patch_out(liblo10k1_connection_t *conn, int patch_num, char *patch_out_name, int *out)
+{
+       return liblo10k1_find_any(conn, FNC_PATCH_OUT_FIND, patch_num, patch_out_name, out);
+}
+
+int liblo10k1_con_add(liblo10k1_connection_t *conn, int multi, int simple, int from_type, int from_patch, int from_io, int to_type, int to_patch, int to_io, int *ci)
+{
+       ld10k1_fnc_connection_t connection_fnc;
+       int err;
+       int conn_id;
+       
+       connection_fnc.what = FNC_CONNECTION_ADD;
+       connection_fnc.multi = multi;
+       connection_fnc.simple = simple;
+       connection_fnc.from_type = from_type;
+       connection_fnc.from_patch = from_patch;
+       connection_fnc.from_io = from_io;
+       connection_fnc.to_type = to_type;
+       connection_fnc.to_patch = to_patch;
+       connection_fnc.to_io = to_io;
+
+       if ((err = send_request(*conn, FNC_CONNECTION_ADD, &connection_fnc, sizeof(ld10k1_fnc_connection_t))) < 0)
+               return err;
+       
+       if ((err = receive_response_data_check(*conn, &conn_id, sizeof(conn_id))) < 0)
+               return err;
+               
+       if (ci)
+               *ci = conn_id;
+       return 0;
+}
+
+int liblo10k1_con_del(liblo10k1_connection_t *conn, int type, int patch, int io, int *ci)
+{
+       ld10k1_fnc_connection_t connection_fnc;
+       int err;
+       int conn_id;
+
+       connection_fnc.what = FNC_CONNECTION_DEL;
+       connection_fnc.from_type = type;
+       connection_fnc.from_patch = patch;
+       connection_fnc.from_io = io;
+       connection_fnc.to_type = -1;
+       connection_fnc.to_patch = -1;
+       connection_fnc.to_io = -1;
+       
+       if ((err = send_request(*conn, FNC_CONNECTION_DEL, &connection_fnc, sizeof(ld10k1_fnc_connection_t))) < 0)
+               return err;
+       
+       if ((err = receive_response_data_check(*conn, &conn_id, sizeof(conn_id))) < 0)
+               return err;
+               
+       if (ci)
+               *ci = conn_id;
+       return 0;
+}
+
+static int liblo10k1_rename_any(liblo10k1_connection_t *conn, int op, int patch_num, int gpr_num, char *name)
+{
+       ld10k1_fnc_name_t name_info;
+
+       name_info.patch_num = patch_num;
+       name_info.gpr = gpr_num;
+       
+       strncpy(name_info.name, name, sizeof(name_info.name) - 1);
+       name_info.name[sizeof(name_info.name) - 1] = '\0';
+       
+       return send_request_check(*conn, op, &name_info, sizeof(ld10k1_fnc_name_t));
+}
+
+int liblo10k1_rename_patch(liblo10k1_connection_t *conn, int patch_num, char *patch_name)
+{
+       return liblo10k1_rename_any(conn, FNC_PATCH_RENAME, patch_num, -1, patch_name);
+}
+
+int liblo10k1_rename_patch_in(liblo10k1_connection_t *conn, int patch_num, int in, char *patch_in_name)
+{
+       return liblo10k1_rename_any(conn, FNC_PATCH_IN_RENAME, patch_num, in, patch_in_name);
+}
+
+int liblo10k1_rename_patch_out(liblo10k1_connection_t *conn, int patch_num, int out, char *patch_out_name)
+{
+       return liblo10k1_rename_any(conn, FNC_PATCH_OUT_RENAME, patch_num, out, patch_out_name);
+}
+
+int liblo10k1_rename_fx(liblo10k1_connection_t *conn, int fx, char *fx_name)
+{
+       return liblo10k1_rename_any(conn, FNC_FX_RENAME, -1, fx, fx_name);
+}
+
+int liblo10k1_rename_in(liblo10k1_connection_t *conn, int in, char *in_name)
+{
+       return liblo10k1_rename_any(conn, FNC_IN_RENAME, -1, in, in_name);
+}
+
+int liblo10k1_rename_out(liblo10k1_connection_t *conn, int out, char *out_name)
+{
+       return liblo10k1_rename_any(conn, FNC_OUT_RENAME, -1, out, out_name);
+}
+
+int liblo10k1_get_io(liblo10k1_connection_t *conn, int op, int io_num, liblo10k1_get_io_t *out);
+int liblo10k1_get_pio(liblo10k1_connection_t *conn, int op, int patch_num, int io_num, liblo10k1_get_io_t *out);
+
+int liblo10k1_get_fx(liblo10k1_connection_t *conn, int fx_num, liblo10k1_get_io_t *out)
+{
+       return liblo10k1_get_io(conn, FNC_GET_FX, fx_num, out);
+}
+
+int liblo10k1_get_in(liblo10k1_connection_t *conn, int in_num, liblo10k1_get_io_t *out)
+{
+       return liblo10k1_get_io(conn, FNC_GET_IN, in_num, out);
+}
+
+int liblo10k1_get_out(liblo10k1_connection_t *conn, int out_num, liblo10k1_get_io_t *out)
+{
+       return liblo10k1_get_io(conn, FNC_GET_OUT, out_num, out);
+}
+
+int liblo10k1_get_pin(liblo10k1_connection_t *conn, int patch_num, int in_num, liblo10k1_get_io_t *out)
+{
+       return liblo10k1_get_pio(conn, FNC_GET_PIN, patch_num, in_num, out);
+}
+
+int liblo10k1_get_pout(liblo10k1_connection_t *conn, int patch_num, int out_num, liblo10k1_get_io_t *out)
+{
+       return liblo10k1_get_pio(conn, FNC_GET_POUT, patch_num, out_num, out);
+}
+
+int liblo10k1_get_io(liblo10k1_connection_t *conn, int op, int io_num, liblo10k1_get_io_t *out)
+{
+       int err;
+       
+       if ((err = send_request(*conn, op, &io_num, sizeof(int))) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, out, sizeof(liblo10k1_get_io_t))) < 0)
+               return err;
+
+       return 0;
+}
+
+int liblo10k1_get_pio(liblo10k1_connection_t *conn, int op, int patch_num, int io_num, liblo10k1_get_io_t *out)
+{
+       int tmp_num[2];
+       int err;
+       
+       tmp_num[0] = patch_num;
+       tmp_num[1] = io_num;
+       
+       if ((err = send_request(*conn, op, tmp_num, sizeof(int) * 2)) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, out, sizeof(liblo10k1_get_io_t))) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1_get_io_count(liblo10k1_connection_t *conn, int op, int *out);
+int liblo10k1_get_pio_count(liblo10k1_connection_t *conn, int op, int patch_num, int *out);
+
+int liblo10k1_get_fx_count(liblo10k1_connection_t *conn, int *out)
+{
+       return liblo10k1_get_io_count(conn, FNC_GET_FX_COUNT, out);
+}
+
+int liblo10k1_get_in_count(liblo10k1_connection_t *conn, int *out)
+{
+       return liblo10k1_get_io_count(conn, FNC_GET_IN_COUNT, out);
+}
+
+int liblo10k1_get_out_count(liblo10k1_connection_t *conn, int *out)
+{
+       return liblo10k1_get_io_count(conn, FNC_GET_OUT_COUNT, out);
+}
+
+int liblo10k1_get_pin_count(liblo10k1_connection_t *conn, int patch_num, int *out)
+{
+       return liblo10k1_get_pio_count(conn, FNC_GET_PIN_COUNT, patch_num, out);
+}
+
+int liblo10k1_get_pout_count(liblo10k1_connection_t *conn, int patch_num, int *out)
+{
+       return liblo10k1_get_pio_count(conn, FNC_GET_POUT_COUNT, patch_num, out);
+}
+
+int liblo10k1_get_io_count(liblo10k1_connection_t *conn, int op, int *out)
+{
+       int err;
+       
+       if ((err = send_request(*conn, op, 0, 0)) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, out, sizeof(int))) < 0)
+               return err;
+
+       return 0;
+}
+
+int liblo10k1_get_pio_count(liblo10k1_connection_t *conn, int op, int patch_num, int *out)
+{
+       int err;
+       
+       if ((err = send_request(*conn, op, &patch_num, sizeof(int))) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, out, sizeof(int))) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1_get_patches_info(liblo10k1_connection_t *conn, liblo10k1_patches_info_t **out, int *count)
+{
+       liblo10k1_patches_info_t *info;
+       int opr, sizer;
+       int err;
+
+       *out = NULL;
+       *count = 0;
+       info = NULL;
+
+       if ((err = send_request(*conn, FNC_GET_PATCHES_INFO, 0, 0)) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       *count = sizer / sizeof(liblo10k1_patches_info_t);
+       if (sizer > 0) {
+               info = (liblo10k1_patches_info_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!info)
+                       return LD10K1_ERR_NO_MEM;
+       }
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0) {
+               free(info);
+               return err;
+       }
+
+       *out = info;
+       return 0;
+}
+
+int liblo10k1_patch_get(liblo10k1_connection_t *conn, int patch_num, liblo10k1_dsp_patch_t **opatch)
+{
+       liblo10k1_dsp_patch_t *patch;
+       int err;
+
+       ld10k1_dsp_patch_t tmp_patch;
+       int opr, sizer;
+
+
+       if ((err = send_request(*conn, FNC_GET_PATCH, &patch_num, sizeof(patch_num))) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       if (opr != FNC_CONTINUE)
+               return LD10K1_ERR_PROTOCOL;
+
+       if ((err = receive_msg_data(*conn, &tmp_patch, sizeof(tmp_patch))) < 0)
+               return err;
+
+       /* alloc patch */
+       patch = liblo10k1_patch_alloc(tmp_patch.in_count, tmp_patch.out_count, tmp_patch.const_count, tmp_patch.static_count, tmp_patch.dynamic_count, tmp_patch.hw_count, tmp_patch.tram_count, tmp_patch.tram_acc_count, tmp_patch.ctl_count, tmp_patch.instr_count);
+       if (!patch)
+               return LD10K1_ERR_NO_MEM;
+
+       strcpy(patch->patch_name, tmp_patch.patch_name);
+
+       /* ins */
+       if (patch->in_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->in_count * sizeof(ld10k1_dsp_p_in_out_t))
+                       goto err_protocol;
+
+               patch->ins = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->ins)
+                       goto err_nomem;
+       }
+
+       /* outs */
+       if (patch->out_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->out_count * sizeof(ld10k1_dsp_p_in_out_t))
+                       goto err_protocol;
+
+               patch->outs = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->outs)
+                       goto err_nomem;
+       }
+
+       /* consts */
+       if (patch->const_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->const_count * sizeof(ld10k1_dsp_p_const_static_t))
+                       goto err_protocol;
+
+               patch->consts = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->consts)
+                       goto err_nomem;
+       }
+
+       /* stas */
+       if (patch->sta_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->sta_count * sizeof(ld10k1_dsp_p_const_static_t))
+                       goto err_protocol;
+
+               patch->stas = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->stas)
+                       goto err_nomem;
+       }
+
+       /* hws */
+       if (patch->hw_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->hw_count * sizeof(ld10k1_dsp_p_hw_t))
+                       goto err_protocol;
+
+               patch->hws = (ld10k1_dsp_p_hw_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->hws)
+                       goto err_nomem;
+       }
+
+       /* ctls */
+       if (patch->ctl_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->ctl_count * sizeof(liblo10k1_dsp_ctl_t))
+                       goto err_protocol;
+
+               patch->ctl = (liblo10k1_dsp_ctl_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->ctl)
+                       goto err_nomem;
+       }
+
+       /* tram grp */
+       if (patch->tram_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->tram_count * sizeof(liblo10k1_dsp_tram_grp_t))
+                       goto err_protocol;
+
+               patch->tram = (liblo10k1_dsp_tram_grp_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->tram)
+                       goto err_nomem;
+       }
+
+       /* tram acc */
+       if (patch->tram_acc_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->tram_acc_count * sizeof(liblo10k1_dsp_tram_acc_t))
+                       goto err_protocol;
+
+               patch->tram_acc = (liblo10k1_dsp_tram_acc_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->tram_acc)
+                       goto err_nomem;
+       }
+
+       /* instr */
+       if (patch->instr_count) {
+               if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+                       return err;
+
+               if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->instr_count * sizeof(liblo10k1_dsp_instr_t))
+                       goto err_protocol;
+
+               patch->instr = (liblo10k1_dsp_instr_t *)receive_msg_data_malloc(*conn, sizer);
+               if (!patch->instr)
+                       goto err_nomem;
+       }
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0) {
+               liblo10k1_patch_free(patch);
+               return err;
+       }
+
+       *opatch = patch;
+       return 0;
+err_nomem:
+       liblo10k1_patch_free(patch);
+       return LD10K1_ERR_NO_MEM;
+
+err_protocol:
+       liblo10k1_patch_free(patch);
+       return LD10K1_ERR_PROTOCOL;
+}
+
+int liblo10k1_dump(liblo10k1_connection_t *conn, void **out, int *size)
+{
+       int opr, sizer;
+       int err;
+       void *dump = NULL;
+
+       if ((err = send_request(*conn, FNC_DUMP, 0, 0)) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       *size = sizer;
+       if (sizer > 0) {
+               dump = receive_msg_data_malloc(*conn, sizer);
+               if (!dump)
+                       return LD10K1_ERR_NO_MEM;
+       }
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0) {
+               free(dump);
+               return err;
+       }
+
+       *out = dump;
+       return 0;
+}
+
+int liblo10k1_check_version(liblo10k1_connection_t *conn)
+{
+       int opr, sizer;
+       int err;
+       ld10k1_fnc_version_t ver;
+
+       if ((err = send_request(*conn, FNC_VERSION, 0, 0)) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       if (sizer == sizeof(ver)) {
+               if ((err = receive_msg_data(*conn, &ver, sizer)) < 0)
+                       return err;
+       }
+       else
+               return LD10K1_ERR_WRONG_VER;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       if (strcmp(ver.ld10k1_version, VERSION) == 0)
+               return 0;
+       else
+               return LD10K1_ERR_WRONG_VER;
+}
+
+int liblo10k1_get_points_info(liblo10k1_connection_t *conn, int **out, int *count)
+{
+       int *info;
+       int opr, sizer;
+       int err;
+
+       info = NULL;
+
+       if ((err = send_request(*conn, FNC_GET_POINTS_INFO, 0, 0)) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       *count = sizer / sizeof(int);
+       if (sizer > 0) {
+               info = (int *)receive_msg_data_malloc(*conn, sizer);
+               if (!info)
+                       return LD10K1_ERR_NO_MEM;
+       }
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0) {
+               free(info);
+               return err;
+       }
+
+       *out = info;
+       return 0;
+}
+
+int liblo10k1_get_point_info(liblo10k1_connection_t *conn, int point_id, liblo10k1_point_info_t *out)
+{
+       int opr, sizer;
+       int err;
+
+       if ((err = send_request(*conn, FNC_GET_POINT_INFO, &point_id, sizeof(point_id))) < 0)
+               return err;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       if (sizer != sizeof(liblo10k1_point_info_t))
+               return LD10K1_ERR_PROTOCOL;
+       if ((err = receive_msg_data(*conn, out, sizer)) < 0)
+               return LD10K1_ERR_PROTOCOL;
+
+       if ((err = receive_response(*conn, &opr, &sizer)) < 0)
+               return err;
+
+       return 0;
+}
+
+int liblo10k1_get_dsp_info(liblo10k1_connection_t *conn, liblo10k1_dsp_info_t *info)
+{
+       int err;
+       
+       if ((err = send_request(*conn, FNC_GET_DSP_INFO, NULL, 0)) < 0)
+               return err;
+
+       if ((err = receive_response_data_check(*conn, info, sizeof(liblo10k1_dsp_info_t))) < 0)
+               return err;
+       
+       return 0;
+}
+
+struct errmsg_t
+{
+       int errnum;
+       char *errmsg;
+};
+
+struct errmsg_t error_text[] =
+{
+       {LD10K1_ERR_UNKNOWN, "Unknown error"},
+       {LD10K1_ERR_COMM_READ, "Error in read from socket"},
+       {LD10K1_ERR_COMM_WRITE, "Error in write to socket"},
+       {LD10K1_ERR_UNKNOWN_PATCH_NUM, "Wrong parameter - patch with this num doesn't exists"},
+       {LD10K1_ERR_PROTOCOL, "ld10k1 is expecting more or less data as it got"},
+       {LD10K1_ERR_COMM_CONN, "Error in socket connect"},
+
+/* add patch */
+       {LD10K1_ERR_PROTOCOL_IN_COUNT, "Wrong in registers count"},
+       {LD10K1_ERR_PROTOCOL_OUT_COUNT, "Wrong out registers count"},
+       {LD10K1_ERR_PROTOCOL_CONST_COUNT, "Wrong const registers count"},
+       {LD10K1_ERR_PROTOCOL_STATIC_COUNT, "Wrong static registers count"},
+       {LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT, "Wrong dynamic registers count"},
+       {LD10K1_ERR_PROTOCOL_HW_COUNT, "Wrong hw registers count"},
+       {LD10K1_ERR_PROTOCOL_TRAM_COUNT, "Wrong tram count"},
+       {LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT, "Wrong tram access registers count"},
+       {LD10K1_ERR_PROTOCOL_CTL_COUNT, "Wrong controls count"},
+       {LD10K1_ERR_PROTOCOL_INSTR_COUNT, "Wrong instructions count"},
+
+/* driver */
+       {LD10K1_ERR_DRIVER_CODE_POKE, "Unable to poke code"},
+       {LD10K1_ERR_DRIVER_INFO, "Unable to get info"},
+       {LD10K1_ERR_DRIVER_CODE_PEEK, "Unable to peek code"},
+       {LD10K1_ERR_DRIVER_PCM_POKE, "Unable to poke pcm"},
+
+/* tram */
+       {LD10K1_ERR_ITRAM_FULL, "Not enought free itram"},
+       {LD10K1_ERR_ETRAM_FULL, "Not enought free etram"},
+       {LD10K1_ERR_TRAM_FULL, "Not enought free tram"},
+       {LD10K1_ERR_TRAM_FULL_GRP, "Not enought free tram group"},
+
+       {LD10K1_ERR_ITRAM_FULL_ACC, "Not enought free itram acc"},
+       {LD10K1_ERR_ETRAM_FULL_ACC, "Not enought free etram acc"},
+       {LD10K1_ERR_TRAM_FULL_ACC, "Not enought free tram acc"},
+
+       {LD10K1_ERR_MAX_CON_PER_POINT, "Maximum connections per point reached"},
+
+/* others */
+       {LD10K1_ERR_NO_MEM, "Not enought free mem"},
+       {LD10K1_ERR_MAX_PATCH_COUNT, "Max patch count excesed"},
+       {LD10K1_ERR_NOT_FREE_REG, "There is not free reg"},
+       {LD10K1_ERR_NOT_FREE_INSTR, "There is no free instruction slot"},
+
+/* patch chceck */
+       {LD10K1_ERR_WRONG_REG_HW_INDEX, "Loaded patch has wrong hw index"},
+       {LD10K1_ERR_WRONG_TRAM_POS, "Loaded patch has wrong tram position"},
+
+       {LD10K1_ERR_WRONG_TRAM_TYPE, "Loaded patch has wrong tram type"},
+       {LD10K1_ERR_WRONG_TRAM_SIZE, "Loaded patch has wrong tram size"},
+       {LD10K1_ERR_WRONG_TRAM_ACC_TYPE, "Loaded patch has wrong tram acc type"},
+
+       {LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE, "Loaded patch has tram gpr index out of range"},
+       {LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE, "Loaded patch has tram acc index out of range"},
+
+       {LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE, "Loaded patch has wrong count of visible gpr for control"},
+       {LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE, "Loaded patch has wrong count of gpr for control"},
+
+       {LD10K1_ERR_CTL_MIN_MAX_RANGE, "Loaded patch has wrong min, max range for control"},
+       {LD10K1_ERR_CTL_TRANLSLATION, "Loaded patch has wrong translation function for control"},
+       {LD10K1_ERR_CTL_REG_INDEX, "Loaded patch has wrong gpr index for control"},
+       {LD10K1_ERR_CTL_REG_VALUE, "Loaded patch has wrong initial value for control"},
+
+       {LD10K1_ERR_INSTR_OPCODE, "Loaded patch has wrong instruction opcode"},
+       {LD10K1_ERR_INSTR_ARG_INDEX, "Loaded patch has wrong argument for instruction"},
+
+       {LD10K1_ERR_UNKNOWN_REG_NUM, "There isn't register with this reg number"},
+       {LD10K1_ERR_UNKNOWN_PATCH_REG_NUM, "There isn't patch register with this reg number for patch"},
+
+       {LD10K1_ERR_CONNECTION, "Couldn't connect patch to io"},
+       {LD10K1_ERR_CONNECTION_FNC, "Not supported connect/disconnect function"},
+
+       {LD10K1_ERR_CTL_EXISTS, "Can't add control because there is one with same name"},
+
+       {LD10K1_ERR_PATCH_RENAME, "Couldn't rename patch"},
+       {LD10K1_ERR_PATCH_REG_RENAME, "Couldn't rename patch register"},
+       {LD10K1_ERR_REG_RENAME, "Couldn't rename register"},
+       {LD10K1_ERR_WRONG_VER, "Wrong ld10k1 version"},
+       {LD10K1_ERR_UNKNOWN_POINT, "Unknown point"},
+       
+       /* errors from liblo10k1ef */
+       {LD10K1_EF_ERR_OPEN, "Can not open file"},
+       {LD10K1_EF_ERR_STAT, "Can not stat file"},
+       {LD10K1_EF_ERR_SIZE, "Wrong file size"},
+       {LD10K1_EF_ERR_READ, "Can not read file"},
+       {LD10K1_EF_ERR_SIGNATURE, "Wrong file signature"},
+       {LD10K1_EF_ERR_FORMAT, "Wrong file format"},
+
+       {LD10K1_EF_ERR_TRANSFORM_CTL, "Can not transform control"},
+       {LD10K1_EF_ERR_TRANSFORM, "Can not transform effect"},
+       {LD10K1_EF_ERR_TRANSFORM_TRANS, "Wrong control translation"},
+       
+       /* errors from liblo10k1lf */
+       {LD10K1_LF_ERR_OPEN, "Can not open file"},
+       {LD10K1_LF_ERR_WRITE, "Can not write file"},
+       {LD10K1_LF_ERR_READ, "Can not read file"},
+       {LD10K1_LF_ERR_SIGNATURE, "Wrong file signature"},
+       {LD10K1_LF_ERR_PART_TYPE, "Wrong part type"},
+       {LD10K1_LF_ERR_PART_SIZE, "Wrong part size"},
+       {LD10K1_LF_ERR_VERSION, "Wrong file version"},
+       {LD10K1_LF_ERR_FILE_TYPE, "Wrong file type"},
+
+       {0, ""}
+};
+
+char *liblo10k1_error_str(int error)
+{
+       int i;
+
+       for (i = 0; error_text[i].errnum != 0; i++)
+               if (error_text[i].errnum == error)
+                       return error_text[i].errmsg;
+       return "Error msg not specified in liblo10k1";
+}
diff --git a/ld10k1/src/liblo10k1ef.c b/ld10k1/src/liblo10k1ef.c
new file mode 100644 (file)
index 0000000..0a3cfdb
--- /dev/null
@@ -0,0 +1,1099 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "ld10k1_error.h"
+#include "ld10k1_fnc.h"
+#include "comm.h"
+#include "liblo10k1.h"
+#include "liblo10k1ef.h"
+
+liblo10k1_emu_patch_t *liblo10k1_emu_new_patch()
+{
+       liblo10k1_emu_patch_t *tmp = (liblo10k1_emu_patch_t *)malloc(sizeof(liblo10k1_emu_patch_t));
+       
+       if (!tmp)
+               return NULL;
+       memset(tmp, 0, sizeof(liblo10k1_emu_patch_t));
+       
+       return tmp;
+}
+
+void liblo10k1_emu_free_patch(liblo10k1_emu_patch_t *p)
+{
+       liblo10k1_emu_patch_set_in_count(p, 0);
+       liblo10k1_emu_patch_set_out_count(p, 0);
+       liblo10k1_emu_patch_set_dyn_count(p, 0);
+       liblo10k1_emu_patch_set_sta_count(p, 0);
+       liblo10k1_emu_patch_set_ctl_count(p, 0);
+       liblo10k1_emu_patch_set_con_count(p, 0);
+       liblo10k1_emu_patch_set_lookup_count(p, 0);
+       liblo10k1_emu_patch_set_delay_count(p, 0);
+       liblo10k1_emu_patch_set_instr_count(p, 0);
+       
+       free(p);
+}
+
+int liblo10k1_emu_patch_set_in_count(liblo10k1_emu_patch_t *p, int count)
+{
+       unsigned int *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (unsigned int *)malloc(sizeof(unsigned int)*count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(unsigned int) * count);
+       }
+       
+       p->in_count = count;
+       if (p->ins)
+               free(p->ins);
+       p->ins = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_out_count(liblo10k1_emu_patch_t *p, int count)
+{
+       unsigned int *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (unsigned int *)malloc(sizeof(unsigned int)*count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(unsigned int) * count);
+       }
+       
+       p->out_count = count;
+       if (p->outs)
+               free(p->outs);
+       p->outs = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_dyn_count(liblo10k1_emu_patch_t *p, int count)
+{
+       unsigned int *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (unsigned int *)malloc(sizeof(unsigned int)*count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(unsigned int) * count);
+       }
+       
+       p->dyn_count = count;
+       if (p->dyns)
+               free(p->dyns);
+       p->dyns = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_sta_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_sc_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_sc_t *)malloc(sizeof(liblo10k1_emu_sc_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_sc_t)*count);
+       }
+       
+       p->sta_count = count;
+       if (p->stas)
+               free(p->stas);
+       p->stas = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_ctl_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_ctl_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_ctl_t *)malloc(sizeof(liblo10k1_emu_ctl_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_ctl_t)*count);
+       }
+       
+       p->ctl_count = count;
+       if (p->ctls)
+               free(p->ctls);
+       p->ctls = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_con_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_sc_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_sc_t *)malloc(sizeof(liblo10k1_emu_sc_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_sc_t)*count);
+       }
+       
+       p->con_count = count;
+       if (p->cons)
+               free(p->cons);
+       p->cons = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_line_count(liblo10k1_emu_tram_t *t, int write, int count)
+{
+       liblo10k1_emu_tram_line_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_tram_line_t *)malloc(sizeof(liblo10k1_emu_tram_line_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_tram_line_t)*count);
+       }
+       
+       if (write) {
+               t->write_line_count = count;
+               if (t->write_lines)
+                       free(t->write_lines);
+               t->write_lines = tmp;
+       } else {
+               t->read_line_count = count;
+               if (t->read_lines)
+                       free(t->read_lines);
+               t->read_lines = tmp;
+       }
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_lookup_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_tram_t *tmp = NULL;
+       int i;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_tram_t *)malloc(sizeof(liblo10k1_emu_tram_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_tram_t)*count);
+       }
+       
+       if (p->tram_lookups) {
+               for (i = 0; i < p->tram_lookup_count; i++) {
+                       liblo10k1_emu_patch_set_line_count(&(p->tram_lookups[i]), 0, 0);
+                       liblo10k1_emu_patch_set_line_count(&(p->tram_lookups[i]), 1, 0);
+               }
+               free(p->tram_lookups);
+       }
+       p->tram_lookup_count = count;
+       p->tram_lookups = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_delay_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_tram_t *tmp = NULL;
+       int i;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_tram_t *)malloc(sizeof(liblo10k1_emu_tram_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_tram_t)*count);
+       }
+       
+       if (p->tram_delays) {
+               for (i = 0; i < p->tram_delay_count; i++) {
+                       liblo10k1_emu_patch_set_line_count(&(p->tram_delays[i]), 0, 0);
+                       liblo10k1_emu_patch_set_line_count(&(p->tram_delays[i]), 1, 0);
+               }
+               free(p->tram_delays);
+       }
+       p->tram_delay_count = count;
+       p->tram_delays = tmp;
+       return 0;
+}
+
+int liblo10k1_emu_patch_set_instr_count(liblo10k1_emu_patch_t *p, int count)
+{
+       liblo10k1_emu_instr_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_emu_instr_t *)malloc(sizeof(liblo10k1_emu_instr_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               memset(tmp, 0, sizeof(liblo10k1_emu_instr_t)*count);
+       }
+       
+       p->instr_count = count;
+       if (p->instrs)
+               free(p->instrs);
+       p->instrs = tmp;
+       return 0;
+}
+
+static int read_byte(char *patch_data, int size, int *pos, unsigned char *out)
+{
+       if (*pos < size) {
+               *out = patch_data[*pos];
+               (*pos)++;
+               return 0;
+       } else
+               return LD10K1_EF_ERR_FORMAT;
+}
+
+static int read_ushort(char *patch_data, int size, int *pos, unsigned short *out)
+{
+       if (*pos + 1 < size) {
+               *out = *((unsigned short *)(patch_data + *pos));
+               *(pos) += 2;
+               return 0;
+       } else
+               return LD10K1_EF_ERR_FORMAT;
+}
+
+static int read_uint(char *patch_data, int size, int *pos, unsigned int *out)
+{
+       if (*pos + 3 < size) {
+               *out = *((unsigned int *)(patch_data + *pos));
+               (*pos) += 4;
+               return 0;
+       } else
+               return LD10K1_EF_ERR_FORMAT;
+}
+
+static int read_string(char *patch_data, int size, int *pos, char *out, int ssize)
+{
+       if (*pos + ssize - 1 < size) {
+               strncpy(out, &(patch_data[*pos]), ssize - 1);
+               out[ssize - 1] = '\0';
+               (*pos) += ssize;
+               return 0;
+       } else
+               return LD10K1_EF_ERR_FORMAT;
+}
+
+int liblo10k1_emu_load_patch(char *file_name, liblo10k1_emu_patch_t **p)
+{
+       struct stat patch_stat;
+       char *patch_data;
+       FILE *patch_file;
+       liblo10k1_emu_patch_t *new_patch = NULL;
+       unsigned int i, j, z, k;
+       int en = 0;
+
+       int file_pos = 0;
+       int file_size = 0;
+       
+       unsigned char byte_tmp;
+       unsigned short ushort_tmp;
+       
+       liblo10k1_emu_tram_t *tmp_tram;
+       liblo10k1_emu_tram_line_t *tmp_tram_lines;
+       
+       unsigned int part1, part2;
+
+       if (!(patch_file = fopen(file_name, "r")))
+               return LD10K1_EF_ERR_OPEN;
+
+       /* first load patch to mem */
+       if (stat(file_name, &patch_stat))
+               return LD10K1_EF_ERR_STAT;
+
+       /* minimal patch len is 57 */
+       if (patch_stat.st_size < 57 || patch_stat.st_size > 1000000)
+               return LD10K1_EF_ERR_SIZE;
+
+       file_size = patch_stat.st_size;
+
+       patch_data = (char *)malloc(patch_stat.st_size);
+       if (!patch_data)
+               return LD10K1_ERR_NO_MEM;
+
+       if (fread(patch_data, patch_stat.st_size, 1, patch_file) != 1) {
+               fclose(patch_file);
+               en = LD10K1_EF_ERR_READ;
+               goto err;
+       } else
+               fclose(patch_file);
+
+       /* signature check */
+       if (strncmp(patch_data, "EMU10K1 FX8010 1", 16) != 0) {
+               en = LD10K1_EF_ERR_SIGNATURE;
+               goto err;
+       }
+       
+       new_patch = liblo10k1_emu_new_patch();
+       if (!new_patch) {
+               en = LD10K1_ERR_NO_MEM;
+               goto err;
+       }
+       
+       /* next patch name */
+       strncpy(new_patch->patch_name, &(patch_data[16]), 31);
+       new_patch->patch_name[31] = '\0';
+
+       /* registers */
+       file_pos = 32+16;
+       
+       /* in count */
+       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+               goto err;
+       
+       if (byte_tmp >= 32) {
+               en = LD10K1_EF_ERR_FORMAT;
+               goto err;
+       }
+       
+       if ((en = liblo10k1_emu_patch_set_in_count(new_patch, byte_tmp)) < 0 ||
+               (en = liblo10k1_emu_patch_set_out_count(new_patch, byte_tmp)) < 0)
+               goto err;
+       
+       /* read in gprs */
+       for (i = 0; i < new_patch->in_count; i++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->ins[i] = byte_tmp;
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->outs[i] = byte_tmp;
+       }
+       
+       /* read dyn gprs */
+       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+               goto err;
+               
+       if ((en = liblo10k1_emu_patch_set_dyn_count(new_patch, byte_tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < new_patch->dyn_count; i++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->dyns[i] = byte_tmp;
+       }
+       
+       /* read sta gprs */
+       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+               goto err;
+               
+       if ((en = liblo10k1_emu_patch_set_sta_count(new_patch, byte_tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < new_patch->sta_count; i++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->stas[i].sc = byte_tmp;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->stas[i].sc_val))) < 0)
+                       goto err;
+       }
+       
+       /* read ctl gprs */
+       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+               goto err;
+               
+       if ((en = liblo10k1_emu_patch_set_ctl_count(new_patch, byte_tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < new_patch->ctl_count; i++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->ctls[i].ctl = byte_tmp;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val))) < 0)
+                       goto err;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val_min))) < 0)
+                       goto err;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val_max))) < 0)
+                       goto err;
+               if ((en = read_string(patch_data, file_size, &file_pos, new_patch->ctls[i].ctl_name, 32)) < 0)
+                       goto err;
+       }
+       
+       /* read const gprs */
+       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+               goto err;
+               
+       if ((en = liblo10k1_emu_patch_set_con_count(new_patch, byte_tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < new_patch->con_count; i++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+               new_patch->cons[i].sc = byte_tmp;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->cons[i].sc_val))) < 0)
+                       goto err;
+       }
+       
+       /* read tram lookup gprs */
+       for (z = 0; z < 2; z++) {
+               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                       goto err;
+       
+               if (z) {
+                       if ((en = liblo10k1_emu_patch_set_delay_count(new_patch, byte_tmp)) < 0)
+                               goto err;
+               } else {                
+                       if ((en = liblo10k1_emu_patch_set_lookup_count(new_patch, byte_tmp)) < 0)
+                               goto err;
+               }
+       
+               for (i = 0; i < (z ? new_patch->tram_delay_count : new_patch->tram_lookup_count); i++) {
+                       /* size */
+                       if (z) {
+                               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->tram_delays[i].size))) < 0)
+                                       goto err;
+                               tmp_tram = new_patch->tram_delays + i;
+                       } else {
+                               if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->tram_lookups[i].size))) < 0)
+                                       goto err;
+                               tmp_tram = new_patch->tram_lookups + i;
+                       }
+                       
+                       for (k = 0; k < 2; k++) {
+                               /* read lines */
+                               if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                                       goto err;
+                               
+                               if ((en = liblo10k1_emu_patch_set_line_count(tmp_tram, k, byte_tmp)) < 0)
+                                       goto err;
+                               
+                               if (k)
+                                       tmp_tram_lines = tmp_tram->write_lines;
+                               else
+                                       tmp_tram_lines = tmp_tram->read_lines;
+                               
+                               for (j = 0; j < (k ? tmp_tram->write_line_count : tmp_tram->read_line_count); j++) {
+                                       if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0)
+                                               goto err;
+                                               
+                                       tmp_tram_lines[j].line = byte_tmp;
+                               
+                                       if ((en = read_uint(patch_data, file_size, &file_pos, &(tmp_tram_lines[j].line_size))) < 0)
+                                               goto err;
+                               }
+                       }
+               }
+       }
+       
+       /* instruction lines */
+       if ((en = read_ushort(patch_data, file_size, &file_pos, &ushort_tmp)) < 0)
+               goto err;
+               
+       if ((en = liblo10k1_emu_patch_set_instr_count(new_patch, ushort_tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < new_patch->instr_count; i++) {
+               if ((en = read_uint(patch_data, file_size, &file_pos, &part1)) < 0)
+                       goto err;
+               if ((en = read_uint(patch_data, file_size, &file_pos, &part2)) < 0)
+                       goto err;
+                       
+               /* fill instr */
+               new_patch->instrs[i].arg[2] = part1 >> 10;
+               new_patch->instrs[i].arg[3] = part1 & 0x3FF;
+               new_patch->instrs[i].op = part2 >> 20;
+               new_patch->instrs[i].arg[0] = (part2 >> 10) & 0x3FF;
+               new_patch->instrs[i].arg[1] = part2 & 0x3FF;
+       }
+       
+       *p = new_patch;
+       
+       if (patch_data)
+               free(patch_data);
+       return 0;
+err:
+       if (patch_data)
+               free(patch_data);
+       if (new_patch)
+               liblo10k1_emu_free_patch(new_patch);
+       return en;
+}
+
+typedef struct
+{
+       unsigned int gpr;
+       unsigned int ld_gpr;
+} used_gpr_t;
+
+
+static int check_if_used(used_gpr_t *gprs, int count, unsigned int gpr)
+{
+       int i;
+       for (i = 0; i < count; i++) {
+               if (gprs[i].gpr == gpr)
+                       return i;
+       }
+       return -1;
+}
+
+static char *default_in_names[] =
+{
+       "IL",
+       "IR",
+       "IRL",
+       "IRR",
+       "IC",
+       "ILFE"
+};
+
+static char *default_out_names[] =
+{
+       "OL",
+       "OR",
+       "ORL",
+       "ORR",
+       "OC",
+       "OLFE"
+};
+
+int liblo10k1_patch_find_ctl_by_name(liblo10k1_dsp_patch_t *p, char *ctl_name)
+{
+       int i;
+       for (i = 0; i < p->ctl_count; i++)
+               if (strcmp(p->ctl[i].name, ctl_name) == 0)
+                       return i;
+       return -1;
+}
+
+int liblo10k1_patch_ctl_set_trans(liblo10k1_dsp_patch_t *p, int idx, int trans) 
+{
+       int i;
+       switch (trans) {
+               case EMU10K1_GPR_TRANSLATION_NONE:
+                       break;
+               case EMU10K1_GPR_TRANSLATION_TABLE100:
+                       if (p->ctl[idx].min != 0 && p->ctl[idx].max != 100)
+                               return LD10K1_EF_ERR_TRANSFORM_TRANS;
+                       break;
+               case EMU10K1_GPR_TRANSLATION_BASS:
+               case EMU10K1_GPR_TRANSLATION_TREBLE:
+                       if (p->ctl[idx].min != 0 && p->ctl[idx].max != 0xFFFFFFFF)
+                               return LD10K1_EF_ERR_TRANSFORM_TRANS;
+                       if (p->ctl[idx].count != 5)
+                               return LD10K1_EF_ERR_TRANSFORM_TRANS;
+                       break;
+               case EMU10K1_GPR_TRANSLATION_ONOFF:
+                       if (p->ctl[idx].min != 0 && p->ctl[idx].max != 1)
+                               return LD10K1_EF_ERR_TRANSFORM_TRANS;
+                       break;
+       }
+       for (i = 0; i < p->ctl[idx].count; i++)
+               if (p->ctl[idx].value[i] < p->ctl[idx].min || p->ctl[idx].value[i] > p->ctl[idx].max)
+                       return LD10K1_EF_ERR_TRANSFORM_TRANS;
+       p->ctl[idx].translation = trans;
+       return 0;
+}
+
+int liblo10k1_patch_ctl_set_vcount(liblo10k1_dsp_patch_t *p, int idx, int vc) 
+{
+       if (p->ctl[idx].count < vc)
+               return LD10K1_EF_ERR_TRANSFORM_CTL;
+       p->ctl[idx].vcount = vc;
+       return 0;
+}
+
+int liblo10k1_patch_ctl_set_index(liblo10k1_dsp_patch_t *p, int idx, int i) 
+{
+       p->ctl[idx].index = i;
+       return 0;
+}
+
+int liblo10k1_patch_ctl_set_value(liblo10k1_dsp_patch_t *p, int idx, int vi, int val) 
+{
+       if (p->ctl[idx].count < vi)
+               return LD10K1_EF_ERR_TRANSFORM_CTL;
+       if (val < p->ctl[idx].min || val > p->ctl[idx].max)
+                       return LD10K1_EF_ERR_TRANSFORM_CTL;
+       p->ctl[idx].value[vi] = val;
+       return 0;
+}
+
+int liblo10k1_emu_transform_patch(liblo10k1_emu_patch_t *ep,  liblo10k1_ctl_transform_t *tctl, int tctl_count, liblo10k1_dsp_patch_t **lp)
+{
+       used_gpr_t used_gpr[0x400];
+       int used_gpr_count = 0;
+       int i, j, k;
+       int gpr;
+       int tmp_cnt;
+       int idx;
+       int en = 0;
+       int io_name_map[6];
+       int transformed;
+       liblo10k1_dsp_ctl_t *tmp_nctl;
+       liblo10k1_emu_ctl_t *tmp_octl;
+       int const_count, hw_count;      /*int ctl_transform_map[256];*/
+       liblo10k1_dsp_patch_t *np = NULL;
+       liblo10k1_emu_tram_t *tram_tmp;
+       liblo10k1_dsp_tram_acc_t *tram_nacc;
+       liblo10k1_emu_tram_line_t *tram_line;
+       int val, addhw, addconst;
+       
+       /* for all instruction get used gpr list */
+       for (i = 0; i < ep->instr_count; i++) {
+               for (j = 0; j < 4; j++) {
+                       gpr = ep->instrs[i].arg[j];
+                       for (k = 0; k < used_gpr_count; k++)
+                               if (gpr == used_gpr[k].gpr)
+                                       break;
+                                       
+                       if (k < used_gpr_count)
+                               continue;
+                       
+                       used_gpr[used_gpr_count].gpr = gpr;
+                       used_gpr[used_gpr_count].ld_gpr = 0;
+                       used_gpr_count++;
+               }
+       }
+       
+       np = liblo10k1_patch_alloc(0, 0, 0, 0, 0, 0, 0, 0, 0, ep->instr_count);
+       if (!np)
+               return LD10K1_ERR_NO_MEM;
+               
+       /* set patch name */
+       strcpy(np->patch_name, ep->patch_name);
+       
+       /* in gprs */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->in_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->ins[i] + 0x100);
+               if (idx >= 0) {
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_IN(tmp_cnt);
+                       if (i < 6)
+                               io_name_map[i] = tmp_cnt;
+                       tmp_cnt++;
+               } else {
+                       if (i < 6)
+                               io_name_map[i] = -1;
+               }
+       }
+               
+       if ((en = liblo10k1_patch_set_in_count(np, tmp_cnt)) < 0)
+               goto err;
+       
+       /* set in name */
+       if (ep->in_count == 2 || /* stereo */
+               ep->in_count == 4 || /* 4 channel */
+               ep->in_count == 6) { /* 5.1 */
+               for (i = 0; i < ep->in_count; i++) {
+                       if (io_name_map[i] >= 0)
+                               strcpy(np->ins[io_name_map[i]].name, default_in_names[i]);
+               }
+       }
+               
+       /* out gprs */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->out_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->outs[i] + 0x100);
+               if (idx >= 0) {
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_OUT(tmp_cnt);
+                       if (i < 6)
+                               io_name_map[i] = tmp_cnt;
+                       tmp_cnt++;
+               } else {
+                       if (i < 6)
+                               io_name_map[i] = -1;
+               }
+       }
+               
+       if ((en = liblo10k1_patch_set_out_count(np, tmp_cnt)) < 0)
+               goto err;
+       
+       /* set out name */
+       if (ep->out_count == 2 || /* stereo */
+               ep->out_count == 4 || /* 4 channel */
+               ep->out_count == 6) { /* 5.1 */
+               for (i = 0; i < ep->out_count; i++) {
+                       if (io_name_map[i] >= 0)
+                               strcpy(np->outs[io_name_map[i]].name, default_out_names[i]);
+               }
+       }
+       
+       /* dyn regs */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->dyn_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->dyns[i] + 0x100);
+               if (idx >= 0) {
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_DYN(tmp_cnt);
+                       tmp_cnt++;
+               }
+       }
+       
+       if ((en = liblo10k1_patch_set_dyn_count(np, tmp_cnt)) < 0)
+               goto err;
+       
+       /* sta regs */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->sta_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->stas[i].sc + 0x100);
+               if (idx >= 0) {
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_STA(tmp_cnt);
+                       tmp_cnt++;
+               }
+       }
+       
+       if ((en = liblo10k1_patch_set_sta_count(np, tmp_cnt)) < 0)
+               goto err;
+               
+       /* sta regs - initilization */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->sta_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->stas[i].sc + 0x100);
+               if (idx >= 0) {
+                       np->stas[tmp_cnt].const_val = ep->stas[i].sc_val;
+                       tmp_cnt++;
+               }
+       }
+       
+       /* FIXME - ak je niektoty ctl pouzity v tctl viackrat tak to zblbne */
+       /* ctls regs */
+       /* first get count of ctls */
+       tmp_cnt = 0;
+       for (i = 0; i < tctl_count; i++)
+               tmp_cnt += tctl[i].emu_ctl_count;
+       
+       if ((en = liblo10k1_patch_set_ctl_count(np, ep->ctl_count - tmp_cnt + tctl_count)) < 0)
+               goto err;
+               
+       tmp_cnt = 0;
+       for (i = 0; i < ep->ctl_count; i++) {
+               tmp_octl = &(ep->ctls[i]);
+               /* find if transformed */
+               transformed = 0;
+               for (j = 0; j < tctl_count; j++) {
+                       for (k = 0; k < tctl[j].emu_ctl_count; k++) {
+                               if (i == tctl[j].emu_ctls[k]) {
+                                       /* it is transformed */
+                                       tmp_nctl = &(np->ctl[j]);
+                                       if (strcmp(tmp_nctl->name, "") != 0) {
+                                               /* initialized - check min, max */
+                                               if (tmp_octl->ctl_val_min != tmp_nctl->min ||
+                                                       tmp_octl->ctl_val_max != tmp_nctl->max) {
+                                                       en = LD10K1_EF_ERR_TRANSFORM_CTL;
+                                                       goto err;
+                                               }
+                                               
+                                               tmp_nctl->value[k] = tmp_octl->ctl_val;
+                                       } else {
+                                               /* initialize it */
+                                               strcpy(tmp_nctl->name, tctl[j].ctl_name);
+                                               tmp_nctl->index = -1;
+                                               tmp_nctl->vcount = tctl[j].emu_ctl_count;/*1;*/
+                                               tmp_nctl->count = tctl[j].emu_ctl_count;/*1;*/
+                                               tmp_nctl->value[k] = tmp_octl->ctl_val;
+                                               tmp_nctl->min = tmp_octl->ctl_val_min;
+                                               tmp_nctl->max = tmp_octl->ctl_val_max;
+                                               tmp_nctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
+                                       }
+                                       
+                                       idx = check_if_used(used_gpr, used_gpr_count, tmp_octl->ctl + 0x100);
+                                       if (idx >= 0)
+                                               used_gpr[idx].ld_gpr = EMU10K1_PREG_CTL(j, k);
+                                       
+                                       transformed = 1;
+                                       break;
+                               }
+                       }
+                       if (transformed)
+                               break;
+               }
+               
+               if (transformed)
+                       continue;
+               /* not transformed */
+               tmp_nctl = &(np->ctl[tmp_cnt + tctl_count]);
+               
+               strcpy(tmp_nctl->name, tmp_octl->ctl_name);
+               tmp_nctl->index = -1;
+               tmp_nctl->vcount = 1;
+               tmp_nctl->count = 1;
+               tmp_nctl->value[0] = tmp_octl->ctl_val;
+               tmp_nctl->min = tmp_octl->ctl_val_min;
+               tmp_nctl->max = tmp_octl->ctl_val_max;
+               tmp_nctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
+
+               idx = check_if_used(used_gpr, used_gpr_count, tmp_octl->ctl + 0x100);
+               if (idx >= 0)
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_CTL(tmp_cnt + tctl_count, 0);
+               
+               tmp_cnt++;
+               
+               if (tmp_cnt > np->ctl_count) {
+                       en = LD10K1_EF_ERR_TRANSFORM_CTL;
+                       goto err;
+               }
+       }
+       
+       if (tmp_cnt + tctl_count < np->ctl_count) {
+               en = LD10K1_EF_ERR_TRANSFORM_CTL;
+               goto err;
+       }
+       
+       /* tram */
+       if ((en = liblo10k1_patch_set_tram_count(np, ep->tram_lookup_count + ep->tram_delay_count)) < 0)
+               goto err;
+       
+       tmp_cnt = 0;
+       for (i = 0; i < ep->tram_lookup_count + ep->tram_delay_count; i++) {
+               if (i < ep->tram_lookup_count)
+                       tram_tmp = &(ep->tram_lookups[i]);
+               else
+                       tram_tmp = &(ep->tram_delays[i - ep->tram_lookup_count]);
+                       
+               tmp_cnt += tram_tmp->read_line_count + tram_tmp->write_line_count;
+               np->tram[i].grp_type = i < ep->tram_lookup_count ? TRAM_GRP_TABLE : TRAM_GRP_DELAY;
+               np->tram[i].grp_size = tram_tmp->size;
+               np->tram[i].grp_pos = TRAM_POS_AUTO;
+       }
+       
+       /* tram acc */
+       if ((en = liblo10k1_patch_set_tram_acc_count(np, tmp_cnt)) < 0)
+               goto err;
+               
+       tmp_cnt = 0;
+       for (i = 0; i < ep->tram_lookup_count + ep->tram_delay_count; i++) {
+               if (i < ep->tram_lookup_count)
+                       tram_tmp = &(ep->tram_lookups[i]);
+               else
+                       tram_tmp = &(ep->tram_delays[i - ep->tram_lookup_count]);
+                       
+               for (k = 0; k < 2; k++) {
+                       for (j = 0; j < (k ? tram_tmp->write_line_count : tram_tmp->read_line_count); j++) {
+                               if (k)
+                                       tram_line = &(tram_tmp->write_lines[j]);
+                               else
+                                       tram_line = &(tram_tmp->read_lines[j]);
+                                       
+                               tram_nacc = &(np->tram_acc[tmp_cnt]);
+                                       
+                               tram_nacc->grp = i;
+                               tram_nacc->acc_offset = tram_line->line_size;
+                               tram_nacc->acc_type = k ? TRAM_ACC_WRITE : TRAM_ACC_READ;
+                               
+                               idx = check_if_used(used_gpr, used_gpr_count, tram_line->line + 0x200);
+                               if (idx >= 0)
+                                       used_gpr[idx].ld_gpr = EMU10K1_PREG_TRAM_DATA(tmp_cnt);
+                               
+                               idx = check_if_used(used_gpr, used_gpr_count, tram_line->line + 0x300);
+                               if (idx >= 0)
+                                       used_gpr[idx].ld_gpr = EMU10K1_PREG_TRAM_ADDR(tmp_cnt);
+                       
+                               tmp_cnt++;
+                       }
+               }
+       }
+       
+       /* const and hw */
+       const_count = 0;
+       hw_count = 0;
+       
+       for (i = 0; i < used_gpr_count; i++) {
+               gpr = used_gpr[i].gpr;
+               
+               if (gpr < 0x40)
+                       hw_count++;
+               else if (gpr < 0x56)
+                       const_count++;
+               else if (gpr < 0x5C)
+                       hw_count++;
+       }
+       
+       /* const regs */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->con_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->cons[i].sc + 0x100);
+               if (idx >= 0) {
+                       used_gpr[idx].ld_gpr = EMU10K1_PREG_CONST(tmp_cnt);
+                       tmp_cnt++;
+               }
+       }
+       
+       /* consts */
+       if ((en = liblo10k1_patch_set_const_count(np, const_count + tmp_cnt)) < 0)
+               goto err;
+               
+       const_count = tmp_cnt;
+       
+       /* const regs - initilization */
+       tmp_cnt = 0;
+       for (i = 0; i < ep->con_count; i++) {
+               idx = check_if_used(used_gpr, used_gpr_count, ep->cons[i].sc + 0x100);
+               if (idx >= 0) {
+                       np->consts[tmp_cnt].const_val = ep->cons[i].sc_val;
+                       tmp_cnt++;
+               }
+       }
+       
+       /* hw */
+       if ((en = liblo10k1_patch_set_hw_count(np, hw_count)) < 0)
+               goto err;
+               
+       hw_count = 0;
+       for (i = 0; i < used_gpr_count; i++) {
+               gpr = used_gpr[i].gpr;
+               addconst = 0;
+               addhw = 0;              
+               
+               if (gpr < 0x40) {
+                       /* fx */
+                       addhw = 1;
+                       if (gpr < 0x10)
+                               val = EMU10K1_REG_FX(gpr);
+                       else if (gpr < 0x20)
+                               val = EMU10K1_REG_IN(gpr - 0x10);
+                       else
+                               val = EMU10K1_REG_OUT(gpr - 0x20);
+               } else {
+                       switch (gpr) {
+                               case 0x40:
+                                       addconst = 1; val = 0x00000000;
+                                       break;
+                               case 0x41:
+                                       addconst = 1; val = 0x00000001;
+                                       break;
+                               case 0x42:
+                                       addconst = 1; val = 0x00000002;
+                                       break;
+                               case 0x43:
+                                       addconst = 1; val = 0x00000003;
+                                       break;
+                               case 0x44:
+                                       addconst = 1; val = 0x00000004;
+                                       break;
+                               case 0x45:
+                                       addconst = 1; val = 0x00000008;
+                                       break;
+                               case 0x46:
+                                       addconst = 1; val = 0x00000010;
+                                       break;
+                               case 0x47:
+                                       addconst = 1; val = 0x00000020;
+                                       break;
+                               case 0x48:
+                                       addconst = 1; val = 0x00000100;
+                                       break;
+                               case 0x49:
+                                       addconst = 1; val = 0x00010000;
+                                       break;
+                               case 0x4A:
+                                       addconst = 1; val = 0x00080000;
+                                       break;
+                               case 0x4B:
+                                       addconst = 1; val = 0x10000000;
+                                       break;
+                               case 0x4C:
+                                       addconst = 1; val = 0x20000000;
+                                       break;
+                               case 0x4D:
+                                       addconst = 1; val = 0x40000000;
+                                       break;
+                               case 0x4E:
+                                       addconst = 1; val = 0x80000000;
+                                       break;
+                               case 0x4F:
+                                       addconst = 1; val = 0x7FFFFFFF;
+                                       break;
+                               case 0x50:
+                                       addconst = 1; val = 0xFFFFFFFF;
+                                       break;
+                               case 0x51:
+                                       addconst = 1; val = 0xFFFFFFFE;
+                                       break;
+                               case 0x52:
+                                       addconst = 1; val = 0xC0000000;
+                                       break;
+                               case 0x53:
+                                       addconst = 1; val = 0x4F1BBCDC;
+                                       break;
+                               case 0x54:
+                                       addconst = 1; val = 0x5A7EF9DB;
+                                       break;
+                               case 0x55:
+                                       addconst = 1; val = 0x00100000;
+                                       break;
+                               case 0x56:
+                                       addhw = 1; val = EMU10K1_NREG_HW_ACCUM;
+                                       break;
+                               case 0x57:
+                                       addhw = 1; val = EMU10K1_NREG_HW_CCR;
+                                       break;
+                               case 0x58:
+                                       addhw = 1; val = EMU10K1_NREG_HW_NOISE1;
+                                       break;
+                               case 0x59:
+                                       addhw = 1; val = EMU10K1_NREG_HW_NOISE2;
+                                       break;
+                               case 0x5A:
+                                       addhw = 1; val = EMU10K1_NREG_HW_IRQ;
+                                       break;
+                               case 0x5B:
+                                       addhw = 1; val = EMU10K1_NREG_HW_DBAC;
+                                       break;
+                               default:
+                                       if (gpr < 0x100) {
+                                               en = LD10K1_EF_ERR_TRANSFORM;
+                                               goto err;
+                                       }
+                                       break;
+                       }
+               }
+               
+               if (addhw) {
+                       np->hws[hw_count].hw_val = val;
+                       used_gpr[i].ld_gpr = EMU10K1_PREG_HW(hw_count);
+                       hw_count++;
+               } else if (addconst) {
+                       np->consts[const_count].const_val = val;
+                       used_gpr[i].ld_gpr = EMU10K1_PREG_CONST(const_count);
+                       const_count++;
+               }       
+       }       
+
+       /* instrs */
+       if ((en = liblo10k1_patch_set_instr_count(np, ep->instr_count)) < 0)
+               goto err;
+       
+       for (i = 0; i < ep->instr_count; i++) {
+               np->instr[i].op_code = ep->instrs[i].op;
+               for (j = 0; j < 4; j++) {
+                       gpr = ep->instrs[i].arg[j];
+                       
+                       idx = check_if_used(used_gpr, used_gpr_count, gpr);
+                       if (!used_gpr[idx].ld_gpr) {
+                               en = LD10K1_EF_ERR_TRANSFORM;
+                               goto err;
+                       }
+                               
+                       np->instr[i].arg[j] = used_gpr[idx].ld_gpr;
+               }
+       }
+       
+       *lp = np;
+       return 0;
+err:
+       if (np)
+               liblo10k1_patch_free(np);
+       return en;
+}
+
diff --git a/ld10k1/src/liblo10k1lf.c b/ld10k1/src/liblo10k1lf.c
new file mode 100644 (file)
index 0000000..3cb1ffc
--- /dev/null
@@ -0,0 +1,1388 @@
+/*
+ *  EMU10k1 loader lib
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "version.h"
+#include "ld10k1.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_error.h"
+#include "comm.h"
+#include "liblo10k1.h"
+#include "liblo10k1lf.h"
+
+#define CREATER_MAJOR LD10K1_LIB_MAJOR
+#define CREATER_MINOR LD10K1_LIB_MINOR
+#define CREATER_SUBMINOR LD10K1_LIB_SUBMINOR
+
+#define FILE_MAJOR 0
+#define FILE_MINOR 1
+#define FILE_SUBMINOR 0
+
+#define READER_MAJOR 0
+#define READER_MINOR 1
+#define READER_SUBMINOR 7
+
+#define LD10K1_FILE_SIGNATURE "LD10K1 NATIVE EFFECT FILE      "
+
+int liblo10k1lf_save_dsp_setup(liblo10k1_file_dsp_setup_t *c, FILE *file);
+
+int liblo10k1lf_save_file_header(FILE *file, unsigned int ft);
+int liblo10k1lf_save_file_info(FILE *file, liblo10k1_file_info_t *fi);
+int liblo10k1lf_save_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, void *data);
+int liblo10k1lf_find_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part);
+int liblo10k1lf_find_part_il(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, int il, liblo10k1_file_part_t *part);
+
+int liblo10k1lf_save_dsp_config(liblo10k1_file_dsp_setup_t *c, char *file_name, liblo10k1_file_info_t *fi)
+{
+       FILE *file = NULL;
+       int err;
+       
+       file = fopen(file_name, "w");
+       if (!file)
+               return LD10K1_LF_ERR_OPEN;
+               
+       if ((err = liblo10k1lf_save_file_header(file, LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP)) < 0)
+               goto err;
+               
+       if ((err = liblo10k1lf_save_file_info(file, fi)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_save_dsp_setup(c, file)) < 0)
+               goto err;
+               
+       fclose(file);
+       return 0;
+err:
+       fclose(file);
+       return err;
+}
+
+int liblo10k1lf_save_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, void *data)
+{
+       liblo10k1_file_part_t part;
+       
+       memset(&part, 0, sizeof(part));
+       part.part_type = part_type;
+       part.part_id = part_id;
+       part.part_length = part_length;
+       
+       if (fwrite(&part, sizeof(liblo10k1_file_part_t), 1, file) != 1)
+               return LD10K1_LF_ERR_WRITE;
+               
+       if (part_length > 0)
+               if (fwrite(data, part_length, 1, file) != 1)
+                       return LD10K1_LF_ERR_WRITE;
+       return 0;
+}
+
+int liblo10k1lf_save_file_header(FILE *file, unsigned int ft)
+{
+       liblo10k1_file_header_t fhdr;
+       liblo10k1_file_part_info_t file_info;
+       int err;
+       
+       strcpy(fhdr.signature, LD10K1_FILE_SIGNATURE);
+       memset(fhdr.reserved, 0, sizeof(fhdr.reserved));
+       
+       if (fwrite(&fhdr, sizeof(liblo10k1_file_header_t), 1, file) != 1)
+               return LD10K1_LF_ERR_WRITE;
+       
+       memset(&file_info, 0, sizeof(file_info));
+       
+       file_info.file_type = ft;
+       
+       file_info.file_version_major = FILE_MAJOR;
+       file_info.file_version_minor = FILE_MINOR;
+       file_info.file_version_subminor = FILE_SUBMINOR; /* file version = 0.0.1 */
+       
+       file_info.minimal_reader_version_major = READER_MAJOR;
+       file_info.minimal_reader_version_minor = READER_MINOR;
+       file_info.minimal_reader_version_subminor = READER_SUBMINOR; /* minimal reader version = 0.1.7 */
+       
+       file_info.creater_version_major = CREATER_MAJOR;
+       file_info.creater_version_minor = CREATER_MINOR;
+       file_info.creater_version_subminor = CREATER_SUBMINOR; /* creater version = 0.1.7 */
+       
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_INFO, sizeof(file_info), &file_info)) < 0)
+               return err;
+       return 0;
+}
+
+int liblo10k1lf_save_string_info(FILE *file, int id, char *str)
+{
+       int str_len;
+       int err;
+       
+       if (str)
+               str_len = strlen(str) + 1;
+       else
+               str_len = 0;
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, id, str_len, str)) < 0)
+               return err;
+       return 0;
+}
+
+int liblo10k1lf_load_string_info(FILE *file, int id, char **str)
+{
+       char *tmp;
+       int err;
+       liblo10k1_file_part_t part;
+       
+       if ((err = liblo10k1lf_find_part_il(file, LD10K1_FP_TYPE_NORMAL, id, 0, 1, &part)) < 0)
+               return err;
+       
+       tmp = NULL;
+       if (part.part_length > 0) {
+               tmp = (char *)malloc(part.part_length);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+                       
+               if (fread(tmp, part.part_length, 1, file) != 1) {
+                       free(tmp);
+                       return LD10K1_LF_ERR_READ;
+               }
+       }
+       
+       if (*str)
+               free(*str);
+       *str = tmp;
+       return 0;
+}
+
+int liblo10k1lf_save_file_info(FILE *file, liblo10k1_file_info_t *fi)
+{
+       int err;
+       
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_NAME, fi->name)) < 0)
+               return err;
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_DESC, fi->desc)) < 0)
+               return err;
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_CREATER, fi->creater)) < 0)
+               return err;
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_AUTHOR, fi->author)) < 0)
+               return err;
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_COPYRIGHT, fi->copyright)) < 0)
+               return err;
+       if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_LICENCE, fi->license)) < 0)
+               return err;
+       return 0;
+}
+
+int liblo10k1lf_load_file_info(FILE *file, liblo10k1_file_info_t **fi)
+{
+       int err;
+       
+       liblo10k1_file_info_t *i = liblo10k1lf_file_info_alloc();
+       
+       if (!i)
+               return LD10K1_ERR_NO_MEM;
+       
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_NAME, &(i->name))) < 0)
+               goto err;
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_DESC, &(i->desc))) < 0)
+               goto err;
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_CREATER, &(i->creater))) < 0)
+               goto err;
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_AUTHOR, &(i->author))) < 0)
+               goto err;
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_COPYRIGHT, &(i->copyright))) < 0)
+               goto err;
+       if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_LICENCE, &(i->license))) < 0)
+               goto err;
+               
+       *fi = i;
+       return 0;
+err:
+       if (i)
+               liblo10k1lf_file_info_free(i);
+       return err;
+}
+
+int liblo10k1lf_save_io(liblo10k1_get_io_t *ios, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_get_io_t), &(ios[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1lf_save_pio(liblo10k1_dsp_pio_t *ios, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_dsp_pio_t), &(ios[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1lf_save_cs(liblo10k1_dsp_cs_t *css, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_dsp_cs_t), &(css[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_hw(liblo10k1_dsp_hw_t *hws, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_HW_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_HW, sizeof(liblo10k1_dsp_hw_t), &(hws[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_HW_LIST, 0, NULL)) < 0)
+               return err;
+
+       return 0;
+}
+
+int liblo10k1lf_save_tram(liblo10k1_dsp_tram_grp_t *trams, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_TRAM_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_TRAM, sizeof(liblo10k1_dsp_tram_grp_t), &(trams[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_TRAM_LIST, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_tram_acc(liblo10k1_dsp_tram_acc_t *tram_accs, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_TRAM_ACC_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_TRAM_ACC, sizeof(liblo10k1_dsp_tram_acc_t), &(tram_accs[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_TRAM_ACC_LIST, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_ctl(liblo10k1_dsp_ctl_t *ctls, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_CTL_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_CTL, sizeof(liblo10k1_dsp_ctl_t), &(ctls[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_CTL_LIST, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_instr(liblo10k1_dsp_instr_t *instrs, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_INSTR_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_INSTR, sizeof(liblo10k1_dsp_instr_t), &(instrs[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_INSTR_LIST, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_points(liblo10k1_point_info_t *points, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_POINT_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_POINT, sizeof(liblo10k1_point_info_t), &(points[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_POINT_LIST, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_patch(liblo10k1_dsp_patch_t *p, FILE *file)
+{
+       int err;
+       liblo10k1_file_patch_info_t pinfo;
+       
+       /* io list start */
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_PATCH, 0, NULL)) < 0)
+               return err;
+               
+       /* patch info */
+       strcpy(pinfo.patch_name, p->patch_name);
+       pinfo.in_count = p->in_count;
+       pinfo.out_count = p->out_count;
+       pinfo.const_count = p->const_count;
+       pinfo.sta_count = p->sta_count;
+       pinfo.dyn_count = p->dyn_count;
+       pinfo.hw_count = p->hw_count;
+       pinfo.tram_count = p->tram_count;
+       pinfo.tram_acc_count = p->tram_acc_count;
+       pinfo.ctl_count = p->ctl_count;
+       pinfo.instr_count = p->instr_count;
+
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_PATCH_INFO, sizeof(liblo10k1_file_patch_info_t), &pinfo)) < 0)
+                       return err;
+                       
+       /* pins */
+       if ((err = liblo10k1lf_save_pio(p->ins, p->in_count, LD10K1_FP_PIN_LIST, LD10K1_FP_PIO, file)) < 0)
+               return err;
+       /* pouts */
+       if ((err = liblo10k1lf_save_pio(p->outs, p->out_count, LD10K1_FP_POUT_LIST, LD10K1_FP_PIO, file)) < 0)
+               return err;
+       /* consts */
+       if ((err = liblo10k1lf_save_cs(p->consts, p->const_count, LD10K1_FP_CONST_LIST, LD10K1_FP_CS, file)) < 0)
+               return err;
+       /* stas */
+       if ((err = liblo10k1lf_save_cs(p->stas, p->sta_count, LD10K1_FP_STA_LIST, LD10K1_FP_CS, file)) < 0)
+               return err;
+       /* hws */
+       if ((err = liblo10k1lf_save_hw(p->hws, p->hw_count, file)) < 0)
+               return err;
+       /* trams */
+       if ((err = liblo10k1lf_save_tram(p->tram, p->tram_count, file)) < 0)
+               return err;
+       /* tram_accs */
+       if ((err = liblo10k1lf_save_tram_acc(p->tram_acc, p->tram_acc_count, file)) < 0)
+               return err;
+       /* ctls */
+       if ((err = liblo10k1lf_save_ctl(p->ctl, p->ctl_count, file)) < 0)
+               return err;
+       /* instrs */
+       if ((err = liblo10k1lf_save_instr(p->instr, p->instr_count, file)) < 0)
+               return err;
+               
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_PATCH, 0, NULL)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_save_dsp_setup(liblo10k1_file_dsp_setup_t *c, FILE *file)
+{
+       liblo10k1_file_part_dsp_setup_t setup;
+       int err;
+       int i;
+       
+       setup.dsp_type = c->dsp_type;
+       setup.fx_count = c->fx_count;
+       setup.in_count = c->in_count;
+       setup.out_count = c->out_count;
+       setup.patch_count = c->patch_count;
+       setup.point_count = c->point_count;
+       
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_DSP_SETUP, sizeof(setup), &setup)) < 0)
+               return err;
+               
+       /* save fx */
+       if ((err = liblo10k1lf_save_io(c->fxs, c->fx_count, LD10K1_FP_FX_LIST, LD10K1_FP_FX, file)) < 0)
+               return err;
+               
+       /* save in */
+       if ((err = liblo10k1lf_save_io(c->ins, c->in_count, LD10K1_FP_IN_LIST, LD10K1_FP_IN, file)) < 0)
+               return err;
+               
+       /* save out */
+       if ((err = liblo10k1lf_save_io(c->outs, c->out_count, LD10K1_FP_OUT_LIST, LD10K1_FP_OUT, file)) < 0)
+               return err;
+       
+       /* save patches */      
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_PATCH_LIST, 0, NULL)) < 0)
+               return err;
+               
+       for (i = 0; i < c->patch_count; i++) {
+               if ((err = liblo10k1lf_save_patch(c->patches[i], file)) < 0)
+                       return err;
+       }
+       
+       if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_PATCH_LIST, 0, NULL)) < 0)
+               return err;
+       
+       /* save points */
+       if ((err = liblo10k1lf_save_points(c->points, c->point_count, file)) < 0)
+               return err;
+               
+       return 0;
+}
+
+liblo10k1_file_dsp_setup_t *liblo10k1lf_dsp_config_alloc()
+{
+       liblo10k1_file_dsp_setup_t *tmp = (liblo10k1_file_dsp_setup_t *)malloc(sizeof(liblo10k1_file_dsp_setup_t));
+       
+       memset(tmp, 0, sizeof(liblo10k1_file_dsp_setup_t));
+       
+       return tmp;
+}
+
+void liblo10k1lf_dsp_config_free(liblo10k1_file_dsp_setup_t *c)
+{
+       int i;
+       
+       if (c->fxs)
+               free(c->fxs);
+       if (c->ins)
+               free(c->ins);
+       if (c->outs)
+               free(c->outs);
+       if (c->patches) {
+               for (i = 0; i < c->patch_count; i++) {
+                       if (c->patches[i])
+                               liblo10k1_patch_free(c->patches[i]);
+               }
+               free(c->patches);
+       }
+       if (c->points)
+               free(c->points);
+}
+
+int liblo10k1lf_dsp_config_set_fx_count(liblo10k1_file_dsp_setup_t *c, int count)
+{
+       liblo10k1_get_io_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+       }
+       
+       if (c->fxs)
+               free(c->fxs);
+               
+       c->fx_count = count;
+       c->fxs = tmp;
+       return 0;
+}      
+       
+int liblo10k1lf_dsp_config_set_in_count(liblo10k1_file_dsp_setup_t *c, int count)
+{      
+       liblo10k1_get_io_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+       }
+       
+       if (c->ins)
+               free(c->ins);
+               
+       c->in_count = count;
+       c->ins = tmp;
+       return 0;
+}
+       
+int liblo10k1lf_dsp_config_set_out_count(liblo10k1_file_dsp_setup_t *c, int count)
+{              
+       liblo10k1_get_io_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+       }
+       
+       if (c->outs)
+               free(c->outs);
+               
+       c->out_count = count;
+       c->outs = tmp;
+       return 0;
+}
+
+int liblo10k1lf_dsp_config_set_patch_count(liblo10k1_file_dsp_setup_t *c, int count)
+{              
+       int i;
+       /* alloc patches list */
+       liblo10k1_dsp_patch_t **tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_dsp_patch_t **)malloc(sizeof(liblo10k1_dsp_patch_t *) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+                       
+               memset(tmp, 0, sizeof(liblo10k1_dsp_patch_t *) * count);
+       }
+       
+       if (c->patches) {
+               for (i = 0; i < c->patch_count; i++) {
+                       if (c->patches[i])
+                               liblo10k1_patch_free(c->patches[i]);
+               }
+               free(c->patches);
+       }
+       
+       c->patch_count = count;
+       c->patches = tmp;
+       return 0;
+}
+       
+int liblo10k1lf_dsp_config_set_point_count(liblo10k1_file_dsp_setup_t *c, int count)
+{              
+       liblo10k1_point_info_t *tmp = NULL;
+       
+       if (count > 0) {
+               tmp = (liblo10k1_point_info_t *)malloc(sizeof(liblo10k1_point_info_t) * count);
+               if (!tmp)
+                       return LD10K1_ERR_NO_MEM;
+               
+               memset(tmp, 0, sizeof(liblo10k1_point_info_t) * count);
+       }
+       
+       if (c->points)
+               free(c->points);
+               
+       c->point_count = count;
+       c->points = tmp;
+       return 0;       
+}
+
+int liblo10k1lf_get_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t **setup)
+{
+       liblo10k1_dsp_info_t info;
+       int err;
+       int i, j, k;
+       
+       liblo10k1_file_dsp_setup_t *s;
+       liblo10k1_patches_info_t *plist;
+       int pcount;
+       int tmp;
+       
+       int *points;
+
+       plist = NULL;
+       points = NULL;
+       s = liblo10k1lf_dsp_config_alloc();
+       if (!s)
+               return LD10K1_ERR_NO_MEM;
+               
+       /* get dsp type */
+       if ((err = liblo10k1_get_dsp_info(conn, &info)) < 0)
+               return err;
+       
+       s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K1;
+       if (info.chip_type == CHIP_LIVE)
+               s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K1;
+       else if (info.chip_type == CHIP_AUDIGY)
+               s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K2;
+
+       /* now get everything what is needed */
+       if ((err = liblo10k1_get_fx_count(conn, &tmp)) < 0)
+               goto err;
+               
+       if ((err = liblo10k1lf_dsp_config_set_fx_count(s, tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < s->fx_count; i++) {
+               if ((err = liblo10k1_get_fx(conn, i, &(s->fxs[i]))) < 0)
+                       goto err;
+       }
+               
+       if ((err = liblo10k1_get_in_count(conn, &tmp)) < 0)
+               goto err;
+       
+       if ((err = liblo10k1lf_dsp_config_set_in_count(s, tmp)) < 0)
+               goto err;
+       
+       for (i = 0; i < s->in_count; i++) {
+               if ((err = liblo10k1_get_in(conn, i, &(s->ins[i]))) < 0)
+                       goto err;
+       }       
+               
+       if ((err = liblo10k1_get_out_count(conn, &tmp)) < 0)
+               goto err;
+               
+       if ((err = liblo10k1lf_dsp_config_set_out_count(s, tmp)) < 0)
+               goto err;
+
+       for (i = 0; i < s->out_count; i++) {
+               if ((err = liblo10k1_get_out(conn, i, &(s->outs[i]))) < 0)
+                       goto err;
+       }
+       
+       if ((err = liblo10k1_get_patches_info(conn, &plist, &pcount)) < 0)
+               goto err;
+               
+       /* alloc patches list */
+       if ((err = liblo10k1lf_dsp_config_set_patch_count(s, pcount)) < 0)
+               goto err;
+       
+       for (i = 0; i < s->patch_count; i++) {
+               if ((err = liblo10k1_patch_get(conn, plist[i].patch_num, &(s->patches[i]))) < 0)
+                       goto err;
+       }
+       
+       if ((err = liblo10k1_get_points_info(conn, &points, &pcount)) < 0)
+               goto err;
+
+       if ((err = liblo10k1lf_dsp_config_set_point_count(s, pcount)) < 0)
+               goto err;
+       
+       for (i = 0; i < s->point_count; i++) {
+               if ((err = liblo10k1_get_point_info(conn, points[i], &(s->points[i]))) < 0)
+                       goto err;
+               
+               /* id to patch index */
+               for (j = 0; j < s->points[i].conn_count;j++) {
+                       if (s->points[i].patch[j] >= 0) {
+                               for (k = 0; k < s->patch_count; k++) {
+                                       if (plist[k].id == s->points[i].patch[j]) {
+                                               s->points[i].patch[j] = k;
+                                               break;
+                                       }
+                               }
+
+                               if (s->points[i].patch[j] != k) {
+                                       err = LD10K1_ERR_UNKNOWN_PATCH_NUM;
+                                       goto err;
+                               }
+                       }
+               }
+       }
+
+       free(plist);
+       free(points);
+
+       *setup = s;
+       return 0;
+err:
+       if (plist)
+               free(plist);
+       if (points)
+               free(points);
+       
+       liblo10k1lf_dsp_config_free(s);
+       return err;
+}
+
+int liblo10k1lf_put_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t *setup)
+{
+       int err;
+       int i, j;
+       int loaded_id;
+       int loaded;
+       int *trans_nums;
+       
+       int tin_type, tout_type;
+       int tin, tout;
+       int tpin, tpout;
+       
+       int pnum;
+       
+       tin_type = 0;
+       tout_type = 0;
+       tin = 0;
+       tout = 0;
+       tpin = 0;
+       tpout = 0;
+       
+       /* first initialize dsp */
+       if ((err = liblo10k1_dsp_init(conn)) < 0)
+               return err;
+               
+       for (i = 0; i < setup->fx_count; i++) {
+               if ((err = liblo10k1_rename_fx(conn, i, setup->fxs[i].name)) < 0)
+                       return err;
+       }
+       
+       for (i = 0; i < setup->in_count; i++) {
+               if ((err = liblo10k1_rename_in(conn, i, setup->ins[i].name)) < 0)
+                       return err;
+       }
+       
+       for (i = 0; i < setup->out_count; i++) {
+               if ((err = liblo10k1_rename_out(conn, i, setup->outs[i].name)) < 0)
+                       return err;
+       }
+       
+       if (setup->patch_count <= 0)
+               return 0;
+       
+       trans_nums = (int *)malloc(sizeof(int) * setup->patch_count);
+       if (!trans_nums)
+               return LD10K1_ERR_NO_MEM;
+       
+       memset(trans_nums, 0, sizeof(int) * setup->patch_count);
+       
+       /* load all patches - remember ids */
+       for (i = 0; i < setup->patch_count; i++) {
+               if ((err = liblo10k1_patch_load(conn, setup->patches[i], -1, &loaded, &loaded_id)) < 0)
+                       goto err;
+               trans_nums[i] = loaded;
+       }
+       
+       /* connect all connections */
+       for (i = 0; i < setup->point_count; i++) {
+               if (setup->points[i].type == CON_IO_NORMAL) {
+                       /* find first pin */
+                       for (j = 0; j < setup->points[i].conn_count;j++)
+                               if (!setup->points[i].io_type[j]) {
+                                       tin_type = CON_IO_PIN;
+                                       tin = setup->points[i].io[j];
+                                       tpin = setup->points[i].patch[j];
+                                       if (tpin >= 0)
+                                               tpin = trans_nums[tpin];
+                                       break;
+                               }
+                               
+                       /* find first pout */
+                       for (j = 0; j < setup->points[i].conn_count;j++)
+                               if (setup->points[i].io_type[j]) {
+                                       tout_type = CON_IO_POUT;
+                                       tout = setup->points[i].io[j];
+                                       tpout = setup->points[i].patch[j];
+                                       if (tpout >= 0)
+                                               tpout = trans_nums[tpout];
+                                       break;
+                               }
+                                               
+                       for (j = 0; j < setup->points[i].conn_count; j++) {
+                               pnum = setup->points[i].patch[j];
+                               if (pnum >= 0)
+                                       pnum = trans_nums[pnum];
+                               if (!setup->points[i].io_type[j]) {
+                                       if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi,
+                                               setup->points[i].simple, CON_IO_PIN, pnum, setup->points[i].io[j],
+                                               tout_type, tpout, tout, NULL)) < 0)
+                                               goto err;
+                               } else {
+                                       if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi,
+                                               setup->points[i].simple, CON_IO_POUT, pnum, setup->points[i].io[j],
+                                               tin_type, tpin, tin, NULL)) < 0)
+                                               goto err;
+                               }
+                       }
+               } else {
+                       tin_type = tout_type = setup->points[i].type;
+                       tin = tout = setup->points[i].io_idx;
+                       tpin = tpout = -1;
+                       
+                       for (j = 0; j < setup->points[i].conn_count; j++) {
+                               pnum = setup->points[i].patch[j];
+                               if (pnum >= 0)
+                                       pnum = trans_nums[pnum];
+                               if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi,
+                                       setup->points[i].simple, setup->points[i].io_type[j] ? CON_IO_POUT : CON_IO_PIN, pnum, setup->points[i].io[j],
+                                       tin_type, tpin, tin, NULL)) < 0)
+                                       goto err;
+                       }
+               }
+       }
+       
+       return 0;
+err:
+       if (trans_nums)
+               free(trans_nums);
+       return err;
+}
+
+int liblo10k1lf_skip_part(FILE *file, liblo10k1_file_part_t *part)
+{
+       char tmp_char;
+       int i;
+       int err;
+       int found_end_part = 0;
+       
+       if (part->part_type == LD10K1_FP_TYPE_NORMAL) {
+               /* read all data */
+               for (i = 0; i < part->part_length; i++)
+                       if (fread(&tmp_char, 1, 1, file) != 1)
+                               return LD10K1_LF_ERR_READ;
+       } else if (part->part_type == LD10K1_FP_TYPE_END) {
+               return 0;
+       } else {        
+               while (!found_end_part) {
+                       /* read next part */
+                       if (fread(part, sizeof(liblo10k1_file_part_t), 1, file) != 1)
+                               return LD10K1_LF_ERR_READ;
+                               
+                       /* check type & id */
+                       if (part->part_type == LD10K1_FP_TYPE_END)
+                               found_end_part = 1;
+                       else {
+                               if ((err = liblo10k1lf_skip_part(file, part)) < 0)
+                                       return err;
+                       }
+               }
+       }
+       return 0;
+}
+
+int liblo10k1lf_find_part_il(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, int il, liblo10k1_file_part_t *part)
+{
+       int err;
+       while (1) {
+               if (fread(part, sizeof(liblo10k1_file_part_t), 1, file) != 1)
+                       return LD10K1_LF_ERR_READ;
+                       
+               /* check type & id */
+               if (part->part_type == part_type && part->part_id == part_id) {
+                       if (part->part_type == LD10K1_FP_TYPE_NORMAL) {
+                               if (il || part->part_length == part_length)
+                                       return 0;
+                               else
+                                       return LD10K1_LF_ERR_PART_SIZE;
+                       } else {
+                               if (part->part_length != 0)
+                                       return LD10K1_LF_ERR_PART_SIZE;
+                               else
+                                       return 0;
+                       }
+               } else {
+                       if ((err = liblo10k1lf_skip_part(file, part)) < 0)
+                               return err;
+               }
+       }
+}
+
+int liblo10k1lf_find_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part)
+{
+       return liblo10k1lf_find_part_il(file, part_type, part_id, part_length, 0, part);
+}
+
+int liblo10k1lf_find_part_ws(FILE *file, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part)
+{
+       return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_NORMAL, part_id, part_length, part);
+}
+
+int liblo10k1lf_find_part_start(FILE *file, unsigned int part_id)
+{
+       liblo10k1_file_part_t part;
+       return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_START, part_id, 0, &part);
+}
+
+int liblo10k1lf_find_part_end(FILE *file, unsigned int part_id)
+{
+       liblo10k1_file_part_t part;
+       return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_END, part_id, 0, &part);
+}
+
+int liblo10k1lf_find_load_part_ws(FILE *file, unsigned int part_id, unsigned int part_length, void *where)
+{
+       int err;
+       liblo10k1_file_part_t part;
+       
+       if ((err = liblo10k1lf_find_part_ws(file, part_id, part_length, &part)) < 0)
+               return err;
+               
+       if (fread(where, part_length, 1, file) != 1)
+               return LD10K1_LF_ERR_READ;
+               
+       return 0;
+}
+
+int liblo10k1lf_can_load_file(FILE *file, unsigned int ft)
+{
+       liblo10k1_file_header_t fhdr;
+       liblo10k1_file_part_info_t file_info;
+       int err;
+       
+       if (fread(&fhdr, sizeof(liblo10k1_file_header_t), 1, file) != 1)
+               return LD10K1_LF_ERR_READ;
+               
+       /* check signature */
+       if (strcmp(fhdr.signature, LD10K1_FILE_SIGNATURE) != 0)
+               return LD10K1_LF_ERR_SIGNATURE;
+       
+       /* now load file info part & check version */
+       if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_INFO, sizeof(file_info), &file_info)) < 0)
+               return err;
+               
+       if (file_info.minimal_reader_version_major > CREATER_MAJOR)
+               return LD10K1_LF_ERR_VERSION;
+               
+       if (file_info.minimal_reader_version_major == CREATER_MAJOR &&
+               file_info.minimal_reader_version_minor > CREATER_MINOR)
+               return LD10K1_LF_ERR_VERSION;
+               
+       if (file_info.minimal_reader_version_major == CREATER_MAJOR &&
+               file_info.minimal_reader_version_minor == CREATER_MINOR &&
+               file_info.minimal_reader_version_subminor > CREATER_SUBMINOR)
+               return LD10K1_LF_ERR_VERSION;
+       
+       /* check file type */
+       if (file_info.file_type != ft)
+               return LD10K1_LF_ERR_FILE_TYPE;
+       
+       return 0;
+}
+
+int liblo10k1lf_load_io(liblo10k1_get_io_t *ios, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, pt, sizeof(liblo10k1_get_io_t), &(ios[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_points(liblo10k1_point_info_t *points, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_POINT_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_POINT, sizeof(liblo10k1_point_info_t), &(points[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_POINT_LIST)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_pio(liblo10k1_dsp_pio_t *ios, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, pt, sizeof(liblo10k1_dsp_pio_t), &(ios[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1lf_load_cs(liblo10k1_dsp_cs_t *css, int count, int ptl, int pt, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file,  pt, sizeof(liblo10k1_dsp_cs_t), &(css[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0)
+               return err;
+       
+       return 0;
+}
+
+int liblo10k1lf_load_hw(liblo10k1_dsp_hw_t *hws, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_HW_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_HW, sizeof(liblo10k1_dsp_hw_t), &(hws[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_HW_LIST)) < 0)
+               return err;
+
+       return 0;
+}
+
+int liblo10k1lf_load_tram(liblo10k1_dsp_tram_grp_t *trams, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_TRAM_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_TRAM, sizeof(liblo10k1_dsp_tram_grp_t), &(trams[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_TRAM_LIST)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_tram_acc(liblo10k1_dsp_tram_acc_t *tram_accs, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_TRAM_ACC_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_TRAM_ACC, sizeof(liblo10k1_dsp_tram_acc_t), &(tram_accs[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_TRAM_ACC_LIST)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_ctl(liblo10k1_dsp_ctl_t *ctls, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_CTL_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_CTL, sizeof(liblo10k1_dsp_ctl_t), &(ctls[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_CTL_LIST)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_instr(liblo10k1_dsp_instr_t *instrs, int count, FILE *file)
+{
+       int i, err;
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_INSTR_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < count; i++) {
+               if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_INSTR, sizeof(liblo10k1_dsp_instr_t), &(instrs[i]))) < 0)
+                       return err;
+       }
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_INSTR_LIST)) < 0)
+               return err;
+               
+       return 0;
+}
+
+int liblo10k1lf_load_patch(liblo10k1_dsp_patch_t **p, FILE *file)
+{
+       int err;
+       liblo10k1_file_patch_info_t pinfo;
+       liblo10k1_dsp_patch_t *patch = NULL;
+       
+       /* io list start */
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_PATCH)) < 0)
+               return err;
+               
+       /* patch info */
+       if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_PATCH_INFO, sizeof(liblo10k1_file_patch_info_t), &pinfo)) < 0)
+               return err;
+       
+       patch = liblo10k1_patch_alloc(pinfo.in_count, pinfo.out_count, pinfo.const_count, pinfo.sta_count, pinfo.dyn_count, 
+               pinfo.hw_count, pinfo.tram_count, pinfo.tram_acc_count, pinfo.ctl_count, pinfo.instr_count);
+       if (!patch) {
+               err = LD10K1_ERR_NO_MEM;
+               goto err;
+       }
+       
+       strcpy(patch->patch_name, pinfo.patch_name);
+       
+       /* pins */
+       if ((err = liblo10k1lf_load_pio(patch->ins, patch->in_count, LD10K1_FP_PIN_LIST, LD10K1_FP_PIO, file)) < 0)
+               return err;
+       /* pouts */
+       if ((err = liblo10k1lf_load_pio(patch->outs, patch->out_count, LD10K1_FP_POUT_LIST, LD10K1_FP_PIO, file)) < 0)
+               return err;
+       /* consts */
+       if ((err = liblo10k1lf_load_cs(patch->consts, patch->const_count, LD10K1_FP_CONST_LIST, LD10K1_FP_CS, file)) < 0)
+               return err;
+       /* stas */
+       if ((err = liblo10k1lf_load_cs(patch->stas, patch->sta_count, LD10K1_FP_STA_LIST, LD10K1_FP_CS, file)) < 0)
+               return err;
+       /* hws */
+       if ((err = liblo10k1lf_load_hw(patch->hws, patch->hw_count, file)) < 0)
+               return err;
+       /* trams */
+       if ((err = liblo10k1lf_load_tram(patch->tram, patch->tram_count, file)) < 0)
+               return err;
+       /* tram_accs */
+       if ((err = liblo10k1lf_load_tram_acc(patch->tram_acc, patch->tram_acc_count, file)) < 0)
+               return err;
+       /* ctls */
+       if ((err = liblo10k1lf_load_ctl(patch->ctl, patch->ctl_count, file)) < 0)
+               return err;
+       /* instrs */
+       if ((err = liblo10k1lf_load_instr(patch->instr, patch->instr_count, file)) < 0)
+               return err;
+               
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_PATCH)) < 0)
+               return err;
+               
+       *p = patch;
+       return 0;
+err:
+       if (patch)
+               liblo10k1_patch_free(patch);
+       return err;     
+}
+
+int liblo10k1lf_load_dsp_setup(liblo10k1_file_dsp_setup_t **c, FILE *file)
+{
+       liblo10k1_file_part_dsp_setup_t setup;
+       int err;
+       int i;
+       
+       liblo10k1_file_dsp_setup_t *cfg;
+       
+       if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_DSP_SETUP, sizeof(setup), &setup)) < 0)
+               return err;
+       
+       cfg = liblo10k1lf_dsp_config_alloc();
+
+       cfg->dsp_type = setup.dsp_type;
+       
+       /* alloc space */
+       if ((err = liblo10k1lf_dsp_config_set_fx_count(cfg, setup.fx_count)) < 0)
+               goto err;
+       if ((err = liblo10k1lf_dsp_config_set_in_count(cfg, setup.in_count)) < 0)
+               goto err;
+       if ((err = liblo10k1lf_dsp_config_set_out_count(cfg, setup.out_count)) < 0)
+               goto err;
+       if ((err = liblo10k1lf_dsp_config_set_patch_count(cfg, setup.patch_count)) < 0)
+               goto err;
+       if ((err = liblo10k1lf_dsp_config_set_point_count(cfg, setup.point_count)) < 0)
+               goto err;
+                       
+       /* load fx */
+       if ((err = liblo10k1lf_load_io(cfg->fxs, cfg->fx_count, LD10K1_FP_FX_LIST, LD10K1_FP_FX, file)) < 0)
+               return err;
+               
+       /* load in */
+       if ((err = liblo10k1lf_load_io(cfg->ins, cfg->in_count, LD10K1_FP_IN_LIST, LD10K1_FP_IN, file)) < 0)
+               return err;
+               
+       /* load out */
+       if ((err = liblo10k1lf_load_io(cfg->outs, cfg->out_count, LD10K1_FP_OUT_LIST, LD10K1_FP_OUT, file)) < 0)
+               return err;
+       
+       /* load patches */      
+       if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_PATCH_LIST)) < 0)
+               return err;
+               
+       for (i = 0; i < cfg->patch_count; i++) {
+               if ((err = liblo10k1lf_load_patch(&(cfg->patches[i]), file)) < 0)
+                       return err;
+       }
+       
+       if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_PATCH_LIST)) < 0)
+               return err;
+       
+       
+       /* load points */
+       if ((err = liblo10k1lf_load_points(cfg->points, cfg->point_count, file)) < 0)
+               return err;
+       
+       *c = cfg;
+       return 0;
+err:
+       if (cfg)
+               liblo10k1lf_dsp_config_free(cfg);
+       return err;
+}
+
+int liblo10k1lf_load_dsp_config(liblo10k1_file_dsp_setup_t **c, char *file_name, liblo10k1_file_info_t **fi)
+{
+       FILE *file = NULL;
+       int err;
+       
+       liblo10k1_file_info_t *i = NULL;
+       
+       file = fopen(file_name, "r");
+       if (!file)
+               return LD10K1_LF_ERR_OPEN;
+               
+       if ((err = liblo10k1lf_can_load_file(file, LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_load_file_info(file, &i)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_load_dsp_setup(c, file)) < 0)
+               goto err;
+               
+       *fi = i;
+       fclose(file);
+       return 0;
+err:
+       if (i)
+               liblo10k1lf_file_info_free(i);
+       fclose(file);
+       return err;
+}
+
+liblo10k1_file_info_t *liblo10k1lf_file_info_alloc()
+{
+       liblo10k1_file_info_t *tmp = (liblo10k1_file_info_t *)malloc(sizeof(liblo10k1_file_info_t));
+       if (tmp)
+               memset(tmp, 0, sizeof(liblo10k1_file_info_t));
+       return tmp;
+}
+
+void liblo10k1lf_file_info_free(liblo10k1_file_info_t *fi)
+{
+       if (fi->name)
+               free(fi->name);
+       if (fi->desc)
+               free(fi->desc);
+       if (fi->creater)
+               free(fi->creater);
+       if (fi->author)
+               free(fi->author);
+       if (fi->copyright)
+               free(fi->copyright);
+       if (fi->license)
+               free(fi->license);
+}
+
+int liblo10k1lf_save_dsp_patch(liblo10k1_dsp_patch_t *p, char *file_name, liblo10k1_file_info_t *fi)
+{
+       FILE *file = NULL;
+       int err;
+       
+       file = fopen(file_name, "w");
+       if (!file)
+               return LD10K1_LF_ERR_OPEN;
+               
+       if ((err = liblo10k1lf_save_file_header(file, LD10K1_FP_INFO_FILE_TYPE_PATCH)) < 0)
+               goto err;
+               
+       if ((err = liblo10k1lf_save_file_info(file, fi)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_save_patch(p, file)) < 0)
+               goto err;
+               
+       fclose(file);
+       return 0;
+err:
+       fclose(file);
+       return err;
+}
+
+int liblo10k1lf_load_dsp_patch(liblo10k1_dsp_patch_t **p, char *file_name, liblo10k1_file_info_t **fi)
+{
+       FILE *file = NULL;
+       int err;
+       
+       liblo10k1_file_info_t *i = NULL;
+       
+       file = fopen(file_name, "r");
+       if (!file)
+               return LD10K1_LF_ERR_OPEN;
+               
+       if ((err = liblo10k1lf_can_load_file(file, LD10K1_FP_INFO_FILE_TYPE_PATCH)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_load_file_info(file, &i)) < 0)
+               goto err;
+               
+       if ((err =  liblo10k1lf_load_patch(p, file)) < 0)
+               goto err;
+               
+       *fi = i;
+       fclose(file);
+       return 0;
+err:
+       if (i)
+               liblo10k1lf_file_info_free(i);
+       fclose(file);
+       return err;
+}
diff --git a/ld10k1/src/lo10k1.c b/ld10k1/src/lo10k1.c
new file mode 100644 (file)
index 0000000..a52945d
--- /dev/null
@@ -0,0 +1,1737 @@
+/*
+ *  EMU10k1 loader
+ *
+ *  Copyright (c) 2003,2004 by Peter Zubaj
+ *
+ *   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 <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <alsa/asoundlib.h>
+#include "version.h"
+#include "comm.h"
+#include "ld10k1_fnc.h"
+#include "ld10k1_error.h"
+#include "ld10k1_debug.h"
+
+#include "liblo10k1.h"
+#include "liblo10k1ef.h"
+#include "liblo10k1lf.h"
+
+char comm_pipe[256];
+liblo10k1_connection_t conn;
+
+static void error(const char *fmt,...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       fprintf(stderr, "Error: ");
+       vfprintf(stderr, fmt, va);
+       fprintf(stderr, "\n");
+       va_end(va);
+}
+
+static void help(char *command)
+{
+       fprintf(stderr,
+               "Usage: %s [-options]\n"
+               "\nAvailable options:\n"
+               "  -h, --help           this help\n"
+               "  -p, --pipe_name      connect to this, default = /tmp/.ld10k1_port\n"
+               "  -l, --list           dump lkoaded patch\n"
+               "  -i, --info           print some info\n"
+               "  -s, --setup          setup DSP\n"
+               "  -a, --add            load patch\n"
+               "  -d, --del            unload patch\n"
+               "  -q, --conadd         connect 2 patches\n"
+               "  -w, --condel         delete connection\n"
+               "      --debug          print debug information\n"
+               "  -n, --defionames     define default in/out names for loaded patch\n"
+               "      --ctrl           modify control parameters for loaded patch\n"
+               "      --patch_name     load patch with this name\n"
+               "      --where          insert patch before\n"
+               "      --renam          rename patch, input, output, fx, patch input, patch output\n"
+               "      --dump           dump DSP setup to file, can by loaded by dl10k1\n"
+               "      --host           lo10k1 uses network socket instead of named socked (host,port)\n"
+               "  -P, --path           include path\n"
+               "      --store          store DSP setup\n"
+               "      --restore        restore DSP setup\n"
+               , command);
+}
+
+typedef struct tag_path_info {
+       char *path;
+       struct tag_path_info *next;
+} path_t;
+
+path_t *first_path;
+path_t *last_path;
+
+static void add_path(char *path)
+{
+       path_t *path_info = malloc(sizeof(path_t));
+
+       path_info->path = strdup(path);
+       path_info->next = NULL;
+
+       if (last_path)
+               last_path->next = path_info;
+
+       last_path = path_info;
+
+       if (!first_path)
+               first_path = path_info;
+}
+
+static void add_paths(char *paths)
+{
+       char *str = strdup(paths);
+       char *path = strtok(str, ":");
+       
+       while (path) {
+               add_path(path);
+
+               path = strtok(NULL, ":");
+       }
+
+       free (str);
+}
+
+static void free_all_paths()
+{
+       path_t *path_info = first_path;
+       path_t *path_info_n = NULL;
+
+       while (path_info) {
+               path_info_n = path_info->next;
+               free(path_info);
+               path_info = path_info_n;
+       }
+}
+
+static liblo10k1_emu_patch_t *try_patch(char *file_name)
+{
+       int en;
+       
+       liblo10k1_emu_patch_t *p = NULL;
+       if ((en = liblo10k1_emu_load_patch(file_name, &p)) < 0)
+               return NULL;
+
+       return p;
+}
+
+static liblo10k1_emu_patch_t *open_patch(char *file_name)
+{
+       liblo10k1_emu_patch_t *patch;
+       path_t *path_info = first_path;
+
+       patch = try_patch(file_name);
+       
+       if (patch)
+               return patch;
+
+       while (path_info) {
+               char path[256]; /* FIXME */
+
+               memset(path, 0, sizeof(path));
+               snprintf(path, sizeof(path)-1, "%s/%s", 
+                        path_info->path, file_name);
+               
+               patch = try_patch(path);
+
+               if (patch) {
+                       return patch;
+               }
+
+               snprintf(path, sizeof(path)-1, "%s/%s.emu10k1", 
+                        path_info->path, file_name);
+
+               patch = try_patch(path);
+
+               if (patch) {
+                       return patch;
+               }
+
+               path_info = path_info->next;
+       }
+
+       return NULL;
+}
+
+static int load_patch(char *file_name, liblo10k1_emu_patch_t **p)
+{
+       liblo10k1_emu_patch_t *patch;
+       
+       if (!(patch = open_patch(file_name))) {
+               error("unable to load patch %s", file_name);
+               return 1;
+       }
+       
+       *p = patch;
+       return 0;
+}
+
+static char get_str(char **str, char *out, int maxlen, char *sep, int isnum)
+{
+       char ch = **str;
+       char *tmpsep;
+       int len = 0;
+       int found = 0;
+       
+       *out = '\0';
+       
+       if (ch == '\0')
+               return ch;
+       
+       len = 0;
+       while (**str && len < maxlen) {
+               found = 0;
+               ch = **str;
+               for (tmpsep = sep; *tmpsep; tmpsep++) {
+                       if (ch == *tmpsep) {
+                               found = 1;
+                               break;
+                       }
+               }
+               
+               if (found)
+                       break;
+               if (isnum && !isdigit(ch))
+                       break;
+               
+               *out++ = *(*str)++;
+                       len++;
+       }
+       
+       *out = '\0';
+       return ch;
+}
+
+static int transfer_patch(int udin, char *ctrl_opt, liblo10k1_emu_patch_t *ep, liblo10k1_dsp_patch_t **p)
+{
+       int i, j, k;
+       
+       char ctrl_from_concate[16][32][MAX_NAME_LEN]; /* max 32 ctrl to 1 and max 16 of this*/
+       char ctrl_to_concate[16][MAX_NAME_LEN]; 
+       int ctrl_to_concate_count;
+       int ctrl_from_count[16];
+       
+       char ctrl_visible[16][MAX_NAME_LEN];
+       char ctrl_visible_max[16];
+       unsigned char ctrl_visible_count;
+
+       char ctrl_translate[16][MAX_NAME_LEN];
+       char ctrl_translate_type[16];
+       unsigned char ctrl_translate_count;
+       
+       char ctrl_index[16][MAX_NAME_LEN];
+       int ctrl_index_val[16];
+       unsigned char ctrl_index_count;
+
+       char ctrl_values[16][MAX_NAME_LEN];
+       int ctrl_values_val[16][32];
+       unsigned char ctrl_values_cnt[16];
+       unsigned char ctrl_values_count;
+
+       char *tmp_str;
+       char *tmp_num;
+       char tmp_num_str[20];
+       
+       char sep;
+
+       liblo10k1_ctl_transform_t *tctl;
+       int ctl_idx;
+       
+       liblo10k1_dsp_patch_t *np = NULL;
+       
+
+       ctrl_to_concate_count = 0;
+       ctrl_visible_count = 0;
+       ctrl_translate_count = 0;
+       ctrl_index_count = 0;
+       ctrl_values_count = 0;
+       for (i = 0; i < 16; i++) {
+               ctrl_from_count[i] = 0;
+               ctrl_to_concate[i][0] = '\0';
+               ctrl_visible[i][0] = '\0';
+               ctrl_visible_max[i] = 1;
+               ctrl_translate[i][0] = '\0';
+               ctrl_translate_type[i] = 1;
+               
+               ctrl_index[i][0] = '\0';
+               ctrl_index_val[i] = -1;
+
+               ctrl_values[i][0] = '\0';
+               ctrl_values_cnt[i] = 0;
+               for (j = 0; j < 32; j++) {
+                       ctrl_from_concate[i][j][0] = '\0';
+                       ctrl_values_val[i][j] = 0;
+               }
+       }
+
+       /* parse ctrl opt */
+
+       /* TODO - check for name boundary */
+       while (ctrl_opt && *ctrl_opt) {
+               switch (*ctrl_opt++) {
+                       case 'c':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (c) - waiting -");
+                                       return 1;
+                               }
+                               while (1) {
+                                       tmp_str = ctrl_from_concate[ctrl_to_concate_count][ctrl_from_count[ctrl_to_concate_count]];
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ",:", 0);
+                                       if (strlen(ctrl_from_concate[ctrl_to_concate_count][ctrl_from_count[ctrl_to_concate_count]]) == 0) {
+                                               error("wrong ctrl option format (c) - wrong source ctrl name");
+                                               return 1;
+                                       }
+                                       ctrl_from_count[ctrl_to_concate_count]++;
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       if (sep != ',') {
+                                               error("wrong ctrl option format (c) - wrong separator - waiting , %c", sep);
+                                               return 1;
+                                       }
+
+                                       ctrl_opt++;
+                               }
+
+                               tmp_str = ctrl_to_concate[ctrl_to_concate_count];
+                               /* next is new ctrl name */
+                               sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ",", 0);
+                               if (strlen(ctrl_to_concate[ctrl_to_concate_count]) == 0) {
+                                       error("wrong ctrl option format (c) - wrong target ctrl name");
+                                       return 1;
+                               }
+                               ctrl_to_concate_count++;
+                               break;
+                       case 'v':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (v) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = ctrl_visible[ctrl_visible_count];
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(ctrl_visible[ctrl_visible_count]) == 0) {
+                                               error("wrong ctrl option format (v) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+
+                               tmp_num = tmp_num_str;
+                               /* next is new ctrl name */
+                               sep = get_str(&ctrl_opt, tmp_num, 10, ",", 1);
+                               if (strlen(tmp_num_str) == 0) {
+                                       error("wrong ctrl option format (v) - wrong vcount count");
+                                       return 1;
+                               }
+                               ctrl_visible_max[ctrl_visible_count] = atoi(tmp_num_str);
+                               ctrl_visible_count++;
+                               break;
+                       case 't':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (t) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = ctrl_translate[ctrl_translate_count];
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(ctrl_translate[ctrl_translate_count]) == 0) {
+                                               error("wrong ctrl option format (t) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+
+                               tmp_num = tmp_num_str;
+                               /* next is new ctrl translate */
+                               sep = get_str(&ctrl_opt, tmp_num, 10, ",", 1);
+                               if (strlen(tmp_num_str) == 0) {
+                                       error("wrong ctrl option format (t) - wrong translation function num");
+                                       return 1;
+                               }
+                               ctrl_translate_type[ctrl_translate_count] = atoi(tmp_num_str);
+                               ctrl_translate_count++;
+                               break;
+                       case 'i':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (i) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = ctrl_index[ctrl_index_count];
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(ctrl_index[ctrl_index_count]) == 0) {
+                                               error("wrong ctrl option format (i) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+
+                               tmp_num = tmp_num_str;
+                               /* next is new ctrl index */
+                               sep = get_str(&ctrl_opt, tmp_num, 10, ",", 1);
+                               if (strlen(tmp_num_str) == 0) {
+                                       error("wrong ctrl option format (i) - wrong index num");
+                                       return 1;
+                               }
+                               ctrl_index_val[ctrl_index_count] = atoi(tmp_num_str);
+                               ctrl_index_count++;
+                               break;
+                       case 's':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (s) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = ctrl_values[ctrl_values_count];
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(ctrl_values[ctrl_values_count]) == 0) {
+                                               error("wrong ctrl option format (s) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+
+                               /* next is new ctrl name */
+                               do {
+                                       tmp_num = tmp_num_str;
+
+                                       sep = get_str(&ctrl_opt, tmp_num, 10, ",#", 1);
+                                       if (strlen(tmp_num_str) == 0) {
+                                               error("wrong ctrl option format (s) - wrong value");
+                                               return 1;
+                                       }
+                                       ctrl_values_val[ctrl_values_count][ctrl_values_cnt[ctrl_values_count]] = atoi(tmp_num_str);
+                                       ctrl_values_cnt[ctrl_values_count]++;
+                                       if (sep != '#')
+                                               break;
+                                       ctrl_opt++;
+                               } while (1);
+                               ctrl_values_count++;
+                               break;
+                       default:
+                               error("wrong ctrl option format - unknown subfunction");
+                               return 1;
+               }
+               if (*ctrl_opt) {
+                       if (*ctrl_opt != ',') {
+                               error("wrong ctrl option format - wrong separator beetwen subfunctions");
+                               return 1;
+                       } else
+                               *ctrl_opt++;
+               }
+       }
+       
+       tctl = (liblo10k1_ctl_transform_t *)malloc(sizeof(liblo10k1_ctl_transform_t) * ctrl_to_concate_count);
+       memset(tctl, 0, sizeof(liblo10k1_ctl_transform_t) * ctrl_to_concate_count);
+       
+       for (i = 0; i < ctrl_to_concate_count; i++) {
+               /* find all controls for this ctl */
+               for (k = 0; k < ctrl_from_count[i]; k++) {
+                       for (j = 0; j < ep->ctl_count; j++) {
+                               if (strcmp(ctrl_from_concate[i][k], ep->ctls[j].ctl_name) == 0) {
+                                       tctl[i].emu_ctls[tctl[i].emu_ctl_count++] = j;
+                                       break;
+                               }
+                       }
+               }
+               strcpy(tctl[i].ctl_name, ctrl_to_concate[i]);
+       }
+       
+       if (liblo10k1_emu_transform_patch(ep,  tctl, ctrl_to_concate_count, &np) < 0)
+               return 1;
+       
+       free(tctl);
+       
+       for (i = 0; i < ctrl_visible_count; i++) {
+               ctl_idx = liblo10k1_patch_find_ctl_by_name(np, ctrl_visible[i]);
+               if (ctl_idx < 0)
+                       goto err;
+               if (liblo10k1_patch_ctl_set_vcount(np, ctl_idx, ctrl_visible_max[i]) < 0)
+                       goto err;
+       }
+
+       for (i = 0; i < ctrl_translate_count; i++) {
+               ctl_idx = liblo10k1_patch_find_ctl_by_name(np, ctrl_translate[i]);
+               if (ctl_idx < 0)
+                       goto err;
+               if (liblo10k1_patch_ctl_set_trans(np, ctl_idx, ctrl_translate_type[i]) < 0)
+                       goto err;
+       }
+       
+       for (i = 0; i < ctrl_index_count; i++) {
+               ctl_idx = liblo10k1_patch_find_ctl_by_name(np, ctrl_index[i]);
+               if (ctl_idx < 0)
+                       goto err;
+               if (liblo10k1_patch_ctl_set_index(np, ctl_idx, ctrl_index_val[i]) < 0)
+                       goto err;
+       }
+
+       for (i = 0; i < ctrl_values_count; i++) {
+               ctl_idx = liblo10k1_patch_find_ctl_by_name(np, ctrl_values[i]);
+               if (ctl_idx < 0)
+                       goto err;
+               for (j = 0; j < ctrl_values_cnt[i]; j++) {
+                       if (liblo10k1_patch_ctl_set_value(np, ctl_idx, j, ctrl_values_val[i][j]) < 0)
+                               goto err;
+               }
+       }
+       
+       *p = np;
+       return 0;
+err:
+       if (np)
+               liblo10k1_patch_free(np);
+       return 1;
+}
+
+static int transfer_native_patch(liblo10k1_dsp_patch_t *p, char *ctrl_opt)
+{
+       unsigned char ctrl_values_count;
+
+       char tmp_name_from_str[MAX_NAME_LEN];
+       char tmp_name_to_str[MAX_NAME_LEN];
+       char *tmp_str;
+       char *tmp_num;
+       char tmp_num_str[20];
+       
+       char sep;
+
+       int ctl_idx;
+               
+       /* parse ctrl opt */
+
+       /* TODO - check for name boundary */
+       while (ctrl_opt && *ctrl_opt) {
+               switch (*ctrl_opt++) {
+                       case 'r':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (r) - waiting -");
+                                       return 1;
+                               }
+                               while (1) {
+                                       tmp_str = tmp_name_from_str;
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ",:", 0);
+                                       if (strlen(tmp_name_from_str) == 0) {
+                                               error("wrong ctrl option format (r) - wrong source ctrl name");
+                                               return 1;
+                                       }
+                                       
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       
+                                       ctrl_opt++;
+                               }
+
+                               tmp_str = tmp_name_to_str;
+                               /* next is new ctrl name */
+                               sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ",", 0);
+                               if (strlen(tmp_name_to_str) == 0) {
+                                       error("wrong ctrl option format (r) - wrong target ctrl name");
+                                       return 1;
+                               }
+                               
+                               ctl_idx = liblo10k1_patch_find_ctl_by_name(p, tmp_name_from_str);
+                               if (ctl_idx < 0) {
+                                       error("unknown ctrl name");
+                                       return 1;
+                               }
+                               strcpy(p->ctl[ctl_idx].name, tmp_name_to_str);
+                               break;
+                       case 'i':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (i) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = tmp_name_from_str;
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(tmp_name_from_str) == 0) {
+                                               error("wrong ctrl option format (i) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+
+                               tmp_num = tmp_num_str;
+                               /* next is new ctrl index */
+                               sep = get_str(&ctrl_opt, tmp_num, 10, ",", 1);
+                               if (strlen(tmp_num_str) == 0) {
+                                       error("wrong ctrl option format (i) - wrong index num");
+                                       return 1;
+                               }
+                               ctl_idx = liblo10k1_patch_find_ctl_by_name(p, tmp_name_from_str);
+                               if (ctl_idx < 0) {
+                                       error("unknown ctrl name");
+                                       return 1;
+                               }
+                               if (liblo10k1_patch_ctl_set_index(p, ctl_idx, atoi(tmp_num_str)) < 0) {
+                                       error("can not set ctrl index");
+                                       return 1;
+                               }
+                               break;
+                       case 's':
+                               if (*ctrl_opt++ != '-') {
+                                       error("wrong ctrl option format (s) - waiting -");
+                                       return 1;
+                               }
+                               while (1)
+                               {
+                                       tmp_str = tmp_name_from_str;
+                                       sep = get_str(&ctrl_opt, tmp_str, MAX_NAME_LEN, ":", 0);
+                                       if (strlen(tmp_name_from_str) == 0) {
+                                               error("wrong ctrl option format (s) - wrong ctrl name");
+                                               return 1;
+                                       }
+
+                                       if (sep == ':') {
+                                               ctrl_opt++;
+                                               break;
+                                       }
+                                       ctrl_opt++;
+                               }
+                               ctl_idx = liblo10k1_patch_find_ctl_by_name(p, tmp_name_from_str);
+                               if (ctl_idx < 0){
+                                       error("unknown ctrl name");
+                                       return 1;
+                               }
+                               
+                               /* next is value */
+                               ctrl_values_count = 0;
+                               do {
+                                       tmp_num = tmp_num_str;
+
+                                       sep = get_str(&ctrl_opt, tmp_num, 10, ",#", 1);
+                                       if (strlen(tmp_num_str) == 0) {
+                                               error("wrong ctrl option format (s) - wrong value");
+                                               return 1;
+                                       }
+                                       if (liblo10k1_patch_ctl_set_value(p, ctl_idx, ctrl_values_count, atoi(tmp_num_str)) < 0){
+                                               error("can not set ctrl value");
+                                               return 1;
+                                       }
+                                       if (sep != '#')
+                                               break;
+                                       ctrl_opt++;
+                                       ctrl_values_count++;
+                               } while (1);
+                               break;
+                       default:
+                               error("wrong ctrl option format - unknown subfunction");
+                               return 1;
+               }
+               if (*ctrl_opt) {
+                       if (*ctrl_opt != ',') {
+                               error("wrong ctrl option format - wrong separator beetwen subfunctions");
+                               return 1;
+                       } else
+                               *ctrl_opt++;
+               }
+       }
+       
+       return 0;
+}
+
+static int list_patch(char *file_name)
+{
+       int err, i, j;
+       liblo10k1_emu_patch_t *p;
+
+       err = load_patch(file_name, &p);
+       if (err)
+               return err;
+
+       /* and now print */
+       printf("Patch name : %s\n", p->patch_name);
+       printf("IN:\n");
+       for (i = 0; i < p->in_count; i++)
+               printf("%03d: %08x\n", i, p->ins[i]);
+       printf("OUT:\n");
+       for (i = 0; i < p->out_count; i++)
+               printf("%03d: %08x\n", i, p->outs[i]);
+       
+       printf("DYN:\n");
+       for (i = 0; i < p->dyn_count; i++)
+               printf("%03d: %08x\n", i, p->dyns[i]);
+       
+       printf("STA:\n");
+       for (i = 0; i < p->sta_count; i++)
+               printf("%03d: %08x  %08x\n", i, p->stas[i].sc, p->stas[i].sc_val);
+
+       printf("CTRL:\n");
+       for (i = 0; i < p->ctl_count; i++)
+               printf("%03d: %08x   %08x  %08x  %08x   %s\n", i, p->ctls[i].ctl, p->ctls[i].ctl_val, p->ctls[i].ctl_val_min, p->ctls[i].ctl_val_max, p->ctls[i].ctl_name);
+       
+       printf("CON:\n");
+       for (i = 0; i < p->con_count; i++)
+               printf("%03d: %08x  %08x\n", i, p->cons[i].sc, p->cons[i].sc_val);
+       
+       printf("TRAM LOOKUP:\n");
+       for (i = 0; i < p->tram_lookup_count; i++) {
+               printf("%03d: %08x\n", i, p->tram_lookups[i].size);
+               for (j = 0; j < p->tram_lookups[i].read_line_count; j++)
+                       printf("  %03d: %c  %03d  %08x  %08x\n", i, 'R', j, p->tram_lookups[i].read_lines[j].line,p->tram_lookups[i].read_lines[j].line_size);
+               for (j = 0; j < p->tram_lookups[i].write_line_count; j++)
+                       printf("  %03d: %c  %03d  %08x  %08x\n", i, 'W', j, p->tram_lookups[i].write_lines[j].line,p->tram_lookups[i].write_lines[j].line_size);
+       }
+       
+       printf("TRAM DELAY:\n");
+       for (i = 0; i < p->tram_delay_count; i++) {
+               printf("%03d: %08x\n", i, p->tram_delays[i].size);
+               for (j = 0; j < p->tram_delays[i].read_line_count; j++)
+                       printf("  %03d: %c  %03d  %08x  %08x\n", i, 'R', j, p->tram_delays[i].read_lines[j].line,p->tram_delays[i].read_lines[j].line_size);
+               for (j = 0; j < p->tram_delays[i].write_line_count; j++)
+                       printf("  %03d: %c  %03d  %08x  %08x\n", i, 'W', j, p->tram_delays[i].write_lines[j].line,p->tram_delays[i].write_lines[j].line_size);
+       }
+               
+       printf("INSTR:\n");
+       for (i = 0; i < p->instr_count; i++)
+               printf("%03d: %08x  %08x  %08x  %08x  %08x\n", i, p->instrs[i].op, p->instrs[i].arg[0], p->instrs[i].arg[1], p->instrs[i].arg[2], p->instrs[i].arg[3]);
+       return 0;
+}
+
+static int add_patch(char *file_name, int udin, char *ctrl_opt, char *opt_patch_name, int where)
+{
+       int err;
+       liblo10k1_emu_patch_t *ep;
+       liblo10k1_dsp_patch_t *p;
+       
+       err = load_patch(file_name, &ep);
+       if (err)
+               return err;
+
+       err = transfer_patch(udin, ctrl_opt, ep, &p);
+       if (err) {
+               error("unable to transfer patch");
+               return err;
+       }
+       
+       if (opt_patch_name) {
+               strncpy(p->patch_name, opt_patch_name, MAX_NAME_LEN - 1);
+               p->patch_name[MAX_NAME_LEN - 1] = '\0';
+       }
+               
+       if ((err = liblo10k1_patch_load(&conn, p, where, NULL, NULL)) < 0) {
+               error("unable to load patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+
+       return 0;
+}
+
+static int load_dsp_patch(char *file_name, char *ctrl_opt, char *opt_patch_name, int where)
+{
+       int err;
+       liblo10k1_dsp_patch_t *p;
+       liblo10k1_file_info_t *fi;
+       
+       fi = NULL;
+       
+       if ((err = liblo10k1lf_load_dsp_patch(&p, file_name, &fi)) < 0) {
+               error("unable to load dsp patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       err = transfer_native_patch(p, ctrl_opt);
+       if (err)
+               goto err;
+       
+       if (opt_patch_name) {
+               strncpy(p->patch_name, opt_patch_name, MAX_NAME_LEN - 1);
+               p->patch_name[MAX_NAME_LEN - 1] = '\0';
+       }
+               
+       if ((err = liblo10k1_patch_load(&conn, p, where, NULL, NULL)) < 0) {
+               error("unable to load dsp patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+
+       liblo10k1lf_file_info_free(fi);
+       liblo10k1_patch_free(p);
+       return 0;
+err:
+       if (fi)
+               liblo10k1lf_file_info_free(fi);
+       if (p)
+               liblo10k1_patch_free(p);
+       return 1;
+}
+
+
+static int save_dsp_patch(char *file_name, int pn)
+{
+       int err;
+       
+       liblo10k1_dsp_patch_t *p;
+       liblo10k1_file_info_t *fi;
+       
+       if (pn < 0) {
+               error("wrong patch num");
+               return 1;
+       }
+       
+       fi = liblo10k1lf_file_info_alloc();
+       if (!fi) {
+               error("no mem");
+               goto err;
+       }
+               
+       if ((err = liblo10k1_patch_get(&conn, pn, &p)) < 0) {
+               error("unable to get dsp patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       fi->creater = strdup("lo10k1 - emu10k1/emu10k2 effect loader for alsa");
+       
+       if ((err = liblo10k1lf_save_dsp_patch(p, file_name, fi)) < 0) {
+               error("unable to save dsp patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       liblo10k1lf_file_info_free(fi);
+       liblo10k1_patch_free(p);
+       return 0;
+err:
+       if (fi)
+               liblo10k1lf_file_info_free(fi);
+       if (p)
+               liblo10k1_patch_free(p);
+       return 1;
+}
+
+void debug_print(char *str)
+{
+       printf(str);
+}
+
+static int debug(int deb)
+{
+       int err;
+       
+       if ((err = liblo10k1_debug(&conn, deb, debug_print)) < 0) {
+               error("unable to debug (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+
+       return 0;
+}
+
+static int del_patch(char *file_name)
+{
+       int err;
+
+       if ((err = liblo10k1_patch_unload(&conn, atoi(file_name))) < 0 ) {
+               error("unable to del patch (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+
+       return 0;
+}
+
+static int setup_dsp()
+{
+       int err;
+
+       if ((err = liblo10k1_dsp_init(&conn)) < 0) {
+               error("unable to setup DSP (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+       
+       return 0;
+}
+
+static int is_num(char *str)
+{
+       int i;
+
+       for (i = 0; i < strlen(str); i++)
+               if (!isdigit(str[i]))
+                       return 0;
+       return 1;
+}
+
+typedef struct
+{
+       char type;
+       int patch;
+       int io;
+} conn_info_t;
+
+char *parse_connect_sym(char *con_str, char *sym, int *len, int max_len)
+{
+       *len = 0;
+       while (*len < max_len && *con_str && *con_str != ',' && *con_str != ')') {
+               *sym++ = *con_str++;
+               (*len)++;
+       }
+
+       *sym++ = '\0';
+       if (*len == 0)
+               return NULL;
+       return con_str;
+}
+
+char *parse_simple_params(char *con_str, char io_type, int pn, conn_info_t *con_info, int *con_info_count, int max_con_info_count)
+{
+       char con_arg[255];
+       int con_arg_len = 0;
+       int io_idx;
+
+       while(1) {
+               if (*con_info_count >= max_con_info_count)
+                       return NULL;
+               if (!(con_str = parse_connect_sym(con_str, con_arg, &con_arg_len, sizeof(con_arg) - 1)))
+                       return NULL;
+               if (*con_str != ')' && *con_str != ',')
+                       return NULL; /* wrong format */
+
+               con_info[*con_info_count].type = io_type;
+
+               if (is_num(con_arg)) {
+                       /* input number */
+                       if (io_type == 'A' || io_type == 'B') {
+                               con_info[*con_info_count].patch = pn;
+                               con_info[(*con_info_count)++].io = atoi(con_arg);
+                       } else {
+                               con_info[*con_info_count].patch = -1;
+                               con_info[(*con_info_count)++].io = atoi(con_arg);
+                       }
+               } else {
+                       /* input name */
+                       switch (io_type) {
+                               case 'A':
+                                       if (liblo10k1_find_patch_in(&conn, pn, con_arg, &io_idx) < 0)
+                                               return NULL;
+                                       con_info[*con_info_count].patch = pn;
+                                       con_info[(*con_info_count)++].io = io_idx;
+                                       break;
+                               case 'B':
+                                       if (liblo10k1_find_patch_out(&conn, pn, con_arg, &io_idx) < 0)
+                                               return NULL;
+                                       con_info[*con_info_count].patch = pn;
+                                       con_info[(*con_info_count)++].io = io_idx;
+                                       break;
+                               case 'F':
+                                       if (liblo10k1_find_fx(&conn, con_arg, &io_idx) < 0)
+                                               return NULL;
+                                       con_info[*con_info_count].patch = -1;
+                                       con_info[(*con_info_count)++].io = io_idx;
+                                       break;
+                               case 'I':
+                                       if (liblo10k1_find_in(&conn, con_arg, &io_idx) < 0)
+                                               return NULL;
+                                       con_info[*con_info_count].patch = -1;
+                                       con_info[(*con_info_count)++].io = io_idx;
+                                       break;
+                               case 'O':
+                                       if (liblo10k1_find_out(&conn, con_arg, &io_idx) < 0)
+                                               return NULL;
+                                       con_info[*con_info_count].patch = -1;
+                                       con_info[(*con_info_count)++].io = io_idx;
+                                       break;
+                       }
+               }
+
+               if (*con_str != ',')
+                       break;
+               con_str++;
+       }
+       return con_str;
+}
+
+char *parse_patch_params(char *con_str, char io_type, conn_info_t *con_info, int *con_info_count, int max_con_info_count)
+{
+       char con_arg[255];
+       int con_arg_len = 0;
+       int i;
+       int patch_num = -1;
+       int io_count = 0;
+
+       if (!(con_str = parse_connect_sym(con_str, con_arg, &con_arg_len, sizeof(con_arg) - 1)))
+               return NULL;
+       if (*con_str != ')' && *con_str != ',')
+               return NULL;
+
+       if (is_num(con_arg))
+               /* patch number */
+               patch_num = atoi(con_arg);
+       else
+               /* patch name - find patch */
+               if (liblo10k1_find_patch(&conn, con_arg, &patch_num) < 0)
+                       return NULL;
+
+       /* argumenty */
+       if (*con_str == ',') {
+               con_str++;
+               if (*con_info_count >= max_con_info_count)
+                       return NULL;
+               if (!(con_str = parse_simple_params(con_str, io_type, patch_num, con_info, con_info_count, max_con_info_count)))
+                       return NULL;
+       } else {
+               /* add all patch inputs or outputs */
+               if (io_type == 'A') {
+                       /* get all inputs */
+                       if (liblo10k1_get_pin_count(&conn, patch_num, &io_count) < 0)
+                               return NULL;
+               } else {
+                       /* get all outputs */
+                       if (liblo10k1_get_pout_count(&conn, patch_num, &io_count) < 0)
+                               return NULL;
+               }
+
+               i = 0;
+               while (i < io_count) {
+                       if (*con_info_count >= max_con_info_count) {
+                               return NULL;
+                       }
+                       con_info[*con_info_count].type = io_type;
+                       con_info[*con_info_count].patch = patch_num;
+                       con_info[(*con_info_count)++].io = i;
+                       i++;
+               }
+       }
+       return con_str;
+}
+
+int parse_connect(int add, char *con_str, int *multi, int *simple, conn_info_t **con_info, int *con_info_count, int max_con_info_count)
+{
+       char con[10];
+       int con_len;
+
+       int ft = 0;
+       while (1) {
+               con_len = 0;
+               for(;*con_str && *con_str != '('; con_str++) {
+                       if (con_len >= sizeof(con) - 1)
+                               return 1;/* ERROR */
+                       con[con_len++] = *con_str;
+               }
+               con[con_len++] = '\0';
+
+               if (*con_str != '(')
+                       return 1;/* ERROR */
+               con_str++;
+
+               if (ft && strcmp(con,"FX") == 0) {
+                       if (!(con_str = parse_simple_params(con_str, 'F', -1, con_info[ft], &(con_info_count[ft]), max_con_info_count)))
+                               return 1;/* ERROR */
+               } else if (ft && strcmp(con,"IN") == 0) {
+                       if (!(con_str = parse_simple_params(con_str, 'I',  -1, con_info[ft], &(con_info_count[ft]), max_con_info_count)))
+                               return 1;/* ERROR */
+               } else if (ft && strcmp(con,"OUT") == 0) {
+                       if (!(con_str = parse_simple_params(con_str, 'O', -1, con_info[ft], &(con_info_count[ft]), max_con_info_count)))
+                               return 1;/* ERROR */
+               } else if (strcmp(con,"PIN") == 0) {
+                       if (!(con_str = parse_patch_params(con_str, 'A', con_info[ft], &(con_info_count[ft]), max_con_info_count)))
+                               return 1;/* ERROR */
+               } else if (strcmp(con,"POUT") == 0) {
+                       if (!(con_str = parse_patch_params(con_str, 'B', con_info[ft], &(con_info_count[ft]), max_con_info_count)))
+                               return 1;/* ERROR */
+               } else
+                       return 1;/* ERROR */
+
+               con_str++;
+
+               if (ft && !*con_str)
+                       return 0; /* OK */
+               if (!add) {
+                       if (!*con_str)
+                               return 0;
+                       else
+                               return 1;
+               }
+               
+               if (add && !ft && (*con_str == '=' || *con_str == '>' || *con_str == ':')) {
+                       ft++;
+                       if (*con_str == '=') {
+                               *multi = 0;
+                               *simple = 0;
+                       } else if (*con_str == ':') {
+                               *multi = 0;
+                               *simple = 1;
+                       } else
+                               *multi = 1;
+
+               } else if (add &&*con_str != '+')
+                       return 1;/* ERROR */
+               /* process next */
+               con_str++;
+       }
+}
+
+int parse_rename(char *con_str, char *io_type, int *pn, int *io, char **new_name)
+{
+       char con[10];
+       int con_len = 0;
+
+       char con_arg1[255];
+       int con_arg_len1 = 0;
+       int is_arg_num1 = 0;
+       int arg_num1 = -1;
+
+       char con_arg2[255];
+       int con_arg_len2 = 0;
+       int is_arg_num2 = 0;
+       int arg_num2 = -1;
+
+       for(;*con_str && *con_str != '('; con_str++) {
+               if (con_len >= sizeof(con) - 1)
+                       return 1;/* ERROR */
+               con[con_len++] = *con_str;
+       }
+       con[con_len++] = '\0';
+
+       if (*con_str != '(')
+               return 1;/* ERROR */
+       con_str++;
+
+       *io_type = '\0';
+       if (strcmp(con,"FX") == 0)
+               *io_type = 'F';
+       else if (strcmp(con,"IN") == 0)
+               *io_type = 'I';
+       else if (strcmp(con,"OUT") == 0)
+               *io_type = 'O';
+       else if (strcmp(con,"PIN") == 0)
+               *io_type = 'A';
+       else if (strcmp(con,"POUT") == 0)
+               *io_type = 'B';
+       else if (strcmp(con,"PATCH") == 0)
+               *io_type = 'P';
+       else
+               return 1;/* ERROR */
+
+       if (!(con_str = parse_connect_sym(con_str, con_arg1, &con_arg_len1, sizeof(con_arg1) - 1)))
+                       return 1;
+
+       if ((is_arg_num1 = is_num(con_arg1)))
+               arg_num1 = atoi(con_arg1);
+
+       if (*io_type == 'A' || *io_type == 'B') {
+               /* two arguments */
+               if (*con_str != ',')
+                       return 1; /* ERROR */
+               con_str++;
+               if (!(con_str = parse_connect_sym(con_str, con_arg2, &con_arg_len2, sizeof(con_arg2) - 1)))
+                       return 1;
+
+               if ((is_arg_num2 = is_num(con_arg2)))
+                       arg_num2 = atoi(con_arg2);
+       }
+
+       if (*con_str != ')')
+               return 1; /* ERROR */
+
+       switch (*io_type) {
+               case 'A':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_patch(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       if (!is_arg_num2)
+                               if (liblo10k1_find_patch_in(&conn, arg_num1, con_arg2, &arg_num2) < 0)
+                                       return 1;
+                       break;
+               case 'B':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_patch(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       if (!is_arg_num2)
+                               if (liblo10k1_find_patch_out(&conn, arg_num1, con_arg2, &arg_num2) < 0)
+                                       return 1;
+                       break;
+               case 'F':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_fx(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       break;
+               case 'I':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_in(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       break;
+               case 'O':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_out(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       break;
+               case 'P':
+                       if (!is_arg_num1)
+                               if (liblo10k1_find_patch(&conn, con_arg1, &arg_num1) < 0)
+                                       return 1;
+                       break;
+       }
+
+       con_str++;
+       if (*con_str != '=')
+               return 1; /* ERROR */
+       con_str++;
+
+       if (*io_type == 'A' || *io_type == 'B' || *io_type == 'P') {
+               *pn = arg_num1;
+               *io = arg_num2;
+       } else {
+               *io = arg_num1;
+       }
+
+       *new_name = con_str;
+       return 0;
+}
+
+static int con_add(char *file_name)
+{
+       int err, i;
+       int multi = 0;
+       int simple = 0;
+
+       conn_info_t con_infof[32];
+       conn_info_t con_infot[32];
+       conn_info_t *con_info[2] = {con_infof, con_infot};
+
+       int con_info_count[2] = {0, 0};
+
+       if (parse_connect(1, file_name, &multi, &simple, con_info, con_info_count, 32)) {
+               error("wrong parameter - connection string");
+               return 1;
+       }
+
+       if (con_info_count[0] != con_info_count[1]) {
+               error("wrong parameter - connection string from <> to");
+               return 1;
+       }
+
+       if (!con_info_count[0]) {
+               error("wrong parameter - connection string");
+               return 1;
+       }
+
+       for (i = 0; i < con_info_count[0]; i++) {
+               if ((err = liblo10k1_con_add(&conn, multi, simple,
+                       con_infof[i].type, con_infof[i].patch, con_infof[i].io,
+                       con_infot[i].type, con_infot[i].patch, con_infot[i].io,
+                       NULL)) < 0) {
+                       error("unable to connect  (ld10k1 error:%s)", liblo10k1_error_str(err));
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static int con_del(char *file_name)
+{
+       conn_info_t con_info[32];
+       int err, i;
+
+       conn_info_t *con_info_p = con_info;
+
+       int con_info_count = 0;
+
+       if (parse_connect(0, file_name, NULL, NULL, &con_info_p, &con_info_count, 32)) {
+               error("wrong parameter - disconnection string");
+               return 1;
+       }
+
+       if (!con_info_count) {
+               error("wrong parameter - disconnection string");
+               return 1;
+       }
+
+       for (i = 0; i < con_info_count; i++) {
+               if ((err = liblo10k1_con_del(&conn, con_info[i].type, con_info[i].patch, con_info[i].io, NULL)) < 0) {
+                       error("unable to connect  (ld10k1 error:%s)", liblo10k1_error_str(err));
+                       return err;
+               }
+       }
+       
+       return 0;
+}
+
+static int rename_arg(char *arg_name)
+{
+       char io_type = '\0';
+       int pn = -1;
+       int io = -1;
+       char *new_name = NULL;
+
+       if (parse_rename(arg_name, &io_type, &pn, &io, &new_name)) {
+               error("wrong parameter for rename");
+               return 1;
+       }
+
+       switch (io_type) {
+               case 'A':
+                       if (liblo10k1_rename_patch_in(&conn, pn, io, new_name) < 0) {
+                               error("couldn't rename patch in");
+                               return 1;
+                       }
+                       break;
+               case 'B':
+                       if (liblo10k1_rename_patch_out(&conn, pn, io, new_name) < 0) {
+                               error("couldn't rename patch out");
+                               return 1;
+                       }
+                       break;
+               case 'F':
+                       if (liblo10k1_rename_fx(&conn, io, new_name) < 0) {
+                               error("couldn't rename fx");
+                               return 1;
+                       }
+                       break;
+               case 'I':
+                       if (liblo10k1_rename_in(&conn, io, new_name) < 0) {
+                               error("couldn't rename in");
+                               return 1;
+                       }
+                       break;
+               case 'O':
+                       if (liblo10k1_rename_out(&conn, io, new_name) < 0) {
+                               error("couldn't rename out");
+                               return 1;
+                       }
+                       break;
+               case 'P':
+                       if (liblo10k1_rename_patch(&conn, pn, new_name) < 0) {
+                               error("couldn't rename patch");
+                               return 1;
+                       }
+                       break;
+       }
+
+       return 0;
+}
+
+static int dump(char *file_name)
+{
+       int err;
+       void *dump = NULL;
+       int size = 0;
+
+       FILE *dump_file = NULL;
+
+       if ((err = liblo10k1_dump(&conn, &dump, &size)) < 0 ) {
+               error("unable to dump (ld10k1 error:%s)", liblo10k1_error_str(err));
+               return err;
+       }
+
+       dump_file = fopen(file_name, "w");
+       if (!dump_file) {
+               free(dump);
+               error("unable to open dump");
+               return 1;
+       }
+
+       if (fwrite(dump, 1, size, dump_file) < size) {
+               free(dump);
+               error("unable to write dump");
+               return 1;
+       }
+
+       free(dump);
+       fclose(dump_file);
+
+       return 0;
+}
+
+static int store_dsp(char *file_name)
+{
+       int err;
+       
+       liblo10k1_file_dsp_setup_t *setup;
+       liblo10k1_file_info_t *fi;
+       
+       fi = liblo10k1lf_file_info_alloc();
+       if (!fi) {
+               error("no mem");
+               goto err;
+       }
+               
+       if ((err = liblo10k1lf_get_dsp_config(&conn, &setup)) < 0) {
+               error("unable to get dsp config (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       fi->creater = strdup("lo10k1 - emu10k1/emu10k2 effect loader for alsa");
+       
+       if ((err = liblo10k1lf_save_dsp_config(setup, file_name, fi)) < 0) {
+               error("unable to store dsp config (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       liblo10k1lf_file_info_free(fi);
+       liblo10k1lf_dsp_config_free(setup);
+       return 0;
+err:
+       if (fi)
+               liblo10k1lf_file_info_free(fi);
+       return 1;
+}
+
+static int restore_dsp(char *file_name)
+{
+       int err;
+       
+       liblo10k1_file_dsp_setup_t *setup;
+       liblo10k1_file_info_t *fi;
+       
+       fi = NULL;
+       
+       if ((err = liblo10k1lf_load_dsp_config(&setup, file_name, &fi)) < 0) {
+               error("unable to restore dsp config (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       if ((err = liblo10k1lf_put_dsp_config(&conn, setup)) < 0) {
+               error("unable to put dsp config (ld10k1 error:%s)", liblo10k1_error_str(err));
+               goto err;
+       }
+       
+       liblo10k1lf_file_info_free(fi);
+       liblo10k1lf_dsp_config_free(setup);
+       return 0;
+err:
+       if (fi)
+               liblo10k1lf_file_info_free(fi);
+       return 1;
+}
+int main(int argc, char *argv[])
+{
+       int  c;
+
+       int opt_list;
+       int opt_setup;
+       int opt_info;
+       int opt_add;
+       int opt_del;
+       int opt_con_add;
+       int opt_con_del;
+       int opt_debug;
+       char *opt_list_patch;
+       int opt_use_default_io_names;
+       char *opt_ctrl;
+       char *opt_patch_name;
+       char *opt_new_name;
+       int opt_where;
+       int option_index = 0;
+       char *opt_dump_name;
+       char *opt_host;
+       char *tmp = NULL;
+       
+       int opt_store;
+       int opt_restore;
+       char *opt_store_restore_file;
+       
+       int opt_load_patch;
+       int opt_save_patch;
+       
+       unsigned int opt_wait_for_conn;
+
+       liblo10k1_param params;
+
+       int err = 0;
+       
+       static struct option long_options[] = {
+                               {"pipe_name", 1, 0, 'p'},
+                               {"list", 1, 0, 'l'},
+                               {"info", 0, 0, 'i'},
+                               {"add", 1, 0, 'a'},
+                               {"del", 1, 0, 'd'},
+                               {"conadd", 1, 0, 'q'},
+                               {"condel", 1, 0, 'w'},
+                               {"debug", 1, 0, 0},
+                               {"defionames", 0, 0, 'n'},
+                               {"ctrl", 1, 0, 0},
+                               {"patch_name", 1, 0, 0},
+                               {"where", 1, 0, 0},
+                               {"setup", 1, 0, 's'},
+                               {"renam", 1, 0, 0},
+                               {"dump", 1, 0, 0},
+                               {"host", 1, 0, 0},
+                               {"path", 1, 0, 'P'},
+                               {"store", 1, 0, 0},
+                               {"restore", 1, 0, 0},
+                               {"load_patch", 1, 0, 0},
+                               {"save_patch", 1, 0, 0},
+                               {"wait", 1, 0, 0},
+                               {0, 0, 0, 0}
+       };
+
+       opt_list = 0;
+       opt_add = 0;
+       opt_del = 0;
+       opt_list_patch = NULL;
+       opt_info = 0;
+       opt_con_add = 0;
+       opt_con_del = 0;
+       opt_debug = 0;
+       opt_use_default_io_names = 0;
+       opt_ctrl = NULL;
+       opt_patch_name = NULL;
+       opt_new_name = NULL;
+       opt_where = -1;
+       opt_setup = 0;
+       opt_dump_name = NULL;
+       opt_host = NULL;
+       
+       opt_store = 0;
+       opt_restore = 0;
+       opt_store_restore_file = NULL;
+       
+       opt_load_patch = 0;
+       opt_save_patch = 0;
+       
+       opt_wait_for_conn = 500;
+
+       strcpy(comm_pipe,"/tmp/.ld10k1_port");
+
+       if (argc > 1 && !strcmp(argv[1], "--help")) {
+               help(argv[0]);
+               return 0;
+       }
+
+       first_path = NULL;
+#ifdef EFFECTSDIR
+       add_paths(EFFECTSDIR);
+#endif
+
+       while ((c = getopt_long(argc, argv, "hil:p:a:d:q:w:nsh:P:",
+               long_options, &option_index)) != EOF) {
+               switch (c) {
+               case 0:
+                       if (strcmp(long_options[option_index].name, "debug") == 0)
+                               opt_debug = atoi(optarg);
+                       else if (strcmp(long_options[option_index].name, "ctrl") == 0)
+                               opt_ctrl = optarg;
+                       else if (strcmp(long_options[option_index].name, "patch_name") == 0)
+                               opt_patch_name = optarg;
+                       else if (strcmp(long_options[option_index].name, "where") == 0)
+                               opt_where = atoi(optarg);
+                       else if (strcmp(long_options[option_index].name, "renam") == 0)
+                               opt_new_name = optarg;
+                       else if (strcmp(long_options[option_index].name, "dump") == 0)
+                               opt_dump_name = optarg;
+                       else if (strcmp(long_options[option_index].name, "host") == 0)
+                               opt_host = optarg;
+                       else if (strcmp(long_options[option_index].name, "wait") == 0) {
+                               opt_wait_for_conn = atoi(optarg);
+                               if (opt_wait_for_conn < 0)
+                                       opt_wait_for_conn = 0;
+                               else if (opt_wait_for_conn > 500)
+                                       opt_wait_for_conn = 500;
+                       }
+                       else if (strcmp(long_options[option_index].name, "store") == 0) {
+                               opt_store = 1;
+                               opt_store_restore_file = optarg;
+                       } else if (strcmp(long_options[option_index].name, "restore") == 0) {
+                               opt_restore = 1;
+                               opt_store_restore_file = optarg;
+                       } else if (strcmp(long_options[option_index].name, "load_patch") == 0) {
+                               opt_load_patch = 1;
+                               opt_store_restore_file = optarg;
+                       } else if (strcmp(long_options[option_index].name, "save_patch") == 0) {
+                               opt_save_patch = 1;
+                               opt_store_restore_file = optarg;
+                       }
+                       break;
+               case 'h':
+                       help(argv[0]);
+                       return 0;
+               case 'l':
+                       opt_list = 1;
+                       opt_list_patch = optarg;
+                       break;
+               case 'p':
+                       strcpy(comm_pipe, optarg);
+                       break;
+               case 'a':
+                       opt_add = 1;
+                       opt_list_patch = optarg;
+                       break;
+               case 'd':
+                       opt_del = 1;
+                       opt_list_patch = optarg;
+                       break;
+               case 'i':
+                       opt_info = 1;
+                       break;
+               case 'q':
+                       opt_con_add = 1;
+                       opt_list_patch = optarg;
+                       break;
+               case 'w':
+                       opt_con_del = 1;
+                       opt_list_patch = optarg;
+                       break;
+               case 'n':
+                       opt_use_default_io_names = 1;
+                       break;
+               case 's':
+                       opt_setup = 1;
+                       break;
+               case 'P':
+                       add_path(optarg);
+                       break;
+               case '?':
+                       break;
+               default:
+                       error("unknown option %c", c);
+                       return 1;
+               }
+       }
+
+       params.wfc = opt_wait_for_conn;
+       if (opt_host) {
+               params.type = COMM_TYPE_IP;
+               params.name = strtok(opt_host, ":");
+               if (!params.name)
+                       error("wrong hostname");
+               tmp = strtok(NULL, ":");
+               if (!tmp)
+                       error("wrong port");
+               params.port = atoi(tmp);
+       } else {
+               params.type = COMM_TYPE_LOCAL;
+               params.name = comm_pipe;
+       }
+
+       params.server = 0;
+
+       while (1) {
+               if ((err = liblo10k1_connect(&params, &conn))) {
+                       error("unable to connect ld10k1");
+                       break;
+               }
+               
+               if ((err = liblo10k1_check_version(&conn))) {
+                       error("Wrong ld10k1 version");
+                       break;
+               }
+               
+               if (opt_store || opt_restore) {
+                       if (opt_store) {
+                               if ((err = store_dsp(opt_store_restore_file)))
+                                       break;
+                       } else {
+                               if ((err = restore_dsp(opt_store_restore_file)))
+                                       break;
+                       }
+               } else {
+                       if (opt_setup)
+                               if ((err = setup_dsp()))
+                                       break;
+                       if (opt_list)
+                               if ((err = list_patch(opt_list_patch)))
+                                       break;
+       
+                       if (opt_add)
+                               if ((err = add_patch(opt_list_patch, opt_use_default_io_names, opt_ctrl, opt_patch_name, opt_where)))
+                                       break;
+                       
+                       if (opt_load_patch)
+                               if ((err = load_dsp_patch(opt_store_restore_file, opt_ctrl, opt_patch_name, opt_where)))
+                                       break;
+                                       
+                       if (opt_save_patch)
+                               if ((err = save_dsp_patch(opt_store_restore_file, opt_where)))
+                                       break;
+       
+                       if (opt_del)
+                               if ((err = del_patch(opt_list_patch)))
+                                       break;
+       
+                       if (opt_con_add)
+                               if ((err = con_add(opt_list_patch)))
+                                       break;
+       
+                       if (opt_con_del)
+                               if ((err = con_del(opt_list_patch)))
+                                       break;
+       
+                       if (opt_debug)
+                               if ((err = debug(opt_debug)))
+                                       break;
+       
+                       if (opt_new_name)
+                               if ((err = rename_arg(opt_new_name)))
+                                       break;
+       
+                       if (opt_dump_name)
+                               if ((err = dump(opt_dump_name)))
+                                       break;
+               }
+               break;
+       }       
+
+       if (liblo10k1_is_open(&conn)) {
+               /*send_msg(conn_num, FNC_CLOSE_CONN, NULL, 0);
+               free_comm(conn_num);*/
+               liblo10k1_disconnect(&conn);
+       }
+       
+       free_all_paths();
+
+       return err;
+}