Added ld10k1 tool by Peter Zubaj.
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
--- /dev/null
+Peter Zubaj <pzad@pobox.sk>
+
+Contributors:
+Mikael Magnusson <mikma@users.sourceforge.net>
\ No newline at end of file
--- /dev/null
+ 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.
--- /dev/null
+ 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!
+
+
--- /dev/null
+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.
+
--- /dev/null
+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)
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+EXTRA_DIST = README emu10k1MIDIEffects.tar.gz
--- /dev/null
+These files are from holborn (Josep Andreu).
+They are for SB Live.
\ No newline at end of file
--- /dev/null
+ 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
+
+
--- /dev/null
+ 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
+
+
--- /dev/null
+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 $@ $<
--- /dev/null
+;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
--- /dev/null
+;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
--- /dev/null
+;; 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
--- /dev/null
+;; 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
--- /dev/null
+;; 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
--- /dev/null
+;; 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
--- /dev/null
+;; 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
--- /dev/null
+;; 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
--- /dev/null
+ 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
--- /dev/null
+;;; 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
+
+
+
+
+
--- /dev/null
+;;; 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
+
+
+
+
+
--- /dev/null
+#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)"
+
+
+
--- /dev/null
+;;; 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
--- /dev/null
+;;; 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
--- /dev/null
+ 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
+
+
--- /dev/null
+#!/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
--- /dev/null
+
+ 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
--- /dev/null
+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
--- /dev/null
+EXTRA_DIST = ld10k1_usage lo10k1_usage dl10k1_usage AudigyTRAM.txt README Audigy-mixer.txt
--- /dev/null
+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
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+EXTRA_DIST = README audigy.dl10k1 audigy_ms.dl10k1
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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"
+
--- /dev/null
+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)
+])
+
--- /dev/null
+#!/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
--- /dev/null
+EXTRA_DIST = README
--- /dev/null
+For alsa 1.0.7rc1 and higher no patches are needed.
\ No newline at end of file
--- /dev/null
+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
--- /dev/null
+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 $@ $<
--- /dev/null
+Most of files in this directory is taken from emu10k1 OSS driver see opensource.creative.com
\ No newline at end of file
--- /dev/null
+;PZU
+ name "2-channel copy"
+
+left IO
+right IO
+
+ macs left,left,$40,$40
+ macs right,right,$40,$40
+
+ end
+
+
+
--- /dev/null
+;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
--- /dev/null
+ 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
--- /dev/null
+;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
--- /dev/null
+; 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
+;========================================
--- /dev/null
+ 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
+
+
+
+
+
+
+
+
--- /dev/null
+;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
+
+
+
+
+
+
+
+
--- /dev/null
+;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
--- /dev/null
+;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
--- /dev/null
+; 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
--- /dev/null
+ 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
+
+
+
--- /dev/null
+ 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
+
+
+
--- /dev/null
+#!/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)"
--- /dev/null
+#!/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)"
--- /dev/null
+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
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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(¶ms, 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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, ®_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, ®_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, ®_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));
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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";
+}
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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(¶ms, &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;
+}