From: Takashi Iwai Date: Fri, 18 Mar 2005 13:40:44 +0000 (+0000) Subject: Add ld10k1 tool X-Git-Tag: v1.0.9rc2~3 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=2df1aa7c20d3919484c5eb5beb6a9a264f1e84a9;p=alsa-tools.git Add ld10k1 tool Added ld10k1 tool by Peter Zubaj. --- diff --git a/Makefile b/Makefile index 8fb3f75..f18a269 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 1.0.9rc1 TOP = . SUBDIRS = ac3dec as10k1 envy24control hdsploader hdspconf hdspmixer \ mixartloader pcxhrloader rmedigicontrol sb16_csp seq sscape_ctl us428control \ - usx2yloader vxloader echomixer + usx2yloader vxloader echomixer ld10k1 all: @for i in $(SUBDIRS); do cd $(TOP)/$$i; ./cvscompile $(CVSCOMPILE_ARGS); cd ..; make -C $$i; done diff --git a/ld10k1/AUTHORS b/ld10k1/AUTHORS new file mode 100644 index 0000000..468a355 --- /dev/null +++ b/ld10k1/AUTHORS @@ -0,0 +1,4 @@ +Peter Zubaj + +Contributors: +Mikael Magnusson \ No newline at end of file diff --git a/ld10k1/COPYING b/ld10k1/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/ld10k1/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ld10k1/COPYING.LIB b/ld10k1/COPYING.LIB new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/ld10k1/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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 + + 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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/ld10k1/ChangeLog b/ld10k1/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/ld10k1/INSTALL b/ld10k1/INSTALL new file mode 100644 index 0000000..56b077d --- /dev/null +++ b/ld10k1/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PREFIX', the package will +use PREFIX as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/ld10k1/Makefile.am b/ld10k1/Makefile.am new file mode 100644 index 0000000..f126058 --- /dev/null +++ b/ld10k1/Makefile.am @@ -0,0 +1,26 @@ +SUBDIRS = setup doc patch dump contrib include src + +aclocaldir=$(datadir)/aclocal +aclocal_DATA=ld10k1.m4 + +sbin_SCRIPTS = ld10k1d + +do_subst = sed -e 's,[@]sbindir[@],$(sbindir),g' \ + -e 's,[@]binarydir[@],$(bindir),g' \ + -e 's,[@]sysconfdir[@],$(sysconfdir),g' + +ld10k1d : ld10k1d.in + $(do_subst) $(srcdir)/ld10k1d.in > ld10k1d + +CLEANFILES = ld10k1d + +noinst_HEADERS = + +EXTRA_DIST = ld10k1.m4 AUTHORS COPYING COPYING.LIB ChangeLog INSTALL \ + README TODO ld10k1d.in + +alsa-dist: distdir + @rm -rf ../distdir/ld10k1 + @mkdir -p ../distdir/ld10k1 + @cp -RLpv $(distdir)/* ../distdir/ld10k1 + @rm -rf $(distdir) diff --git a/ld10k1/NEWS b/ld10k1/NEWS new file mode 100644 index 0000000..dd95883 --- /dev/null +++ b/ld10k1/NEWS @@ -0,0 +1,61 @@ +0.1.8 + Sync with ALSA 1.0.8rc1 +0.1.7test4 + ld10k1 options for pid file and log file - Mikael Magnusson + Script for start and end of ld10k1 +0.1.7test3 + Fixed bug in liblo10k1lf_save_patch - Mikael Magnusson + ld10k1 will exit with error code if it can not connect to ld10k1 - Mikael Magnusson +0.1.7test2 + License for liblo10k1 was changed from GPL to LGPL. Other parts are still GPLed. + Fixed getopt_long handling - Mikael Magnusson + Fixed free bug in liblo10k1lf_get_dsp_config - Mikael Magnusson + Fixed (copy & paste) bug in liblo10k1lf_load_patch - thanks to Mikael Magnusson +0.1.7test1 + !!! This version of ld10k1 requires ALSA 1.0.7 - both alsa-lib and alsa-driver !!! + !!! In current kernel 2.6.8.1 is still ALSA 1.0.4 !!! + Moved emu patch loading to liblo10k1 + Moved emu patch to ld10k1 patch transforming to liblo10k1 + DSP config can by stored and restored. + New lo10k1 options --store, --restore, --save_patch, --load_patch, --wait + Some source reorganization. + Source cleaning - Mikael Magnusson +0.1.6 + Moved ld10k1 and dl10k1 to sbin directory - Mikael Magnusson + Fixed bug in call to ld10k1_free_reserved_ctls - Mikael Magnusson + Some cleanup from Mikael Magnusson + ld10k1 not use list.h header from linux kernel - Mikael Magnusson + configure.in and makefile.am cleanup - Mikael Magnusson + Init script for sb live, effect path - Mikael Magnusson + Daemonize of ld10k1, some ideas from Mikael Magnusson. + Aditional cleanups. +0.1.5 + Fixed bug in control index. + Reworking of communication between client and server. + Some work on liblo10k1 to support GUI. + Support for ALSA 1.0.6rc1 + Fixed bug in connecion add +0.1.4 + Control indexes can be used now - see -ctrl (i option) + Check for AC97 controls which can not be deleted. + Corrected bug in free_comm - Mikael Magnusson + Some cleanup from Mikael Magnusson + Splitted lo10k1 to two parts - lo10k1 and liblo10k1. + Fixed bug in tram allocation. + Some effects for SB Live from Josep Andreu (holborn) in contrib subdir + Check if ld10k1 run under root +0.1.3p2 + Corected bug in accept_comm. Thanks to Mikael Magnusson and Joachim Falk +0.1.3p1 + Corrected bug for constant registers +0.1.3 + Dump loader (dl10k1). + ld10k1 can now use named socked or normal netework socket + Simpler connecting outputs from multiple outputs to input +0.1.2 + Rewriten some parts (many new bugs) + Simpler connecting +0.1.1 + Working TRAM on Audigy, many bugs fixed, many new bugs +0.1 + Initial release \ No newline at end of file diff --git a/ld10k1/README b/ld10k1/README new file mode 100644 index 0000000..c1ed3ae --- /dev/null +++ b/ld10k1/README @@ -0,0 +1,34 @@ +This is attempt to make EMU10K1 (EMU10K2) patch loader for ALSA. +This is work in progress. It is not very user friendly. +Loading, unloading, connecting, disconnecting patches works. +It should by able to load identical setup for Audigy as it is in kernel driver. +This dissables AC3 passthrough on SB Live. + +ALSA (both alsa-lib and in kernel drivers) version 1.0.7rc1 and higher are required. + +There are two parts: +Server - ld10k1 - runing as service - it is storing driver state - it must run + under root or by setuided +Client - lo10k1 - controls server +and dump loader dl10k1 - loads dumps previously created with lo10k1 & ld10k1. + +For options list run +./ld10k1 -h +and +./lo10k1 -h +and +./dl10k1 -h +and look in doc directory. + +ld10k1 will clear card DSP program and you will hear nothing. +You must load some patches to route sound from inputs to outputs (use audigy_init script for +audigy 1, 2 or init_live for sb live). +After loading patch check and set oss mixer emulation through proc file (/proc/asound/card/oss_mixer) + +In directory setup are some patches which I use on my Audigy for testing. +With this you will have exactly same mixer as with original driver (+headphone control, not tested +AudigyDrive inputs and outputs, AC3 passthrought). +Most of them are from emu-tools-0.9.4 package from OSS driver (but not all). +Use as10k1 compiler from alsa-tools package to compile patches. + +Peter Zubaj \ No newline at end of file diff --git a/ld10k1/TODO b/ld10k1/TODO new file mode 100644 index 0000000..ec413ea --- /dev/null +++ b/ld10k1/TODO @@ -0,0 +1,19 @@ +Priority: + +High + - TRAM sharing between AC3 passthrough and other effects + - ac3 passthrough for SB Live - now is dissabled +Medium + - effect repositry + - clean source + - optimalize GPR ussage for connect + - change notification for ld10k1 clients + - control range checking against translation + - optimalization - is getting slow + - conection del - returned id is sometime invalid +Low + - little and big endian conversion on save and read + - utility to enable control of mixer elements from midi + - modify as10k1 to support feature that alsa allows for emu10k1 + +and much more diff --git a/ld10k1/configure.in b/ld10k1/configure.in new file mode 100644 index 0000000..a17076d --- /dev/null +++ b/ld10k1/configure.in @@ -0,0 +1,55 @@ +AC_INIT(src/ld10k1.c) +AM_INIT_AUTOMAKE(ld10k1, 0.1.8) + +AC_CONFIG_HEADERS(config.h) +AC_PROG_CC +AC_PROG_LD +AC_PROG_INSTALL +AC_HEADER_STDC +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AM_PATH_ALSA(1.0.8, [], []) +CFLAGS="$CFLAGS $ALSA_CFLAGS -Wall" +LIBS="$LIBS $ALSA_LIBS" + +effectsdir='$(pkgdatadir)/effects' +AC_SUBST(effectsdir) + +#taken from alsa-lib +dnl Make a symlink for inclusion of lo10k1/xxx.h +if test ! -L include/lo10k1 ; then + echo "Making a symlink include/lo10k1" + rm -f include/lo10k1 + ln -sf . include/lo10k1 +fi + +#taken from aclocal.m4 for alsa-lib - start +AC_DEFUN([SAVE_LIBRARY_VERSION], [ +AC_MSG_CHECKING(for library version) +LD10K1_LIB_VERSION=$VERSION +echo $VERSION > $srcdir/version +AC_DEFINE_UNQUOTED(VERSION, "$LD10K1_LIB_VERSION", [ld10k1 library version string]) +AC_SUBST(LD10K1_LIB_VERSION) +LD10K1_LIB_MAJOR=`echo $VERSION | cut -d . -f 1` +AC_SUBST(LD10K1_LIB_MAJOR) +LD10K1_LIB_MINOR=`echo $VERSION | cut -d . -f 2` +AC_SUBST(LD10K1_LIB_MINOR) +LD10K1_LIB_SUBMINOR=`echo $VERSION | cut -d . -f 3 | sed -e 's/^\([[^[:alpha:]]]*\)\(.*\)$/\1/g'` +AC_SUBST(LD10K1_LIB_SUBMINOR) +AC_MSG_RESULT(major $LD10K1_LIB_MAJOR minor $LD10K1_LIB_MINOR subminor $LD10K1_LIB_SUBMINOR) +AC_SUBST(LD10K1_LIB_EXTRAVER) +]) + +SAVE_LIBRARY_VERSION +#taken from aclocal.m4 for alsa-lib - end + +AC_OUTPUT(Makefile + setup/Makefile + setup/effects/Makefile + doc/Makefile + patch/Makefile + dump/Makefile + contrib/Makefile + contrib/emu10k1MIDIEffects/Makefile + include/Makefile + src/Makefile) diff --git a/ld10k1/contrib/Makefile.am b/ld10k1/contrib/Makefile.am new file mode 100644 index 0000000..f6b01b2 --- /dev/null +++ b/ld10k1/contrib/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = README emu10k1MIDIEffects.tar.gz diff --git a/ld10k1/contrib/README b/ld10k1/contrib/README new file mode 100644 index 0000000..90d2d99 --- /dev/null +++ b/ld10k1/contrib/README @@ -0,0 +1,2 @@ +These files are from holborn (Josep Andreu). +They are for SB Live. \ No newline at end of file diff --git a/ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm new file mode 100644 index 0000000..1bd180d --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS1.asm @@ -0,0 +1,17 @@ + name "3volBUS1" + + + include "emu_constants.asm" +;volBUS1 control #1,0,#1 + +inl IO +inr IO +in3 IO + +out equ inl + + acc3 out,inl,inr,in3 + + end + + diff --git a/ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm new file mode 100644 index 0000000..c37c21c --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/3volBUS2.asm @@ -0,0 +1,18 @@ + name "volBUS2" + + + include "emu_constants.asm" +;volBUS2 control #1,0,#1 + + +inl IO +inr IO +in3 IO +out equ inl + + + acc3 out,inl,inr,in3 + + end + + diff --git a/ld10k1/contrib/emu10k1MIDIEffects/Makefile.am b/ld10k1/contrib/emu10k1MIDIEffects/Makefile.am new file mode 100644 index 0000000..f773708 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/Makefile.am @@ -0,0 +1,34 @@ +EXTRA_DIST = \ + volBUS1.asm \ + 3volBUS2.asm \ + emu_constants.asm \ + freberv.asm \ + gain_4.asm \ + michorusL.asm \ + michorusR.asm \ + volLR.asm \ + emu_constants.inc \ + fv-basstreble.inc \ + fv-controls.inc \ + fv-filters-reduced.inc \ + fv-filters.inc \ + fv-routes.inc \ + refl-big.inc \ + refl-default.inc \ + pontodo5 + +dist_effects_DATA = \ + 3volBUS1.emu10k1 \ + 3volBUS2.emu10k1 \ + freberv.emu10k1 \ + gain_4.emu10k1 \ + michorusL.emu10k1 \ + michorusR.emu10k1 \ + volLR.emu10k1 + +CLEANFILES = $(dist_effects_DATA) + +SUFFIXEC = .asm .emu10k1 + +.asm.emu10k1: + as10k1 -o $@ $< diff --git a/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm new file mode 100644 index 0000000..d385104 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.asm @@ -0,0 +1,117 @@ +;some hardware constants C_[n], 'n' indicates negative value +; +;these are in 2's complement representation + +C_0 equ $040 ;;00000000 +C_1 equ $041 ;;00000001 +C_2 equ $042 ;;00000002 +C_3 equ $043 ;;00000003 +C_4 equ $044 ;;00000004 +C_8 equ $045 ;;00000008 +C_16 equ $046 ;;00000010 +C_32 equ $047 ;;00000020 +C_256 equ $048 ;;00000100 +C_65536 equ $049 ;;00010000 +C_2^23 equ $04A ;;00080000 +C_2^28 equ $04b ;;10000000 +C_2^29 equ $04c ;;20000000 (C_max /4) +1 +C_2^30 equ $04d ;;40000000 ( C_max / 2 ) + 1 (almost half) +C_nmax equ $04e ;;80000000 most negative number +C_max equ $04f ;;7fffffff most positive number +C_n1 equ $050 ;;ffffffff -1 +C_n2 equ $051 ;;fffffffe -2 +C_n2^30 equ $052 ;;c0000000 C_nmax /2 + +C_LSshift equ $55 ;;to left shift an address by using macsints + ;;for fractional addresses + + +ZERO equ C_0; +ONE equ C_1; + +;;; Hardware Registers: + +ACCUM equ $56 +CCR equ $57 +NOISE1 equ $58 +NOISE2 equ $59 +IRQ equ $5A +DBAC equ $5B + +and macro dest,srcA,srcB + andxor dest,srcA,srcB,C_0 + endm + +xor macro dest,srcA,srcB + andxor dest,C_n1,srcA,srcB + endm + +not macro dest,src + andxor dest,src,C_n1,C_n1 + endm + +nand macro dest,srcA,srcB + andxor dest,srcA,srcB,C_n1 + endm + +or macro dest,srcA,srcB + not C_0,srcA + andxor dest,ACCUM,srcA,srcB + endm + +nor macro dest,srcA,scrB + not dest,srcA + andxor dest,srcB,dest,srcA + not dest,dest + endm + + +neg macro dest,src + macs1 dest,C_0,C_1,C_nmax + endm + +;;; branch on: +;;; ==0 +beq macro count + skip CCR,CCR,C_8,count + endm +;;; !=0 +bne macro count + skip CCR,CCR,C_256,count + endm +;;; <0 +blt macro count + skip CCR,CCR,C_4,count + endm +;;; always branch +bra macro count + skip C_0,C_max,C_max,count + endm +;;; on saturation +bsa macro count + skip CCR,CCR,C_16,count + endm +bge macro count +C___80 con $80 + skip CCR,CCR,C___80,count + endm + +bgt macro count +C___180 con $180 + skip CCR,CCR,C___180,count + endm + +move macro dest,src + macs dest,src,C_0,C_0 + endm + + end + +;;; usefull for testing values before a skip +test macro test + macs C_0,test,C_0,C_0 + endm + +cmp macro src1.scr2 + macints C_0,src1,C_n1,src2 + endm diff --git a/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc new file mode 100644 index 0000000..7e07717 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/emu_constants.inc @@ -0,0 +1,118 @@ +;some hardware constants C_[n], 'n' indicates negative value +; +;these are in 2's complement representation + +C_0 equ $040 ;;00000000 +C_1 equ $041 ;;00000001 +C_2 equ $042 ;;00000002 +C_3 equ $043 ;;00000003 +C_4 equ $044 ;;00000004 +C_8 equ $045 ;;00000008 +C_16 equ $046 ;;00000010 +C_32 equ $047 ;;00000020 +C_256 equ $048 ;;00000100 +C_65536 equ $049 ;;00010000 +C_2^23 equ $04A ;;00080000 +C_2^28 equ $04b ;;10000000 +C_2^29 equ $04c ;;20000000 (C_max /4) +1 +C_2^30 equ $04d ;;40000000 ( C_max / 2 ) + 1 (almost half) +C_nmax equ $04e ;;80000000 most negative number +C_max equ $04f ;;7fffffff most positive number +C_n1 equ $050 ;;ffffffff -1 +C_n2 equ $051 ;;fffffffe -2 +C_n2^30 equ $052 ;;c0000000 C_nmax /2 + +C_LSshift equ $55 ;;to left shift an address by using macsints + ;;for fractional addresses + + +ZERO equ C_0; +ONE equ C_1; + +;;; Hardware Registers: + +ACCUM equ $56 +CCR equ $57 +NOISE1 equ $58 +NOISE2 equ $59 +IRQ equ $5A +DBAC equ $5B + +and macro dest,srcA,srcB + andxor dest,srcA,srcB,C_0 + endm + +xor macro dest,srcA,srcB + andxor dest,C_n1,srcA,srcB + endm + +not macro dest,src + andxor dest,src,C_n1,C_n1 + endm + +nand macro dest,srcA,srcB + andxor dest,srcA,srcB,C_n1 + endm + +or macro dest,srcA,srcB + not C_0,srcA + andxor dest,ACCUM,srcA,srcB + endm + +nor macro dest,srcA,scrB + not dest,srcA + andxor dest,srcB,dest,srcA + not dest,dest + endm + + +neg macro dest,src + macs1 dest,C_0,C_1,C_nmax + endm + +;;; branch on: +;;; ==0 +beq macro count + skip CCR,CCR,C_8,count + endm +;;; !=0 +bne macro count + skip CCR,CCR,C_256,count + endm +;;; <0 +blt macro count + skip CCR,CCR,C_4,count + endm +;;; always branch +bra macro count + skip C_0,C_max,C_max,count + endm +;;; on saturation +bsa macro count + skip CCR,CCR,C_16,count + endm +bge macro count +C___80 con $80 + skip CCR,CCR,C___80,count + endm + +bgt macro count +C___180 con $180 + skip CCR,CCR,C___180,count + endm + +move macro dest,src + macs dest,src,C_0,C_0 + endm + + +;;; usefull for testing values before a skip +test macro test + macs C_0,test,C_0,C_0 + endm + +cmp macro src1,scr2 + macints C_0,src1,C_n1,src2 + endm + + end diff --git a/ld10k1/contrib/emu10k1MIDIEffects/freberv.asm b/ld10k1/contrib/emu10k1MIDIEffects/freberv.asm new file mode 100644 index 0000000..3fe1b9e --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/freberv.asm @@ -0,0 +1,156 @@ +;; fv10k1.m4 - fv10k1 package +;; This implements Jezar Wakefield's Freeverb algorithm +;; +;; Copyright (C) 2001 Oleg Smirnov +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv10k1.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + + name "Freeverb" + + include "emu_constants.inc" + include "fv-routes.inc" + include "fv-controls.inc" + include "fv-basstreble.inc" + + ; IO lines right/left +ior io +iol io + + + ; No room reflection support - load full set of Freeverb filters and put + ; them into ITRAM first + include "fv-filters.inc" + ; delay lines for channel & reverb predelay will use XTRAM +dlyr delay &2 +dlyl delay &2 + + +writer twrite dlyr,0 +writel twrite dlyl,0 +oreadr tread dlyr,64 ; use 64 samples to avoid some TRAM glitches +oreadl tread dlyl,64 +revreadr tread dlyr,64 +revreadl tread dlyl,64 + +input dyn 1 ; wet reverb input [== (inl+inr)*gain ] + +dly_b2 sta 0,0 ; storage for second bass/treble filter +dly_t2 sta 0,0 + + +dly_b3 sta 0,0 +dly_t3 sta 0,0 +dly_b4 sta 0,0 +dly_t4 sta 0,0 + +reflr dyn 2 +refll dyn 2 +reverbr dyn 1 +reverbl dyn 1 +ptr dyn 2 +ptl dyn 2 + + + + + + + + ;;; update TRAM read addresses from control GPRs + acc3 oreadr.a,delay_r,writer.a,C_0 + acc3 oreadl.a,delay_l,writel.a,C_0 + acc3 revreadr.a,revdelay,writer.a,C_0 + acc3 revreadl.a,revdelay,writel.a,C_0 + + ;;; init reverb outputs (and clear ACCUM for code below) + macs fvrev_l,C_0,C_0,C_0 + macs fvrev_r,C_0,C_0,C_0 + + ;;; accumulate reverb inputs ( predelayed R+L * revgain ) + ;;; and at the same time pass input to output w/delay + macmv ior,oreadr,revreadr,revgain + macs input,ACCUM,revreadl,revgain + acc3 iol,oreadl,C_0,C_0 + acc3 writer,ior,C_0,C_0 + acc3 writel,iol,C_0,C_0 + + ;;; apply & accumulate comb filters + do_comb_filters fvrev_l,fvrev_r + + ;;; apply allpass filters + do_allpass_filters fvrev_l,fvrev_r + + ;;; feed accumulated values to outputs, multiplying by wet & dry controls + interp tmp,fvrev_l,wet1,fvrev_r + interp tmpout,fvrev_r,wet1,fvrev_l + macs fvrev_l,tmp,revreadl,dry + macs fvrev_r,tmpout,revreadr,dry + + ;;; apply bass/treble controls to output + test revdefeat + bne .skipbasstreble + basstreble fvrev_l,fvrev_l,revbass,revtreble,dly_b1,dly_t1 + basstreble fvrev_r,fvrev_r,revbass,revtreble,dly_b2,dly_t2 +.skipbasstreble + + ;;; reset level meters at specified interval (use DBAC to track it) + andxor tmp,DBAC,level_interval,C_0 + bne .skipreset + acc3 maxlev_fr,C_0,C_0,C_0 + acc3 maxlev_fl,C_0,C_0,C_0 + acc3 maxlev_rr,C_0,C_0,C_0 + acc3 maxlev_rl,C_0,C_0,C_0 +.skipreset + + + ;;; apply reflection levels and bass/treble + macs reflr,C_0,fvrefl_fr,refl_f + macs refll,C_0,fvrefl_fl,refl_f + + macs reflr,reflr,fvrefl_rr,refl_f ; two-speaker mode - add in other line + macs refll,refll,fvrefl_rl,refl_f + + + ;;; apply reverb levels + macs reverbr,C_0,fvrev_r,reverb_f + macs reverbl,C_0,fvrev_l,reverb_f + + + + + ;;; write in+reverb_reflections to output + ;;; use macmv accumulation for extra precision +makeoutput MACRO io,refl,reverb,passthru + macs C_0,C_0,C_0,C_0 + macmv tmp,tmp,refl,C_max + + macmv tmp,C_0,io,ptf_level + + macs io,ACCUM,reverb,C_max + ENDM + makeoutput ior,reflr,reverbr,ptr + makeoutput iol,refll,reverbl,ptl + + ;;; maintain the maximum level +maxlevel MACRO io,maxlev + tstneg tmp,io,io,C_0 ; tmp = abs(io) + limit maxlev,tmp,tmp,maxlev ; maxlevel=max(tmp,maxlevel) + ENDM + maxlevel ior.o,maxlev_fr + maxlevel iol.o,maxlev_fl + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc new file mode 100644 index 0000000..e727673 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/fv-basstreble.inc @@ -0,0 +1,112 @@ +;; fv-basstreble.m4 - fv10k1 package +;; Defines macros for bass/treble filters +;; +;; This is wholly derived from Daniel Bertrand's tone.asm in the emu10k1 +;; driver (see emu10k1/utils/as10k1/effects/tone.asm). +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv-basstreble.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + +;;; a and b coefs for bass: + + +b_b con 2.736129417e-01 5.240710533e-01 2.620355267e-01 +a_b con 9.560258858e-01 -4.576868881e-01 + +;;; a and b coef for treble: +b_t con -4.982305773e-01 9.964611547e-01 -4.982305773e-01 +a_t con 9.317583774e-01 -4.356836381e-01 + +scalein con 2.449e-05, 1.157407407e-04 +scaleout con 128, 16192 + +dly_b1 sta 0,0 +dly_t1 sta 0,0 + +tmp dyn 1 ; miscellaneous temp storage +tmpout dyn 1 + +;;; end of bass/treble definitions + +;;; +;;; This macro applies the bass/treble controls (based on eq2.asm) +;;; +basstreble MACRO dest,source,tone_bass,tone_treble,dly_b,dly_t + ;;; tone_bass filter(iir): + macw tmp, C_0, dly_b+1, a_b+1 + macw tmp, tmp, dly_b , a_b + macw tmp,tmp,source,scalein + macints tmp, C_0, tmp, C_2 + + macs C_0,C_0,C_0,C_0 + macmv dly_b+1,dly_b, dly_b+1, b_b+2 + macmv dly_b,tmp, dly_b, b_b+1 + macw tmp,ACCUM, tmp, b_b + macs tmp,C_0,tone_bass,tmp + macints tmpout,C_0,tmp,scaleout + + ;;; tone_treble + macw tmp, C_0, dly_t+1, a_t+1 + macw tmp, tmp, dly_t , a_t + macw tmp, tmp, source,scalein+1 + macints tmp,C_0,tmp,C_2 + + macs C_0,C_0,C_0,C_0 + macmv dly_t+1,dly_t, dly_t+1, b_t+2 + macmv dly_t,tmp, dly_t, b_t+1 + macw tmp,ACCUM, tmp, b_t + macs tmp,C_0,tone_treble,tmp + + macints dest,tmpout,tmp,scaleout+1 + + ENDM + +;;; +;;; This macro applies the bass/treble controls (based on eq2.asm) +;;; and stores results into two separate GPRs +;;; +basstreblesep MACRO dest_b,dest_t,source,tone_bass,tone_treble,dly_b,dly_t + ;;; tone_bass filter(iir): + macw tmp, C_0, dly_b+1, a_b+1 + macw tmp, tmp, dly_b , a_b + macw tmp,tmp,source,scalein + macints tmp, C_0, tmp, C_2 + + macs C_0,C_0,C_0,C_0 + macmv dly_b+1,dly_b, dly_b+1, b_b+2 + macmv dly_b,tmp, dly_b, b_b+1 + macw tmp,ACCUM, tmp, b_b + macs tmp,C_0,tone_bass,tmp + macints tmpout,C_0,tmp,scaleout + + ;;; tone_treble + macw tmp, C_0, dly_t+1, a_t+1 + macw tmp, tmp, dly_t , a_t + macw tmp, tmp, source,scalein+1 + macints tmp,C_0,tmp,C_2 + + macs C_0,C_0,C_0,C_0 + macmv dly_t+1,dly_t, dly_t+1, b_t+2 + macmv dly_t,tmp, dly_t, b_t+1 + macw tmp,ACCUM, tmp, b_t + macs tmp,C_0,tone_treble,tmp + + macints dest_t,C_0,tmp,scaleout+1 + acc3 dest_b,tmpout,C_0,C_0 + + ENDM + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc new file mode 100644 index 0000000..d2ac8cb --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/fv-controls.inc @@ -0,0 +1,121 @@ +;; fv-controls.asm - fv10k1 package +;; Defines control GPRs for the fv10k1 package +;; +;; Copyright (C) 2001 Oleg Smirnov +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv-controls.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + + ; debugging registers +;debug control #0,#0,#1 +;debug2 control #0,#0,#1 +;debug3 control #0,#0,#1 +;debug4 control #0,#0,#1 + + + ; This delay is applied to the input before passing it through + ; to the output. Note that this is independent of the room reflections + ; or reverb delays, and mainly intended to compensate for pathlength + ; differential in an environment where the speakers are not equidistant + ; from the listening position (i.e. a car!). 1/Vsound is about 3 ms/m. +delay_r control &0,&0,&0.8 +delay_l control &0,&0,&0.8 + + ; high-frequency damping for room reflections +refldamp control #0,#0,#1 + + ; delay for start of reverbrations. Note that this control is ignored + ; when using input patches with a room reflection engine -- there we use + ; a constant revdelay instead. +revdelay control &.002,&0,&1 + + ; gains for "wet" reverbrations +revgain control #0.10,#0,#1 + + ; room size parameter, 0-1. Bigger values produce deeper reverb. +roomsize control #.90,#0,#1 + + ; room dampening 0-1 +damp control #.2,#0,#1 + + ; allpass filter feedback -- normally constant at .5 +allpassfeed control #.2,#0,#1 + + ; "wet1" level controls the amount of left/right reverb intermixing: + ; L = L*(1-wet1) + R*wet1 + ; R = R*(1-wet1) + L*wet1 + ; (original Freeverb uses wet1 and wet2, computed from "wet" and "width": + ; wet1 = wet*(width+1)/2 + ; wet2 = wet*(1-width)/2 ) +wet1 control #0,#0,#1 + + ; "dry" reverb level: + ; output = reverb + input*dry + ; Note that this is somewhat different from the "passthru" level, since + ; reverb bass/treble [and predelay, if any] are applied to the dry signal, + ; but not to the passthru signal +dry control #0,#0,#1 + + ; bass and treble controls for the reverb engine +revbass control #0,#0,#1 +revtreble control #0,#0,#1 + ; set to 1 to skip reverb bass/treble filters +revdefeat control #1,#0,#1 + + ; fractional levels of reflections for F and R speakers +refl_f control #0,#0,#1 +refl_r control #0,#0,#1 + ; additional integer gains for rear reflections +refl_rgain control #0,#0,#1 + + + ; fractional levels of reverbs for F and R speakers +reverb_f control #0.8,#0,#1 +reverb_r control #0.0,#0,#1 + ; additional integer gains for rear reverbs +reverb_rgain control #0,#0,#1 + + ; passthru controls (separate for front/rear) + ; output = input*passthru + reverbs + reflections +ptf_level control #1,#0,#1 +ptr_level control #0,#0,#1 + ; additional integer gains for rear passthru +ptr_gain control #0,#0,#1 + + ; separate bass/treble controls are available for the rear passthrus +ptr_bass control #0,#0,#1 +ptr_treble control #0,#0,#1 +ptr_defeat control #0,#0,1 + + ; Max output level meters. Output patches update these GPRs with the + ; maximum output level encountered. +maxlev_fr control #1,#0,#1 +maxlev_fl control #1,#0,#1 +maxlev_rr control #.0,#0,#1 +maxlev_rl control #.0,#0,#1 + + ; interval at which level meters are reset. For an interval of 2N samples, + ; it should be set to (2^N-1)*$800. + ; The DBAC register is ANDed by this value, and if the result is 0, + ; the meters are reset. $800 corresponds to 1 sample. + ; $0efff00 is 4096 samples + ; $0fffE00 is 8192 samples + ; $1fffC00 is 16384 samples + ; $3fff800 is 32768 samples + ; $7fff800 is 65536 samples +level_interval control $1fffC00,$0,$8000000 + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc new file mode 100644 index 0000000..e7357cd --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters-reduced.inc @@ -0,0 +1,174 @@ +;; fv-filters.m4 - fv10k1 package +;; defines delay lines and GPRs for Freeverb's comb and allpass filters +;; +;; Copyright (C) 2001 Oleg Smirnov +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv-filters.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + +; This is a shorter version that only uses 32 address lines + + + + + + + + + + + + + + + +;;; macro to apply & accumulate a comb filter +comb MACRO dest,rdelay,wdelay,filterstore + acc3 dest,dest,rdelay,C_0 + interp filterstore,rdelay,damp,filterstore + macs wdelay,input,filterstore,roomsize + endm + +;;; macro to apply an allpass filter +allpass MACRO dest,rdelay,wdelay + macs wdelay,dest,rdelay,allpassfeed + macs1 dest,rdelay,dest,C_max + endm + + + + + + + +;;; Freeverb reduced mode - comb filter delay lines go ahead, since for +;;; reduced Freeverb we do not want to use internal TRAM -- it may be out +;;; of address lines thanks to the reflection engine, so external TRAM +;;; is preferrable. Hence longer delays (for comb filters) go first. + +;;; Freeverb reduced mode - 4 comb filters only + +csl5 sta 0 +csr5 sta 0 + +cdl5 delay 1569 +cdr5 delay 1594 +wcdl5 twrite cdl5,0 +wcdr5 twrite cdr5,0 +rcdl5 tread cdl5,1549 +rcdr5 tread cdr5,1574 + + + +csl6 sta 0 +csr6 sta 0 + +cdl6 delay 1645 +cdr6 delay 1670 +wcdl6 twrite cdl6,0 +wcdr6 twrite cdr6,0 +rcdl6 tread cdl6,1625 +rcdr6 tread cdr6,1650 + + + +csl7 sta 0 +csr7 sta 0 + +cdl7 delay 1717 +cdr7 delay 1742 +wcdl7 twrite cdl7,0 +wcdr7 twrite cdr7,0 +rcdl7 tread cdl7,1697 +rcdr7 tread cdr7,1722 + + + +csl8 sta 0 +csr8 sta 0 + +cdl8 delay 1782 +cdr8 delay 1807 +wcdl8 twrite cdl8,0 +wcdr8 twrite cdr8,0 +rcdl8 tread cdl8,1762 +rcdr8 tread cdr8,1787 + + +;;; define macro to apply all comb filters to land r +do_comb_filters MACRO l,r + comb l,rcdl5,wcdl5,csl5 + comb l,rcdl6,wcdl6,csl6 + comb l,rcdl7,wcdl7,csl7 + comb l,rcdl8,wcdl8,csl8 + comb r,rcdr5,wcdr5,csr5 + comb r,rcdr6,wcdr6,csr6 + comb r,rcdr7,wcdr7,csr7 + comb r,rcdr8,wcdr8,csr8 + ENDM + +;;; Now define the allpass filter delay lines +;;; 4 allpass filters + +apl1 delay 626 +apr1 delay 651 +wapl1 twrite apl1,0 +wapr1 twrite apr1,0 +rapl1 tread apl1,606 +rapr1 tread apr1,631 + + + +apl2 delay 500 +apr2 delay 525 +wapl2 twrite apl2,0 +wapr2 twrite apr2,0 +rapl2 tread apl2,480 +rapr2 tread apr2,505 + + + +apl3 delay 391 +apr3 delay 416 +wapl3 twrite apl3,0 +wapr3 twrite apr3,0 +rapl3 tread apl3,371 +rapr3 tread apr3,396 + + + +apl4 delay 265 +apr4 delay 290 +wapl4 twrite apl4,0 +wapr4 twrite apr4,0 +rapl4 tread apl4,245 +rapr4 tread apr4,270 + + +do_allpass_filters MACRO l,r + allpass l,rapl1,wapl1 + allpass l,rapl2,wapl2 + allpass l,rapl3,wapl3 + allpass l,rapl4,wapl4 + allpass r,rapr1,wapr1 + allpass r,rapr2,wapr2 + allpass r,rapr3,wapr3 + allpass r,rapr4,wapr4 + ENDM + + + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc new file mode 100644 index 0000000..12ee8a0 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/fv-filters.inc @@ -0,0 +1,227 @@ +;; fv-filters.m4 - fv10k1 package +;; defines delay lines and GPRs for Freeverb's comb and allpass filters +;; +;; Copyright (C) 2001 Oleg Smirnov +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv-filters.m4,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + + + + + + + + + + + + + + + + + +;;; macro to apply & accumulate a comb filter +comb MACRO dest,rdelay,wdelay,filterstore + acc3 dest,dest,rdelay,C_0 + interp filterstore,rdelay,damp,filterstore + macs wdelay,input,filterstore,roomsize + endm + +;;; macro to apply an allpass filter +allpass MACRO dest,rdelay,wdelay + macs wdelay,dest,rdelay,allpassfeed + macs1 dest,rdelay,dest,C_max + endm + + + + + + +; +;;; Freeverb full mode - allpass filter delay lines go ahead, since +;;; wed rather use internal TRAM. Hence shorter delays go first. +;;; 4 allpass filters + +apl1 delay 626 +apr1 delay 651 +wapl1 twrite apl1,0 +wapr1 twrite apr1,0 +rapl1 tread apl1,606 +rapr1 tread apr1,631 + + + +apl2 delay 500 +apr2 delay 525 +wapl2 twrite apl2,0 +wapr2 twrite apr2,0 +rapl2 tread apl2,480 +rapr2 tread apr2,505 + + + +apl3 delay 391 +apr3 delay 416 +wapl3 twrite apl3,0 +wapr3 twrite apr3,0 +rapl3 tread apl3,371 +rapr3 tread apr3,396 + + + +apl4 delay 265 +apr4 delay 290 +wapl4 twrite apl4,0 +wapr4 twrite apr4,0 +rapl4 tread apl4,245 +rapr4 tread apr4,270 + + +do_allpass_filters MACRO l,r + allpass l,rapl1,wapl1 + allpass l,rapl2,wapl2 + allpass l,rapl3,wapl3 + allpass l,rapl4,wapl4 + allpass r,rapr1,wapr1 + allpass r,rapr2,wapr2 + allpass r,rapr3,wapr3 + allpass r,rapr4,wapr4 + ENDM + +;;; Now define the comb filter delay lines + +;;; Freeverb full mode - 8 comb filters + +csl1 sta 0 +csr1 sta 0 + +cdl1 delay 1236 +cdr1 delay 1261 +wcdl1 twrite cdl1,0 +wcdr1 twrite cdr1,0 +rcdl1 tread cdl1,1216 +rcdr1 tread cdr1,1241 + + + +csl2 sta 0 +csr2 sta 0 + +cdl2 delay 1314 +cdr2 delay 1339 +wcdl2 twrite cdl2,0 +wcdr2 twrite cdr2,0 +rcdl2 tread cdl2,1294 +rcdr2 tread cdr2,1319 + + + +csl3 sta 0 +csr3 sta 0 + +cdl3 delay 1411 +cdr3 delay 1436 +wcdl3 twrite cdl3,0 +wcdr3 twrite cdr3,0 +rcdl3 tread cdl3,1391 +rcdr3 tread cdr3,1416 + + + +csl4 sta 0 +csr4 sta 0 + +cdl4 delay 1498 +cdr4 delay 1523 +wcdl4 twrite cdl4,0 +wcdr4 twrite cdr4,0 +rcdl4 tread cdl4,1478 +rcdr4 tread cdr4,1503 + + + +csl5 sta 0 +csr5 sta 0 + +cdl5 delay 1569 +cdr5 delay 1594 +wcdl5 twrite cdl5,0 +wcdr5 twrite cdr5,0 +rcdl5 tread cdl5,1549 +rcdr5 tread cdr5,1574 + + + +csl6 sta 0 +csr6 sta 0 + +cdl6 delay 1645 +cdr6 delay 1670 +wcdl6 twrite cdl6,0 +wcdr6 twrite cdr6,0 +rcdl6 tread cdl6,1625 +rcdr6 tread cdr6,1650 + + + +csl7 sta 0 +csr7 sta 0 + +cdl7 delay 1717 +cdr7 delay 1742 +wcdl7 twrite cdl7,0 +wcdr7 twrite cdr7,0 +rcdl7 tread cdl7,1697 +rcdr7 tread cdr7,1722 + + + +csl8 sta 0 +csr8 sta 0 + +cdl8 delay 1782 +cdr8 delay 1807 +wcdl8 twrite cdl8,0 +wcdr8 twrite cdr8,0 +rcdl8 tread cdl8,1762 +rcdr8 tread cdr8,1787 + + +do_comb_filters MACRO l,r + comb l,rcdl1,wcdl1,csl1 + comb l,rcdl2,wcdl2,csl2 + comb l,rcdl3,wcdl3,csl3 + comb l,rcdl4,wcdl4,csl4 + comb l,rcdl5,wcdl5,csl5 + comb l,rcdl6,wcdl6,csl6 + comb l,rcdl7,wcdl7,csl7 + comb l,rcdl8,wcdl8,csl8 + comb r,rcdr1,wcdr1,csr1 + comb r,rcdr2,wcdr2,csr2 + comb r,rcdr3,wcdr3,csr3 + comb r,rcdr4,wcdr4,csr4 + comb r,rcdr5,wcdr5,csr5 + comb r,rcdr6,wcdr6,csr6 + comb r,rcdr7,wcdr7,csr7 + comb r,rcdr8,wcdr8,csr8 + ENDM + +;' + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc b/ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc new file mode 100644 index 0000000..a45a9cb --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/fv-routes.inc @@ -0,0 +1,37 @@ +;; fv-routes.asm - fv10k1 package +;; Defines routing GPRs +;; +;; Copyright (C) 2001 Oleg Smirnov +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; $Id: fv-routes.inc,v 1.1 2001/09/28 01:56:20 dbertrand Exp $ + + ; These registers are used to pass samples from the fv10k1 engine. + ; fv10k1 attaches to two (R+L) input lines, and generates three sets + ; of outputs: reverbs, reflections front, reflections rear. + ; Separate output patches are responsible for mixing these outputs + ; into their respective output lines + +fvrev_r control #1,#0,#1 +fvrev_l control #1,#0,#1 + + ; Directional outputs of room reflection engine +fvrefl_fl control #1,#0,#1 +fvrefl_rl control #0,#0,#1 +fvrefl_fr control #1,#0,#1 +fvrefl_rr control #0,#0,#1 + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm b/ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm new file mode 100644 index 0000000..6cb3bd3 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/gain_4.asm @@ -0,0 +1,19 @@ + name "4-channel Gain" + +;;; The next line controls the amount of gain (must be an integer) +gain constant 4 + + +signal1 io +signal2 io +signal3 io +signal4 io + + + macints signal1, $40, signal1, gain ; signal= 0 + signal * gain + macints signal2, $40, signal2, gain + macints signal3, $40, signal3, gain + macints signal4, $40, signal4, gain + + + end diff --git a/ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm b/ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm new file mode 100644 index 0000000..8d279a5 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/michorusL.asm @@ -0,0 +1,87 @@ +;;; Simple Chorus +;;; Author:Daniel Bertrand +;;; Date: Oct 12, 2000 + +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. + +;;; References: +;;; http://www.harmony-central.com/Effects/Articles/Chorus + + +;;; speed(formerly "delta")=2*pi*freq/48000 +;;; this give us our delta value for a specific freq (0.1-0.3Hz is good) + + + include "emu_constants.asm" + name "ChorusL" + +in IO + +outl equ in + + + +speedL control 4e-05 , 0 , 1e-4 ; Controls frequency (radians) +delayL control &32e-3 ,&10e-3 , &80e-3; twice (2*) average delay (sec) +widthL control #0.8 ,0 ,#1 ; width control +mixL control #1 ,0 ,#1 ; forward mix + +;; sine generator storage spaces: +sinx sta 0 +cosx sta #0.5 + +tmp dyn +tmp2 dyn + +;;; Two Delay Lines: + + +dly delay &80e-3 ;10msec delay line + +write twrite dly,0 ; tram writes +ready tread dly,0 ; tram reads +reada tread dly,0 + +;;;The code: + + +;;; two opcode sinewave generator (I love this chip!): + macs sinx,sinx,speedL,cosx + macs1 cosx,cosx,speedL,sinx + +;;; 0.5Asint+0.5: + macs tmp,C_2^30,sinx,widthL + +;;; calculate address: + macs ready.a,write.a,delayL,tmp + +;second addresses for interpolation: +;(interesting how the emu engineers decided that $800 wasn't a needed value) + macints reada.a,ready.a,C_8,C_256 + + +;;; Write to the delay line: + + macs write,C_0,in,C_2^29 + + + +;;; output values: +;;; 0x55 is 00100000 (?) + macints tmp,C_0,reada.a,C_LSshift; get least significant part of address + + interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings + + macs outl,tmp2,tmp2,mixL + + + + end + + + + + diff --git a/ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm b/ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm new file mode 100644 index 0000000..fabe17e --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/michorusR.asm @@ -0,0 +1,87 @@ +;;; Simple Chorus +;;; Author:Daniel Bertrand +;;; Date: Oct 12, 2000 + +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. + +;;; References: +;;; http://www.harmony-central.com/Effects/Articles/Chorus + + +;;; speed(formerly "delta")=2*pi*freq/48000 +;;; this give us our delta value for a specific freq (0.1-0.3Hz is good) + + + include "emu_constants.asm" + name "ChorusR" + +in IO + +outr equ in + + +speedR control 5e-05 , 0 , 1e-4 ; Controls frequency (radians) +delayR control &30e-3 ,&10e-3 , &80e-3; twice (2*) average delay (sec) +widthR control #0.78 ,0 ,#1 ; width control +mixR control #1 ,0 ,#1 ; forward mix + +;; sine generator storage spaces: +sinx sta 0 +cosx sta #0.5 + +tmp dyn +tmp2 dyn + +;;; Two Delay Lines: + + +dly delay &80e-3 ;10msec delay line + +write twrite dly,0 ; tram writes +ready tread dly,0 ; tram reads +reada tread dly,0 + +;;;The code: + + +;;; two opcode sinewave generator (I love this chip!): + macs sinx,sinx,speedR,cosx + macs1 cosx,cosx,speedR,sinx + +;;; 0.5Asint+0.5: + macs tmp,C_2^30,sinx,widthR + +;;; calculate address: + macs ready.a,write.a,delayR,tmp + +;second addresses for interpolation: +;(interesting how the emu engineers decided that $800 wasn't a needed value) + macints reada.a,ready.a,C_8,C_256 + + +;;; Write to the delay line: + + macs write,C_0,in,C_2^29 + + + +;;; output values: +;;; 0x55 is 00100000 (?) + macints tmp,C_0,reada.a,C_LSshift; get least significant part of address + + interp tmp2,ready,tmp,reada ;interpolate in-between the two delay line readings + + macs outr,tmp2,tmp2,mixR + + + + + end + + + + + diff --git a/ld10k1/contrib/emu10k1MIDIEffects/pontodo5 b/ld10k1/contrib/emu10k1MIDIEffects/pontodo5 new file mode 100644 index 0000000..ef2b41b --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/pontodo5 @@ -0,0 +1,64 @@ +#Reset DSP +lo10k1 -s + +#load MASTER L,R +lo10k1 -n -a volLR.emu10k1 + +#load Bus L and BUS R +lo10k1 -n -a 3volBUS1.emu10k1 +lo10k1 -n -a 3volBUS2.emu10k1 + +#load Chorus Effect +lo10k1 -n -a michorusL.emu10k1 +lo10k1 -n -a michorusR.emu10k1 + +#load gain +lo10k1 -n -a gain_4.emu10k1 + +#load reverb +lo10k1 -n -a freberv.emu10k1 + +lo10k1 -q "PIN(5,0)=FX(4)" +lo10k1 -q "PIN(5,1)=FX(5)" +lo10k1 -q "PIN(5,2)=FX(13)" +lo10k1 -q "PIN(5,3)=FX(13)" + +#Input Chorus with FX(13) MIDI_Chorus_FX +lo10k1 -q "PIN(3)=POUT(5,2)" +lo10k1 -q "PIN(4)=POUT(5,3)" + +#reverb + +lo10k1 -q "PIN(6,0)=FX(12)" +lo10k1 -q "PIN(6,1)=FX(12)" + + + +#Mix in BUS L FX_MIDI_Left + Chorus Effect +lo10k1 -q "PIN(1,1)=POUT(5,0)" +lo10k1 -q "PIN(1,0)=POUT(3)" +lo10k1 -q "PIN(1,2)=POUT(6,0)" + +#Mix in BUS R FX:MIDI_Right + Chorus Effect +lo10k1 -q "PIN(2,1)=POUT(5,1)" +lo10k1 -q "PIN(2,0)=POUT(4)" +lo10k1 -q "PIN(2,2)=POUT(6,1)" + + + +#BUS L to Master L +lo10k1 -q "PIN(0,0)=POUT(1,0)" + +#BUS R to Master R +lo10k1 -q "PIN(0,1)=POUT(2,0)" + + + + + +#Master to Ouputs +lo10k1 -q "POUT(0,0)=OUT(0)" +lo10k1 -q "POUT(0,1)=OUT(1)" + + + diff --git a/ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc b/ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc new file mode 100644 index 0000000..298e053 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/refl-big.inc @@ -0,0 +1,337 @@ +;;; FV10K1 room relections code +;;; Generates room reflections according to file big.room.rp, and stores +;;; them in GPRs fvrefl_[fl|fr|rl|rr]. +;;; Built on Sat Jan 24 13:18:00 2004 from room definition file big.room.rp. + + ; define delays and dampening constants +readr0 tread dlyr,&0.070249 +readl0 tread dlyl,&0.070249 +fl0 constant #-0.028783 +fr0 constant #-0.011243 +dmpstore_r0 sta 0,0,0 +dmpstore_l0 sta 0,0,0 +readr1 tread dlyr,&0.070249 +readl1 tread dlyl,&0.070249 +fl1 constant #-0.011243 +fr1 constant #-0.028783 +dmpstore_r1 sta 0,0,0 +dmpstore_l1 sta 0,0,0 +readr2 tread dlyr,&0.059064 +readl2 tread dlyl,&0.059064 +fl2 constant #0.054798 +fr2 constant #0.021405 +dmpstore_r2 sta 0,0 +dmpstore_l2 sta 0,0 +readr3 tread dlyr,&0.059064 +readl3 tread dlyl,&0.059064 +fl3 constant #0.021405 +fr3 constant #0.054798 +dmpstore_r3 sta 0,0 +dmpstore_l3 sta 0,0 +readr4 tread dlyr,&0.001778 +readl4 tread dlyl,&0.001778 +fl4 constant #-0.428866 +fr4 constant #-0.167526 +dmpstore_r4 sta 0 +dmpstore_l4 sta 0 +readr5 tread dlyr,&0.001778 +readl5 tread dlyl,&0.001778 +fl5 constant #-0.167526 +fr5 constant #-0.428866 +dmpstore_r5 sta 0 +dmpstore_l5 sta 0 +readr6 tread dlyr,&0.048126 +readl6 tread dlyl,&0.048126 +fl6 constant #-0.106417 +fr6 constant #-0.041569 +dmpstore_r6 sta 0 +dmpstore_l6 sta 0 +readr7 tread dlyr,&0.048126 +readl7 tread dlyl,&0.048126 +fl7 constant #-0.041569 +fr7 constant #-0.106417 +dmpstore_r7 sta 0 +dmpstore_l7 sta 0 +readr8 tread dlyr,&0.059064 +readl8 tread dlyl,&0.059064 +fl8 constant #0.054798 +fr8 constant #0.021405 +dmpstore_r8 sta 0,0 +dmpstore_l8 sta 0,0 +readr9 tread dlyr,&0.059064 +readl9 tread dlyl,&0.059064 +fl9 constant #0.021405 +fr9 constant #0.054798 +dmpstore_r9 sta 0,0 +dmpstore_l9 sta 0,0 +readr10 tread dlyr,&0.077324 +readl10 tread dlyl,&0.077324 +fr10 constant #-0.047167 +rr10 constant #-0.002611 +dmpstore_r10 sta 0,0,0 +dmpstore_l10 sta 0,0,0 +readr11 tread dlyr,&0.051184 +readl11 tread dlyl,&0.051184 +fr11 constant #0.103186 +rr11 constant #0.012640 +dmpstore_r11 sta 0,0 +dmpstore_l11 sta 0,0 +readr12 tread dlyr,&0.035389 +readl12 tread dlyl,&0.035389 +fr12 constant #0.160243 +rr12 constant #0.008872 +dmpstore_r12 sta 0,0 +dmpstore_l12 sta 0,0 +readr13 tread dlyr,&0.050379 +readl13 tread dlyl,&0.050379 +fr13 constant #-0.161577 +rr13 constant #-0.019793 +dmpstore_r13 sta 0 +dmpstore_l13 sta 0 +readr14 tread dlyr,&0.034414 +readl14 tread dlyl,&0.034414 +fr14 constant #-0.252993 +rr14 constant #-0.014007 +dmpstore_r14 sta 0 +dmpstore_l14 sta 0 +readr15 tread dlyr,&0.079794 +readl15 tread dlyl,&0.079794 +fr15 constant #0.065450 +rr15 constant #0.008018 +dmpstore_r15 sta 0,0 +dmpstore_l15 sta 0,0 +readr16 tread dlyr,&0.068240 +readl16 tread dlyl,&0.068240 +fr16 constant #0.085203 +rr16 constant #0.004717 +dmpstore_r16 sta 0,0 +dmpstore_l16 sta 0,0 +readr17 tread dlyr,&0.077324 +readl17 tread dlyl,&0.077324 +fr17 constant #-0.047167 +rr17 constant #-0.002611 +dmpstore_r17 sta 0,0,0 +dmpstore_l17 sta 0,0,0 + + + ;;; Accumulate reflections for FL + interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0 + interp dmpstore_l0+1,dmpstore_l0+0,refldamp,dmpstore_l0+1 + interp dmpstore_l0+2,dmpstore_l0+1,refldamp,dmpstore_l0+2 + interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0 + interp dmpstore_r0+1,dmpstore_r0+0,refldamp,dmpstore_r0+1 + interp dmpstore_r0+2,dmpstore_r0+1,refldamp,dmpstore_r0+2 + interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0 + interp dmpstore_r1+1,dmpstore_r1+0,refldamp,dmpstore_r1+1 + interp dmpstore_r1+2,dmpstore_r1+1,refldamp,dmpstore_r1+2 + interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0 + interp dmpstore_l1+1,dmpstore_l1+0,refldamp,dmpstore_l1+1 + interp dmpstore_l1+2,dmpstore_l1+1,refldamp,dmpstore_l1+2 + interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0 + interp dmpstore_l2+1,dmpstore_l2+0,refldamp,dmpstore_l2+1 + interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0 + interp dmpstore_r2+1,dmpstore_r2+0,refldamp,dmpstore_r2+1 + interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0 + interp dmpstore_r3+1,dmpstore_r3+0,refldamp,dmpstore_r3+1 + interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0 + interp dmpstore_l3+1,dmpstore_l3+0,refldamp,dmpstore_l3+1 + interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0 + interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0 + interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0 + interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0 + interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0 + interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0 + interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0 + interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0 + interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0 + interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1 + interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0 + interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1 + interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0 + interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1 + interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0 + interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1 + interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0 + interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1 + interp dmpstore_l10+2,dmpstore_l10+1,refldamp,dmpstore_l10+2 + interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0 + interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1 + interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0 + interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1 + interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0 + interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0 + interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0 + interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1 + interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0 + interp dmpstore_l16+1,dmpstore_l16+0,refldamp,dmpstore_l16+1 + interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0 + interp dmpstore_l17+1,dmpstore_l17+0,refldamp,dmpstore_l17+1 + interp dmpstore_l17+2,dmpstore_l17+1,refldamp,dmpstore_l17+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l0+2,fl0 + macmv tmp,C_0,dmpstore_r0+2,fr0 + macmv tmp,C_0,dmpstore_r1+2,fl1 + macmv tmp,C_0,dmpstore_l1+2,fr1 + macmv tmp,C_0,dmpstore_l2+1,fl2 + macmv tmp,C_0,dmpstore_r2+1,fr2 + macmv tmp,C_0,dmpstore_r3+1,fl3 + macmv tmp,C_0,dmpstore_l3+1,fr3 + macmv tmp,C_0,dmpstore_l4+0,fl4 + macmv tmp,C_0,dmpstore_r4+0,fr4 + macmv tmp,C_0,dmpstore_r5+0,fl5 + macmv tmp,C_0,dmpstore_l5+0,fr5 + macmv tmp,C_0,dmpstore_l6+0,fl6 + macmv tmp,C_0,dmpstore_r6+0,fr6 + macmv tmp,C_0,dmpstore_r7+0,fl7 + macmv tmp,C_0,dmpstore_l7+0,fr7 + macmv tmp,C_0,dmpstore_l8+1,fl8 + macmv tmp,C_0,dmpstore_r8+1,fr8 + macmv tmp,C_0,dmpstore_r9+1,fl9 + macmv tmp,C_0,dmpstore_l9+1,fr9 + macmv tmp,C_0,dmpstore_l10+2,fr10 + macmv tmp,C_0,dmpstore_r11+1,fr11 + macmv tmp,C_0,dmpstore_l12+1,fr12 + macmv tmp,C_0,dmpstore_r13+0,fr13 + macmv tmp,C_0,dmpstore_l14+0,fr14 + macmv tmp,C_0,dmpstore_r15+1,fr15 + macmv tmp,C_0,dmpstore_l16+1,fr16 + macs fvrefl_fl,ACCUM,dmpstore_l17+2,fr17 + + ;;; Accumulate reflections for FR + interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0 + interp dmpstore_l0+1,dmpstore_l0+0,refldamp,dmpstore_l0+1 + interp dmpstore_l0+2,dmpstore_l0+1,refldamp,dmpstore_l0+2 + interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0 + interp dmpstore_r0+1,dmpstore_r0+0,refldamp,dmpstore_r0+1 + interp dmpstore_r0+2,dmpstore_r0+1,refldamp,dmpstore_r0+2 + interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0 + interp dmpstore_r1+1,dmpstore_r1+0,refldamp,dmpstore_r1+1 + interp dmpstore_r1+2,dmpstore_r1+1,refldamp,dmpstore_r1+2 + interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0 + interp dmpstore_l1+1,dmpstore_l1+0,refldamp,dmpstore_l1+1 + interp dmpstore_l1+2,dmpstore_l1+1,refldamp,dmpstore_l1+2 + interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0 + interp dmpstore_l2+1,dmpstore_l2+0,refldamp,dmpstore_l2+1 + interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0 + interp dmpstore_r2+1,dmpstore_r2+0,refldamp,dmpstore_r2+1 + interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0 + interp dmpstore_r3+1,dmpstore_r3+0,refldamp,dmpstore_r3+1 + interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0 + interp dmpstore_l3+1,dmpstore_l3+0,refldamp,dmpstore_l3+1 + interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0 + interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0 + interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0 + interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0 + interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0 + interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0 + interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0 + interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0 + interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0 + interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1 + interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0 + interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1 + interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0 + interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1 + interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0 + interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1 + interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0 + interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1 + interp dmpstore_r10+2,dmpstore_r10+1,refldamp,dmpstore_r10+2 + interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0 + interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1 + interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0 + interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1 + interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0 + interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0 + interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0 + interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1 + interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0 + interp dmpstore_r16+1,dmpstore_r16+0,refldamp,dmpstore_r16+1 + interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0 + interp dmpstore_r17+1,dmpstore_r17+0,refldamp,dmpstore_r17+1 + interp dmpstore_r17+2,dmpstore_r17+1,refldamp,dmpstore_r17+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l0+2,fr0 + macmv tmp,C_0,dmpstore_r0+2,fl0 + macmv tmp,C_0,dmpstore_r1+2,fr1 + macmv tmp,C_0,dmpstore_l1+2,fl1 + macmv tmp,C_0,dmpstore_l2+1,fr2 + macmv tmp,C_0,dmpstore_r2+1,fl2 + macmv tmp,C_0,dmpstore_r3+1,fr3 + macmv tmp,C_0,dmpstore_l3+1,fl3 + macmv tmp,C_0,dmpstore_l4+0,fr4 + macmv tmp,C_0,dmpstore_r4+0,fl4 + macmv tmp,C_0,dmpstore_r5+0,fr5 + macmv tmp,C_0,dmpstore_l5+0,fl5 + macmv tmp,C_0,dmpstore_l6+0,fr6 + macmv tmp,C_0,dmpstore_r6+0,fl6 + macmv tmp,C_0,dmpstore_r7+0,fr7 + macmv tmp,C_0,dmpstore_l7+0,fl7 + macmv tmp,C_0,dmpstore_l8+1,fr8 + macmv tmp,C_0,dmpstore_r8+1,fl8 + macmv tmp,C_0,dmpstore_r9+1,fr9 + macmv tmp,C_0,dmpstore_l9+1,fl9 + macmv tmp,C_0,dmpstore_r10+2,fr10 + macmv tmp,C_0,dmpstore_l11+1,fr11 + macmv tmp,C_0,dmpstore_r12+1,fr12 + macmv tmp,C_0,dmpstore_l13+0,fr13 + macmv tmp,C_0,dmpstore_r14+0,fr14 + macmv tmp,C_0,dmpstore_l15+1,fr15 + macmv tmp,C_0,dmpstore_r16+1,fr16 + macs fvrefl_fr,ACCUM,dmpstore_r17+2,fr17 + + ;;; Accumulate reflections for RL + interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0 + interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1 + interp dmpstore_l10+2,dmpstore_l10+1,refldamp,dmpstore_l10+2 + interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0 + interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1 + interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0 + interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1 + interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0 + interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0 + interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0 + interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1 + interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0 + interp dmpstore_l16+1,dmpstore_l16+0,refldamp,dmpstore_l16+1 + interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0 + interp dmpstore_l17+1,dmpstore_l17+0,refldamp,dmpstore_l17+1 + interp dmpstore_l17+2,dmpstore_l17+1,refldamp,dmpstore_l17+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l10+2,rr10 + macmv tmp,C_0,dmpstore_r11+1,rr11 + macmv tmp,C_0,dmpstore_l12+1,rr12 + macmv tmp,C_0,dmpstore_r13+0,rr13 + macmv tmp,C_0,dmpstore_l14+0,rr14 + macmv tmp,C_0,dmpstore_r15+1,rr15 + macmv tmp,C_0,dmpstore_l16+1,rr16 + macs fvrefl_rl,ACCUM,dmpstore_l17+2,rr17 + + ;;; Accumulate reflections for RR + interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0 + interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1 + interp dmpstore_r10+2,dmpstore_r10+1,refldamp,dmpstore_r10+2 + interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0 + interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1 + interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0 + interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1 + interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0 + interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0 + interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0 + interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1 + interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0 + interp dmpstore_r16+1,dmpstore_r16+0,refldamp,dmpstore_r16+1 + interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0 + interp dmpstore_r17+1,dmpstore_r17+0,refldamp,dmpstore_r17+1 + interp dmpstore_r17+2,dmpstore_r17+1,refldamp,dmpstore_r17+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_r10+2,rr10 + macmv tmp,C_0,dmpstore_l11+1,rr11 + macmv tmp,C_0,dmpstore_r12+1,rr12 + macmv tmp,C_0,dmpstore_l13+0,rr13 + macmv tmp,C_0,dmpstore_r14+0,rr14 + macmv tmp,C_0,dmpstore_l15+1,rr15 + macmv tmp,C_0,dmpstore_r16+1,rr16 + macs fvrefl_rr,ACCUM,dmpstore_r17+2,rr17 + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc b/ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc new file mode 100644 index 0000000..30e7d6b --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/refl-default.inc @@ -0,0 +1,320 @@ +;;; FV10K1 room relections code +;;; Generates room reflections according to file default.room.rp, and stores +;;; them in GPRs fvrefl_[fl|fr|rl|rr]. +;;; Built on Sat Jan 24 13:18:00 2004 from room definition file default.room.rp. + + ; define delays and dampening constants +readr0 tread dlyr,&0.003511 +readl0 tread dlyl,&0.003511 +fl0 constant #-0.371429 +fr0 constant #-0.092857 +dmpstore_r0 sta 0 +dmpstore_l0 sta 0 +readr1 tread dlyr,&0.003511 +readl1 tread dlyl,&0.003511 +fl1 constant #-0.092857 +fr1 constant #-0.371429 +dmpstore_r1 sta 0 +dmpstore_l1 sta 0 +readr2 tread dlyr,&0.006548 +readl2 tread dlyl,&0.006548 +fr2 constant #-0.508333 +dmpstore_r2 sta 0 +dmpstore_l2 sta 0 +readr3 tread dlyr,&0.007252 +readl3 tread dlyl,&0.007252 +fl3 constant #-0.298947 +fr3 constant #-0.074737 +dmpstore_r3 sta 0 +dmpstore_l3 sta 0 +readr4 tread dlyr,&0.007252 +readl4 tread dlyl,&0.007252 +fl4 constant #-0.074737 +fr4 constant #-0.298947 +dmpstore_r4 sta 0 +dmpstore_l4 sta 0 +readr5 tread dlyr,&0.009261 +readl5 tread dlyl,&0.009261 +fr5 constant #0.270341 +dmpstore_r5 sta 0,0 +dmpstore_l5 sta 0,0 +readr6 tread dlyr,&0.012327 +readl6 tread dlyl,&0.012327 +fr6 constant #0.240611 +dmpstore_r6 sta 0,0 +dmpstore_l6 sta 0,0 +readr7 tread dlyr,&0.016174 +readl7 tread dlyl,&0.016174 +fr7 constant #-0.253287 +rr7 constant #-0.015830 +dmpstore_r7 sta 0 +dmpstore_l7 sta 0 +readr8 tread dlyr,&0.016690 +readl8 tread dlyl,&0.016690 +fl8 constant #0.105486 +fr8 constant #0.026371 +dmpstore_r8 sta 0,0 +dmpstore_l8 sta 0,0 +readr9 tread dlyr,&0.016690 +readl9 tread dlyl,&0.016690 +fl9 constant #0.026371 +fr9 constant #0.105486 +dmpstore_r9 sta 0,0 +dmpstore_l9 sta 0,0 +readr10 tread dlyr,&0.016690 +readl10 tread dlyl,&0.016690 +fl10 constant #0.105486 +fr10 constant #0.026371 +dmpstore_r10 sta 0,0 +dmpstore_l10 sta 0,0 +readr11 tread dlyr,&0.016690 +readl11 tread dlyl,&0.016690 +fl11 constant #0.026371 +fr11 constant #0.105486 +dmpstore_r11 sta 0,0 +dmpstore_l11 sta 0,0 +readr12 tread dlyr,&0.018195 +readl12 tread dlyl,&0.018195 +fr12 constant #0.147307 +rr12 constant #0.009207 +dmpstore_r12 sta 0,0 +dmpstore_l12 sta 0,0 +readr13 tread dlyr,&0.020577 +readl13 tread dlyl,&0.020577 +fr13 constant #-0.098203 +dmpstore_r13 sta 0,0,0 +dmpstore_l13 sta 0,0,0 +readr14 tread dlyr,&0.020577 +readl14 tread dlyl,&0.020577 +fr14 constant #0.142194 +rr14 constant #0.008887 +dmpstore_r14 sta 0,0 +dmpstore_l14 sta 0,0 +readr15 tread dlyr,&0.020577 +readl15 tread dlyl,&0.020577 +fr15 constant #-0.098203 +dmpstore_r15 sta 0,0,0 +dmpstore_l15 sta 0,0,0 +readr16 tread dlyr,&0.021591 +readl16 tread dlyl,&0.021591 +rl16 constant #-0.130920 +rr16 constant #-0.071413 +dmpstore_r16 sta 0 +dmpstore_l16 sta 0 +readr17 tread dlyr,&0.021591 +readl17 tread dlyl,&0.021591 +rl17 constant #-0.071413 +rr17 constant #-0.130920 +dmpstore_r17 sta 0 +dmpstore_l17 sta 0 +readr18 tread dlyr,&0.023355 +readl18 tread dlyl,&0.023355 +rl18 constant #0.078182 +rr18 constant #0.042646 +dmpstore_r18 sta 0,0 +dmpstore_l18 sta 0,0 +readr19 tread dlyr,&0.023355 +readl19 tread dlyl,&0.023355 +rl19 constant #0.042646 +rr19 constant #0.078182 +dmpstore_r19 sta 0,0 +dmpstore_l19 sta 0,0 + + + ;;; Accumulate reflections for FL + interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0 + interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0 + interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0 + interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0 + interp dmpstore_l2+0,readl2,refldamp,dmpstore_l2+0 + interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0 + interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0 + interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0 + interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0 + interp dmpstore_l5+0,readl5,refldamp,dmpstore_l5+0 + interp dmpstore_l5+1,dmpstore_l5+0,refldamp,dmpstore_l5+1 + interp dmpstore_l6+0,readl6,refldamp,dmpstore_l6+0 + interp dmpstore_l6+1,dmpstore_l6+0,refldamp,dmpstore_l6+1 + interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0 + interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0 + interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1 + interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0 + interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1 + interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0 + interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1 + interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0 + interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1 + interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0 + interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1 + interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0 + interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1 + interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0 + interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1 + interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0 + interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1 + interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0 + interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1 + interp dmpstore_l13+0,readl13,refldamp,dmpstore_l13+0 + interp dmpstore_l13+1,dmpstore_l13+0,refldamp,dmpstore_l13+1 + interp dmpstore_l13+2,dmpstore_l13+1,refldamp,dmpstore_l13+2 + interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0 + interp dmpstore_r14+1,dmpstore_r14+0,refldamp,dmpstore_r14+1 + interp dmpstore_l15+0,readl15,refldamp,dmpstore_l15+0 + interp dmpstore_l15+1,dmpstore_l15+0,refldamp,dmpstore_l15+1 + interp dmpstore_l15+2,dmpstore_l15+1,refldamp,dmpstore_l15+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l0+0,fl0 + macmv tmp,C_0,dmpstore_r0+0,fr0 + macmv tmp,C_0,dmpstore_r1+0,fl1 + macmv tmp,C_0,dmpstore_l1+0,fr1 + macmv tmp,C_0,dmpstore_l2+0,fr2 + macmv tmp,C_0,dmpstore_l3+0,fl3 + macmv tmp,C_0,dmpstore_r3+0,fr3 + macmv tmp,C_0,dmpstore_r4+0,fl4 + macmv tmp,C_0,dmpstore_l4+0,fr4 + macmv tmp,C_0,dmpstore_l5+1,fr5 + macmv tmp,C_0,dmpstore_l6+1,fr6 + macmv tmp,C_0,dmpstore_r7+0,fr7 + macmv tmp,C_0,dmpstore_l8+1,fl8 + macmv tmp,C_0,dmpstore_r8+1,fr8 + macmv tmp,C_0,dmpstore_r9+1,fl9 + macmv tmp,C_0,dmpstore_l9+1,fr9 + macmv tmp,C_0,dmpstore_l10+1,fl10 + macmv tmp,C_0,dmpstore_r10+1,fr10 + macmv tmp,C_0,dmpstore_r11+1,fl11 + macmv tmp,C_0,dmpstore_l11+1,fr11 + macmv tmp,C_0,dmpstore_r12+1,fr12 + macmv tmp,C_0,dmpstore_l13+2,fr13 + macmv tmp,C_0,dmpstore_r14+1,fr14 + macs fvrefl_fl,ACCUM,dmpstore_l15+2,fr15 + + ;;; Accumulate reflections for FR + interp dmpstore_l0+0,readl0,refldamp,dmpstore_l0+0 + interp dmpstore_r0+0,readr0,refldamp,dmpstore_r0+0 + interp dmpstore_r1+0,readr1,refldamp,dmpstore_r1+0 + interp dmpstore_l1+0,readl1,refldamp,dmpstore_l1+0 + interp dmpstore_r2+0,readr2,refldamp,dmpstore_r2+0 + interp dmpstore_l3+0,readl3,refldamp,dmpstore_l3+0 + interp dmpstore_r3+0,readr3,refldamp,dmpstore_r3+0 + interp dmpstore_r4+0,readr4,refldamp,dmpstore_r4+0 + interp dmpstore_l4+0,readl4,refldamp,dmpstore_l4+0 + interp dmpstore_r5+0,readr5,refldamp,dmpstore_r5+0 + interp dmpstore_r5+1,dmpstore_r5+0,refldamp,dmpstore_r5+1 + interp dmpstore_r6+0,readr6,refldamp,dmpstore_r6+0 + interp dmpstore_r6+1,dmpstore_r6+0,refldamp,dmpstore_r6+1 + interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0 + interp dmpstore_l8+0,readl8,refldamp,dmpstore_l8+0 + interp dmpstore_l8+1,dmpstore_l8+0,refldamp,dmpstore_l8+1 + interp dmpstore_r8+0,readr8,refldamp,dmpstore_r8+0 + interp dmpstore_r8+1,dmpstore_r8+0,refldamp,dmpstore_r8+1 + interp dmpstore_r9+0,readr9,refldamp,dmpstore_r9+0 + interp dmpstore_r9+1,dmpstore_r9+0,refldamp,dmpstore_r9+1 + interp dmpstore_l9+0,readl9,refldamp,dmpstore_l9+0 + interp dmpstore_l9+1,dmpstore_l9+0,refldamp,dmpstore_l9+1 + interp dmpstore_l10+0,readl10,refldamp,dmpstore_l10+0 + interp dmpstore_l10+1,dmpstore_l10+0,refldamp,dmpstore_l10+1 + interp dmpstore_r10+0,readr10,refldamp,dmpstore_r10+0 + interp dmpstore_r10+1,dmpstore_r10+0,refldamp,dmpstore_r10+1 + interp dmpstore_r11+0,readr11,refldamp,dmpstore_r11+0 + interp dmpstore_r11+1,dmpstore_r11+0,refldamp,dmpstore_r11+1 + interp dmpstore_l11+0,readl11,refldamp,dmpstore_l11+0 + interp dmpstore_l11+1,dmpstore_l11+0,refldamp,dmpstore_l11+1 + interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0 + interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1 + interp dmpstore_r13+0,readr13,refldamp,dmpstore_r13+0 + interp dmpstore_r13+1,dmpstore_r13+0,refldamp,dmpstore_r13+1 + interp dmpstore_r13+2,dmpstore_r13+1,refldamp,dmpstore_r13+2 + interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0 + interp dmpstore_l14+1,dmpstore_l14+0,refldamp,dmpstore_l14+1 + interp dmpstore_r15+0,readr15,refldamp,dmpstore_r15+0 + interp dmpstore_r15+1,dmpstore_r15+0,refldamp,dmpstore_r15+1 + interp dmpstore_r15+2,dmpstore_r15+1,refldamp,dmpstore_r15+2 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l0+0,fr0 + macmv tmp,C_0,dmpstore_r0+0,fl0 + macmv tmp,C_0,dmpstore_r1+0,fr1 + macmv tmp,C_0,dmpstore_l1+0,fl1 + macmv tmp,C_0,dmpstore_r2+0,fr2 + macmv tmp,C_0,dmpstore_l3+0,fr3 + macmv tmp,C_0,dmpstore_r3+0,fl3 + macmv tmp,C_0,dmpstore_r4+0,fr4 + macmv tmp,C_0,dmpstore_l4+0,fl4 + macmv tmp,C_0,dmpstore_r5+1,fr5 + macmv tmp,C_0,dmpstore_r6+1,fr6 + macmv tmp,C_0,dmpstore_l7+0,fr7 + macmv tmp,C_0,dmpstore_l8+1,fr8 + macmv tmp,C_0,dmpstore_r8+1,fl8 + macmv tmp,C_0,dmpstore_r9+1,fr9 + macmv tmp,C_0,dmpstore_l9+1,fl9 + macmv tmp,C_0,dmpstore_l10+1,fr10 + macmv tmp,C_0,dmpstore_r10+1,fl10 + macmv tmp,C_0,dmpstore_r11+1,fr11 + macmv tmp,C_0,dmpstore_l11+1,fl11 + macmv tmp,C_0,dmpstore_l12+1,fr12 + macmv tmp,C_0,dmpstore_r13+2,fr13 + macmv tmp,C_0,dmpstore_l14+1,fr14 + macs fvrefl_fr,ACCUM,dmpstore_r15+2,fr15 + + ;;; Accumulate reflections for RL + interp dmpstore_r7+0,readr7,refldamp,dmpstore_r7+0 + interp dmpstore_r12+0,readr12,refldamp,dmpstore_r12+0 + interp dmpstore_r12+1,dmpstore_r12+0,refldamp,dmpstore_r12+1 + interp dmpstore_r14+0,readr14,refldamp,dmpstore_r14+0 + interp dmpstore_r14+1,dmpstore_r14+0,refldamp,dmpstore_r14+1 + interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0 + interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0 + interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0 + interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0 + interp dmpstore_l18+0,readl18,refldamp,dmpstore_l18+0 + interp dmpstore_l18+1,dmpstore_l18+0,refldamp,dmpstore_l18+1 + interp dmpstore_r18+0,readr18,refldamp,dmpstore_r18+0 + interp dmpstore_r18+1,dmpstore_r18+0,refldamp,dmpstore_r18+1 + interp dmpstore_r19+0,readr19,refldamp,dmpstore_r19+0 + interp dmpstore_r19+1,dmpstore_r19+0,refldamp,dmpstore_r19+1 + interp dmpstore_l19+0,readl19,refldamp,dmpstore_l19+0 + interp dmpstore_l19+1,dmpstore_l19+0,refldamp,dmpstore_l19+1 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_r7+0,rr7 + macmv tmp,C_0,dmpstore_r12+1,rr12 + macmv tmp,C_0,dmpstore_r14+1,rr14 + macmv tmp,C_0,dmpstore_l16+0,rl16 + macmv tmp,C_0,dmpstore_r16+0,rr16 + macmv tmp,C_0,dmpstore_r17+0,rl17 + macmv tmp,C_0,dmpstore_l17+0,rr17 + macmv tmp,C_0,dmpstore_l18+1,rl18 + macmv tmp,C_0,dmpstore_r18+1,rr18 + macmv tmp,C_0,dmpstore_r19+1,rl19 + macs fvrefl_rl,ACCUM,dmpstore_l19+1,rr19 + + ;;; Accumulate reflections for RR + interp dmpstore_l7+0,readl7,refldamp,dmpstore_l7+0 + interp dmpstore_l12+0,readl12,refldamp,dmpstore_l12+0 + interp dmpstore_l12+1,dmpstore_l12+0,refldamp,dmpstore_l12+1 + interp dmpstore_l14+0,readl14,refldamp,dmpstore_l14+0 + interp dmpstore_l14+1,dmpstore_l14+0,refldamp,dmpstore_l14+1 + interp dmpstore_l16+0,readl16,refldamp,dmpstore_l16+0 + interp dmpstore_r16+0,readr16,refldamp,dmpstore_r16+0 + interp dmpstore_r17+0,readr17,refldamp,dmpstore_r17+0 + interp dmpstore_l17+0,readl17,refldamp,dmpstore_l17+0 + interp dmpstore_l18+0,readl18,refldamp,dmpstore_l18+0 + interp dmpstore_l18+1,dmpstore_l18+0,refldamp,dmpstore_l18+1 + interp dmpstore_r18+0,readr18,refldamp,dmpstore_r18+0 + interp dmpstore_r18+1,dmpstore_r18+0,refldamp,dmpstore_r18+1 + interp dmpstore_r19+0,readr19,refldamp,dmpstore_r19+0 + interp dmpstore_r19+1,dmpstore_r19+0,refldamp,dmpstore_r19+1 + interp dmpstore_l19+0,readl19,refldamp,dmpstore_l19+0 + interp dmpstore_l19+1,dmpstore_l19+0,refldamp,dmpstore_l19+1 + macs C_0,C_0,C_0,C_0 ; reset accumulator + macmv tmp,C_0,dmpstore_l7+0,rr7 + macmv tmp,C_0,dmpstore_l12+1,rr12 + macmv tmp,C_0,dmpstore_l14+1,rr14 + macmv tmp,C_0,dmpstore_l16+0,rr16 + macmv tmp,C_0,dmpstore_r16+0,rl16 + macmv tmp,C_0,dmpstore_r17+0,rr17 + macmv tmp,C_0,dmpstore_l17+0,rl17 + macmv tmp,C_0,dmpstore_l18+1,rr18 + macmv tmp,C_0,dmpstore_r18+1,rl18 + macmv tmp,C_0,dmpstore_r19+1,rr19 + macs fvrefl_rr,ACCUM,dmpstore_l19+1,rl19 + + END diff --git a/ld10k1/contrib/emu10k1MIDIEffects/volLR.asm b/ld10k1/contrib/emu10k1MIDIEffects/volLR.asm new file mode 100644 index 0000000..f2041f0 --- /dev/null +++ b/ld10k1/contrib/emu10k1MIDIEffects/volLR.asm @@ -0,0 +1,16 @@ + name "volLR" + + + include "emu_constants.asm" +volLR control #1,0,#1 + +inl IO +inr IO +outl equ inl +outr equ inr + + macs outl,inl.o,inl,volLR + macs outr,inr.o,inr,volLR + end + + diff --git a/ld10k1/cvscompile b/ld10k1/cvscompile new file mode 100644 index 0000000..3a5537d --- /dev/null +++ b/ld10k1/cvscompile @@ -0,0 +1,25 @@ +#!/bin/bash + +if test "x$AUTOMAKE_DIR" = "x"; then + if test -d /usr/local/share/automake; then + AUTOMAKE_DIR=/usr/local/share/automake + fi + if test -d /usr/share/automake; then + AUTOMAKE_DIR="/usr/share/automake" + fi +fi + +for f in install-sh mkinstalldirs missing; do + cp -av $AUTOMAKE_DIR/$f . +done + +aclocal $ACLOCAL_FLAGS +automake --add-missing --copy +touch depcomp +autoconf +export CFLAGS='-O2 -Wall -pipe -g' +echo "CFLAGS=$CFLAGS" +echo "./configure $@" +./configure $@ +unset CFLAGS +make diff --git a/ld10k1/doc/Audigy-mixer.txt b/ld10k1/doc/Audigy-mixer.txt new file mode 100644 index 0000000..5132fd9 --- /dev/null +++ b/ld10k1/doc/Audigy-mixer.txt @@ -0,0 +1,345 @@ + + Sound Blaster Audigy mixer / default DSP code + =========================================== + +This is based on SB-Live-mixer.txt. + +The EMU10K2 chips have a DSP part which can be programmed to support +various ways of sample processing, which is described here. +(This acticle does not deal with the overall functionality of the +EMU10K2 chips. See the manuals section for further details.) + +The ALSA driver programs this portion of chip by default code +(can be altered later) which offers the following functionality: + + +1) Digital mixer controls +------------------------- + +These controls are built using the DSP instructions. They offer extended +functionality. Only the default build-in code in the ALSA driver is described +here. Note that the controls work as attenuators: the maximum value is the +neutral position leaving the signal unchanged. Note that if the same destination +is mentioned in multiple controls, the signal is accumulated and can be wrapped +(set to maximal or minimal value without checking of overflow). + + +Explanation of used abbreviations: + +DAC - digital to analog converter +ADC - analog to digital converter +I2S - one-way three wire serial bus for digital sound by Philips Semiconductors + (this standard is used for connecting standalone DAC and ADC converters) +LFE - low frequency effects (subwoofer signal) +AC97 - a chip containing an analog mixer, DAC and ADC converters +IEC958 - S/PDIF +FX-bus - the EMU10K2 chip has an effect bus containing 64 accumulators. + Each of the synthesizer voices can feed its output to these accumulators + and the DSP microcontroller can operate with the resulting sum. + +name='PCM Front Playback Volume',index=0 + +This control is used to attenuate samples for left and right front PCM FX-bus +accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM +samples for 5.1 playback. The result samples are forwarded to the front DAC PCM +slots of the Philips DAC. + +name='PCM Surround Playback Volume',index=0 + +This control is used to attenuate samples for left and right surround PCM FX-bus +accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM +samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM +slots of the Philips DAC. + +name='PCM Center Playback Volume',index=0 + +This control is used to attenuate samples for center PCM FX-bus accumulator. +ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample +is forwarded to the center DAC PCM slot of the Philips DAC. + +name='PCM LFE Playback Volume',index=0 + +This control is used to attenuate sample for LFE PCM FX-bus accumulator. +ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample +is forwarded to the LFE DAC PCM slot of the Philips DAC. + +name='PCM Playback Volume',index=0 + +This control is used to attenuate samples for left and right PCM FX-bus +accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for +stereo playback. The result samples are forwarded to the front DAC PCM slots +of the Philips DAC. + +name='PCM Capture Volume',index=0 + +This control is used to attenuate samples for left and right PCM FX-bus +accumulator. ALSA uses accumulators 0 and 1 for left and right PCM. +The result is forwarded to the ADC capture FIFO (thus to the standard capture +PCM device). + +name='Music Playback Volume',index=0 + +This control is used to attenuate samples for left and right MIDI FX-bus +accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples. +The result samples are forwarded to the front DAC PCM slots of the AC97 codec. + +name='Music Capture Volume',index=0 + +These controls are used to attenuate samples for left and right MIDI FX-bus +accumulator. ALSA uses accumulators 4 and 5 for left and right PCM. +The result is forwarded to the ADC capture FIFO (thus to the standard capture +PCM device). + +name='Mic Playback Volume',index=0 + +This control is used to attenuate samples for left and right Mic input. +For Mic input is used AC97 codec. The result samples are forwarded to +the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic +capture FIFO (device 1 - 16bit/8KHz mono) too without volume control. + +name='Mic Capture Volume',index=0 + +This control is used to attenuate samples for left and right Mic input. +The result is forwarded to the ADC capture FIFO (thus to the standard capture +PCM device). + +name='Audigy CD Playback Volume',index=0 + +This control is used to attenuate samples from left and right IEC958 TTL +digital inputs (usually used by a CDROM drive). The result samples are +forwarded to the front DAC PCM slots of the Philips DAC. + +name='Audigy CD Capture Volume',index=0 + +This control is used to attenuate samples from left and right IEC958 TTL +digital inputs (usually used by a CDROM drive). The result samples are +forwarded to the ADC capture FIFO (thus to the standard capture PCM device). + +name='IEC958 Optical Playback Volume',index=0 + +This control is used to attenuate samples from left and right IEC958 optical +digital input. The result samples are forwarded to the front DAC PCM slots +of the Philips DAC. + +name='IEC958 Optical Capture Volume',index=0 + +This control is used to attenuate samples from left and right IEC958 optical +digital inputs. The result samples are forwarded to the ADC capture FIFO +(thus to the standard capture PCM device). + +name='Line2 Playback Volume',index=0 + +This control is used to attenuate samples from left and right I2S ADC +inputs (on the AudigyDrive). The result samples are forwarded to the front +DAC PCM slots of the Philips DAC. + +name='Line2 Capture Volume',index=1 + +This control is used to attenuate samples from left and right I2S ADC +inputs (on the AudigyDrive). The result samples are forwarded to the ADC +capture FIFO (thus to the standard capture PCM device). + +name='Analog Mix Playback Volume',index=0 + +This control is used to attenuate samples from left and right I2S ADC +inputs from Philips ADC. The result samples are forwarded to the front +DAC PCM slots of the Philips DAC. This contains mix from analog sources +like CD, Line In, Aux, .... + +name='Analog Mix Capture Volume',index=1 + +This control is used to attenuate samples from left and right I2S ADC +inputs Philips ADC. The result samples are forwarded to the ADC +capture FIFO (thus to the standard capture PCM device). + +name='Aux2 Playback Volume',index=0 + +This control is used to attenuate samples from left and right I2S ADC +inputs (on the AudigyDrive). The result samples are forwarded to the front +DAC PCM slots of the Philips DAC. + +name='Aux2 Capture Volume',index=1 + +This control is used to attenuate samples from left and right I2S ADC +inputs (on the AudigyDrive). The result samples are forwarded to the ADC +capture FIFO (thus to the standard capture PCM device). + +name='Front Playback Volume',index=0 + +All stereo signals are mixed together and mirrored to surround, center and LFE. +This control is used to attenuate samples for left and right front speakers of +this mix. + +name='Surround Playback Volume',index=0 + +All stereo signals are mixed together and mirrored to surround, center and LFE. +This control is used to attenuate samples for left and right surround speakers of +this mix. + +name='Center Playback Volume',index=0 + +All stereo signals are mixed together and mirrored to surround, center and LFE. +This control is used to attenuate sample for center speaker of this mix. + +name='LFE Playback Volume',index=0 + +All stereo signals are mixed together and mirrored to surround, center and LFE. +This control is used to attenuate sample for LFE speaker of this mix. + +name='Tone Control - Switch',index=0 + +This control turns the tone control on or off. The samples for front, rear +and center / LFE outputs are affected. + +name='Tone Control - Bass',index=0 + +This control sets the bass intensity. There is no neutral value!! +When the tone control code is activated, the samples are always modified. +The closest value to pure signal is 20. + +name='Tone Control - Treble',index=0 + +This control sets the treble intensity. There is no neutral value!! +When the tone control code is activated, the samples are always modified. +The closest value to pure signal is 20. + +name='Master Playback Volume',index=0 + +This control is used to attenuate samples for front, surround, center and +LFE outputs. + +name='IEC958 Optical Raw Playback Switch',index=0 + +If this switch is on, then the samples for the IEC958 (S/PDIF) digital +output are taken only from the raw FX8010 PCM, otherwise standard front +PCM samples are taken. + + +2) PCM stream related controls +------------------------------ + +name='EMU10K1 PCM Volume',index 0-31 + +Channel volume attenuation in range 0-0xffff. The maximum value (no +attenuation) is default. The channel mapping for three values is +as follows: + + 0 - mono, default 0xffff (no attenuation) + 1 - left, default 0xffff (no attenuation) + 2 - right, default 0xffff (no attenuation) + +name='EMU10K1 PCM Send Routing',index 0-31 + +This control specifies the destination - FX-bus accumulators. There 24 +values with this mapping: + + 0 - mono, A destination (FX-bus 0-63), default 0 + 1 - mono, B destination (FX-bus 0-63), default 1 + 2 - mono, C destination (FX-bus 0-63), default 2 + 3 - mono, D destination (FX-bus 0-63), default 3 + 4 - mono, E destination (FX-bus 0-63), default 0 + 5 - mono, F destination (FX-bus 0-63), default 0 + 6 - mono, G destination (FX-bus 0-63), default 0 + 7 - mono, H destination (FX-bus 0-63), default 0 + 8 - left, A destination (FX-bus 0-63), default 0 + 9 - left, B destination (FX-bus 0-63), default 1 + 10 - left, C destination (FX-bus 0-63), default 2 + 11 - left, D destination (FX-bus 0-63), default 3 + 12 - left, E destination (FX-bus 0-63), default 0 + 13 - left, F destination (FX-bus 0-63), default 0 + 14 - left, G destination (FX-bus 0-63), default 0 + 15 - left, H destination (FX-bus 0-63), default 0 + 16 - right, A destination (FX-bus 0-63), default 0 + 17 - right, B destination (FX-bus 0-63), default 1 + 18 - right, C destination (FX-bus 0-63), default 2 + 19 - right, D destination (FX-bus 0-63), default 3 + 20 - right, E destination (FX-bus 0-63), default 0 + 21 - right, F destination (FX-bus 0-63), default 0 + 22 - right, G destination (FX-bus 0-63), default 0 + 23 - right, H destination (FX-bus 0-63), default 0 + +Don't forget that it's illegal to assign a channel to the same FX-bus accumulator +more than once (it means 0=0 && 1=0 is an invalid combination). + +name='EMU10K1 PCM Send Volume',index 0-31 + +It specifies the attenuation (amount) for given destination in range 0-255. +The channel mapping is following: + + 0 - mono, A destination attn, default 255 (no attenuation) + 1 - mono, B destination attn, default 255 (no attenuation) + 2 - mono, C destination attn, default 0 (mute) + 3 - mono, D destination attn, default 0 (mute) + 4 - mono, E destination attn, default 0 (mute) + 5 - mono, F destination attn, default 0 (mute) + 6 - mono, G destination attn, default 0 (mute) + 7 - mono, H destination attn, default 0 (mute) + 8 - left, A destination attn, default 255 (no attenuation) + 9 - left, B destination attn, default 0 (mute) + 10 - left, C destination attn, default 0 (mute) + 11 - left, D destination attn, default 0 (mute) + 12 - left, E destination attn, default 0 (mute) + 13 - left, F destination attn, default 0 (mute) + 14 - left, G destination attn, default 0 (mute) + 15 - left, H destination attn, default 0 (mute) + 16 - right, A destination attn, default 0 (mute) + 17 - right, B destination attn, default 255 (no attenuation) + 18 - right, C destination attn, default 0 (mute) + 19 - right, D destination attn, default 0 (mute) + 20 - right, E destination attn, default 0 (mute) + 21 - right, F destination attn, default 0 (mute) + 22 - right, G destination attn, default 0 (mute) + 23 - right, H destination attn, default 0 (mute) + + + +4) MANUALS/PATENTS: +------------------- + +ftp://opensource.creative.com/pub/doc +------------------------------------- + + Files: + LM4545.pdf AC97 Codec + + m2049.pdf The EMU10K1 Digital Audio Processor + + hog63.ps FX8010 - A DSP Chip Architecture for Audio Effects + + +WIPO Patents +------------ + Patent numbers: + WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999) + streams + + WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999) + + WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction + Execution and Audio Data Sequencing (Jan. 14, 1999) + + +US Patents (http://www.uspto.gov/) +---------------------------------- + + US 5925841 Digital Sampling Instrument employing cache memory (Jul. 20, 1999) + + US 5928342 Audio Effects Processor integrated on a single chip (Jul. 27, 1999) + with a multiport memory onto which multiple asynchronous + digital sound samples can be concurrently loaded + + US 5930158 Processor with Instruction Set for Audio Effects (Jul. 27, 1999) + + US 6032235 Memory initialization circuit (Tram) (Feb. 29, 2000) + + US 6138207 Interpolation looping of audio samples in cache connected to (Oct. 24, 2000) + system bus with prioritization and modification of bus transfers + in accordance with loop ends and minimum block sizes + + US 6151670 Method for conserving memory storage using a (Nov. 21, 2000) + pool of short term memory registers + + US 6195715 Interrupt control for multiple programs communicating with (Feb. 27, 2001) + a common interrupt by associating programs to GP registers, + defining interrupt register, polling GP registers, and invoking + callback routine associated with defined interrupt register diff --git a/ld10k1/doc/AudigyTRAM.txt b/ld10k1/doc/AudigyTRAM.txt new file mode 100644 index 0000000..4bb2095 --- /dev/null +++ b/ld10k1/doc/AudigyTRAM.txt @@ -0,0 +1,39 @@ +TRAM setup: + +TCBS (0x44) and TCB (0x41) has same meaning as on SB Live + +Internal TRAM size is 0x4000 +Max external TRAM size is 0x100000 - as on SB Live + +Register description: + +0xdb - Internal TRAM Delay Base Address Counter +0xde - External TRAM Delay Base Address Counter + +0x100 - 0x1ff - tram access control registers (?) + - only 5 bit valid + bit : 4 - 0 - use log. compresion on write and read + 1 - use raw access - data from/to tram are read/wrote + as 16 bit samples + bits : 321 - ??? + 001 - read from tram + 010 - read from tram + 011 - write to tram + 0111, 1001 + 100 - read from tram + 101 - read from tram + 110 - read from tram + others - ????? + bit: 0 - 0 - normal mode + 1 - clear tram - set to data register valid address + until TRAM counter reaches this address, reads from + tram will return 0, then this flag is zeroed and + tram is working in normal mode, working for read +0x200 - 0x2ff - tram access data registers + - same as on SB Live +0x300 - 0x3ff - tram access address registers + - address format - host: 32 bit offset 20 bit integer part + 12 bit fractional part + to set offset to 0x123(SB Live) - 0x123 << 11 (Audigy) + - address format - DSP: same as SB Live ??? + +internal TRAM has index 0x00 - 0xbf +external TRAM has index 0xc0 - 0xff \ No newline at end of file diff --git a/ld10k1/doc/Makefile.am b/ld10k1/doc/Makefile.am new file mode 100644 index 0000000..20b3d22 --- /dev/null +++ b/ld10k1/doc/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = ld10k1_usage lo10k1_usage dl10k1_usage AudigyTRAM.txt README Audigy-mixer.txt diff --git a/ld10k1/doc/README b/ld10k1/doc/README new file mode 100644 index 0000000..c0d0017 --- /dev/null +++ b/ld10k1/doc/README @@ -0,0 +1,5 @@ +ld10k1_usage - short command line help for ld10k1 +lo10k1_usage - short command line help for lo10k1 +dl10k1_usage - short command line help for dl10k1 +AudigyTRAM.txt - everythink what I know about TRAM on Audigy +Audigy-mixer.txt - some info on audigy 1,2 mixer \ No newline at end of file diff --git a/ld10k1/doc/dl10k1_usage b/ld10k1/doc/dl10k1_usage new file mode 100644 index 0000000..deddf85 --- /dev/null +++ b/ld10k1/doc/dl10k1_usage @@ -0,0 +1,19 @@ +dl10k1 is dump loader +You can load config with ld10k1, lo10k1 and then make dump. This dum can be loaded without usage +of ld10k1 + +Parameters: + +-h or --help + Prints short help message + +-c num or --card num + Use card number num - dl10k1 will use device with name hw:0 + + example: + dl10k1 -c 1 + Use card 1 + +-d or --dump + File with dump + diff --git a/ld10k1/doc/ld10k1_usage b/ld10k1/doc/ld10k1_usage new file mode 100644 index 0000000..58493c3 --- /dev/null +++ b/ld10k1/doc/ld10k1_usage @@ -0,0 +1,36 @@ +ld10k1 is server part - linker - it must run to use loader +There must be exactly one instance for one emu10k1 based card wich you want use. + +Parameters: + +-h or --help + Prints short help message + +-c num or --card num + Use card number num - ld10k1 will use device with name hw:0 + + example: + ld10k1 -c 1 + Use card 1 + +-p name or --pipe_name name + ld10k1 will listen on named socked name. This socket is used for communication with lo10k1. + Default is /tmp/.ld10k1_port + +-t size or --tram_size size + Initialize initial TRAM size to size size. Size is rounded up to next valid value. Size is in samples and + can be one of 0 - external tram is disabled, 1 - 16384, 2 - 32768, 3 - 65536, 4 - 131072, 5 - 262144, + 6 -524288, 7 - 1048576, 8 - 1048576. For Audigy 1, Audigy 2 you need patch from patch directory, + because current ALSA version doesn't supports TRAM on these cards. + + example: + ld10k1 -t 7 + +-n or --network + ld10k1 default uses named socket, this switch to use network socket. You can use --port options to + define port to listen + +--port portnum + listen on port portnum. +-d or --daemon + ld10k1 runs as daemon. \ No newline at end of file diff --git a/ld10k1/doc/lo10k1_usage b/ld10k1/doc/lo10k1_usage new file mode 100644 index 0000000..69791ff --- /dev/null +++ b/ld10k1/doc/lo10k1_usage @@ -0,0 +1,245 @@ +lo10k1 is loader. + +Parameters: + +-h or --help + Prints short help message + +-l patch_name or --list path_name + List some usefull informations about patch in file patch_name. lo10k1 uses patch produced by as10k1 from + alsatools package. + +-p name or --pipe_name name + lo10k1 will use local named pipe with name name to communication with linker. Default is /tmp/.ld10k1_port + +-i or --info + Prints some info about card - not wery usefull + +-a patch_name or --add patch_name + Loads patch from file patch_name to DSP + +-d num or --del num + Unloads patch with number num from DSP. Use option --debug 4 to obtain patch numbers. + +--conadd conn_string + Connects patches between each others or to inputs or outputs. + Format of conn_string: + FX buses: + FX(f1, ...) - specify fx bus register f1 can be number or fx bus register name + Names can be optained by lo10k1 --debug 7 + FX(1) + FX(1,2) + FX(FX_PCM_Left,FX_PCM_Right) + + Inputs: + IN(i1, ...) - specify input register i1 can be number or input register name + Names can be optained by lo10k1 --debug 8 + IN(1) + IN(1,2) + IN(IN_AC97_Left,IN_AC97_Right) + + Outputs: + OUT(o1, ...) - specify input register o1 can be number or input register name + Names can be optained by lo10k1 --debug 9 + OUT(1) + OUT(1,2) + OUT(OUT_AC97_Front_Left,OUT_AC97_Front_Right) + + Patch inputs: + PIN(p, i1, ...) - p is patch number or patch name, i1 is input register i1 can be number or input register name + Patch numbers and names can be optained by lo10k1 --debug 5 + Names can be optained by lo10k1 --debug patch_num + PIN(1) - all patch inputs for patch 1 + PIN(Volume,IL,IL) - inputs IL and IR for patch Volume + PIN(2,0,1,2,3,4,5) - inputs 0,1,2,3,4,5 patch 2 + + Patch outputs: + POUT(p, o1, ...) - p is patch number or patch name, o1 is output register o1 can be number or outpur register name + Patch numbers and names can be optained by lo10k1 --debug 5 + Names can be optained by lo10k1 --debug patch_num + POUT(1) - all patch outputs for patch 1 + POUT(Volume,OL,OL) - outputs OL and OR for patch Volume + POUT(2,0,1,2,3,4,5) - outputs 0,1,2,3,4,5 patch 2 + + + - connecting two patches: + something1=something2 + or + something1:something2 + or + something1>something2 + something1,something2 - strings specify fx bus, input, output, patch input or patch output + something1 - must be patch input or output + + Difference between = and > is that = connect only two patches > enables connecting more + patches together. If you have three patches p1,p2,p3 - p1 with output o1, p2 with input i2, + and p3 with input i3. + PIN(p2,i2)=POUT(p1,o1) - will connect p1 with p2 + then next connect + PIN(p3,i3)=POUT(p1,o1) - will disconnect p1 and p2 and connect p1 with p2 + but + PIN(p3,i3)>POUT(p1,o1) - will connect p1 and p2 - p2 input i2 and p3 input i3 will be connected + to p1 output o1 + + Diffrence between = and : is that = allocate extra instructions and register to properly add + sources. : uses same register for all sources and patches must care about this register. + + Counts of connected inputs and outputs must be same. + + FX busses, inputs and outputs can have multiple patches connected to them. + Examples: + lo10k1 --conadd "PIN(1)=FX(0,1)" + - connect to patch 1 input to fx bus 0 and 1 + + lo10k1 --conadd "PIN(2)=POUT(PCM)" + - connect to all patch 2 inputs all outputs from patch PCM + + +--condel conndel_string + Disconnects patch register. + Format of conndel_string: + something + something - strings specify patch input or patch output + + Examples: + lo10k1 --condel "PIN(1)" + - disconnect all inputs of patch 1 + + lo10k1 --condel "POUT(PCM1,1,Center))" + - disconnect output 1 and Center from patch PCM + +--debug num + Prints on console some debug information. + mum = 1 - prints registers information + mum = 2 - prints consts information + mum = 3 - prints instruction information + mum = 4 - prints information about TRAM + mum = 5 - prints loaded patch names and numbers + mum = 6 - prints patch order in DSP instruction memory + mum = 7 - prints fx information + mum = 8 - prints input information + mum = 9 - prints output information + mum = 100 and more - prints informations about loaded patches (--debug 100 - about patch number 0, + -- debug 101 about patch number 1, and so on) + +--defionames + When patch is loaded, this assign default names for patch input and output registers. + Input/Output count: + 1/1 - In/Out + 2/2 - IL,IR/OL,OR + 4/4 - IL,IR,IRL,IRR/OL,OR,ORL,ORR + 6/6 - IL,IR,IRL,IRR,IC,ILFE/OL,OR,ORL,ORR,OC,OLFE + where: + In = Input + On = Output + IL = Input Left + OL = Output Left + IR = Input Right + OR = Output Right + IRL = Input Rear Left + ORL = Output Rear Left + IRR = Input Rear Right + ORR = Output Rear Right + IC = Input Center + OC = Output Center + ILFE = Input LFE + OLFE = Output LFE + +--ctrl string + This options is used to concate, rename controls and sets various parameters for controls + String format: + + c-name1,name2,...namen:outname + + This concate controls with names name1, name2, ..namen to one control with name outname + Input controls must have same range and are single channel (this is limitation of as10k1). + Output control has n channes. This can be used only for as10k1 file format. + + example: + c-masterl,masterr:master,t-master:1 + + Concate two controls masterl and masterr into one stereo control master with translaton table100 + + t-name:type + + This sets translate function whitch translate range and current value from mixer value to gpr + value for control with name name. This can be used only for as10k1 file format. + Type can be: + 0 - no translation is used + 1 - table 100 - range 0-100 in mixer is translated to range 0-2^31 + 2 - bass - range 0-40 in mixer is translated to range 0-2^31 - used for bass control + 3 - treble - range 0-40 in mixer is translated to range 0-2^31 - used for treble control + 4 - on/off - control uses range 0-1 + + v-name:count + + This sets number off visible channel in mixer. This can be used only for as10k1 file format. + + example: + v-bass:1 + + for bass control which has 5 channels is in mixer visible only one + + s-name:value1#value2# ... + + This sets initial value for control. + + i-name:value + + Sets control index value to control + + r-name:outname + + This rename control with name name to control with name outname. This can be used only for native file format. + + example: + r-master:PCM Master + + Rename control master to control PCM Master + +--patch_name name + Sets name for actualy loaded patch (it is used with -a option). Dafault name comes from patch file. + +--where num + Used with -a option. Actualy loaded path will by loaded before patch with order num. + You can get patch order with --debug 5 + +--setup + When this option is used DSP on card is cleared. + +--renam something=new_name + Same string as in connection add and plus PATCH(p) - specify patch with name p or number p + + Examples: + lo10k1 --renam "IN(5)=CD Left" + - renames input 5 to CD Left + + lo10k1 --renam "PATCH(Volume)=Mic Volume" + - renames patch Volume to Mic Volume + + lo10k1 --renam "PIN(Volume,IC)=Center IN" + - renames patch Volume input IL to Center IN + +--dump file + This will dump dsp instructions and register to file. This file can be loaded with dl10k1 without + ld10k1. + +--host machine:port + ld10k1 default uses named socket, this switch to use network socket. + +-P or --path add effect search paths (default will lo10k1 search in effects dir) + +--store file.ld10k1 + Stores DSP config to native ld10k1 file file.ld10k1 + +--restore file.ld10k1 + Restores DSP config from native ld10k1 file file.ld10k1 + +--save_patch file.ld10k1 + Saves patch specified with --where option to file file.ld10k1 + +--load_patch file.ld10k1 + Loads patch to dsp on position specified with --where option from file file.ld10k1 + +--wait msec + Wait for ld10k1 for msec mili second. \ No newline at end of file diff --git a/ld10k1/dump/Makefile.am b/ld10k1/dump/Makefile.am new file mode 100644 index 0000000..4970035 --- /dev/null +++ b/ld10k1/dump/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = README audigy.dl10k1 audigy_ms.dl10k1 diff --git a/ld10k1/dump/README b/ld10k1/dump/README new file mode 100644 index 0000000..c80aa06 --- /dev/null +++ b/ld10k1/dump/README @@ -0,0 +1,4 @@ +audigy_ms.dl10k1 - dump with default configuration + mute switches + capture switches + headphone + You can load this with dl10k1 -d audigy_ms.dl10k1 +audigy.dl10k1 - dump with default configuration + headphone + You can load this with dl10k1 -d audigy_p.dl10k1 diff --git a/ld10k1/dump/audigy.dl10k1 b/ld10k1/dump/audigy.dl10k1 new file mode 100644 index 0000000..a3ff9f1 Binary files /dev/null and b/ld10k1/dump/audigy.dl10k1 differ diff --git a/ld10k1/dump/audigy_ms.dl10k1 b/ld10k1/dump/audigy_ms.dl10k1 new file mode 100644 index 0000000..b49cffd Binary files /dev/null and b/ld10k1/dump/audigy_ms.dl10k1 differ diff --git a/ld10k1/include/Makefile.am b/ld10k1/include/Makefile.am new file mode 100644 index 0000000..f9e8bc9 --- /dev/null +++ b/ld10k1/include/Makefile.am @@ -0,0 +1,33 @@ +lo10k1includedir = $(includedir)/lo10k1 +lo10k1include_HEADERS = version.h comm.h liblo10k1.h liblo10k1ef.h ld10k1_error.h ld10k1_fnc.h liblo10k1lf.h lo10k1.h + +INCLUDES = -I$(top_srcdir)/include + +#taken from alsa-lib - start +CLEANFILES = stamp-vh version.h lo10k1 + +version.h: stamp-vh + @: + +stamp-vh: $(top_builddir)/configure.in + @echo "/*" > ver.tmp + @echo " * version.h" >> ver.tmp + @echo " */" >> ver.tmp + @echo "" >> ver.tmp + @echo "#define LD10K1_LIB_MAJOR $(LD10K1_LIB_MAJOR) /**< major number of library version */" >> ver.tmp + @echo "#define LD10K1_LIB_MINOR $(LD10K1_LIB_MINOR) /**< minor number of library version */" >> ver.tmp + @echo "#define LD10K1_LIB_SUBMINOR $(LD10K1_LIB_SUBMINOR) /**< subminor number of library version */" >> ver.tmp + @echo "/** library version */" >> ver.tmp + @echo "#define LD10K1_LIB_VERSION ((LD10K1_LIB_MAJOR<<16)|\\" >> ver.tmp + @echo " (LD10K1_LIB_MINOR<<8)|\\" >> ver.tmp + @echo " LD10K1_LIB_SUBMINOR)" >> ver.tmp + @echo "/** library version (string) */" >> ver.tmp + @echo "#define LD10K1_LIB_VERSION_STR \"$(LD10K1_LIB_VERSION)\"" >> ver.tmp + @echo >> ver.tmp + @cmp -s version.h ver.tmp \ + || (echo "Updating version.h"; \ + cp ver.tmp version.h; \ + echo timestamp > stamp-vh) + -@rm -f ver.tmp + +#taken from alsa-lib - end \ No newline at end of file diff --git a/ld10k1/include/comm.h b/ld10k1/include/comm.h new file mode 100644 index 0000000..2293aaa --- /dev/null +++ b/ld10k1/include/comm.h @@ -0,0 +1,71 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __COMM_H +#define __COMM_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct msg_req +{ + int op; + int size; +}; + +struct msg_resp +{ + int op; + int err; + int size; +}; + +#define COMM_TYPE_LOCAL 0 +#define COMM_TYPE_IP 1 + +typedef struct +{ + int type; + int server; + char *name; + unsigned short port; + int wfc; +} comm_param; + +int setup_comm(comm_param *param); +int connect_comm(int conn_num, comm_param *param); +int listen_comm(int conn_num); +int accept_comm(int conn_num); +int free_comm(int conn_num); +int send_request(int conn_num, int op, void *data, int data_size); +int send_response(int conn_num, int op, int err, void *data, int data_size); +int send_msg_data(int conn_num, void *data, int data_size); +int receive_request(int conn_num, int *op, int *data_size); +int receive_response(int conn_num, int *op, int *data_size); +int receive_msg_data(int conn_num, void *data, int data_size); +void *receive_msg_data_malloc(int conn_num, int data_size); + +#ifdef __cplusplus +} +#endif + +#endif /* __COMM_H */ diff --git a/ld10k1/include/ld10k1_error.h b/ld10k1/include/ld10k1_error.h new file mode 100644 index 0000000..a36ba78 --- /dev/null +++ b/ld10k1/include/ld10k1_error.h @@ -0,0 +1,104 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_ERROR_H +#define __LD10K1_ERROR_H + +#define LD10K1_ERR_UNKNOWN -1 /* unknown error */ +#define LD10K1_ERR_COMM_READ -2 /* errorn in read from socket */ +#define LD10K1_ERR_COMM_WRITE -3 /* error in write to socket */ +#define LD10K1_ERR_UNKNOWN_PATCH_NUM -4 /* wrong parameter - patch with this num doesn't exists */ +#define LD10K1_ERR_PROTOCOL -5 /* ld10k1 is expecting more or less data as it got */ +#define LD10K1_ERR_COMM_CONN -29 /* */ + +#define LD10K1_ERR_PROTOCOL_IN_COUNT -6 /* */ +#define LD10K1_ERR_PROTOCOL_OUT_COUNT -7 /* */ +#define LD10K1_ERR_PROTOCOL_CONST_COUNT -8 /* */ +#define LD10K1_ERR_PROTOCOL_STATIC_COUNT -9 /* */ +#define LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT -10 /* */ +#define LD10K1_ERR_PROTOCOL_HW_COUNT -11 /* */ +#define LD10K1_ERR_PROTOCOL_TRAM_COUNT -12 /* */ +#define LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT -13 /* */ +#define LD10K1_ERR_PROTOCOL_CTL_COUNT -14 /* */ +#define LD10K1_ERR_PROTOCOL_INSTR_COUNT -15 /* */ + +/* driver */ +#define LD10K1_ERR_DRIVER_CODE_POKE -16 /* unable to poke code */ +#define LD10K1_ERR_DRIVER_INFO -17 /* unable to get info */ +#define LD10K1_ERR_DRIVER_CODE_PEEK -18 /* unable to peek code */ +#define LD10K1_ERR_DRIVER_PCM_POKE -19 /* unable to poke pcm */ + +/* tram */ +#define LD10K1_ERR_ITRAM_FULL -20 /* not enought free itram */ +#define LD10K1_ERR_ETRAM_FULL -21 /* not enought free etram */ +#define LD10K1_ERR_TRAM_FULL -22 /* not enought free tram */ +#define LD10K1_ERR_TRAM_FULL_GRP -23 /* not enought free tram group */ + +#define LD10K1_ERR_ITRAM_FULL_ACC -25 /* not enought free itram acc */ +#define LD10K1_ERR_ETRAM_FULL_ACC -26 /* not enought free etram acc */ +#define LD10K1_ERR_TRAM_FULL_ACC -27 /* not enought free tram acc */ + +#define LD10K1_ERR_MAX_CON_PER_POINT -28 /* maximum connections per point reached */ + +/* others */ +#define LD10K1_ERR_NO_MEM -30 /* not enought free mem */ +#define LD10K1_ERR_MAX_PATCH_COUNT -31 /* max patch count excesed */ +#define LD10K1_ERR_NOT_FREE_REG -32 /* there is not free reg */ +#define LD10K1_ERR_NOT_FREE_INSTR -34 /* there is no free instruction slot */ + +/* patch chceck */ +#define LD10K1_ERR_WRONG_REG_HW_INDEX -36 /* */ +#define LD10K1_ERR_WRONG_TRAM_POS -37 /* */ + +#define LD10K1_ERR_WRONG_TRAM_TYPE -39 /* */ +#define LD10K1_ERR_WRONG_TRAM_SIZE -40 /* */ +#define LD10K1_ERR_WRONG_TRAM_ACC_TYPE -41 /* */ + +#define LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE -42 /* */ +#define LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE -43 /* */ + +#define LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE -48 /* */ +#define LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE -49 /* */ + +#define LD10K1_ERR_CTL_MIN_MAX_RANGE -50 /* */ +#define LD10K1_ERR_CTL_TRANLSLATION -51 /* */ +#define LD10K1_ERR_CTL_REG_INDEX -52 /* */ +#define LD10K1_ERR_CTL_REG_VALUE -53 /* */ + +#define LD10K1_ERR_INSTR_OPCODE -54 /* */ +#define LD10K1_ERR_INSTR_ARG_INDEX -56 /* */ + +#define LD10K1_ERR_UNKNOWN_REG_NUM -57 /* */ +#define LD10K1_ERR_UNKNOWN_PATCH_REG_NUM -58 /* */ + +#define LD10K1_ERR_CONNECTION -59 /* can't connect */ +#define LD10K1_ERR_CONNECTION_FNC -60 /* wrong connection funcion requested */ + +#define LD10K1_ERR_CTL_EXISTS -61 /* */ + +#define LD10K1_ERR_PATCH_RENAME -62 /* */ +#define LD10K1_ERR_PATCH_REG_RENAME -63 /* */ +#define LD10K1_ERR_REG_RENAME -64 /* */ +#define LD10K1_ERR_WRONG_VER -65 /* wrong ld10k1 <=> lo10k1 version */ + +#define LD10K1_ERR_UNKNOWN_POINT -66 /* */ + +#endif /* __LD10K1_ERROR_H */ diff --git a/ld10k1/include/ld10k1_fnc.h b/ld10k1/include/ld10k1_fnc.h new file mode 100644 index 0000000..b027336 --- /dev/null +++ b/ld10k1/include/ld10k1_fnc.h @@ -0,0 +1,386 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_FNC_H +#define __LD10K1_FNC_H + +#define MAX_NAME_LEN 256 +#define MAX_CTL_GPR_COUNT 32 +#define EMU10K1_GPR_TRANSLATION_LAST EMU10K1_GPR_TRANSLATION_ONOFF + +#define EMU10K1_REG_TYPE_NONE 0 +#define EMU10K1_REG_TYPE_FX 1 +#define EMU10K1_REG_TYPE_INPUT 2 +#define EMU10K1_REG_TYPE_OUTPUT 3 +#define EMU10K1_REG_TYPE_HW 4 +#define EMU10K1_REG_TYPE_TRAM_CTL 5 /* only on Audigy */ +#define EMU10K1_REG_TYPE_TRAM_DATA 6 +#define EMU10K1_REG_TYPE_TRAM_ADDR 7 +#define EMU10K1_REG_TYPE_NORMAL 8 +#define EMU10K1_REG_TYPE_CONST 9 +#define EMU10K1_REG_TYPE_ALL 10 +#define EMU10K1_REG_TYPE_NAMED 11 + +#define EMU10K1_REG_TYPE_MASK 0xF0000000 + +/* access macros */ +#define EMU10K1_REG_TYPE(type) (((type) << 28) & EMU10K1_REG_TYPE_MASK) +#define EMU10K1_REG_TYPE_B(type) (((type) & EMU10K1_REG_TYPE_MASK) >> 28) +#define EMU10K1_REG_FX(fxnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_FX) | ((fxnum) & 0x3F)) +#define EMU10K1_REG_IN(innum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_INPUT) | ((innum) & 0x1F)) +#define EMU10K1_REG_OUT(outnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_OUTPUT) | ((outnum) & 0x3F)) +#define EMU10K1_REG_HW(hwnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_HW) | ((hwnum) & 0x3F)) +#define EMU10K1_REG_TRAM_CTL(ctlnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_CTL) | ((ctlnum) & 0xFF)) +#define EMU10K1_REG_TRAM_DATA(datanum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_DATA) | ((datanum) & 0xFF)) +#define EMU10K1_REG_TRAM_ADDR(addrnum) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_TRAM_ADDR) | ((addrnum) & 0xFF)) +#define EMU10K1_REG_NORMAL(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_NORMAL) | ((num) & 0x1FF)) +#define EMU10K1_REG_CONST(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_CONST) | ((num) & 0x2ff)) +#define EMU10K1_REG_ALL(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_ALL) | ((num) & 0x7FF)) +#define EMU10K1_REG_NAMED(num) (EMU10K1_REG_TYPE(EMU10K1_REG_TYPE_ALL) | ((num) & 0xFFFFFFF)) + +/* this will not be changed */ +/* FX buses */ +#define EMU10K1_NREG_FXBUS_PCM_LEFT EMU10K1_REG_NAMED(0x0000) +#define EMU10K1_NREG_FXBUS_PCM_RIGHT EMU10K1_REG_NAMED(0x0001) +#define EMU10K1_NREG_FXBUS_PCM_FRONT_LEFT EMU10K1_REG_NAMED(0x0002) +#define EMU10K1_NREG_FXBUS_PCM_FRONT_RIGHT EMU10K1_REG_NAMED(0x0003) +#define EMU10K1_NREG_FXBUS_PCM_REAR_LEFT EMU10K1_REG_NAMED(0x0004) +#define EMU10K1_NREG_FXBUS_PCM_REAR_RIGHT EMU10K1_REG_NAMED(0x0005) +#define EMU10K1_NREG_FXBUS_PCM_CENTER EMU10K1_REG_NAMED(0x0006) +#define EMU10K1_NREG_FXBUS_PCM_LFE EMU10K1_REG_NAMED(0x0007) +#define EMU10K1_NREG_FXBUS_MIDI_LEFT EMU10K1_REG_NAMED(0x0008) +#define EMU10K1_NREG_FXBUS_MIDI_RIGHT EMU10K1_REG_NAMED(0x0009) +#define EMU10K1_NREG_FXBUS_MIDI_REVERB EMU10K1_REG_NAMED(0x000A) +#define EMU10K1_NREG_FXBUS_MIDI_CHORUS EMU10K1_REG_NAMED(0x000B) + +#define EMU10K1_A_NREG_FXBUS_PT_LEFT EMU10K1_REG_NAMED(0x000C) +#define EMU10K1_A_NREG_FXBUS_PT_RIGHT EMU10K1_REG_NAMED(0x000D) + +/* inputs */ +#define EMU10K1_NREG_IN_AC97_LEFT EMU10K1_REG_NAMED(0x0100) +#define EMU10K1_NREG_IN_AC97_RIGHT EMU10K1_REG_NAMED(0x0101) +#define EMU10K1_NREG_IN_SPDIF_CD_LEFT EMU10K1_REG_NAMED(0x0102) +#define EMU10K1_NREG_IN_SPDIF_CD_RIGHT EMU10K1_REG_NAMED(0x0103) +#define EMU10K1_NREG_IN_SPDIF_OPT_LEFT EMU10K1_REG_NAMED(0x0104) +#define EMU10K1_NREG_IN_SPDIF_OPT_RIGHT EMU10K1_REG_NAMED(0x0105) +#define EMU10K1_NREG_IN_I2S_1_LEFT EMU10K1_REG_NAMED(0x0106) +#define EMU10K1_NREG_IN_I2S_1_RIGHT EMU10K1_REG_NAMED(0x0107) +#define EMU10K1_NREG_IN_I2S_2_LEFT EMU10K1_REG_NAMED(0x0108) +#define EMU10K1_NREG_IN_I2S_2_RIGHT EMU10K1_REG_NAMED(0x0109) + +#define EMU10K1_L_NREG_IN_SPDIF_COAX_LEFT EMU10K1_REG_NAMED(0x010A) +#define EMU10K1_L_NREG_IN_SPDIF_COAX_RIGHT EMU10K1_REG_NAMED(0x010B) +#define EMU10K1_L_NREG_IN_ZOOM_LEFT EMU10K1_REG_NAMED(0x010C) +#define EMU10K1_L_NREG_IN_ZOOM_RIGHT EMU10K1_REG_NAMED(0x010D) +#define EMU10K1_L_NREG_IN_LINE_1_LEFT EMU10K1_REG_NAMED(0x010E) +#define EMU10K1_L_NREG_IN_LINE_1_RIGHT EMU10K1_REG_NAMED(0x010F) +#define EMU10K1_L_NREG_IN_LINE_2_LEFT EMU10K1_REG_NAMED(0x0110) +#define EMU10K1_L_NREG_IN_LINE_2_RIGHT EMU10K1_REG_NAMED(0x0111) + +#define EMU10K1_A_NREG_IN_LINE_1_LEFT EMU10K1_REG_NAMED(0x0112) +#define EMU10K1_A_NREG_IN_LINE_1_RIGHT EMU10K1_REG_NAMED(0x0113) +#define EMU10K1_A_NREG_IN_LINE_2_LEFT EMU10K1_REG_NAMED(0x0114) +#define EMU10K1_A_NREG_IN_LINE_2_RIGHT EMU10K1_REG_NAMED(0x0115) +#define EMU10K1_A_NREG_IN_LINE_3_LEFT EMU10K1_REG_NAMED(0x0116) +#define EMU10K1_A_NREG_IN_LINE_3_RIGHT EMU10K1_REG_NAMED(0x0117) +/* outputs */ +#define EMU10K1_NREG_OUT_FRONT_LEFT EMU10K1_REG_NAMED(0x0200) +#define EMU10K1_NREG_OUT_FRONT_RIGHT EMU10K1_REG_NAMED(0x0201) +#define EMU10K1_NREG_OUT_REAR_LEFT EMU10K1_REG_NAMED(0x0202) +#define EMU10K1_NREG_OUT_REAR_RIGHT EMU10K1_REG_NAMED(0x0203) +#define EMU10K1_NREG_OUT_CENTER EMU10K1_REG_NAMED(0x0204) +#define EMU10K1_NREG_OUT_LFE EMU10K1_REG_NAMED(0x0205) +#define EMU10K1_NREG_OUT_AC97_LEFT EMU10K1_REG_NAMED(0x0206) +#define EMU10K1_NREG_OUT_AC97_RIGHT EMU10K1_REG_NAMED(0x0207) +#define EMU10K1_NREG_OUT_ADC_LEFT EMU10K1_REG_NAMED(0x0208) +#define EMU10K1_NREG_OUT_ADC_RIGHT EMU10K1_REG_NAMED(0x0209) +#define EMU10K1_NREG_OUT_MIC EMU10K1_REG_NAMED(0x020A) +#define EMU10K1_NREG_OUT_HEADPHONE_LEFT EMU10K1_REG_NAMED(0x020B) +#define EMU10K1_NREG_OUT_HEADPHONE_RIGHT EMU10K1_REG_NAMED(0x020C) + +#define EMU10K1_L_NREG_OUT_OPT_LEFT EMU10K1_REG_NAMED(0x020D) +#define EMU10K1_L_NREG_OUT_OPT_RIGHT EMU10K1_REG_NAMED(0x020E) + +#define EMU10K1_A_NREG_OUT_D_FRONT_LEFT EMU10K1_REG_NAMED(0x020F) +#define EMU10K1_A_NREG_OUT_D_FRONT_RIGHT EMU10K1_REG_NAMED(0x0210) +#define EMU10K1_A_NREG_OUT_D_REAR_LEFT EMU10K1_REG_NAMED(0x0211) +#define EMU10K1_A_NREG_OUT_D_REAR_RIGHT EMU10K1_REG_NAMED(0x0212) +#define EMU10K1_A_NREG_OUT_D_CENTER EMU10K1_REG_NAMED(0x0213) +#define EMU10K1_A_NREG_OUT_D_LFE EMU10K1_REG_NAMED(0x0214) + +/* hardware */ +#define EMU10K1_NREG_CONST_00000000 EMU10K1_REG_NAMED(0x0300) +#define EMU10K1_NREG_CONST_00000001 EMU10K1_REG_NAMED(0x0301) +#define EMU10K1_NREG_CONST_00000002 EMU10K1_REG_NAMED(0x0302) +#define EMU10K1_NREG_CONST_00000003 EMU10K1_REG_NAMED(0x0303) +#define EMU10K1_NREG_CONST_00000004 EMU10K1_REG_NAMED(0x0304) +#define EMU10K1_NREG_CONST_00000008 EMU10K1_REG_NAMED(0x0305) +#define EMU10K1_NREG_CONST_00000010 EMU10K1_REG_NAMED(0x0306) +#define EMU10K1_NREG_CONST_00000020 EMU10K1_REG_NAMED(0x0307) +#define EMU10K1_NREG_CONST_00000100 EMU10K1_REG_NAMED(0x0308) +#define EMU10K1_NREG_CONST_00010000 EMU10K1_REG_NAMED(0x0309) +#define EMU10K1_L_NREG_CONST_00080000 EMU10K1_REG_NAMED(0x030A) +#define EMU10K1_A_NREG_CONST_00000800 EMU10K1_REG_NAMED(0x030B) +#define EMU10K1_NREG_CONST_10000000 EMU10K1_REG_NAMED(0x030C) +#define EMU10K1_NREG_CONST_20000000 EMU10K1_REG_NAMED(0x030D) +#define EMU10K1_NREG_CONST_40000000 EMU10K1_REG_NAMED(0x030E) +#define EMU10K1_NREG_CONST_80000000 EMU10K1_REG_NAMED(0x030F) +#define EMU10K1_NREG_CONST_7FFFFFFF EMU10K1_REG_NAMED(0x0310) +#define EMU10K1_NREG_CONST_FFFFFFFF EMU10K1_REG_NAMED(0x0311) +#define EMU10K1_NREG_CONST_FFFFFFFE EMU10K1_REG_NAMED(0x0312) +#define EMU10K1_NREG_CONST_C0000000 EMU10K1_REG_NAMED(0x0313) +#define EMU10K1_NREG_CONST_4F1BBCDC EMU10K1_REG_NAMED(0x0314) +#define EMU10K1_NREG_CONST_5A7EF9DB EMU10K1_REG_NAMED(0x0315) +#define EMU10K1_NREG_CONST_00100000 EMU10K1_REG_NAMED(0x0316) + +#define EMU10K1_NREG_HW_ACCUM EMU10K1_REG_NAMED(0x0317) +#define EMU10K1_NREG_HW_CCR EMU10K1_REG_NAMED(0x0318) +#define EMU10K1_NREG_HW_NOISE1 EMU10K1_REG_NAMED(0x0319) +#define EMU10K1_NREG_HW_NOISE2 EMU10K1_REG_NAMED(0x031A) +#define EMU10K1_NREG_HW_IRQ EMU10K1_REG_NAMED(0x031B) +#define EMU10K1_NREG_HW_DBAC EMU10K1_REG_NAMED(0x031C) +#define EMU10K1_A_NREG_HW_DBACE EMU10K1_REG_NAMED(0x031D) + +/* patch registers */ +#define EMU10K1_PREG_TYPE_IN 1 +#define EMU10K1_PREG_TYPE_OUT 2 +#define EMU10K1_PREG_TYPE_CONST 3 +#define EMU10K1_PREG_TYPE_STA 4 +#define EMU10K1_PREG_TYPE_DYN 5 +#define EMU10K1_PREG_TYPE_HW 6 +#define EMU10K1_PREG_TYPE_CTL 7 +#define EMU10K1_PREG_TYPE_TRAM_DATA 8 +#define EMU10K1_PREG_TYPE_TRAM_ADDR 9 + +#define EMU10K1_PREG_TYPE_MASK 0xF0000000 + +/* access macros */ +#define EMU10K1_PREG_TYPE(type) (((type) << 28) & EMU10K1_PREG_TYPE_MASK) +#define EMU10K1_PREG_TYPE_B(type) (((type) & EMU10K1_PREG_TYPE_MASK) >> 28) +#define EMU10K1_PREG_IN(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_IN) | ((num) & 0x1F)) +#define EMU10K1_PREG_OUT(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_OUT) | ((num) & 0x1F)) +#define EMU10K1_PREG_CONST(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_CONST) | ((num) & 0xFF)) +#define EMU10K1_PREG_STA(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_STA) | ((num) & 0xFF)) +#define EMU10K1_PREG_DYN(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_DYN) | ((num) & 0xFF)) +#define EMU10K1_PREG_HW(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_HW) | ((num) & 0xFF)) +#define EMU10K1_PREG_CTL(ctlnum, num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_CTL) | (((ctlnum) & 0xFF) << 8) | ((num) & 0xFF)) +#define EMU10K1_PREG_TRAM_DATA(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_TRAM_DATA) | ((num) & 0xFF)) +#define EMU10K1_PREG_TRAM_ADDR(num) (EMU10K1_REG_TYPE(EMU10K1_PREG_TYPE_TRAM_ADDR) | ((num) & 0xFF)) + +typedef struct { + char name[MAX_NAME_LEN]; +} ld10k1_dsp_p_in_out_t; + +typedef struct { + unsigned int const_val; +} ld10k1_dsp_p_const_static_t; + +typedef struct { + unsigned int hw_val; +} ld10k1_dsp_p_hw_t; + + +#define EMU10K1_GPR_TRANSLATION_NONE 0 +#define EMU10K1_GPR_TRANSLATION_TABLE100 1 +#define EMU10K1_GPR_TRANSLATION_BASS 2 +#define EMU10K1_GPR_TRANSLATION_TREBLE 3 +#define EMU10K1_GPR_TRANSLATION_ONOFF 4 + +typedef struct { + char name[44]; + int index; /* -1 - auto choose index */ + unsigned int vcount; /* count of GPR (1..32) */ + unsigned int count; /* count of GPR (1..32) */ + unsigned int value[MAX_CTL_GPR_COUNT]; + unsigned int min; /* minimum range */ + unsigned int max; /* maximum range */ + unsigned int translation; +} ld10k1_dsp_ctl_t; + +typedef struct { + unsigned int op_code; + unsigned int arg[4]; +} ld10k1_dsp_instr_t; + +#define TRAM_GRP_DELAY 1 +#define TRAM_GRP_TABLE 2 + +#define TRAM_POS_NONE 0 +#define TRAM_POS_AUTO 1 +#define TRAM_POS_INTERNAL 2 +#define TRAM_POS_EXTERNAL 3 + +typedef struct { + unsigned int grp_type; + unsigned int grp_size; + unsigned int grp_pos; +} ld10k1_dsp_tram_grp_t; + +#define TRAM_ACC_READ 1 +#define TRAM_ACC_WRITE 2 +#define TRAM_ACC_ZERO 4 + +typedef struct { + unsigned int acc_type; + unsigned int acc_offset; + unsigned int grp; +} ld10k1_dsp_tram_acc_t; + +typedef struct { + char patch_name[MAX_NAME_LEN]; + int id; + unsigned int in_count; + unsigned int out_count; + unsigned int const_count; + unsigned int static_count; + unsigned int dynamic_count; + unsigned int hw_count; + unsigned int tram_count; + unsigned int tram_acc_count; + unsigned int ctl_count; + unsigned int instr_count; +} ld10k1_dsp_patch_t; + + +#define CON_IO_FX 'F' +#define CON_IO_IN 'I' +#define CON_IO_OUT 'O' +#define CON_IO_PIN 'A' +#define CON_IO_POUT 'B' +#define CON_IO_NORMAL '\0' + +/* must be changed in ld10k1.h too */ +#define POINT_MAX_CONN_PER_POINT 15 +typedef struct { + int id; + int type; + int io_idx; + int simple; + int multi; + unsigned int conn_count; + int io_type[POINT_MAX_CONN_PER_POINT]; + int patch[POINT_MAX_CONN_PER_POINT]; + int io[POINT_MAX_CONN_PER_POINT]; +} ld10k1_dsp_point_t; + +typedef struct { + int where; + ld10k1_dsp_patch_t patch; +} ld10k1_fnc_patch_add_t; + +typedef struct { + int where; +} ld10k1_fnc_patch_del_t; + +typedef struct { + int what; + int multi; + int simple; + int from_type; + int from_patch; + int from_io; + int to_type; + int to_patch; + int to_io; +} ld10k1_fnc_connection_t; + +typedef struct { + int patch_num; + int gpr; + char name[MAX_NAME_LEN]; +} ld10k1_fnc_name_t; + +typedef struct { + char name[MAX_NAME_LEN]; +} ld10k1_fnc_get_io_t; + +typedef struct { + int patch_num; + int id; + char patch_name[MAX_NAME_LEN]; +} ld10k1_fnc_patches_info_t; + +typedef struct { + char ld10k1_version[MAX_NAME_LEN]; +} ld10k1_fnc_version_t; + +#define CHIP_LIVE 0 +#define CHIP_AUDIGY 1 + +typedef struct { + unsigned int chip_type; +} ld10k1_fnc_dsp_info_t; + +#define FNC_PATCH_ADD 1 +#define FNC_PATCH_DEL 2 + +#define FNC_CONNECTION_ADD 3 +#define FNC_CONNECTION_DEL 4 + +#define FNC_PATCH_RENAME 5 +#define FNC_PATCH_FIND 6 + +#define FNC_GET_FX 11 +#define FNC_GET_IN 12 +#define FNC_GET_OUT 13 +#define FNC_GET_PIN 14 +#define FNC_GET_POUT 15 + +#define FNC_GET_FX_COUNT 21 +#define FNC_GET_IN_COUNT 22 +#define FNC_GET_OUT_COUNT 23 +#define FNC_GET_PIN_COUNT 24 +#define FNC_GET_POUT_COUNT 25 + +#define FNC_FX_RENAME 30 +#define FNC_IN_RENAME 31 +#define FNC_OUT_RENAME 32 +#define FNC_PATCH_IN_RENAME 33 +#define FNC_PATCH_OUT_RENAME 34 + + +#define FNC_GET_PATCHES_INFO 40 +#define FNC_GET_PATCH 41 + +#define FNC_FX_FIND 50 +#define FNC_IN_FIND 51 +#define FNC_OUT_FIND 52 +#define FNC_PATCH_IN_FIND 53 +#define FNC_PATCH_OUT_FIND 54 + +#define FNC_DUMP 60 + +#define FNC_GET_POINTS_INFO 70 +#define FNC_GET_POINT_INFO 71 + +#define FNC_GET_DSP_INFO 97 + +#define FNC_VERSION 98 +#define FNC_DSP_INIT 99 + +#define FNC_OK 100 +#define FNC_ERR 101 +#define FNC_CONTINUE 102 +#define FNC_CLOSE_CONN 103 + +#define FNC_DEBUG 200 + +#endif /* __LD10K1_FNC_H */ diff --git a/ld10k1/include/liblo10k1.h b/ld10k1/include/liblo10k1.h new file mode 100644 index 0000000..9f57850 --- /dev/null +++ b/ld10k1/include/liblo10k1.h @@ -0,0 +1,142 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LIBLO10K1_H +#define __LIBLO10K1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBLO10K1_ERR_DEBUG -10000 + +typedef ld10k1_dsp_p_in_out_t liblo10k1_dsp_pio_t; +typedef ld10k1_dsp_p_const_static_t liblo10k1_dsp_cs_t; +typedef ld10k1_dsp_p_hw_t liblo10k1_dsp_hw_t; +typedef ld10k1_dsp_ctl_t liblo10k1_dsp_ctl_t; +typedef ld10k1_dsp_instr_t liblo10k1_dsp_instr_t; +typedef ld10k1_dsp_tram_grp_t liblo10k1_dsp_tram_grp_t; +typedef ld10k1_dsp_tram_acc_t liblo10k1_dsp_tram_acc_t; +typedef ld10k1_fnc_get_io_t liblo10k1_get_io_t; + +typedef struct { + char patch_name[MAX_NAME_LEN]; + unsigned int in_count; + liblo10k1_dsp_pio_t *ins; + unsigned int out_count; + liblo10k1_dsp_pio_t *outs; + unsigned int const_count; + liblo10k1_dsp_cs_t *consts; + unsigned int sta_count; + liblo10k1_dsp_cs_t *stas; + unsigned int dyn_count; + unsigned int hw_count; + liblo10k1_dsp_hw_t *hws; + unsigned int tram_count; + liblo10k1_dsp_tram_grp_t *tram; + unsigned int tram_acc_count; + liblo10k1_dsp_tram_acc_t *tram_acc; + unsigned int ctl_count; + liblo10k1_dsp_ctl_t *ctl; + unsigned int instr_count; + liblo10k1_dsp_instr_t *instr; +} liblo10k1_dsp_patch_t; + +typedef int liblo10k1_connection_t; +typedef ld10k1_fnc_patches_info_t liblo10k1_patches_info_t; + +typedef ld10k1_fnc_dsp_info_t liblo10k1_dsp_info_t; + +typedef ld10k1_dsp_point_t liblo10k1_point_info_t; + +typedef comm_param liblo10k1_param; + +void liblo10k1_connection_init(liblo10k1_connection_t *conn); +int liblo10k1_connect(liblo10k1_param *param, liblo10k1_connection_t *conn); +int liblo10k1_is_open(liblo10k1_connection_t *conn); +int liblo10k1_disconnect(liblo10k1_connection_t *conn); + +liblo10k1_dsp_patch_t *liblo10k1_patch_alloc(int in_count, int out_count, int const_count, int sta_count, int dyn_count, int hw_count, int tram_count, int tram_acc_count, int ctl_count, int instr_count); +void liblo10k1_patch_free(liblo10k1_dsp_patch_t *patch); + +int liblo10k1_patch_set_in_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_out_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_const_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_sta_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_dyn_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_hw_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_tram_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_tram_acc_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_ctl_count(liblo10k1_dsp_patch_t *p, int count); +int liblo10k1_patch_set_instr_count(liblo10k1_dsp_patch_t *p, int count); + +int liblo10k1_patch_load(liblo10k1_connection_t *conn, liblo10k1_dsp_patch_t *patch, int before, int *loaded, int *loaded_id); +int liblo10k1_patch_unload(liblo10k1_connection_t *conn, int patch_num); +int liblo10k1_patch_get(liblo10k1_connection_t *conn, int patch_num, liblo10k1_dsp_patch_t **patch); + +int liblo10k1_debug(liblo10k1_connection_t *conn, int deb, void (*prn_fnc)(char *)); + +int liblo10k1_dsp_init(liblo10k1_connection_t *conn); + +int liblo10k1_find_patch(liblo10k1_connection_t *conn, char *patch_name, int *out); +int liblo10k1_find_fx(liblo10k1_connection_t *conn, char *fx_name, int *out); +int liblo10k1_find_in(liblo10k1_connection_t *conn, char *in_name, int *out); +int liblo10k1_find_out(liblo10k1_connection_t *conn, char *out_name, int *out); +int liblo10k1_find_patch_in(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out); +int liblo10k1_find_patch_out(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out); + +int liblo10k1_rename_patch(liblo10k1_connection_t *conn, int patch_num, char *patch_name); +int liblo10k1_rename_fx(liblo10k1_connection_t *conn, int fx, char *fx_name); +int liblo10k1_rename_in(liblo10k1_connection_t *conn, int in, char *in_name); +int liblo10k1_rename_out(liblo10k1_connection_t *conn, int out, char *out_name); +int liblo10k1_rename_patch_in(liblo10k1_connection_t *conn, int patch_num, int in, char *patch_in_name); +int liblo10k1_rename_patch_out(liblo10k1_connection_t *conn, int patch_num, int out, char *patch_out_name); + +int liblo10k1_con_add(liblo10k1_connection_t *conn, int multi, int simple, int from_type, int from_patch, int from_io, int to_type, int to_patch, int to_io, int *ci); +int liblo10k1_con_del(liblo10k1_connection_t *conn, int type, int patch, int io, int *ci); + +int liblo10k1_get_fx(liblo10k1_connection_t *conn, int fx_num, liblo10k1_get_io_t *out); +int liblo10k1_get_in(liblo10k1_connection_t *conn, int in_num, liblo10k1_get_io_t *out); +int liblo10k1_get_out(liblo10k1_connection_t *conn, int out_num, liblo10k1_get_io_t *out); +int liblo10k1_get_pin(liblo10k1_connection_t *conn, int patch_num, int in_num, liblo10k1_get_io_t *out); +int liblo10k1_get_pout(liblo10k1_connection_t *conn, int patch_num, int out_num, liblo10k1_get_io_t *out); + +int liblo10k1_get_fx_count(liblo10k1_connection_t *conn, int *count); +int liblo10k1_get_in_count(liblo10k1_connection_t *conn, int *count); +int liblo10k1_get_out_count(liblo10k1_connection_t *conn, int *count); +int liblo10k1_get_pin_count(liblo10k1_connection_t *conn, int patch_num, int *count); +int liblo10k1_get_pout_count(liblo10k1_connection_t *conn, int patch_num, int *count); + +int liblo10k1_get_patches_info(liblo10k1_connection_t *conn, liblo10k1_patches_info_t **out, int *count); +int liblo10k1_get_points_info(liblo10k1_connection_t *conn, int **out, int *count); +int liblo10k1_get_point_info(liblo10k1_connection_t *conn, int point_id, liblo10k1_point_info_t *out); +int liblo10k1_dump(liblo10k1_connection_t *conn, void **out, int *size); +int liblo10k1_check_version(liblo10k1_connection_t *conn); + +int liblo10k1_get_dsp_info(liblo10k1_connection_t *conn, liblo10k1_dsp_info_t *info); + +char *liblo10k1_error_str(int error); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBLO10K1_H */ diff --git a/ld10k1/include/liblo10k1ef.h b/ld10k1/include/liblo10k1ef.h new file mode 100644 index 0000000..fb95025 --- /dev/null +++ b/ld10k1/include/liblo10k1ef.h @@ -0,0 +1,128 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LIBLO10K1EF_H +#define __LIBLO10K1EF_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned int sc; + unsigned int sc_val; +} liblo10k1_emu_sc_t; + +typedef struct { + unsigned int ctl; + unsigned int ctl_val; + unsigned int ctl_val_min; + unsigned int ctl_val_max; + char ctl_name[32]; +} liblo10k1_emu_ctl_t; + +typedef struct { + unsigned int line; + unsigned int line_size; +} liblo10k1_emu_tram_line_t; + +typedef struct { + unsigned int size; + unsigned int read_line_count; + liblo10k1_emu_tram_line_t *read_lines; + unsigned int write_line_count; + liblo10k1_emu_tram_line_t *write_lines; +} liblo10k1_emu_tram_t; + +typedef struct { + unsigned int op; + unsigned int arg[4]; +} liblo10k1_emu_instr_t; + +typedef struct { + char patch_name[32]; + unsigned int in_count; + unsigned int *ins; + unsigned int out_count; + unsigned int *outs; + unsigned int dyn_count; + unsigned int *dyns; + unsigned int sta_count; + liblo10k1_emu_sc_t *stas; + unsigned int ctl_count; + liblo10k1_emu_ctl_t *ctls; + unsigned int con_count; + liblo10k1_emu_sc_t *cons; + unsigned int tram_lookup_count; + liblo10k1_emu_tram_t *tram_lookups; + unsigned int tram_delay_count; + liblo10k1_emu_tram_t *tram_delays; + unsigned int instr_count; + liblo10k1_emu_instr_t *instrs; +} liblo10k1_emu_patch_t; + +liblo10k1_emu_patch_t *liblo10k1_emu_new_patch(); +void liblo10k1_emu_free_patch(liblo10k1_emu_patch_t *p); + +int liblo10k1_emu_patch_set_in_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_out_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_dyn_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_sta_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_ctl_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_con_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_lookup_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_delay_count(liblo10k1_emu_patch_t *p, int count); +int liblo10k1_emu_patch_set_instr_count(liblo10k1_emu_patch_t *p, int count); + +int liblo10k1_emu_patch_set_line_count(liblo10k1_emu_tram_t *t, int write, int count); +int liblo10k1_emu_load_patch(char *file_name, liblo10k1_emu_patch_t **p); + +typedef struct +{ + int emu_ctls[32]; + int emu_ctl_count; + char ctl_name[44]; +} liblo10k1_ctl_transform_t; + +int liblo10k1_emu_transform_patch(liblo10k1_emu_patch_t *ep, liblo10k1_ctl_transform_t *tctl, int tctl_count, liblo10k1_dsp_patch_t **lp); +int liblo10k1_patch_find_ctl_by_name(liblo10k1_dsp_patch_t *p, char *ctl_name); +int liblo10k1_patch_ctl_set_trans(liblo10k1_dsp_patch_t *p, int idx, int trans); +int liblo10k1_patch_ctl_set_vcount(liblo10k1_dsp_patch_t *p, int idx, int vc); +int liblo10k1_patch_ctl_set_index(liblo10k1_dsp_patch_t *p, int idx, int i); +int liblo10k1_patch_ctl_set_value(liblo10k1_dsp_patch_t *p, int idx, int vi, int val); + + +#define LD10K1_EF_ERR_OPEN -1000 /* error at file open */ +#define LD10K1_EF_ERR_STAT -1001 /* error at file stat */ +#define LD10K1_EF_ERR_SIZE -1002 /* wrong file size */ +#define LD10K1_EF_ERR_READ -1003 /* error at file read */ +#define LD10K1_EF_ERR_SIGNATURE -1004 /* wrong file signature */ +#define LD10K1_EF_ERR_FORMAT -1005 /* wrong file format */ + +#define LD10K1_EF_ERR_TRANSFORM_CTL -1100 /* wrong ctl transformation */ +#define LD10K1_EF_ERR_TRANSFORM -1101 /* wrong transformation */ +#define LD10K1_EF_ERR_TRANSFORM_TRANS -1102 /* wrong ctl translation */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBLO10K1EF_H */ diff --git a/ld10k1/include/liblo10k1lf.h b/ld10k1/include/liblo10k1lf.h new file mode 100644 index 0000000..c51bb44 --- /dev/null +++ b/ld10k1/include/liblo10k1lf.h @@ -0,0 +1,221 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LIBLO10K1LF_H +#define __LIBLO10K1LF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* description of structures used in native ld10k1 files */ + +typedef struct { + /* asciz string with signature - have to be + "LD10K1 NATIVE EFFECT FILE " + 01234567890123456789012345678901 */ + char signature[32]; + /* don't use this */ + char reserved[32]; +} liblo10k1_file_header_t; + +/* don't use this */ +#define LD10K1_FP_TYPE_RESERVED 0 +/* normal part type, part_length is valid */ +#define LD10K1_FP_TYPE_NORMAL 1 +/* part start type, part_length have to be 0 */ +#define LD10K1_FP_TYPE_START 2 +/* part end type, part_length have to be 0 */ +#define LD10K1_FP_TYPE_END 3 + +/* parts can be nested */ +typedef struct { + /* don't use this */ + unsigned int reserved : 2, + /* part type definition + - normal + - part content start + - part content end */ + part_type : 6, + part_id : 24; + /* part data length */ + unsigned int part_length; +} liblo10k1_file_part_t; + +#define LD10K1_FP_INFO 0 +#define LD10K1_FP_DSP_SETUP 1 +#define LD10K1_FP_FX 2 +#define LD10K1_FP_FX_LIST 3 +#define LD10K1_FP_IN 4 +#define LD10K1_FP_IN_LIST 5 +#define LD10K1_FP_OUT 6 +#define LD10K1_FP_OUT_LIST 7 +#define LD10K1_FP_PATCH 8 +#define LD10K1_FP_PATCH_LIST 9 +#define LD10K1_FP_PATCH_INFO 10 +#define LD10K1_FP_PIO 11 +#define LD10K1_FP_PIN_LIST 12 +#define LD10K1_FP_POUT_LIST 13 +#define LD10K1_FP_CS 14 +#define LD10K1_FP_CONST_LIST 15 +#define LD10K1_FP_STA_LIST 16 +#define LD10K1_FP_DYN_LIST 17 +#define LD10K1_FP_HW 18 +#define LD10K1_FP_HW_LIST 19 +#define LD10K1_FP_TRAM 20 +#define LD10K1_FP_TRAM_LIST 21 +#define LD10K1_FP_TRAM_ACC 22 +#define LD10K1_FP_TRAM_ACC_LIST 23 +#define LD10K1_FP_CTL 24 +#define LD10K1_FP_CTL_LIST 25 +#define LD10K1_FP_INSTR 26 +#define LD10K1_FP_INSTR_LIST 27 +#define LD10K1_FP_POINT 28 +#define LD10K1_FP_POINT_LIST 29 + +#define LD10K1_FP_FILE_INFO_NAME 30 +#define LD10K1_FP_FILE_INFO_DESC 31 +#define LD10K1_FP_FILE_INFO_CREATER 32 +#define LD10K1_FP_FILE_INFO_AUTHOR 33 +#define LD10K1_FP_FILE_INFO_COPYRIGHT 34 +#define LD10K1_FP_FILE_INFO_LICENCE 35 + +/* file contains whole dsp config */ +#define LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP 0 +/* file contains only 1 patch */ +#define LD10K1_FP_INFO_FILE_TYPE_PATCH 1 + + +typedef struct { + unsigned int file_type; + /* file version + application can ignore this version and read file, + but must be prepared to ignore unknown parts */ + unsigned int file_version_major : 8, + file_version_minor : 8, + file_version_subminor : 8, + file_version_pad : 8; + /* minimal version of lo10k1/ld10k1 which will load file + application must be prepared to ignore unknown parts */ + unsigned int minimal_reader_version_major : 8, + minimal_reader_version_minor : 8, + minimal_reader_version_subminor : 8, + minimal_reader_version_pad : 8; + /* version of lo10k1/ld10k1 which which created file */ + unsigned int creater_version_major : 8, + creater_version_minor : 8, + creater_version_subminor : 8, + creater_version_pad : 8; +} liblo10k1_file_part_info_t; + +#define LD10K1_FP_INFO_DSP_TYPE_EMU10K1 0 +#define LD10K1_FP_INFO_DSP_TYPE_EMU10K2 1 +typedef struct { + unsigned int dsp_type; + /* tram size to setup */ + /* unsigned int externa_tram_size; */ + /* used to restore io names */ + unsigned int fx_count; + unsigned int in_count; + unsigned int out_count; + /* patch count contained in this file */ + unsigned int patch_count; + /* point count contained in this file */ + unsigned int point_count; +} liblo10k1_file_part_dsp_setup_t; + + +/* structure used to store and restore config */ +typedef struct { + unsigned int dsp_type; + /* used to restore io names */ + unsigned int fx_count; + liblo10k1_get_io_t *fxs; + unsigned int in_count; + liblo10k1_get_io_t *ins; + unsigned int out_count; + liblo10k1_get_io_t *outs; + /* patch count contained in this file */ + unsigned int patch_count; + liblo10k1_dsp_patch_t **patches; + /* point count contained in this file */ + unsigned int point_count; + liblo10k1_point_info_t *points; +} liblo10k1_file_dsp_setup_t; + +typedef struct { + char patch_name[MAX_NAME_LEN]; + unsigned int in_count; + unsigned int out_count; + unsigned int const_count; + unsigned int sta_count; + unsigned int dyn_count; + unsigned int hw_count; + unsigned int tram_count; + unsigned int tram_acc_count; + unsigned int ctl_count; + unsigned int instr_count; +} liblo10k1_file_patch_info_t; + +int liblo10k1lf_get_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t **setup); +int liblo10k1lf_put_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t *setup); + +liblo10k1_file_dsp_setup_t *liblo10k1lf_dsp_config_alloc(); +void liblo10k1lf_dsp_config_free(liblo10k1_file_dsp_setup_t *c); + +typedef struct { + /* file name */ + char *name; + /* file description */ + char *desc; + /* description of creater application - can be anything */ + char *creater; + /* author */ + char *author; + /* copyright string */ + char *copyright; + /* licence use for this file */ + char *license; +} liblo10k1_file_info_t; + +liblo10k1_file_info_t *liblo10k1lf_file_info_alloc(); +void liblo10k1lf_file_info_free(liblo10k1_file_info_t *fi); + +int liblo10k1lf_save_dsp_config(liblo10k1_file_dsp_setup_t *c, char *file_name, liblo10k1_file_info_t *fi); +int liblo10k1lf_load_dsp_config(liblo10k1_file_dsp_setup_t **c, char *file_name, liblo10k1_file_info_t **fi); + +int liblo10k1lf_save_dsp_patch(liblo10k1_dsp_patch_t *p, char *file_name, liblo10k1_file_info_t *fi); +int liblo10k1lf_load_dsp_patch(liblo10k1_dsp_patch_t **p, char *file_name, liblo10k1_file_info_t **fi); + +#define LD10K1_LF_ERR_OPEN -2000 +#define LD10K1_LF_ERR_WRITE -2001 +#define LD10K1_LF_ERR_READ -2002 +#define LD10K1_LF_ERR_SIGNATURE -2003 +#define LD10K1_LF_ERR_PART_TYPE -2004 +#define LD10K1_LF_ERR_PART_SIZE -2005 +#define LD10K1_LF_ERR_VERSION -2006 +#define LD10K1_LF_ERR_FILE_TYPE -2007 + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBLO10K1LF_H */ diff --git a/ld10k1/include/lo10k1.h b/ld10k1/include/lo10k1.h new file mode 100644 index 0000000..67a8af1 --- /dev/null +++ b/ld10k1/include/lo10k1.h @@ -0,0 +1,42 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LO10K1_H +#define __LO10K1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif /* __LO10K1_H */ diff --git a/ld10k1/include/version.h b/ld10k1/include/version.h new file mode 100644 index 0000000..1ab5f70 --- /dev/null +++ b/ld10k1/include/version.h @@ -0,0 +1,14 @@ +/* + * version.h + */ + +#define LD10K1_LIB_MAJOR 0 /**< major number of library version */ +#define LD10K1_LIB_MINOR 1 /**< minor number of library version */ +#define LD10K1_LIB_SUBMINOR 8 /**< subminor number of library version */ +/** library version */ +#define LD10K1_LIB_VERSION ((LD10K1_LIB_MAJOR<<16)|\ + (LD10K1_LIB_MINOR<<8)|\ + LD10K1_LIB_SUBMINOR) +/** library version (string) */ +#define LD10K1_LIB_VERSION_STR "0.1.8" + diff --git a/ld10k1/ld10k1.m4 b/ld10k1/ld10k1.m4 new file mode 100644 index 0000000..9b51dc1 --- /dev/null +++ b/ld10k1/ld10k1.m4 @@ -0,0 +1,135 @@ +dnl Configure Paths for ld10k1 - stolen from ASLA (1.0.5a) +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +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 +], [ +/* ensure backward compatibility */ +# if(LD10K1_LIB_MAJOR > $ld10k1_min_major_version) + exit(0); +# else +# if(LD10K1_LIB_MAJOR < $ld10k1_min_major_version) +# error not present +# endif + +# if(LD10K1_LIB_MINOR > $ld10k1_min_minor_version) + exit(0); +# else +# if(LD10K1_LIB_MINOR < $ld10k1_min_minor_version) +# error not present +# endif + +# if(LD10K1_LIB_SUBMINOR < $ld10k1_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of liblo10k1 not found.)]) + ld10k1_found=no] +) +AC_LANG_RESTORE + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +if test "x$enable_ld10k1test" = "xyes"; then +AC_CHECK_LIB([lo10k1], [liblo10k1_connection_init],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable liblo10k1 was found.)]) + ld10k1_found=no] +) +fi + +if test "x$ld10k1_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-llo10k1//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-llo10k1 $LIBS" +fi +if test "x$ld10k1_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$ld10k1_save_CFLAGS" + LDFLAGS="$ld10k1_save_LDFLAGS" + LIBS="$ld10k1_save_LIBS" + LD10K1_CFLAGS="" + LD10K1_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(LD10K1_CFLAGS) +AC_SUBST(LD10K1_LIBS) +]) + diff --git a/ld10k1/ld10k1d.in b/ld10k1/ld10k1d.in new file mode 100644 index 0000000..28d10e2 --- /dev/null +++ b/ld10k1/ld10k1d.in @@ -0,0 +1,79 @@ +#!/bin/bash + +test -x@sbindir@/ld10k1 || exit 0 + +card=$2 +socket=/tmp/.ld10k1_port + +if [ -z "$card" ]; then + card=0 +elif [ "$card" = "0" ] ; then + card=0 +else + socket=$socket"_"$card +fi + +pidfile=/var/run/ld10k1_$card.pid +dspsetup=/etc/dspstate_$card.ld10k1 + +start() { + if [ ! -f $pidfile ] ; then + echo $"Starting ld10k1" + @sbindir@/ld10k1 -d -c $card -p $socket -i $pidfile >/dev/null 2>&1 + if [ -f $dspsetup ]; then + echo $"Restoring DSP setup" + @binarydir@/lo10k1 -p $socket --restore $dspsetup >/dev/null 2>&1 + fi + else + echo $"ld10k1 running" + fi + return 0 +} + +stop() { + if [ -f $pidfile ] ; then + echo $"Storing DSP setup" + @binarydir@/lo10k1 -p $socket --store $dspsetup >/dev/null 2>&1 + echo $"Stoping ld10k1" + pid= + local line p + read line < $pidfile + for p in $line ; do + [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" + done + kill -s 9 $pid >/dev/null 2>&1 + + if [ -f $pidfile ] ; then + rm -f $pidfile >/dev/null 2>&1 + fi + else + echo $"ld10k1 not runing" + fi + return 0 +} + +save() { + if [ -f $pidfile ] ; then + echo $"Storing DSP setup" + @binarydir@/lo10k1 -p $socket --store $dspsetup >/dev/null 2>&1 + else + echo $"ld10k1 not runing" + fi + return 0 +} + + +case "$1" in +start) + start + ;; +stop) + stop + ;; +save) + save + ;; +*) + echo $"Usage $0 {start|stop}" + exit 1 +esac diff --git a/ld10k1/patch/Makefile.am b/ld10k1/patch/Makefile.am new file mode 100644 index 0000000..952fde6 --- /dev/null +++ b/ld10k1/patch/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = README diff --git a/ld10k1/patch/README b/ld10k1/patch/README new file mode 100644 index 0000000..808044b --- /dev/null +++ b/ld10k1/patch/README @@ -0,0 +1 @@ +For alsa 1.0.7rc1 and higher no patches are needed. \ No newline at end of file diff --git a/ld10k1/setup/Makefile.am b/ld10k1/setup/Makefile.am new file mode 100644 index 0000000..e89502c --- /dev/null +++ b/ld10k1/setup/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = effects + +EXTRA_DIST = init_audigy.in init_live.in +bin_SCRIPTS = init_audigy init_live + +do_subst = sed -e 's,[@]datadir[@],$(datadir),g' \ + -e 's,[@]PERL[@],$(PERL),g' \ + -e 's,[@]PACKAGE[@],$(PACKAGE),g' \ + -e 's,[@]VERSION[@],$(VERSION),g' \ + -e 's,[@]bindir[@],$(bindir),g' + +init_live: init_live.in + $(do_subst) $(srcdir)/init_live.in > init_live + +init_audigy: init_audigy.in + $(do_subst) $(srcdir)/init_audigy.in > init_audigy + +CLEANFILES = init_live init_audigy \ No newline at end of file diff --git a/ld10k1/setup/effects/Makefile.am b/ld10k1/setup/effects/Makefile.am new file mode 100644 index 0000000..14cd60c --- /dev/null +++ b/ld10k1/setup/effects/Makefile.am @@ -0,0 +1,18 @@ +EXTRA_DIST = README emu_constants.asm \ + simple.asm vol_master.asm tone.asm \ + vol_2.asm output.asm switch_2.asm \ + sto51.asm switch_6.asm copy_2.asm \ + prologic.asm fxbus.asm + + +dist_effects_DATA = simple.emu10k1 vol_master.emu10k1 tone.emu10k1 \ + vol_2.emu10k1 output.emu10k1 switch_2.emu10k1 \ + sto51.emu10k1 switch_6.emu10k1 copy_2.emu10k1 \ + prologic.emu10k1 fxbus.emu10k1 + +CLEANFILES = $(dist_effects_DATA) + +SUFFIXEC = .asm .emu10k1 + +.asm.emu10k1: + as10k1 -o $@ $< diff --git a/ld10k1/setup/effects/README b/ld10k1/setup/effects/README new file mode 100644 index 0000000..2185537 --- /dev/null +++ b/ld10k1/setup/effects/README @@ -0,0 +1 @@ +Most of files in this directory is taken from emu10k1 OSS driver see opensource.creative.com \ No newline at end of file diff --git a/ld10k1/setup/effects/copy_2.asm b/ld10k1/setup/effects/copy_2.asm new file mode 100644 index 0000000..9f3b240 --- /dev/null +++ b/ld10k1/setup/effects/copy_2.asm @@ -0,0 +1,13 @@ +;PZU + name "2-channel copy" + +left IO +right IO + + macs left,left,$40,$40 + macs right,right,$40,$40 + + end + + + diff --git a/ld10k1/setup/effects/emu_constants.asm b/ld10k1/setup/effects/emu_constants.asm new file mode 100644 index 0000000..f215604 --- /dev/null +++ b/ld10k1/setup/effects/emu_constants.asm @@ -0,0 +1,151 @@ +;some hardware constants C_[n], 'n' indicates negative value +; +;these are in 2's complement representation + +C_0 equ $040 ;;00000000 +C_1 equ $041 ;;00000001 +C_2 equ $042 ;;00000002 +C_3 equ $043 ;;00000003 +C_4 equ $044 ;;00000004 +C_8 equ $045 ;;00000008 +C_16 equ $046 ;;00000010 +C_32 equ $047 ;;00000020 +C_256 equ $048 ;;00000100 +C_65536 equ $049 ;;00010000 +C_2^23 equ $04A ;;00080000 +C_2^28 equ $04b ;;10000000 +C_2^29 equ $04c ;;20000000 (C_max /4) +1 +C_2^30 equ $04d ;;40000000 ( C_max / 2 ) + 1 (almost half) +C_nmax equ $04e ;;80000000 most negative number +C_max equ $04f ;;7fffffff most positive number +C_n1 equ $050 ;;ffffffff -1 +C_n2 equ $051 ;;fffffffe -2 +C_n2^30 equ $052 ;;c0000000 C_nmax /2 + +C_LSshift equ $55 ;;to left shift an address by using macsints + ;;for fractional addresses + + +ZERO equ C_0; +ONE equ C_1; + +;;; Hardware Registers: + +ACCUM equ $56 +CCR equ $57 +NOISE1 equ $58 +NOISE2 equ $59 +IRQ equ $5A +DBAC equ $5B + +and macro dest,srcA,srcB + andxor dest,srcA,srcB,C_0 + endm + +xor macro dest,srcA,srcB + andxor dest,C_n1,srcA,srcB + endm + +not macro dest,src + andxor dest,src,C_n1,C_n1 + endm + +nand macro dest,srcA,srcB + andxor dest,srcA,srcB,C_n1 + endm + +or macro dest,srcA,srcB + not C_0,srcA + andxor dest,ACCUM,srcA,srcB + endm + +nor macro dest,srcA,scrB + not dest,srcA + andxor dest,srcB,dest,srcA + not dest,dest + endm + + +neg macro dest,src + macs1 dest,C_0,C_1,C_nmax + endm + +;;; branch on: +;;; ==0 +beq macro count + skip CCR,CCR,C_8,count + endm +;;; !=0 +bne macro count + skip CCR,CCR,C_256,count + endm +;;; <0 +blt macro count + skip CCR,CCR,C_4,count + endm +;;; <=0 +ble macro count +C___1008 con $1008 + skip CCR,CCR,C___1008,count + endm +;;; always branch +bra macro count + skip C_0,C_max,C_max,count + endm +;;; on saturation- for now - as10k1 can not handle more than 25 macros +;bsa macro count +; skip CCR,CCR,C_16,count +; endm +bge macro count +C___80 con $80 + skip CCR,CCR,C___80,count + endm + +bgt macro count +C___180 con $180 + skip CCR,CCR,C___180,count + endm + +move macro dest,src + macs dest,src,C_0,C_0 + endm +fracmult macro dest, src1, src2 + macs dest,$40, src1, src2 + endm +intmult macro dest, src1, src2 + macints dest, $40, src1, src2 + endm +add macro dest, src1, src2 + acc3 dest, $40, src1, src2 + endm + +;;; usefull for testing values before a skip +test macro test + macs C_0,test,C_0,C_0 + endm + +cmp macro src1,scr2 + macints C_0,src1,C_n1,src2 + endm + + +;---------------------------------------- +; dest = src1 - src2 +sub macro dest, src1, src2 + macints dest, src1, src2, C_n1 + endm + +;---------------------------------------- +; LowPassFilter +lpf macro yy, mm, xx + interp yy, yy, mm, xx + endm + +;---------------------------------------- +; HighPassFilter +hpf macro yy, ss, mm, xx + interp ss, ss, mm, xx + sub yy, xx, ss + endm + + end \ No newline at end of file diff --git a/ld10k1/setup/effects/fxbus.asm b/ld10k1/setup/effects/fxbus.asm new file mode 100644 index 0000000..3f1a1a6 --- /dev/null +++ b/ld10k1/setup/effects/fxbus.asm @@ -0,0 +1,30 @@ + name "FXBUS" + include "emu_constants.asm" + + ;; From alsa driver pci/emu10k1/emufx.c _volume_add + +pcm_l io +pcm_r io +pcm_lr io +pcm_rr io +midi_l io +midi_r io +pcm_c io +pcm_lf io +spdif_l io +spdif_r io + + ;; Process FX Buses + + macints pcm_l, C_0, pcm_l, C_4 + macints pcm_r, C_0, pcm_r, C_4 + macints pcm_lr, C_0, pcm_lr, C_4 + macints pcm_rr, C_0, pcm_rr, C_4 + macints midi_l, C_0, midi_l, C_4 + macints midi_r, C_0, midi_r, C_4 + macints pcm_c, C_0, pcm_c, C_4 + macints pcm_lf, C_0, pcm_lf, C_4 + macints spdif_l, C_0, spdif_l, C_4 + macints spdif_r, C_0, spdif_r, C_4 + + end diff --git a/ld10k1/setup/effects/output.asm b/ld10k1/setup/effects/output.asm new file mode 100644 index 0000000..61b74b0 --- /dev/null +++ b/ld10k1/setup/effects/output.asm @@ -0,0 +1,61 @@ +;PZU +;parts are taken from passthrough-audigy + + name "Output patch" + include "emu_constants.asm" + +;inputs - and analog outputs +Left IO +Right IO +LeftSurr IO +RightSurr IO +Center IO +LFE IO +; these are used for digital output +DLeft IO +DRight IO +DLeftSurr IO +DRightSurr IO +DCenter IO +DLFE IO + +enableL control 0,0,1 +enableR control 0,0,1 + +tmp_a dyn +tmp_b dyn +mask con $ffff0000 + + +;simple copy to analog output + macs Left, Left, C_0, C_0 + macs Right, Right, C_0, C_0 + macs LeftSurr, LeftSurr, C_0, C_0 + macs RightSurr, RightSurr, C_0, C_0 + macs Center, Center, C_0, C_0 + macs LFE, LFE, C_0, C_0 +; + macs DLeft, Left, C_0, C_0 + macs DRight, Right, C_0, C_0 + macs C_0, enableL, C_0, C_0 + beq .endL + macs tmp_a, DLeft, C_0, C_0 + ble .next_a + acc3 tmp_a, C_0, C_65536, tmp_a +.next_a + and DLeft, tmp_a, mask +.endL + macs C_0, enableR, C_0, C_0 + beq .end + macs tmp_b, DRight, C_0, C_0 + ble .next_b + acc3 tmp_b, C_0, C_65536, tmp_b +.next_b + and DRight, tmp_b, mask +.end + macs DLeftSurr, LeftSurr, C_0, C_0 + macs DRightSurr, RightSurr, C_0, C_0 + macs DCenter, Center, C_0, C_0 + macs DLFE, LFE, C_0, C_0 + + end \ No newline at end of file diff --git a/ld10k1/setup/effects/prologic.asm b/ld10k1/setup/effects/prologic.asm new file mode 100644 index 0000000..9fc2d6e --- /dev/null +++ b/ld10k1/setup/effects/prologic.asm @@ -0,0 +1,115 @@ +; Surround Active Matrix for Emu10k1 +; Author: Robert Mazur +; Date: Jan 14, 2002 +; Version 1.1 + +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. + +;======================================== + + name "ProLogic" + + include "emu_constants.asm" + + +;======================================== + +delline delay &0.02 ; 0.02 sec delay +write twrite delline,&0 ; write at 0 sec +read tread delline,&0.02 ; read at 0.02 sec + +;---------------------------------------- +ml con #0.575997 ; lpf 7000Hz +yl sta 0 + +mlp con #0.277015 ; lpf 2500Hz +mhp con #3.7076e-2 ; hpf 300Hz +ylp sta 0 +shp sta 0 + +;---------------------------------------- +Lt io ; Stereo Left In +Rt io ; Stereo Right In +L equ Lt ; Front Left Out +R equ Rt ; Front Right Out +Ls io +Rs io +C io ; Center + +;---------------------------------------- +tmp dyn + +ll dyn +rr dyn + +vcal sta #0.5 +vcar sta #0.5 + +fl sta 0 +fr sta 0 +mf con #0.013 ; ~ 100Hz + +;---------------------------------------- +; abs(x) +tmp_abs dyn +abs macro ret, xx + sub tmp_abs, C_0, xx + limit ret, C_0, tmp_abs, xx + endm + + +;======================================== +; Start +;======================================== + +;; Servo + + fracmult ll, vcal, Lt ; ll = vcal * Lt + abs tmp, ll ; tmp = abs(ll) + lpf fl, mf, tmp ; fl = LowPass((n)Hz, tmp); + + fracmult rr, vcar, Rt ; rr = vcar * Rt + abs tmp, rr ; tmp = abs(rr) + lpf fr, mf, tmp ; fr = LowPass((n)Hz, tmp); + + intmult ll, C_2, ll ; vca0 = 0.5 so we must multiply 'll' and 'rr' by 2 + intmult rr, C_2, rr + + sub tmp, fr, fl ; serv = fr - fl + + macints vcal, C_2^30, C_2, tmp ;vcal = vca0 + 2*serv + macints vcar, C_2^30, C_n2, tmp ;vcar = vca0 - 2*serv + +;; Suround + + sub tmp, ll, rr ; delay.in = L - R + + lpf yl, ml, tmp ; yl = LowPass(7kHz, delay.out) = rear + +; macs L, Lt, vcar, yl ; L = Lt - vcar * S Remove Surround from front speakers +; macs1 R, Rt, vcal, yl ; R = Rt + vcal * S + + move write, yl ; delay surround + + fracmult tmp, vcar, read ; Ls = 2 * vcar * rear ( 2* becouse vca0 = 0.5) + intmult Ls,C_2,tmp + fracmult tmp, vcal, read ; Rs = 2 * vcal * rear + intmult Rs,C_2,tmp + +;; Center + + add tmp, ll, rr ; tmp = L + R + + hpf tmp, shp, mhp, tmp ; tmp = HighPass(300Hz, tmp) + lpf ylp, mlp, tmp ; ylp = LowPass(2.5kHz, tmp) = center + + move C, ylp ; Center + + sub R, Rt, read ; R = R - rear + sub L, Lt, read ; L = L - rear + + end +;======================================== diff --git a/ld10k1/setup/effects/simple.asm b/ld10k1/setup/effects/simple.asm new file mode 100644 index 0000000..b16eb6f --- /dev/null +++ b/ld10k1/setup/effects/simple.asm @@ -0,0 +1,39 @@ + name "Simple 5.1 volume" + include "emu_constants.asm" + +inl io +outl equ inl +inr io +outr equ inr +inrl io +outrl equ inrl +inrr io +outrr equ inrr +inc io +outc equ inc +inlfe io +outlfe equ inlfe + +Left control 0,0,100 +Right control 0,0,100 +LeftSurr control 0,0,100 +RightSurr control 0,0,100 +Center control 0,0,100 +LFE control 0,0,100 + + macs outl,C_0, Left, inl + macs outr,C_0, Right, inr + macs outc,C_0, Center, inc + macs outrl,C_0, LeftSurr, inrl + macs outrr,C_0, RightSurr, inrr + macs outlfe,C_0, LFE, inlfe + + end + + + + + + + + diff --git a/ld10k1/setup/effects/sto51.asm b/ld10k1/setup/effects/sto51.asm new file mode 100644 index 0000000..4564f9a --- /dev/null +++ b/ld10k1/setup/effects/sto51.asm @@ -0,0 +1,60 @@ +;PZU + name "Simple 5.1 for Wave" + include "emu_constants.asm" + +inl io +outl equ inl +inr io +outr equ inr +inrl io +outrl equ inrl +inrr io +outrr equ inrr +inc io +outc equ inc +inlfe io +outlfe equ inlfe + +Left control 0,0,100 +Right control 0,0,100 +LeftSurr control 0,0,100 +RightSurr control 0,0,100 +Center control 0,0,100 +LFE control 0,0,100 + +tmp dyn +c40 con $40000000 + + +tmpl dyn +tmpr dyn + +;5.1 playback + macs tmpl, inl, C_0, C_0 + macs tmpr, inr, C_0, C_0 + +; macs outl, inl.o, Left, tmpl +; macs outr, inr.o, Right, tmpr +; macs outrl, inrl.o, LeftSurr, tmpl +; macs outrr, inrr.o, RightSurr, tmpr +; interp tmp, tmpl, c40, tmpr +; macs outc, inc.o, Center, tmp +; macs outlfe, inlfe.o, LFE, tmp + + macs outl, $40, Left, tmpl + macs outr, $40, Right, tmpr + macs outrl, $40, LeftSurr, tmpl + macs outrr, $40, RightSurr, tmpr + interp tmp, tmpl, c40, tmpr + macs outc, $40, Center, tmp + macs outlfe, $40, LFE, tmp + + end + + + + + + + + diff --git a/ld10k1/setup/effects/switch_2.asm b/ld10k1/setup/effects/switch_2.asm new file mode 100644 index 0000000..1c66a77 --- /dev/null +++ b/ld10k1/setup/effects/switch_2.asm @@ -0,0 +1,21 @@ +;PZU + name "Switch 2 - channel" + include "emu_constants.asm" + +Left IO +Right IO + +switchL control 0,0,1 +switchR control 0,0,1 + + macints Left, C_0, Left, switchL + macints Right, C_0, Right, switchR +; macs C_0, switchL, C_0, C_0 +; beq .left +; macs Left, Left, C_0, C_0 +;.left +; macs C_0, switchR, C_0, C_0 +; beq .end +; macs Right, Right, C_0, C_0 +;.end + end \ No newline at end of file diff --git a/ld10k1/setup/effects/switch_6.asm b/ld10k1/setup/effects/switch_6.asm new file mode 100644 index 0000000..f46f16f --- /dev/null +++ b/ld10k1/setup/effects/switch_6.asm @@ -0,0 +1,29 @@ +;PZU + name "Switch 6 - channel" + include "emu_constants.asm" + +Left IO +Right IO +LeftSurr IO +RightSurr IO +Center IO +LFE IO + +switch control 0,0,1 + + macints Left, C_0, Left, switch + macints Right, C_0, Right, switch + macints LeftSurr, C_0, LeftSurr, switch + macints RightSurr, C_0, RightSurr, switch + macints Center, C_0, Center, switch + macints LFE, C_0, LFE, switch +; macs C_0, switch, C_0, C_0 +; beq .end +; macs Left, Left, C_0, C_0 +; macs Right, Right, C_0, C_0 +; macs LeftSurr, LeftSurr, C_0, C_0 +; macs RightSurr, RightSurr, C_0, C_0 +; macs Center, Center, C_0, C_0 +; macs LFE, LFE, C_0, C_0 +;.end + end \ No newline at end of file diff --git a/ld10k1/setup/effects/tone.asm b/ld10k1/setup/effects/tone.asm new file mode 100644 index 0000000..6c74962 --- /dev/null +++ b/ld10k1/setup/effects/tone.asm @@ -0,0 +1,110 @@ +; stolen from alsa-driver + + name "Tone - Bass, Treble" + include "emu_constants.asm" + +inl io +toutl equ inl +inr io +toutr equ inr +inrl io +toutrl equ inrl +inrr io +toutrr equ inrr +inc io +toutc equ inc +inlfe io +toutlfe equ inlfe + +; Tone Control - Bass +bass0 control 20, 0, 40 +bass1 control 20, 0, 40 +bass2 control 20, 0, 40 +bass3 control 20, 0, 40 +bass4 control 20, 0, 40 + +; Tone Control - Treble +treble0 control 20, 0, 40 +treble1 control 20, 0, 40 +treble2 control 20, 0, 40 +treble3 control 20, 0, 40 +treble4 control 20, 0, 40 + +; Tone Control - Switch +toneonoff control 0, 0, 1 + +; temporary +templb sta 0, 0, 0, 0, 0 +templt sta 0, 0, 0, 0, 0 +temprb sta 0, 0, 0, 0, 0 +temprt sta 0, 0, 0, 0, 0 +temprlb sta 0, 0, 0, 0, 0 +temprlt sta 0, 0, 0, 0, 0 +temprrb sta 0, 0, 0, 0, 0 +temprrt sta 0, 0, 0, 0, 0 +tempcb sta 0, 0, 0, 0, 0 +tempct sta 0, 0, 0, 0, 0 + +outl dyn +outr dyn +outrl dyn +outrr dyn +outc dyn +outlfe dyn + +tmp sta 0, 0 + +BT macro tempb, tempt, chn + macs C_0, C_0, chn, bass0 + macmv tempb+1, tempb, tempb+1, bass2 + macmv tempb, chn, tempb, bass1 + macmv tempb+3, tempb+2, tempb+3, bass4 + macs tempb+2, ACCUM, tempb+2, bass3 + acc3 tempb+2, tempb+2, tempb+2, C_0 + + macs C_0, C_0, tempb+2, treble0 + macmv tempt+1, tempt, tempt+1, treble2 + macmv tempt, tempb+2, tempt, treble1 + macmv tempt+3, tempt+2, tempt+3, treble4 + macs tempt+2, ACCUM, tempt+2, treble3 + macints tempt+2, C_0, tempt+ 2, C_16 + + acc3 chn, tempt+2, C_0, C_0 + endm + +SONOFF macro out, in + macints tmp, C_0, out, toneonoff + andxor tmp+1, toneonoff, C_1, C_1 + macints tmp+1, C_0, in, tmp+1 + acc3 out, tmp, tmp+1, C_0 + endm + +;Process tone control + macs outl, inl, C_0, C_0 + macs outr, inr, C_0, C_0 + macs outrl, inrl, C_0, C_0 + macs outrr, inrr, C_0, C_0 + macs outc, inc, C_0, C_0 + macs outlfe, inlfe, C_0, C_0 + + BT templb, templt, outl + BT temprb, temprt, outr + BT temprlb, temprlt, outrl + BT temprrb, temprrt, outrr + BT tempcb, tempct, outc + + SONOFF outl, inl + SONOFF outr, inr + SONOFF outrl, inrl + SONOFF outrr, inrr + SONOFF outc, inc + SONOFF outlfe, inlfe + + macs toutl, outl, C_0, C_0 + macs toutr, outr, C_0, C_0 + macs toutrl, outrl, C_0, C_0 + macs toutrr, outrr, C_0, C_0 + macs toutc, outc, C_0, C_0 + macs toutlfe, outlfe, C_0, C_0 + + end \ No newline at end of file diff --git a/ld10k1/setup/effects/vol_2.asm b/ld10k1/setup/effects/vol_2.asm new file mode 100644 index 0000000..8676d1e --- /dev/null +++ b/ld10k1/setup/effects/vol_2.asm @@ -0,0 +1,15 @@ + name "2-channel Vol" + +Left control 0,0,100 +Right control 0,0,100 + +signal_l IO +signal_r IO + + macs signal_l,$40,signal_l,Left + macs signal_r,$40,signal_r,Right + + end + + + diff --git a/ld10k1/setup/effects/vol_master.asm b/ld10k1/setup/effects/vol_master.asm new file mode 100644 index 0000000..9673e00 --- /dev/null +++ b/ld10k1/setup/effects/vol_master.asm @@ -0,0 +1,23 @@ + name "Master Vol" + +VolM control 0,0,100 +;VolM control 100,0,#1 + +left IO +right IO +rleft IO +rright IO +center IO +lfe IO + + macs left.o,$40,left,VolM + macs right.o,$40,right,VolM + macs rleft.o,$40,rleft,VolM + macs rright.o,$40,rright,VolM + macs center.o,$40,center,VolM + macs lfe.o,$40,lfe,VolM + + end + + + diff --git a/ld10k1/setup/init_audigy.in b/ld10k1/setup/init_audigy.in new file mode 100644 index 0000000..eaa32df --- /dev/null +++ b/ld10k1/setup/init_audigy.in @@ -0,0 +1,246 @@ +#!/bin/sh + +LO10K1=@bindir@/lo10k1 + +#PCM Multi +$LO10K1 -s -n --ctrl c-Left,Right:PCM\ Front\ Playback\ Volume,t-PCM\ Front\ Playback\ Volume:1,c-LeftSurr,RightSurr:PCM\ Surround\ Playback\ Volume,t-PCM\ Surround\ Playback\ Volume:1,c-Center:PCM\ Center\ Playback\ Volume,t-PCM\ Center\ Playback\ Volume:1,c-LFE:PCM\ LFE\ Playback\ Volume,t-PCM\ LFE\ Playback\ Volume:1 --patch_name PCM\ Multi\ Volume -a simple.emu10k1 +#Input +$LO10K1 --conadd "PIN(PCM Multi Volume)=FX(8,9,2,3,6,7)" + +#PCM switch +#$LO10K1 -n --ctrl c-switchL,switchR:PCM\ Playback\ Switch,t-PCM\ Playback\ Switch:4 --patch_name PCM\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(PCM Switch,0,1)=FX(0,1)" +#PCM +$LO10K1 -n --ctrl c-Left,Right:PCM\ Playback\ Volume,t-PCM\ Playback\ Volume:1 --patch_name PCM\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(PCM Switch,0,1)=PIN(PCM Volume,0,1)" +$LO10K1 --conadd "PIN(PCM Volume,0,1)=FX(0,1)" +#PCM Capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:PCM\ Capture\ Switch,t-PCM\ Capture\ Switch:4 --patch_name PCM\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(PCM Cap Switch,0,1)=FX(0,1)" +# PCM Capture +$LO10K1 -n --ctrl c-Left,Right:PCM\ Capture\ Volume,t-PCM\ Capture\ Volume:1 --patch_name PCM\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(PCM Cap Switch,0,1)=PIN(PCM Cap Volume,0,1)" +$LO10K1 --conadd "PIN(PCM Cap Volume,0,1)=FX(0,1)" + +#Analog Mix switch +#$LO10K1 -n --ctrl c-switchL,switchR:Analog\ Mix\ Playback\ Switch,t-Analog\ Mix\ Playback\ Switch:4 --patch_name Analog\ Mix\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Analog Mix Switch)=IN(10,11)" +#Analog Mix +$LO10K1 -n --ctrl c-Left,Right:Analog\ Mix\ Playback\ Volume,t-Analog\ Mix\ Playback\ Volume:1,s-Analog\ Mix\ Playback\ Volume:100#100 --patch_name Analog\ Mix\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Analog Mix Switch)=PIN(Analog Mix Volume)" +$LO10K1 --conadd "PIN(Analog Mix Volume)=IN(10,11)" +#Analog Mix capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Analog\ Mix\ Capture\ Switch,t-Analog\ Mix\ Capture\ Switch:4 --patch_name Analog\ Mix\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Analog Mix Cap Switch)=IN(10,11)" +#Analog Mix Capture +$LO10K1 -n --ctrl c-Left,Right:Analog\ Mix\ Capture\ Volume,t-Analog\ Mix\ Capture\ Volume:1 --patch_name Analog\ Mix\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Analog Mix Cap Switch)=PIN(Analog Mix Cap Volume)" +$LO10K1 --conadd "PIN(Analog Mix Cap Volume)=IN(10,11)" + +#Music switch +#$LO10K1 -n --ctrl c-switchL,switchR:Music\ Playback\ Switch,t-Music\ Playback\ Switch:4 --patch_name Music\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Music Switch)=FX(4,5)" +#Music +$LO10K1 -n --ctrl c-Left,Right:Music\ Playback\ Volume,t-Music\ Playback\ Volume:1 --patch_name Music\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Music Switch)=PIN(Music Volume)" +$LO10K1 --conadd "PIN(Music Volume)=FX(4,5)" +#Music capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Music\ Capture\ Switch,t-Music\ Capture\ Switch:4 --patch_name Music\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Music Cap Switch)=FX(4,5)" +#Music Capture +$LO10K1 -n --ctrl c-Left,Right:Music\ Capture\ Volume,t-Music\ Capture\ Volume:1 --patch_name Music\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Music Cap Switch)=PIN(Music Cap Volume)" +$LO10K1 --conadd "PIN(Music Cap Volume)=FX(4,5)" + +#Mic switch +#$LO10K1 -n --ctrl c-switchL,switchR:Mic\ Playback\ Switch,t-Mic\ Playback\ Switch:4 --patch_name Mic\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Mic Switch)=IN(0,1)" +#Mic +$LO10K1 -n --ctrl c-Left,Right:Mic\ Playback\ Volume,t-Mic\ Playback\ Volume:1 --patch_name Mic\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Mic Switch)=PIN(Mic Volume)" +$LO10K1 --conadd "PIN(Mic Volume)=IN(0,1)" +#Mic capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Mic\ Capture\ Switch,t-Mic\ Capture\ Switch:4 --patch_name Mic\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Mic Cap Switch)=IN(0,1)" +#Mic Capture +$LO10K1 -n --ctrl c-Left,Right:Mic\ Capture\ Volume,t-Mic\ Capture\ Volume:1 --patch_name Mic\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Mic Cap Switch)=PIN(Mic Cap Volume)" +$LO10K1 --conadd "PIN(Mic Cap Volume)=IN(0,1)" + +#Audigy CD switch +#$LO10K1 -n --ctrl c-switchL,switchR:Audigy\ CD\ Playback\ Switch,t-Audigy\ CD\ Playback\ Switch:4 --patch_name Audigy\ CD\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Audigy CD Switch)=IN(2,3)" +#Audigy CD +$LO10K1 -n --ctrl c-Left,Right:Audigy\ CD\ Playback\ Volume,t-Audigy\ CD\ Playback\ Volume:1 --patch_name Audigy\ CD\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Audigy CD Switch)=PIN(Audigy CD Volume)" +$LO10K1 --conadd "PIN(Audigy CD Volume)=IN(2,3)" +#Audigy CD capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Audigy\ CD\ Capture\ Switch,t-Audigy\ CD\ Capture\ Switch:4 --patch_name Audigy\ CD\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Audigy CD Cap Switch)=IN(2,3)" +#Audigy CD Capture +$LO10K1 -n --ctrl c-Left,Right:Audigy\ CD\ Capture\ Volume,t-Audigy\ CD\ Capture\ Volume:1 --patch_name Audigy\ CD\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Audigy CD Cap Switch)=PIN(Audigy CD Cap Volume)" +$LO10K1 --conadd "PIN(Audigy CD Cap Volume)=IN(2,3)" + +#Optical & Coaxial IN switch +#$LO10K1 -n --ctrl c-switchL,switchR:IEC958\ Opt\ and\ Coax\ Playback\ Switch,t-IEC958\ Opt\ and\ Coax\ Playback\ Switch:4 --patch_name Opt\ and\ Coax\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Opt and Coax Switch)=IN(4,5)" +#Optical & Coaxial IN +$LO10K1 -n --ctrl c-Left,Right:IEC958\ Opt\ and\ Coax\ Playback\ Volume,t-IEC958\ Opt\ and\ Coax\ Playback\ Volume:1 --patch_name Opt\ and\ Coax\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Opt and Coax Switch)=PIN(Opt and Coax Volume)" +$LO10K1 --conadd "PIN(Opt and Coax Volume)=IN(4,5)" +#Optical & Coaxial IN capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:IEC958\ Opt\ and\ Coax\ Capture\ Switch,t-IEC958\ Opt\ and\ Coax\ Capture\ Switch:4 --patch_name Opt\ and\ Coax\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Opt and Coax Cap Switch)=IN(4,5)" +#Optical & Coaxial IN Capture +$LO10K1 -n --ctrl c-Left,Right:IEC958\ Opt\ and\ Coax\ Capture\ Volume,t-IEC958\ Opt\ and\ Coax\ Capture\ Volume:1 --patch_name Opt\ and\ Coax\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Opt and Coax Cap Switch)=PIN(Opt and Coax Cap Volume)" +$LO10K1 --conadd "PIN(Opt and Coax Cap Volume)=IN(4,5)" + +#Line2 switch +#$LO10K1 -n --ctrl c-switchL,switchR:Line2\ Playback\ Switch,t-Line2\ Playback\ Switch:4 --patch_name Line2\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Line2 Switch)=IN(8,9)" +#Line2 +$LO10K1 -n --ctrl c-Left,Right:Line2\ Playback\ Volume,t-Line2\ Playback\ Volume:1 --patch_name Line2\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Line2 Switch)=PIN(Line2 Volume)" +$LO10K1 --conadd "PIN(Line2 Volume)=IN(8,9)" +#Line2 capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Line2\ Capture\ Switch,t-Line2\ Capture\ Switch:4 --patch_name Line2\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Line2 Cap Switch)=IN(8,9)" +#Line2 Capture +$LO10K1 -n --ctrl c-Left,Right:Line2\ Capture\ Volume,t-Line2\ Capture\ Volume:1 --patch_name Line2\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Line2 Cap Switch)=PIN(Line2 Cap Volume)" +$LO10K1 --conadd "PIN(Line2 Cap Volume)=IN(8,9)" + +#Aux2 switch +#$LO10K1 -n --ctrl c-switchL,switchR:Aux2\ Playback\ Switch,t-Aux2\ Playback\ Switch:4 --patch_name Aux2\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Aux2 Switch)=IN(12,13)" +#Aux2 +$LO10K1 -n --ctrl c-Left,Right:Aux2\ Playback\ Volume,t-Aux2\ Playback\ Volume:1 --patch_name Aux2\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Aux2 Switch)=PIN(Aux2 Volume)" +$LO10K1 --conadd "PIN(Aux2 Volume)=IN(12,13)" +#Aux2 capture switch +#$LO10K1 -n --ctrl c-switchL,switchR:Aux2\ Capture\ Switch,t-Aux2\ Capture\ Switch:4 --patch_name Aux2\ Cap\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "PIN(Aux2 Cap Switch)=IN(12,13)" +#Aux2 Capture +$LO10K1 -n --ctrl c-Left,Right:Aux2\ Capture\ Volume,t-Aux2\ Capture\ Volume:1 --patch_name Aux2\ Cap\ Volume -a vol_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Aux2 Cap Switch)=PIN(Aux2 Cap Volume)" +$LO10K1 --conadd "PIN(Aux2 Cap Volume)=IN(12,13)" + +#1 +#Stereo to 5.1 +$LO10K1 -n --ctrl c-Left,Right:Front\ Playback\ Volume,t-Front\ Playback\ Volume:1,s-Front\ Playback\ Volume:100#100,c-LeftSurr,RightSurr:Surround\ Playback\ Volume,t-Surround\ Playback\ Volume:1,c-Center:Center\ Playback\ Volume,t-Center\ Playback\ Volume:1,c-LFE:LFE\ Playback\ Volume,t-LFE\ Playback\ Volume:1 --patch_name Stereo\ To\ 51 -a sto51.emu10k1 +#Input +$LO10K1 --conadd "POUT(PCM Volume)=PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Analog Mix Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Music Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Mic Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Audigy CD Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Opt and Coax Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Line2 Volume)>PIN(Stereo To 51,0,1)" +$LO10K1 --conadd "POUT(Aux2 Volume)>PIN(Stereo To 51,0,1)" + + +#Capture +#$LO10K1 -n --patch_name Capture\ Copy -a copy_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(PCM Cap Volume)=PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Analog Mix Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Music Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Mic Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Audigy CD Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Opt and Coax Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Line2 Cap Volume)>PIN(Capture Copy)" +#$LO10K1 --conadd "POUT(Aux2 Cap Volume)>PIN(Capture Copy)" +#Output +#$LO10K1 --conadd "POUT(Capture Copy)=OUT(22,23)" + +$LO10K1 --conadd "POUT(PCM Cap Volume)=OUT(22,23)" +$LO10K1 --conadd "POUT(Analog Mix Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Music Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Mic Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Audigy CD Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Opt and Coax Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Line2 Cap Volume)>OUT(22,23)" +$LO10K1 --conadd "POUT(Aux2 Cap Volume)>OUT(22,23)" + + +#Tone +$LO10K1 -n --ctrl c-bass0,bass1,bass2,bass3,bass4:Tone\ Control\ -\ Bass,t-Tone\ Control\ -\ Bass:2,v-Tone\ Control\ -\ Bass:1,c-treble0,treble1,treble2,treble3,treble4:Tone\ Control\ -\ Treble,t-Tone\ Control\ -\ Treble:3,v-Tone\ Control\ -\ Treble:1,c-toneonoff:Tone\ Control\ -\ Switch,t-Tone\ Control\ -\ Switch:4 --patch_name Tone\ Controls -a tone.emu10k1 +#Input +$LO10K1 --conadd "POUT(PCM Multi Volume)=PIN(Tone Controls)" +$LO10K1 --conadd "POUT(Stereo To 51)>PIN(Tone Controls)" + +#Master +$LO10K1 -n --ctrl c-VolM:Master\ Playback\ Volume,t-Master\ Playback\ Volume:1 --patch_name Master\ Volume -a vol_master.emu10k1 +#Inputs +$LO10K1 --conadd "POUT(Tone Controls)>PIN(Master Volume)" + +#Master switch +#$LO10K1 -n --ctrl c-switch:Master\ Playback\ Switch,t-Master\ Playback\ Switch:4 --patch_name Master\ Switch -a switch_6.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Master Volume)=PIN(Master Switch)" + +#Output +$LO10K1 -n --ctrl c-enableL,enableR:IEC958\ Optical\ Raw\ Playback\ Switch,t-IEC958\ Optical\ Raw\ Playback\ Switch:4 --patch_name Output -a output.emu10k1 +#Inputs +#$LO10K1 --conadd "POUT(Master Switch)=PIN(Output,0,1,2,3,4,5)" +$LO10K1 --conadd "POUT(Master Volume)=PIN(Output,0,1,2,3,4,5)" +$LO10K1 --conadd "PIN(Output,6,7)=FX(20,21)" +#Output +$LO10K1 --conadd "POUT(Output,0,1,2,3,4,5)=OUT(8,9,14,15,10,11)" +#$LO10K1 --conadd "POUT(Output,2,3,4,5)=OUT(14,15,10,11)" +$LO10K1 --conadd "POUT(Output,6,7,8,9,10,11)=OUT(0,1,6,7,2,3)" + +#$LO10K1 -n --patch_name delay1 -a delay.emu10k1 +#$LO10K1 --conadd "POUT(delay1,0)=OUT(8)" +#$LO10K1 --conadd "PIN(delay1,0)=POUT(Output,0)" + +#$LO10K1 -n --patch_name delay2 -a delay.emu10k1 +#$LO10K1 --conadd "POUT(delay2,0)=OUT(9)" +#$LO10K1 --conadd "PIN(delay2,0)=POUT(Output,1)" + +#Headphone +$LO10K1 -n --ctrl c-Left,Right:Headphone\ Playback\ Volume,t-Headphone\ Playback\ Volume:1 --patch_name Headphone\ Volume -a vol_2.emu10k1 +#Input +$LO10K1 --conadd "PIN(Headphone Volume,0,1)>PIN(Stereo To 51,0,1)" + +#Headphone switch +#$LO10K1 -n --ctrl c-switchL,switchR:Headphone\ Playback\ Switch,t-Headphone\ Playback\ Switch:4 --patch_name Headphone\ Switch -a switch_2.emu10k1 +#Input +#$LO10K1 --conadd "POUT(Headphone Volume)=PIN(Headphone Switch)" +#Output +#$LO10K1 --conadd "POUT(Headphone Switch,0,1)=OUT(4,5)" +$LO10K1 --conadd "POUT(Headphone Volume,0,1)=OUT(4,5)" diff --git a/ld10k1/setup/init_live.in b/ld10k1/setup/init_live.in new file mode 100644 index 0000000..9b83059 --- /dev/null +++ b/ld10k1/setup/init_live.in @@ -0,0 +1,390 @@ +#!/bin/sh +# +# Copyright (c) 2004 Mikael Magnusson +# + +LO10K1=@bindir@/lo10k1 + +#LO10K1="valgrind --num-callers=6 ../lo10k1" + +DEBUG=0 + +function runlo10k1 +{ + if test $DEBUG -gt 2 ; then + echo $LO10K1 "$@" + fi + + $LO10K1 "$@" + + res=$? + + + if test $res -ne 0 ; then + echo Failed $LO10K1 "$@" + fi +} + +function connect +{ + from=$1 + op=$2 + to=$3 + + if test $DEBUG -gt 1 ; then + echo "connect $from $op $to" + fi + + runlo10k1 --conadd "$from$op$to" +} + +function copy +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 0 ; then + echo "copy \"$name\" $port" + fi + + # Copy + runlo10k1 -n --patch_name "$name Copy" -a copy_2.emu10k1 + # Input + connect "PIN($name Copy)" '=' "$port" +} + +function volume +{ + local name=$1 + local port=$2 + local default=$3 + + if test $DEBUG -gt 1 ; then + echo "volume \"$name\" $port default=$default" + fi + + # Volume + runlo10k1 -n --ctrl "c-Left,Right:$name Volume,t-$name Volume:1,s-$name Volume:$default" --patch_name "$name Volume" -a vol_2.emu10k1 + # Input + connect "PIN($name Volume)" '=' "$port" +} + +function master_volume +{ + local name=$1 + local port=$2 + local default=$3 + + if test $DEBUG -gt 1 ; then + echo "master volume \"$name\" $port default=$default" + fi + + # Master + runlo10k1 -n --ctrl "c-VolM:$name Volume,t-$name Volume:1,s-$name Volume:$default" --patch_name "$name Volume" -a vol_master.emu10k1 + # Input + connect "$port" '=' "PIN($name Volume)" +} + +function switch +{ + local name=$1 + local port=$2 + local default=$3 + + if test $DEBUG -gt 1 ; then + echo "switch \"$name\" $port default=$default" + fi + + # Switch + runlo10k1 -n --ctrl "c-switchL,switchR:$name Switch,t-$name Switch:4,s-$name Switch:$default" --patch_name "$name Switch" -a switch_2.emu10k1 + # Input + connect "PIN($name Switch)" '>' "$port" +} + +function master_switch +{ + local name=$1 + local port=$2 + local default=$3 + + if test $DEBUG -gt 1 ; then + echo "master_switch \"$name\" $port default=$default" + fi + + # Master switch + runlo10k1 -n --ctrl "c-switch:$name Switch,t-$name Switch:4,s-$name Switch:$default" --patch_name "$name Switch" -a switch_6.emu10k1 + # Input + connect "PIN($name Switch)" '=' "$port" +} + +function playback +{ + name=$1 + port=$2 + + if test $DEBUG -gt 0 ; then + echo "playback \"$name\" $port" + fi + + # Switch + switch "$name Playback" "$port" "1#1" + volume "$name Playback" "POUT($name Playback Switch)" "0#0" + # Output + connect "POUT($name Playback Volume)" '>' "PIN(Wave Stereo To 51,0,1)" +} + +function playback_noswitch +{ + name=$1 + port=$2 + + if test $DEBUG -gt 0 ; then + echo "playback_noswitch \"$name\" $port" + fi + + # Switch + volume "$name Playback" "$port" "0#0" + # Output + connect "POUT($name Playback Volume)" '>' "PIN(Wave Stereo To 51,0,1)" +} + +function capture +{ + name=$1 + port=$2 + + if test $DEBUG -gt 0 ; then + echo "capture \"$name\" $port" + fi + + # Capture switch + switch "$name Capture" "$port" "0#0" + volume "$name Capture" "POUT($name Capture Switch)" "100#100" + # Output + connect "POUT($name Capture Volume)" '>' "OUT(OUT_PCM_Capture_Left,OUT_PCM_Capture_Right)" +} + +function capture_noswitch +{ + name=$1 + port=$2 + + if test $DEBUG -gt 0 ; then + echo "capture_noswitch \"$name\" $port" + fi + + # Capture switch + volume "$name Capture" "$port" "100#100" + # Output + connect "POUT($name Capture Volume)" '>' "OUT(OUT_PCM_Capture_Left,OUT_PCM_Capture_Right)" +} + +function master +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 0 ; then + echo "master \"$name\" $port" + fi + + # Switch + master_volume "$name Playback" "$port" "100" + master_switch "$name Playback" "POUT($name Playback Volume)" "1" +} + +function dump_patches +{ + num=$1 + + for (( i=0; $i < $num; i=$i+1 )); do + p=$(( $i + 100)) + runlo10k1 --debug $p + done + + + exit +} + + +function simple_stereo_to_51 +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 1 ; then + echo "simple_stereo_to_51 \"$name\" $port" + fi + +# Stereo to 5.1 + runlo10k1 -n --ctrl "c-Left,Right:$name Playback Volume,t-$name Playback Volume:1,s-$name Playback Volume:100#100,c-LeftSurr,RightSurr:$name Surround Playback Volume,t-$name Surround Playback Volume:1,c-Center:$name Center Playback Volume,t-$name Center Playback Volume:1,c-LFE:$name LFE Playback Volume,t-$name LFE Playback Volume:1" --patch_name "$name Stereo To 51" -a sto51.emu10k1 +# Input + connect "$port" '>' "PIN($name Stereo To 51,0,1)" + +# Output + connect "POUT($name Stereo To 51,0,1,2,3,4)" '>' "PIN(Tone Control,0,1,2,3,4)" +} + +function prologic +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 1 ; then + echo "prologic \"$name\" $port" + fi + +# Stereo to 5.1 + runlo10k1 -n --ctrl "" --patch_name "$name Stereo To 51" -a prologic.emu10k1 +# Input + connect "PIN($name Stereo To 51,0,1)" '>' "$port" + +# PCM Multi + runlo10k1 -n --ctrl "c-Left,Right:$name Playback Volume,t-$name Playback Volume:1,c-LeftSurr,RightSurr:$name Surround Playback Volume,t-$name Surround Playback Volume:1,c-Center:$name Center Playback Volume,t-$name Center Playback Volume:1,c-LFE:$name LFE Playback Volume,t-LFE Playback Volume:1" --patch_name "$name Multi Volume" -a simple.emu10k1 +# Input + connect "POUT($name Stereo To 51)" '=' "PIN($name Multi Volume,0,1,2,3,4)" + +# Output + connect "POUT($name Multi Volume,0,1,2,3,4)" '>' "PIN(Tone Control,0,1,2,3,4)" +} + +function stereo_to_51 +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 0 ; then + echo "stereo_to_51 \"$name\" $port" + fi + +# simple_stereo_to_51 "$name" "$port" + prologic "$name" "$port" + +} + +function tone +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 0 ; then + echo "tone \"$name\" $port" + fi + +# +# Tone +# + runlo10k1 -n --ctrl "c-bass0,bass1,bass2,bass3,bass4:$name - Bass,t-$name - Bass:2,v-$name - Bass:1,c-treble0,treble1,treble2,treble3,treble4:$name - Treble,t-$name - Treble:3,v-$name - Treble:1,c-toneonoff:$name - Switch,t-$name - Switch:4" --patch_name "${name}" -a tone.emu10k1 +} + +function multi_playback +{ + local name=$1 + local port=$2 + + if test $DEBUG -gt 0 ; then + echo "multi_playback \"$name\" $port" + fi + +# PCM Multi + runlo10k1 -n --ctrl "c-Left,Right:PCM Front Playback Volume,t-PCM Front Playback Volume:1,c-LeftSurr,RightSurr:Surround Playback Volume,t-Surround Playback Volume:1,c-Center:Center Playback Volume,t-Center Playback Volume:1,c-LFE:LFE Playback Volume,t-LFE Playback Volume:1" --patch_name "$name Multi Volume" -a simple.emu10k1 +# Input + connect "PIN($name Multi Volume)" '>' "$port" +# Output + connect "POUT($name Multi Volume)" '>' "PIN(Tone Control)" +} + +function fxbus +{ + runlo10k1 --patch_name "FX Bus" -a fxbus.emu10k1 + connect "PIN(FX Bus)" '=' "FX(FX_PCM_Left,FX_PCM_Right,FX_PCM_Surr_Left,FX_PCM_Surr_Right,FX_MIDI_Left,FX_MIDI_Right,FX_Center,FX_LFE,8,9)" + + fx_multi="POUT(FX Bus,0,1,2,3,6,7)" + fx_front="POUT(FX Bus,0,1)" + fx_rear="POUT(FX Bus,2,3)" + fx_midi="POUT(FX Bus,4,5)" + fx_pcm="POUT(FX Bus,8,9)" +} + +#dump_patches 16 + +runlo10k1 -s + +tone "Tone Control" + +fxbus + +#copy "FX89" "FX(8,9)" +stereo_to_51 "Wave" "$fx_pcm" + +# +# FXBUS +# +multi_playback "PCM" "$fx_multi" + +capture "PCM Front" "$fx_front" +capture "Wave" "$fx_pcm" +capture "Surround" "$fx_rear" + +playback "Music" "$fx_midi" +capture "Music" "$fx_midi" + + +# +# INPUTS +# +playback "AC97" "IN(IN_AC97_Left,IN_AC97_Right)" +capture_noswitch "AC97" "IN(IN_AC97_Left,IN_AC97_Right)" + +# playback "IEC958 TTL" "IN(IN_TTL_IEC958_Left,IN_TTL_IEC958_Right)" +# capture "IEC958 TTL" "IN(IN_TTL_IEC958_Left,IN_TTL_IEC958_Right)" + +# playback "Zoom Video" "IN(IN_Zoom_Video_Left,IN_Zoom_Video_Right)" +# capture "Zoom Video" "IN(IN_Zoom_Video_Left,IN_Zoom_Video_Right)" + +# playback "IEC958 LiveDrive" "IN(IN_Optical_IEC958_Left,IN_Optical_IEC958_Right)" +# capture "IEC958 LiveDrive" "IN(IN_Optical_IEC958_Left,IN_Optical_IEC958_Right)" + +# playback "Line LiveDrive" "IN(IN_Line_Mic_1_Left,IN_Line_Mic_1_Right)" +# capture "Line LiveDrive" "IN(IN_Line_Mic_1_Left,IN_Line_Mic_1_Right)" + +# playback "IEC958 Coaxial" "IN(IN_Coax_IEC958_Left,IN_Coax_IEC958_Right)" +# capture "IEC958 Coaxial" "IN(IN_Coax_IEC958_Left,IN_Coax_IEC958_Right)" + +# playback "Line2 LiveDrive" "IN(IN_Line_Mic_2_Left,IN_Line_Mic_2_Right)" +# capture "Line2 LiveDrive" "IN(IN_Line_Mic_2_Left,IN_Line_Mic_2_Right)" + + +master_volume="Master_2 Playback Volume" +master_switch="Master_2 Playback Switch" + +master "Master_2" "POUT(Tone Control)" +connect "POUT($master_switch)" '>' "OUT(OUT_AC97_Left,OUT_AC97_Right,OUT_Analog_Surr_Left,OUT_Analog_Surr_Right,OUT_AC97_Center,OUT_AC97_LFE)" + +exit +# Headphone + +# Headphone Switch +runlo10k1 -n --ctrl "c-switchL:Headphone Center Playback Switch,c-switchR:Headphone LFE Playback Switch,t-Headphone Center Playback Switch:4,t-Headphone LFE Playback Switch:4,i-Headphone Center Playback Switch:1,i-Headphone LFE P\ +layback Switch:1" --patch_name "Headphone Center Playback Switch" -a switch_2.emu10k1 +#Input +#connect "POUT(Headphone Playback Volume)" '' "PIN(Headphone Center Playback Switch)" +#Output +#connect "POUT(Headphone Center Playback Switch,0,1)" '' "OUT(OUT_Headphone_Left,OUT_Headphone_Right)" + +# Headphone Volume +runlo10k1 -n --ctrl "c-Left,Right:Headphone Playback Volume,t-Headphone Playback Volume#1:1,i-Headphone Playback Volume:1" --patch_name "Headphone Playback Volume" -a vol_2.emu10k1 +#Input +#runlo10k1 --conadd "PIN(Headphone Playback Volume,0,1)>PIN(Wave Stereo To 51,0,1)" +#connect "POUT(Headphone Playback Volume,0,1)" '>' "PIN(Wave Stereo To 51,0,1)" +#connect "POUT(Tone Control,0,1)" '=' "PIN(Headphone Playback Volume,0,1)" +#connect "POUT(Headphone Playback SwitchTone Control,0,1)" '=' "PIN(Headphone Playback Volume,0,1)" + +#Output +runlo10k1 -n --ctrl "c-enableL,enableR:IEC958 Optical Raw Playback Switch,t-IEC958 Optical Raw Playback Switch:4" --patch_name "Output" -a output.emu10k1 +#Inputs +runlo10k1 --conadd "POUT(Master Switch)=PIN(Output,0,1,2,3,4,5)" +#runlo10k1 --conadd "PIN(Output,6,7)=FX(20,21)" +#Output +runlo10k1 --conadd "POUT(Output,0,1,2,3,4,5)=OUT(0,1,8,9,17,18)" +runlo10k1 --conadd "POUT(Output,6,7,8,9,10,11)=OUT(0,1,2,3,4,5)" diff --git a/ld10k1/src/Makefile.am b/ld10k1/src/Makefile.am new file mode 100644 index 0000000..243011c --- /dev/null +++ b/ld10k1/src/Makefile.am @@ -0,0 +1,25 @@ +bin_PROGRAMS = lo10k1 +sbin_PROGRAMS = ld10k1 dl10k1 +ld10k1_SOURCES = ld10k1.c ld10k1_fnc.c ld10k1_fnc1.c ld10k1_debug.c \ + ld10k1_driver.c comm.c ld10k1_tram.c \ + ld10k1_dump.c ld10k1_mixer.c\ + ld10k1.h ld10k1_fnc_int.h ld10k1_fnc1.h ld10k1_debug.h \ + ld10k1_driver.h bitops.h ld10k1_tram.h \ + ld10k1_dump.h ld10k1_dump_file.h ld10k1_mixer.h +ld10k1_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS) +ld10k1_LDADD = $(ALSA_LIBS) + +#liblo10k1_ladir = $(includedir)/lo10k1 +lib_LTLIBRARIES = liblo10k1.la +liblo10k1_la_SOURCES = comm.c liblo10k1.c liblo10k1ef.c liblo10k1lf.c +#liblo10k1_la_HEADERS = comm.h liblo10k1.h liblo10k1ef.h ld10k1_error.h ld10k1_fnc.h liblo10k1lf.h + +lo10k1_SOURCES = lo10k1.c +lo10k1_CFLAGS = $(ALSA_CFLAGS) -DEFFECTSDIR='"$(effectsdir)"' +lo10k1_LDADD = liblo10k1.la + +dl10k1_SOURCES = dl10k1.c ld10k1_dump_file.h +dl10k1_CFLAGS = $(ALSA_CFLAGS) +dl10k1_LDADD = $(ALSA_LIBS) + +INCLUDES=-I$(top_srcdir)/include \ No newline at end of file diff --git a/ld10k1/src/bitops.h b/ld10k1/src/bitops.h new file mode 100644 index 0000000..03f106f --- /dev/null +++ b/ld10k1/src/bitops.h @@ -0,0 +1,50 @@ +#ifndef _PZ_GENERIC_BITOPS_H_ +#define _PZ_GENERIC_BITOPS_H_ +/* this is from linux kernel header */ +/* + * For the benefit of those who are trying to port Linux to another + * architecture, here are some C-language equivalents. You should + * recode these in the native assembly language, if at all possible. + * To guarantee atomicity, these routines call cli() and sti() to + * disable interrupts while they operate. (You have to provide inline + * routines to cli() and sti().) + * + * Also note, these routines assume that you have 32 bit longs. + * You will have to change this if you are trying to port Linux to the + * Alpha architecture or to a Cray. :-) + * + * C language equivalents written by Theodore Ts'o, 9/26/92 + */ + +__inline__ int set_bit(int nr, unsigned long * addr) +{ + int mask, retval; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *addr) != 0; + *addr |= mask; + return retval; +} + +__inline__ int clear_bit(int nr, unsigned long * addr) +{ + int mask, retval; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *addr) != 0; + *addr &= ~mask; + return retval; +} + +__inline__ int test_bit(int nr, unsigned long * addr) +{ + int mask; + + addr += nr >> 5; + mask = 1 << (nr & 0x1f); + return ((mask & *addr) != 0); +} + +#endif /* _PZ_GENERIC_BITOPS_H */ diff --git a/ld10k1/src/comm.c b/ld10k1/src/comm.c new file mode 100644 index 0000000..f010e20 --- /dev/null +++ b/ld10k1/src/comm.c @@ -0,0 +1,349 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "comm.h" +#include "ld10k1_error.h" + +/* taken from glibc example */ +int setup_comm(comm_param *param) +{ + int sock; + struct sockaddr_un lname; + struct sockaddr_in iname; + size_t size; + + /* Create the socket. */ + if (param->type == COMM_TYPE_LOCAL) + sock = socket (PF_LOCAL, SOCK_STREAM, 0); + else + sock = socket (PF_INET, SOCK_STREAM, 0); + if (sock < 0) + return -1; + + if (param->server) { + if (param->type == COMM_TYPE_LOCAL) { + unlink(param->name); + + /* Bind a name to the socket. */ + memset(&lname, 0, sizeof(struct sockaddr_un)); + lname.sun_family = AF_LOCAL; + strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1); + lname.sun_path[sizeof (lname.sun_path) - 1] = '\0'; + + /* The size of the address is + the offset of the start of the filename, + plus its length, + plus one for the terminating null byte. + Alternatively you can just do: + size = SUN_LEN (&name); + */ + size = (offsetof (struct sockaddr_un, sun_path) + strlen (lname.sun_path) + 1); + + if (bind (sock, (struct sockaddr *) &lname, size) < 0) + return -1; + + chmod(param->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + } else { + /* Give the socket a name. */ + memset(&iname, 0, sizeof(struct sockaddr_in)); + iname.sin_family = AF_INET; + iname.sin_port = htons (param->port); + iname.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(sock, (struct sockaddr *) &iname, sizeof (iname)) < 0) + return -1; + } + } + + return sock; +} + +int connect_comm(int conn_num, comm_param *param) +{ + struct sockaddr_un lname; + struct sockaddr_in iname; + struct hostent *hostinfo; + size_t size; + + int attempt; + int max_attempt; + int not_connected; + + attempt = 0; + if (param->wfc) + max_attempt = param->wfc / 10; + else + max_attempt = 0; + + if (param->type == COMM_TYPE_LOCAL) { + memset(&lname, 0, sizeof(struct sockaddr_un)); + lname.sun_family = AF_LOCAL; + strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1); + lname.sun_path[sizeof(lname.sun_path) - 1] = '\0'; + + size = (offsetof(struct sockaddr_un, sun_path)) + strlen(lname.sun_path) + 1; + + while (1) + { + not_connected = connect(conn_num, (struct sockaddr *) &lname, size); + if (!not_connected) + break; + if (attempt >= max_attempt) + return -1; + attempt++; + usleep(10000); + } + } else { + memset(&iname, 0, sizeof(struct sockaddr_in)); + iname.sin_family = AF_INET; + iname.sin_port = htons(param->port); + hostinfo = gethostbyname(param->name); + if (hostinfo == NULL) + return -1; + iname.sin_addr = *(struct in_addr *)hostinfo->h_addr; + + while (1) + { + not_connected = connect(conn_num, (struct sockaddr *) &iname, sizeof(struct sockaddr_in)); + if (!not_connected) + break; + if (attempt >= max_attempt) + return -1; + attempt++; + usleep(10000); + } + } + return 0; +} + +int listen_comm(int conn_num) +{ + if (listen(conn_num, 1) < 0) + return -1; + return 0; +} + +int accept_comm(int conn_num) +{ + struct sockaddr addr; + socklen_t addr_len; + int sock; + + addr_len = sizeof(addr); + + sock = accept(conn_num, &addr, &addr_len); + + if (sock < 0) + return -1; + + return sock; +} + +int free_comm(int conn_num) +{ + if (shutdown(conn_num, 2)) + return -1; + if (close(conn_num) < 0) + return -1; + + return 0; +} + +#define MAX_ATEMPT 5 + +int read_all(int conn_num, void *data, int data_size) +{ + int offset = 0; + int how_much = data_size; + int atempt = 0; + int readed = 0; + + while (atempt < MAX_ATEMPT && how_much > 0) { + readed = read(conn_num, ((char *)data) + offset, how_much); + if (readed < 0) + return LD10K1_ERR_COMM_READ; + offset += readed; + how_much -= readed; + atempt++; + if (how_much > 0) + usleep(10000); + } + + if (how_much > 0) + return LD10K1_ERR_COMM_READ; + else + return data_size; +} + +int write_all(int conn_num, void *data, int data_size) +{ + int offset = 0; + int how_much = data_size; + int atempt = 0; + int writed = 0; + + while (atempt < MAX_ATEMPT && how_much > 0) { + writed = write(conn_num, ((char *)data) + offset, how_much); + if (writed < 0) + return LD10K1_ERR_COMM_WRITE; + offset += writed; + how_much -= writed; + atempt++; + if (how_much > 0) + usleep(50000); + } + + if (how_much > 0) + return LD10K1_ERR_COMM_WRITE; + else + return data_size; +} + +int send_request(int conn_num, int op, void *data, int data_size) +{ + int nbytes; + struct msg_req header; + + header.op = op; + header.size = data_size; + + /* header */ + nbytes = write_all(conn_num, &header, sizeof(header)); + if (nbytes < 0) + return nbytes; + + if (data_size > 0) { + /* data */ + nbytes = write_all(conn_num, data, data_size); + if (nbytes < 0) + return nbytes; + } + return 0; +} + +int send_response(int conn_num, int op, int err, void *data, int data_size) +{ + int nbytes; + struct msg_resp header; + + header.op = op; + header.err = err; + header.size = data_size; + + /* header */ + nbytes = write_all(conn_num, &header, sizeof(header)); + if (nbytes < 0) + return nbytes; + + if (data_size > 0) { + /* data */ + nbytes = write_all(conn_num, data, data_size); + if (nbytes < 0) + return nbytes; + } + return 0; +} + +int send_msg_data(int conn_num, void *data, int data_size) +{ + int nbytes; + + if (data_size > 0) { + /* data */ + nbytes = write_all(conn_num, data, data_size); + if (nbytes < 0) + return nbytes; + } + return 0; +} + +int receive_request(int conn_num, int *op, int *data_size) +{ + struct msg_req header; + int nbytes; + + nbytes = read_all(conn_num, &header, sizeof(header)); + if (nbytes < 0) + return nbytes; + if (nbytes == 0) { + *op = -1; + *data_size = 0; + return 0; + } + *op = header.op; + *data_size = header.size; + return 0; +} + +int receive_response(int conn_num, int *op, int *data_size) +{ + struct msg_resp header; + int nbytes; + + nbytes = read_all(conn_num, &header, sizeof(header)); + if (nbytes < 0) + return nbytes; + if (nbytes == 0) { + *op = -1; + *data_size = 0; + return 0; + } + *op = header.op; + *data_size = header.size; + if (header.err < 0) + return header.err; + return 0; +} + +int receive_msg_data(int conn_num, void *data, int data_size) +{ + int nbytes; + nbytes = read_all(conn_num, data, data_size); + if (nbytes < 0) + return nbytes; + return 0; +} + +void *receive_msg_data_malloc(int conn_num, int data_size) +{ + void *tmp; + + tmp = malloc(data_size); + if (!tmp) + return NULL; + + if (receive_msg_data(conn_num, tmp, data_size)) { + free(tmp); + return NULL; + } + return tmp; +} diff --git a/ld10k1/src/dl10k1.c b/ld10k1/src/dl10k1.c new file mode 100644 index 0000000..7ca3f43 --- /dev/null +++ b/ld10k1/src/dl10k1.c @@ -0,0 +1,615 @@ +/* + * EMU10k1 dump loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * Hwdep usage based on sb16_csp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* TODO - kontrola dat, ktore nahravam */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include + +#include "ld10k1_dump_file.h" + +#define DL10K1_SIGNATURE "DUMP Image (dl10k1)" +int card = 0; +snd_hwdep_t *handle; +const char *card_proc_id; + +void error(const char *fmt,...) +{ + va_list va; + + va_start(va, fmt); + fprintf(stderr, "Error: "); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); + va_end(va); +} + +static void help(char *command) +{ + fprintf(stderr, + "Usage: %s [-options]\n" + "\nAvailable options:\n" + " -h, --help this help\n" + " -c, --card select card number, default = 0\n" + " -d, --dump file with dump\n" + , command); +} + +int driver_set_tram_size(int tram_size) +{ + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) { + error("unable to setup tram"); + return 1; + } + return 0; +} + +void free_code_struct(emu10k1_fx8010_code_t *code) +{ + if (code->gpr_map) + free(code->gpr_map); + if (code->tram_data_map) + free(code->tram_data_map); + if (code->tram_addr_map) + free(code->tram_addr_map); + if (code->code) + free(code->code); +} + +int alloc_code_struct(emu10k1_fx8010_code_t *code) +{ + /* alloc code structure */ + code->gpr_map = NULL; + code->tram_data_map = NULL; + code->tram_addr_map = NULL; + code->code = NULL; + + code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200); + if (!code->gpr_map) + goto err; + memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200); + + code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100); + if (!code->tram_data_map) + goto err; + memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100); + + code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100); + if (!code->tram_addr_map) + goto err; + memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100); + + code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2); + if (!code->code) + goto err; + memset(code->code, 0, sizeof(uint32_t) * 1024 * 2); + + return 0; +err: + free_code_struct(code); + return -1; +} + +int driver_init_dsp(int audigy) +{ + int i; + emu10k1_fx8010_code_t code; + emu10k1_fx8010_control_gpr_t *ctrl; + emu10k1_ctl_elem_id_t *ids; + emu10k1_fx8010_pcm_t ipcm; + unsigned int *iptr; + + if (alloc_code_struct(&code) < 0) { + error("no mem"); + return 1; + } + + /* get count of controls */ + code.gpr_list_control_count = 0; + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) { + error("unable to peek code"); + free_code_struct(&code); + return 1; + } + + ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total); + if (!ctrl) { + error("no mem"); + free_code_struct(&code); + return 1; + } + + code.gpr_list_control_count = code.gpr_list_control_total; + code.gpr_list_controls = ctrl; + + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = 0x0; + for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++) + code.tram_valid[i] = 0x0; + for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++) + code.code_valid[i] = 0x0;; + + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) { + error("unable to peek code"); + free_code_struct(&code); + free(ctrl); + return 1; + } + + + /* new name */ + strcpy(code.name, DL10K1_SIGNATURE); + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = ~0; + + for (i = 0; i < sizeof(code.gpr_valid) * 8; i++) + code.gpr_map[i] = 0; + + ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total); + if (!ids) { + free_code_struct(&code); + free(ctrl); + error("no mem"); + return 1; + } + + code.gpr_del_control_count = code.gpr_list_control_total; + if (code.gpr_del_control_count) { + for (i = 0; i < code.gpr_del_control_count; i++) { + memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t)); + } + } + + free(ctrl); + + code.gpr_del_controls = ids; + code.gpr_list_control_count = 0; + code.gpr_add_control_count = 0; + code.gpr_list_control_count = 0; + + for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++) + code.tram_valid[i] = ~0; + for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++) + code.code_valid[i] = ~0; + + for (i = 0; i < sizeof(code.tram_valid) * 8; i++) { + code.tram_addr_map[i] = 0; + code.tram_data_map[i] = 0; + } + + for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2) + if (audigy) { + *iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff); + *(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff); + } else { + *iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff); + *(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff); + } + + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) { + error("unable to poke code"); + free_code_struct(&code); + free(ids); + return 1; + } + + free(ids); + + /* delete tram pcm dsp part */ + if (!audigy) { + for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) { + ipcm.substream = i; + ipcm.channels = 0; + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) { + error("unable to poke code"); + free_code_struct(&code); + return 1; + } + } + } + return 0; +} + +int dump_load(int audigy, char *file_name) +{ + struct stat dump_stat; + void *dump_data, *ptr; + FILE *dump_file; + emu10k1_fx8010_control_gpr_t *ctrl = NULL; + ld10k1_ctl_dump_t *fctrl = NULL; + unsigned int *fgpr = NULL; + ld10k1_tram_dump_t *ftram = NULL; + ld10k1_instr_dump_t *finstr = NULL; + int i, j; + unsigned int vaddr, addr; + int op; + + unsigned int *iptr; + + emu10k1_fx8010_code_t code; + + ld10k1_dump_t *header = NULL; + + /* first load patch to mem */ + if (stat(file_name, &dump_stat)) { + error("unable to load patch %s", file_name); + return 1; + } + + /* minimal dump len is size of header */ + if (dump_stat.st_size < sizeof(ld10k1_dump_t)) { + error("unable to load dump %s (wrong file size)", file_name); + return 1; + } + + + dump_data = malloc(dump_stat.st_size); + if (!dump_data) { + error("no mem"); + return 1; + } + + dump_file = fopen(file_name, "r"); + if (!dump_file) { + error("unable to open file %s", file_name); + goto err; + } + + if (fread(dump_data, dump_stat.st_size, 1, dump_file) != 1) { + error("unable to read data from file %s", file_name); + goto err; + } else + fclose(dump_file); + + /* signature check */ + + header = (ld10k1_dump_t *)dump_data; + if (strncmp(header->signature, "LD10K1 DUMP 001", 16) != 0) { + error("wrong dump file %s (wrong signature)", file_name); + goto err; + } + + /*printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t), + header->ctl_count, sizeof(ld10k1_ctl_dump_t), + header->gpr_count, sizeof(unsigned int), + header->tram_count, sizeof(ld10k1_tram_dump_t), + header->instr_count, sizeof(ld10k1_instr_dump_t));*/ + + /*check size */ + if (sizeof(ld10k1_dump_t) + + header->ctl_count * sizeof(ld10k1_ctl_dump_t) + + header->gpr_count * sizeof(unsigned int) + + header->tram_count * sizeof(ld10k1_tram_dump_t) + + header->instr_count * sizeof(ld10k1_instr_dump_t) != dump_stat.st_size) + goto err; + + /* check dump type */ + if (header->dump_type == DUMP_TYPE_LIVE && audigy) { + error("can't load dump from Live to Audigy"); + goto err1; + } else if ((header->dump_type == DUMP_TYPE_AUDIGY_OLD || + header->dump_type == DUMP_TYPE_AUDIGY) && + !audigy) { + error("can't load dump from Audigy to Live"); + goto err1; + } else if (header->dump_type == DUMP_TYPE_AUDIGY_OLD) { + error("can't load dump from Audigy (not patched drivers) to Audigy (current drivers)"); + goto err1; + } + + ptr = dump_data; + ptr += sizeof(ld10k1_dump_t); + + ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count); + if (!ctrl) { + error("no mem"); + goto err1; + } + + if (alloc_code_struct(&code) < 0) { + error("no mem"); + return 1; + } + + + strcpy(code.name, DL10K1_SIGNATURE); + + /* copy ctls */ + fctrl = (ld10k1_ctl_dump_t *)ptr; + memset(ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count); + for (i = 0; i < header->ctl_count; i++) { + strcpy(ctrl[i].id.name, fctrl[i].name); + ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER; + ctrl[i].id.index = fctrl[i].index; + ctrl[i].vcount = fctrl[i].vcount; + ctrl[i].count = fctrl[i].count; + for (j = 0; j < 32; j++) { + ctrl[i].gpr[j] = fctrl[i].gpr_idx[j]; + ctrl[i].value[j] = fctrl[i].value[j]; + } + ctrl[i].min = fctrl[i].min; + ctrl[i].max = fctrl[i].max; + ctrl[i].translation = fctrl[i].translation; + } + code.gpr_add_control_count = header->ctl_count; + code.gpr_add_controls = ctrl; + + code.gpr_del_control_count = 0; + code.gpr_del_controls = NULL; + + code.gpr_list_control_count = 0; + code.gpr_list_controls = NULL; + + /* copy gprs */ + ptr += sizeof(ld10k1_ctl_dump_t) * header->ctl_count; + fgpr = (unsigned int *)ptr; + + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = ~0; + + for (i = 0; i < header->gpr_count; i++) + code.gpr_map[i] = fgpr[i]; + + ptr += sizeof(unsigned int) * header->gpr_count; + ftram = (ld10k1_tram_dump_t *)ptr; + /* tram addr + data */ + for (i = 0; i < header->tram_count; i++) { + addr = ftram[i].addr; + vaddr = addr & 0xFFFFF; + op = ftram[i].type; + + set_bit(i, code.tram_valid); + switch(op) { + case DUMP_TRAM_READ: + if (audigy) + vaddr = vaddr | 0x2 << 20; + else + vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN; + break; + case DUMP_TRAM_WRITE: + if (audigy) + vaddr = vaddr | 0x6 << 20; + else + vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN; + break; + case DUMP_TRAM_NULL: + default: + vaddr = 0; + break; + } + + code.tram_addr_map[i] = vaddr; + code.tram_data_map[i] = ftram[i].data; + } + + ptr += sizeof(ld10k1_tram_dump_t) * header->tram_count; + finstr = (ld10k1_instr_dump_t *)ptr; + for (iptr = code.code, i = 0; i < header->instr_count; i++, iptr += 2) { + set_bit(i, code.code_valid); + if (finstr[i].used) { + if (audigy) { + *iptr = ((finstr[i].arg[2] & 0x7ff) << 12) | (finstr[i].arg[3] & 0x7ff); + *(iptr + 1) = ((finstr[i].op & 0x0f) << 24) | ((finstr[i].arg[0] & 0x7ff) << 12) | (finstr[i].arg[1] & 0x7ff); + } else { + if (i < 0x200) { + *iptr = ((finstr[i].arg[2] & 0x3ff) << 10) | (finstr[i].arg[3] & 0x3ff); + *(iptr + 1) = ((finstr[i].op & 0x0f) << 20) | ((finstr[i].arg[0] & 0x3ff) << 10) | (finstr[i].arg[1] & 0x3ff); + } + } + } else { + if (audigy) { + *iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff); + *(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff); + } else { + if (i < 0x200) { + *iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff); + *(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff); + } + } + } + } + + if (header->dump_type != DUMP_TYPE_AUDIGY_OLD && + driver_set_tram_size(header->tram_size)) + goto err1; + + if (driver_init_dsp(audigy)) + goto err1; + + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) { + error("unable to poke code"); + goto err1; + } + + if (dump_data) + free(dump_data); + + if (ctrl) + free(ctrl); + + return 0; + +err: + error("wrong dump file format %s", file_name); +err1: + free_code_struct(&code); + if (dump_data) + free(dump_data); + if (ctrl) + free(ctrl); + + return 1; +} + +int main(int argc, char *argv[]) +{ + int dev; + int c; + int err; + int audigy; + + int opt_help = 0; + char *opt_dump_file = NULL; + + char card_id[32]; + snd_ctl_t *ctl_handle; + snd_ctl_card_info_t *card_info; + snd_hwdep_info_t *hwdep_info; + + char name[16]; + + snd_ctl_card_info_alloca(&card_info); + snd_hwdep_info_alloca(&hwdep_info); + + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"card", 1, 0, 'c'}, + {"dump", 1, 0, 'd'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + while ((c = getopt_long(argc, argv, "hc:d:", + long_options, &option_index)) != EOF) { + switch (c) { +/* case 0: */ +/* break; */ + case 'h': + opt_help = 1; + break; + case 'd': + opt_dump_file = optarg; + break; + case 'c': + card = snd_card_get_index(optarg); + if (card < 0 || card > 31) { + error("wrong -c argument '%s'\n", optarg); + return 1; + } + break; + default: + return 1; + } + } + + if (opt_help) { + help(argv[0]); + return 0; + } + + if (!opt_dump_file) { + error("dump file not specified"); + return 1; + } + + if (getuid() != 0 ) + { + error("You are not running dl10k1 as root."); + return 1; + } + + /* Get control handle for selected card */ + sprintf(card_id, "hw:%i", card); + if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) { + error("control open (%s): %s", card_id, snd_strerror(err)); + return 1; + } + + /* Read control hardware info from card */ + if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) { + error("control hardware info (%s): %s", card_id, snd_strerror(err)); + exit(1); + } + + if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) { + error("card id (%s): %s", card_id, snd_strerror(err)); + exit(1); + } + + + /* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */ + if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 && + strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 && + strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 && + strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) { + error("not a EMU10K1/EMU10K2 based card"); + exit(1); + } + + if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 || + strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0) + audigy = 1; + else + audigy = 0; + + /* find EMU10k1 hardware dependant device and execute command */ + dev = -1; + err = 1; + while (1) { + if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0) + error("hwdep next device (%s): %s", card_id, snd_strerror(err)); + if (dev < 0) + break; + snd_hwdep_info_set_device(hwdep_info, dev); + if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) { + if (err != -ENOENT) + error("control hwdep info (%s): %s", card_id, snd_strerror(err)); + continue; + } + if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) { + sprintf(name, "hw:%i,%i", card, dev); + + /* open EMU10k1 hwdep device */ + if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) { + error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err)); + exit(1); + } + + err = dump_load(audigy, opt_dump_file); + + snd_hwdep_close(handle); + + break; + } + } + + snd_ctl_close(ctl_handle); + + return 0; +} diff --git a/ld10k1/src/ld10k1.c b/ld10k1/src/ld10k1.c new file mode 100644 index 0000000..7359f13 --- /dev/null +++ b/ld10k1/src/ld10k1.c @@ -0,0 +1,347 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * Hwdep usage based on sb16_csp + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/ld10k1/src/ld10k1.h b/ld10k1/src/ld10k1.h new file mode 100644 index 0000000..aa10304 --- /dev/null +++ b/ld10k1/src/ld10k1.h @@ -0,0 +1,292 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_H +#define __LD10K1_H + +#define MAX_CONST_COUNT 0x220 +#define MAX_GPR_COUNT 0x200 +#define MAX_TRAM_COUNT 0x100 + +/* instructions */ +typedef struct { + unsigned int used: 1, + modified: 1; + unsigned int op_code; + unsigned int arg[4]; +} ld10k1_instr_t; + +/* tram */ +typedef struct { + unsigned int used: 1, + type: 2, + req_pos: 2, + pos: 2; + unsigned int size; + unsigned int offset; + int acc_count; +} ld10k1_tram_grp_t; + +#define TRAM_OP_NULL 0 +#define TRAM_OP_READ 1 +#define TRAM_OP_WRITE 2 + +typedef struct { + unsigned int used: 1, + modified: 1; + unsigned int op; + unsigned int addr_val; + unsigned int data_val; +} ld10k1_tram_hwacc_t; + +typedef struct { + unsigned int used: 1, + type: 2; + unsigned int offset; + unsigned int hwacc; + unsigned int grp; +} ld10k1_tram_acc_t; + +typedef struct { + unsigned int size; + unsigned int max_hwacc; + ld10k1_tram_hwacc_t *hwacc; + unsigned int used_hwacc; +} ld10k1_tram_t; + +#define MAX_CONN_PER_POINT 15 +#define MAX_INSTR_PER_POINT 7 + +#define INSERT_BEFORE_OWNER 0 +#define INSERT_AFTER_OWNER 1 + +typedef struct ld10k1_conn_point_tag +{ + struct ld10k1_conn_point_tag *next; + + int id; + int con_count; /* count of io connected to this point */ + unsigned int con_gpr_idx; + int type[MAX_CONN_PER_POINT]; + struct ld10k1_patch_tag *patch[MAX_CONN_PER_POINT]; + int io[MAX_CONN_PER_POINT]; + unsigned int out_gpr_idx[MAX_CONN_PER_POINT]; + + int simple; + + int reserved_gpr; + int reserved_instr; + + struct ld10k1_patch_tag *owner; + int position; + + unsigned int out_instr_offset; + ld10k1_instr_t out_instr[MAX_INSTR_PER_POINT]; +} ld10k1_conn_point_t; + +typedef struct { + char *name; + ld10k1_conn_point_t *point; +} ld10k1_p_in_out_t; + +typedef struct { + unsigned int gpr_idx; + unsigned int const_val; +} ld10k1_p_const_sta_t; + +typedef struct { + unsigned int gpr_idx; +} ld10k1_p_dyn_t; + +typedef struct { + unsigned int reg_idx; + unsigned int gpr_idx; +} ld10k1_p_hw_t; + +typedef struct { + unsigned int grp_type; + unsigned int grp_size; + unsigned int grp_pos; + unsigned int grp_idx; +} ld10k1_p_tram_grp_t; + +typedef struct { + unsigned int acc_type; + unsigned int acc_offset; + unsigned int acc_idx; + unsigned int grp; +} ld10k1_p_tram_acc_t; + +typedef struct { + char name[44]; + int index; + int want_index; + unsigned int vcount; /* count of GPR (1..32) */ + unsigned int count; /* count of GPR (1..32) */ + unsigned int gpr_idx[32]; /* GPR number(s) */ + unsigned int value[32]; + unsigned int min; /* minimum range */ + unsigned int max; /* maximum range */ + unsigned int translation; /* typ - 0 - bool, num 1 - enum */ +} ld10k1_ctl_t; + +typedef struct ld10k1_ctl_list_item_tag { + struct ld10k1_ctl_list_item_tag *next; + ld10k1_ctl_t ctl; +} ld10k1_ctl_list_item_t; + +typedef struct ld10k1_patch_tag { + char *patch_name; + int order; + int id; + + unsigned int in_count; + ld10k1_p_in_out_t *ins; + + unsigned int out_count; + ld10k1_p_in_out_t *outs; + + unsigned int const_count; + ld10k1_p_const_sta_t *consts; + + unsigned int sta_count; + ld10k1_p_const_sta_t *stas; + + unsigned int dyn_count; + ld10k1_p_dyn_t *dyns; + + unsigned int hw_count; + ld10k1_p_hw_t *hws; + + unsigned int tram_count; + ld10k1_p_tram_grp_t *tram_grp; + + unsigned int tram_acc_count; + ld10k1_p_tram_acc_t *tram_acc; + + unsigned int ctl_count; + ld10k1_ctl_t *ctl; + + unsigned int instr_count; + unsigned int instr_offset; + ld10k1_instr_t *instr; +} ld10k1_patch_t; + +#define EMU10K1_PATCH_MAX 128 + +typedef struct { + unsigned int gpr_idx; + unsigned int const_val; + unsigned int hw; + unsigned int ref; + unsigned int used: 1; +} ld10k1_dsp_const_t; + +#define GPR_USAGE_NONE 0 +#define GPR_USAGE_NORMAL 1 +#define GPR_USAGE_CONST 2 +#define GPR_USAGE_DYNAMIC 3 + +typedef struct { + unsigned int gpr_usage; + unsigned int val; + unsigned int ref; + unsigned int modified: 1, + used: 1; +} ld10k1_dsp_gpr_t; + +/* reserved ctls - for example AC97 */ + +typedef struct { + char name[44]; + unsigned int index; +} ld10k1_reserved_ctl_t; + +typedef struct ld10k1_reserved_ctl_list_item_tag { + struct ld10k1_reserved_ctl_list_item_tag *next; + ld10k1_reserved_ctl_t res_ctl; +} ld10k1_reserved_ctl_list_item_t; + +typedef struct { + int audigy; + const char *card_id; + + /* registers */ + unsigned int fx_count; + ld10k1_p_in_out_t fxs[0x40]; + + unsigned int in_count; + ld10k1_p_in_out_t ins[0x20]; + + unsigned int out_count; + ld10k1_p_in_out_t outs[0x40]; + + unsigned int consts_max_count; + ld10k1_dsp_const_t consts[MAX_CONST_COUNT]; + + unsigned int regs_max_count; + ld10k1_dsp_gpr_t regs[MAX_GPR_COUNT]; + + /* instructions */ + unsigned int instr_count; + ld10k1_instr_t instr[1024]; + + unsigned int instr_free; + + /* internal tram */ + ld10k1_tram_t i_tram; + + /* external tram */ + ld10k1_tram_t e_tram; + + unsigned int max_tram_grp; + ld10k1_tram_grp_t tram_grp[MAX_TRAM_COUNT]; + + unsigned int max_tram_acc; + ld10k1_tram_acc_t tram_acc[MAX_TRAM_COUNT]; + + unsigned int max_itram_hwacc; + ld10k1_tram_hwacc_t itram_hwacc[0xC0]; + unsigned int max_etram_hwacc; + ld10k1_tram_hwacc_t etram_hwacc[0x40]; + + unsigned int patch_count; + ld10k1_patch_t *patch_ptr[EMU10K1_PATCH_MAX]; + unsigned int patch_order[EMU10K1_PATCH_MAX]; + + unsigned short patch_id_gens[EMU10K1_PATCH_MAX]; + + ld10k1_ctl_list_item_t *add_ctl_list; + int add_list_count; + + ld10k1_ctl_list_item_t *del_ctl_list; + int del_list_count; + + ld10k1_ctl_list_item_t *ctl_list; + int ctl_list_count; + + ld10k1_reserved_ctl_list_item_t *reserved_ctl_list; + + ld10k1_conn_point_t *point_list; +} ld10k1_dsp_mgr_t; + +void error(const char *fmt,...); +#endif /* __LD10K1_H */ diff --git a/ld10k1/src/ld10k1_debug.c b/ld10k1/src/ld10k1_debug.c new file mode 100644 index 0000000..6ba0ec6 --- /dev/null +++ b/ld10k1/src/ld10k1_debug.c @@ -0,0 +1,667 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include "ld10k1.h" +#include "ld10k1_fnc.h" +#include "ld10k1_fnc1.h" +#include "ld10k1_debug.h" +#include "ld10k1_error.h" +#include "ld10k1_tram.h" +#include +#include +#include + +static char *usage_str[] = { + "NONE", + "NORMAL", + "CONST", + "DYNAMIC" +}; + +char debug_line[1000]; +int send_debug_line(int data_conn) +{ + return send_response(data_conn, FNC_CONTINUE, 0, debug_line, strlen(debug_line) + 1); +} + +int ld10k1_debug_new_gpr_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx) +{ + int usage; + int value; + int ref_count; + int modified; + + modified = dsp_mgr->regs[idx].modified; + usage = dsp_mgr->regs[idx].gpr_usage; + value = dsp_mgr->regs[idx].val; + ref_count = dsp_mgr->regs[idx].ref; + + sprintf(debug_line, "%c 0x%03x : %-12s 0x%08x %3d\n", + modified ? '*' : ' ', + idx, + usage_str[usage], + value, + ref_count); + return send_debug_line(data_conn); +} + +int ld10k1_debug_new_gpr_read_hdr(int data_conn) +{ + sprintf(debug_line, "M Idx Usage Value Ref\n"); + return send_debug_line(data_conn); +} + +static int ld10k1_debug_new_gpr_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + + sprintf(debug_line, "FX8010 GPR List\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + if ((err = ld10k1_debug_new_gpr_read_hdr(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->regs_max_count; i++) + if (dsp_mgr->regs[i].used) + if ((err = ld10k1_debug_new_gpr_read_one(data_conn, dsp_mgr, i)) < 0) + return err; + return 0; +} + +static int ld10k1_debug_new_fx_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + + sprintf(debug_line, "FX8010 FX List\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->fx_count; i++) { + sprintf(debug_line, "%03x : %-20s\n", + i, + dsp_mgr->fxs[i].name ? dsp_mgr->fxs[i].name : ""); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + return 0; +} + +static int ld10k1_debug_new_in_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + + sprintf(debug_line, "FX8010 IN List\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->in_count; i++) { + sprintf(debug_line, "%03x : %-20s\n", + i, + dsp_mgr->ins[i].name ? dsp_mgr->ins[i].name : ""); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + return 0; +} + +static int ld10k1_debug_new_out_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + + sprintf(debug_line, "FX8010 OUT List\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->out_count; i++) { + sprintf(debug_line, "%03x : %-20s\n", + i, + dsp_mgr->outs[i].name ? dsp_mgr->outs[i].name : ""); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + return 0; +} + +int ld10k1_debug_new_const_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx) +{ + int hw; + int value; + int ref_count; + + hw = dsp_mgr->consts[idx].hw; + value = dsp_mgr->consts[idx].const_val; + ref_count = dsp_mgr->consts[idx].ref; + + sprintf(debug_line, "0x%03x : 0x%08x %c %3d\n", + idx, + value, + hw ? '*' : ' ', + ref_count); + return send_debug_line(data_conn); +} + +int ld10k1_debug_new_const_read_hdr(int data_conn) +{ + sprintf(debug_line, "Idx Value HW Ref\n"); + return send_debug_line(data_conn); +} + +static int ld10k1_debug_new_const_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + + sprintf(debug_line, "CONST List\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + if ((err = ld10k1_debug_new_const_read_hdr(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->consts_max_count; i++) + if (dsp_mgr->consts[i].used) + if ((err = ld10k1_debug_new_const_read_one(data_conn, dsp_mgr, i)) < 0) + return err; + return 0; +} + +char *instr_name[] = { + "MACS", + "MACS1", + "MACW", + "MACW1", + "MACINTS", + "MACINTW", + "ACC3", + "MACMV", + "ANDXOR", + "TSTNEG", + "LIMIT", + "LIMIT1", + "LOG", + "EXP", + "INTERP", + "SKIP", +}; + +static void ld10k1_debug_decode_preg_idx(char *type, unsigned int reg) +{ + switch ((reg & EMU10K1_PREG_TYPE_MASK) >> 28) { + case EMU10K1_PREG_TYPE_IN: + sprintf(type, "IN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_OUT: + sprintf(type, "OUT(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_CONST: + sprintf(type, "CON(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_STA: + sprintf(type, "STA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_DYN: + sprintf(type, "DYN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_HW: + sprintf(type, "HW(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_CTL: + sprintf(type, "CTL(%03d, %03d)", (reg & ~EMU10K1_PREG_TYPE_MASK) >> 8, reg & ~EMU10K1_PREG_TYPE_MASK & 0xFF); + break; + case EMU10K1_PREG_TYPE_TRAM_DATA: + sprintf(type, "TD(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + case EMU10K1_PREG_TYPE_TRAM_ADDR: + sprintf(type, "TA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK); + break; + default: + sprintf(type, "??? 0x%08x", reg); + } +} + +int ld10k1_debug_new_code_read_one(int data_conn, int preg, ld10k1_instr_t *instr, unsigned int idx) +{ + char type1[100]; + char type2[100]; + char type3[100]; + char type4[100]; + + if (instr->used) { + if (preg) { + ld10k1_debug_decode_preg_idx(type1, instr->arg[0]); + ld10k1_debug_decode_preg_idx(type2, instr->arg[1]); + ld10k1_debug_decode_preg_idx(type3, instr->arg[2]); + ld10k1_debug_decode_preg_idx(type4, instr->arg[3]); + + sprintf(debug_line, "%c 0x%03x : %-10s %s, %s, %s, %s\n", + instr->modified ? '*' : ' ', + idx, + instr_name[instr->op_code], + type1, + type2, + type3, + type4); + } else { + sprintf(debug_line, "%c 0x%03x : %-10s 0x%03x, 0x%03x, 0x%03x, 0x%03x\n", + instr->modified ? '*' : ' ', + idx, + instr_name[instr->op_code], + instr->arg[0], + instr->arg[1], + instr->arg[2], + instr->arg[3]); + } + + return send_debug_line(data_conn); + } else { + sprintf(debug_line, "%c 0x%03x : NOT USED\n", + instr->modified ? '*' : ' ', + idx); + return send_debug_line(data_conn); + } +} + +int ld10k1_debug_new_code_read_hdr(int data_conn) +{ + sprintf(debug_line, "M Idx OPCODE\n"); + return send_debug_line(data_conn); +} + +static int ld10k1_debug_new_code_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + int err; + ld10k1_instr_t *instr; + + sprintf(debug_line, "FX8010 Code\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->instr_count; i++) { + instr = &(dsp_mgr->instr[i]); + if (instr->used) + if ((err = ld10k1_debug_new_code_read_one(data_conn, 0, instr, i)) < 0) + return err; + } + return 0; +} + +static int ld10k1_debug_new_tram_info_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i, j; + int err; + + char *req_pos_str; + char *pos_str; + + ld10k1_tram_acc_t *tram_acc; + unsigned int data, addr; + + int ifree = dsp_mgr->i_tram.size; + int efree = dsp_mgr->e_tram.size; + + sprintf(debug_line, "TRAM\n\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + sprintf(debug_line, "Internal tram size: 0x%08x\n", dsp_mgr->i_tram.size); + if ((err = send_debug_line(data_conn)) < 0) + return err; + sprintf(debug_line, "External tram size: 0x%08x\n", dsp_mgr->e_tram.size); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + sprintf(debug_line, "\nTram groups:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + for (i = 0; i < dsp_mgr->max_tram_grp; i++) { + if (dsp_mgr->tram_grp[i].used) { + sprintf(debug_line, "%03d %10s ", i, dsp_mgr->tram_grp[i].type == TRAM_GRP_DELAY ? "DELAY" : "TABLE"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + req_pos_str = "NONE"; + if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_AUTO) + req_pos_str = "AUTO"; + else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_INTERNAL) + req_pos_str = "INTERNAL"; + else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_EXTERNAL) + req_pos_str = "EXTERNAL"; + + pos_str = "NONE"; + if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) { + pos_str = "INTERNAL"; + ifree -= dsp_mgr->tram_grp[i].size; + } else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) { + pos_str = "EXTERNAL"; + efree -= dsp_mgr->tram_grp[i].size; + } + + sprintf(debug_line, "%10s %10s %08x %08x %03d\n", req_pos_str, pos_str, + dsp_mgr->tram_grp[i].size, dsp_mgr->tram_grp[i].offset, dsp_mgr->tram_grp[i].acc_count); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + for (j = 0; j < dsp_mgr->max_tram_acc; j++) { + tram_acc = &(dsp_mgr->tram_acc[j]); + + ld10k1_tram_get_hwacc(dsp_mgr, tram_acc->hwacc, &addr, &data); + if ((tram_acc->used) && (tram_acc->grp == i)) { + sprintf(debug_line, " %c%c%c Off:0x%08x HWacc:%03d ADDR:0x%08x DATA:0x%08x\n", + (tram_acc->type & TRAM_ACC_READ) ? 'R' : '-', + (tram_acc->type & TRAM_ACC_WRITE) ? 'W' : '-', + (tram_acc->type & TRAM_ACC_ZERO) ? 'Z' : '-', + tram_acc->offset, + tram_acc->hwacc, + addr, + data); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + } + } + } + return 0; +} + +int ld10k1_debug_new_patch_read1(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch) +{ + int i, j; + int err; + + ld10k1_conn_point_t *point; + + sprintf(debug_line, "Patch name: %s\n\n", patch->patch_name); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + /* in list */ + sprintf(debug_line, "IN registers:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->in_count; i++) { + sprintf(debug_line, "%03d %s -> 0x%08x\n", i, + patch->ins[i].name ? patch->ins[i].name : "", + patch->ins[i].point ? patch->ins[i].point->con_gpr_idx : 0); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + point = patch->ins[i].point; + if (point != NULL) + for (j = 0; j < MAX_CONN_PER_POINT; j++) { + if (point->out_gpr_idx[j] != 0) { + sprintf(debug_line, " +0x%08x\n", point->out_gpr_idx[j]); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + } + } + + /* out list */ + sprintf(debug_line, "OUT registers:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->out_count; i++) { + sprintf(debug_line, "%03d %s -> 0x%08x\n", i, + patch->outs[i].name ? patch->outs[i].name : "", + patch->outs[i].point ? patch->outs[i].point->con_gpr_idx : 0); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* const list */ + sprintf(debug_line, "CONST registers:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->const_count; i++) { + sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i, + patch->consts[i].const_val, + patch->consts[i].gpr_idx); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* sta list */ + sprintf(debug_line, "STA registers:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->sta_count; i++) { + sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i, + patch->stas[i].const_val, + patch->stas[i].gpr_idx); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* hw list */ + sprintf(debug_line, "HW registers:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->hw_count; i++) { + sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i, + patch->hws[i].reg_idx, + patch->hws[i].gpr_idx); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* tram list */ + sprintf(debug_line, "\nUsed tram groups:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->tram_count; i++) { + sprintf(debug_line, "%03d 0x%01x 0x%08x 0x%01x -> %03d\n", i, + patch->tram_grp[i].grp_type, + patch->tram_grp[i].grp_size, + patch->tram_grp[i].grp_pos, + patch->tram_grp[i].grp_idx); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* tram acc list */ + sprintf(debug_line, "\nUsed tram acc:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->tram_acc_count; i++) { + sprintf(debug_line, "%03d 0x%01x 0x%08x 0x%03x -> 0x%03x\n", i, + patch->tram_acc[i].acc_type, + patch->tram_acc[i].acc_offset, + patch->tram_acc[i].grp, + patch->tram_acc[i].acc_idx); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + + /* cotrol list */ + sprintf(debug_line, "\nUsed controls:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < patch->ctl_count; i++) { + sprintf(debug_line, "%03d\n", i); + if ((err = send_debug_line(data_conn)) < 0) + return err; + sprintf(debug_line, " Name:%s\n", patch->ctl[i].name); + if ((err = send_debug_line(data_conn)) < 0) + return err; + sprintf(debug_line, " Min: 0x%08x\n", patch->ctl[i].min); + if ((err = send_debug_line(data_conn)) < 0) + return err; + sprintf(debug_line, " Max: 0x%08x\n", patch->ctl[i].max); + if ((err = send_debug_line(data_conn)) < 0) + return err; + sprintf(debug_line, " GPRS:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (j = 0; j < patch->ctl[i].count; j++) { + sprintf(debug_line, " %03d 0x%08x -> 0x%08x %c\n", j, + patch->ctl[i].value[j], + patch->ctl[i].gpr_idx[j], + j < patch->ctl[i].vcount ? 'v' : ' '); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + } + + /* instruction list */ + sprintf(debug_line, "\nCode:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + + if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0) + return err; + for (i = 0; i < patch->instr_count; i++) { + ld10k1_instr_t *instr; + + instr = &(patch->instr[i]); + if ((err = ld10k1_debug_new_code_read_one(data_conn, 1, instr, i)) < 0) + return err; + } + return 0; +} + +static int ld10k1_debug_new_patch_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, int idx) +{ + ld10k1_patch_t *patch; + patch = dsp_mgr->patch_ptr[idx]; + if (!patch) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + + return ld10k1_debug_new_patch_read1(data_conn, dsp_mgr, patch); +} + +static int ld10k1_debug_new_patch_list_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + ld10k1_patch_t *patch; + int err; + + sprintf(debug_line, "\nPatch List:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < EMU10K1_PATCH_MAX; i++) { + patch = dsp_mgr->patch_ptr[i]; + if (patch) { + sprintf(debug_line, "%03d %s\n\n", i, patch->patch_name); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + } + return 0; +} + +static int ld10k1_debug_new_patch_order_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i, idx; + ld10k1_patch_t *patch; + int err; + + sprintf(debug_line, "\nPatch order:\n"); + if ((err = send_debug_line(data_conn)) < 0) + return err; + for (i = 0; i < dsp_mgr->patch_count; i++) { + idx = dsp_mgr->patch_order[i]; + patch = dsp_mgr->patch_ptr[idx]; + if (patch) { + sprintf(debug_line, "%03d %03d %s\n\n", i, idx, patch->patch_name); + if ((err = send_debug_line(data_conn)) < 0) + return err; + } + } + + return 0; +} + +int ld10k1_fnc_debug(int data_conn, int op, int size) +{ + ld10k1_fnc_debug_t debug_info; + int err; + + if (size != sizeof(ld10k1_fnc_debug_t)) + return LD10K1_ERR_PROTOCOL; + + if ((err = receive_msg_data(data_conn, &debug_info, sizeof(ld10k1_fnc_debug_t)))) + return err; + + if (debug_info.what >= 100 && debug_info.what <= 100 + EMU10K1_PATCH_MAX) { + if ((err = ld10k1_debug_new_patch_read(data_conn, &dsp_mgr, debug_info.what - 100)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 1) { + /* registers */ + if ((err = ld10k1_debug_new_gpr_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 2) { + /* registers */ + if ((err = ld10k1_debug_new_const_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 3) { + /* instruction */ + if ((err = ld10k1_debug_new_code_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 4) { + /* tram */ + if ((err = ld10k1_debug_new_tram_info_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 5) { + if ((err = ld10k1_debug_new_patch_list_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 6) { + if ((err = ld10k1_debug_new_patch_order_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 7) { + /* fx */ + if ((err = ld10k1_debug_new_fx_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 8) { + /* in */ + if ((err = ld10k1_debug_new_in_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else if (debug_info.what == 9) { + /* out */ + if ((err = ld10k1_debug_new_out_read(data_conn, &dsp_mgr)) < 0) + return err; + if ((err = send_response_ok(data_conn)) < 0) + return err; + } else + if ((err = send_response_ok(data_conn)) < 0) + return err; + + return 0; +} diff --git a/ld10k1/src/ld10k1_debug.h b/ld10k1/src/ld10k1_debug.h new file mode 100644 index 0000000..519eab3 --- /dev/null +++ b/ld10k1/src/ld10k1_debug.h @@ -0,0 +1,30 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_DEBUG_H +#define __LD10K1_DEBUG_H + +typedef struct { + int what; +} ld10k1_fnc_debug_t; + +int ld10k1_fnc_debug(int data_conn, int op, int size); + +#endif /* __LD10K1_DEBUG_H */ diff --git a/ld10k1/src/ld10k1_driver.c b/ld10k1/src/ld10k1_driver.c new file mode 100644 index 0000000..3742773 --- /dev/null +++ b/ld10k1/src/ld10k1_driver.c @@ -0,0 +1,541 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "bitops.h" +#include "ld10k1.h" +#include "ld10k1_driver.h" +#include "ld10k1_error.h" +#include "ld10k1_fnc.h" +#include "ld10k1_fnc_int.h" + +//#define DEBUG_DRIVER 1 + +extern snd_hwdep_t *handle; + +void ld10k1_syntetize_instr(int audigy, int op, int arg1, int arg2, int arg3, int arg4, unsigned int *out) +{ + if (audigy) { + *out = ((arg3 & 0x7ff) << 12) | (arg4 & 0x7ff); + *(out + 1) = ((op & 0x0f) << 24) | ((arg1 & 0x7ff) << 12) | (arg2 & 0x7ff); + } else { + *out = ((arg3 & 0x3ff) << 10) | (arg4 & 0x3ff); + *(out + 1) = ((op & 0x0f) << 20) | ((arg1 & 0x3ff) << 10) | (arg2 & 0x3ff); + } +} + +void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr); +void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg); +void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code); + +/* outputs what must be initialized on audigy */ +static int audigy_must_init_output[] = { + 0x68, 0, + 0x69, 0, + 0x6a, 0, + 0x6b, 0, + 0x6e, 0, + 0x6f, 0, + -1}; + +#define LD10K1_SIGNATURE "LD10K1 ver. " VERSION " managed DSP code" + +void ld10k1_free_code_struct(emu10k1_fx8010_code_t *code) +{ + if (code->gpr_map) + free(code->gpr_map); + if (code->tram_data_map) + free(code->tram_data_map); + if (code->tram_addr_map) + free(code->tram_addr_map); + if (code->code) + free(code->code); +} + +int ld10k1_alloc_code_struct(emu10k1_fx8010_code_t *code) +{ + /* alloc code structure */ + code->gpr_map = NULL; + code->tram_data_map = NULL; + code->tram_addr_map = NULL; + code->code = NULL; + + code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200); + if (!code->gpr_map) + goto err; + memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200); + + code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100); + if (!code->tram_data_map) + goto err; + memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100); + + code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100); + if (!code->tram_addr_map) + goto err; + memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100); + + code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2); + if (!code->code) + goto err; + memset(code->code, 0, sizeof(uint32_t) * 1024 * 2); + + return 0; +err: + ld10k1_free_code_struct(code); + return LD10K1_ERR_NO_MEM; +} + +int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr) +{ + emu10k1_fx8010_code_t code; + emu10k1_fx8010_control_gpr_t *add_ctrl; + emu10k1_ctl_elem_id_t *del_ids; + + ld10k1_ctl_list_item_t *item; + unsigned int i, j; + int max; + int modified; + unsigned int addr; + unsigned int vaddr; + unsigned int op; + unsigned int idx_offset; + unsigned int *iptr; + ld10k1_ctl_t gctl; + + int err; + + if ((err = ld10k1_alloc_code_struct(&code)) < 0) + return err; + + /* new name */ + strcpy(code.name, LD10K1_SIGNATURE); + + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = 0; + for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++) + code.tram_valid[i] = 0; + for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++) + code.code_valid[i] = 0; + + /* registers */ + for (i = 0; i < dsp_mgr->regs_max_count; i++) + if (dsp_mgr->regs[i].modified) { + set_bit(i, code.gpr_valid); + code.gpr_map[i] = dsp_mgr->regs[i].val; + } + + /* tram addr + data */ + for (j = 0; j < 2; j++) { + max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc); + for (i = 0; i < max; i++) { + modified = (j == 0 ? dsp_mgr->itram_hwacc[i].modified : dsp_mgr->etram_hwacc[i].modified); + if (modified) { + addr = (j == 0 ? dsp_mgr->itram_hwacc[i].addr_val : dsp_mgr->etram_hwacc[i].addr_val); + vaddr = addr & 0xFFFFF; + idx_offset = (j == 0 ? 0 : dsp_mgr->max_itram_hwacc); + op = (j == 0 ? dsp_mgr->itram_hwacc[i].op : dsp_mgr->etram_hwacc[i].op); + + set_bit(i + idx_offset, code.tram_valid); + switch(op) { + case TRAM_OP_READ: + if (dsp_mgr->audigy) + vaddr = vaddr | 0x2 << 20; + else + vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN; + break; + case TRAM_OP_WRITE: + if (dsp_mgr->audigy) + vaddr = vaddr | 0x6 << 20; + else + vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN; + break; + case TRAM_OP_NULL: + default: + vaddr = 0; + break; + } + + code.tram_addr_map[i + idx_offset] = vaddr; + code.tram_data_map[i + idx_offset] = (j == 0 ? dsp_mgr->itram_hwacc[i].data_val : dsp_mgr->etram_hwacc[i].data_val); + } + } + } + + /* controls to add */ + if (dsp_mgr->add_list_count > 0) { + add_ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count); + memset(add_ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count); + for (i = 0, item = dsp_mgr->add_ctl_list; item != NULL; item = item->next, i++) { + strcpy(add_ctrl[i].id.name, item->ctl.name); + add_ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER; + add_ctrl[i].id.index = item->ctl.index; + add_ctrl[i].vcount = item->ctl.vcount; + add_ctrl[i].count = item->ctl.count; + for (j = 0; j < 32; j++) { + add_ctrl[i].gpr[j] = item->ctl.gpr_idx[j]; + add_ctrl[i].value[j] = item->ctl.value[j]; + } + add_ctrl[i].min = item->ctl.min; + add_ctrl[i].max = item->ctl.max; + add_ctrl[i].translation = item->ctl.translation; + } + } else + add_ctrl = NULL; + + code.gpr_add_control_count = dsp_mgr->add_list_count; + code.gpr_add_controls = add_ctrl; + + /* controls to del */ + if (dsp_mgr->del_list_count > 0) { + del_ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count); + memset(del_ids, 0, sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count); + for (i = 0, item = dsp_mgr->del_ctl_list; item != NULL; item = item->next, i++) { + strcpy(del_ids[i].name, item->ctl.name); + del_ids[i].iface = EMU10K1_CTL_ELEM_IFACE_MIXER; + del_ids[i].index = item->ctl.index; + } + } else + del_ids = NULL; + + code.gpr_del_control_count = dsp_mgr->del_list_count; + code.gpr_del_controls = del_ids; + + code.gpr_list_control_count = 0; + + for (iptr = code.code, i = 0; i < dsp_mgr->instr_count; i++, iptr += 2) { + if (dsp_mgr->instr[i].modified) { + set_bit(i, code.code_valid); + if (dsp_mgr->instr[i].used) { + if (dsp_mgr->audigy) { + ld10k1_syntetize_instr(dsp_mgr->audigy, + dsp_mgr->instr[i].op_code, + dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr); + } else { + if (i < 0x200) { + ld10k1_syntetize_instr(dsp_mgr->audigy, + dsp_mgr->instr[i].op_code, + dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr); + } + } + } else { + if (dsp_mgr->audigy) { + ld10k1_syntetize_instr(dsp_mgr->audigy, + 0x0f, + 0xc0, 0xc0, 0xcf, 0xc0, iptr); + } else { + if (i < 0x200) { + ld10k1_syntetize_instr(dsp_mgr->audigy, + 0x06, + 0x40, 0x40, 0x40, 0x40, iptr); + } + } + } + } + } + + /* check initialization of i2s outputs on audigy */ + if (dsp_mgr->audigy) + ld10k1_check_must_init_output(dsp_mgr, &code); + + +#ifndef DEBUG_DRIVER + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) { + error("unable to poke code"); + ld10k1_free_code_struct(&code); + if (add_ctrl) + free(add_ctrl); + if (del_ids) + free(del_ids); + return LD10K1_ERR_DRIVER_CODE_POKE; + } +#endif + + /* update state */ + for (item = dsp_mgr->del_ctl_list; item != NULL; item = item->next) { + strcpy(gctl.name, item->ctl.name); + ld10k1_del_control_from_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &gctl); + } + + ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count); + + for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next) + ld10k1_add_control_to_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &(item->ctl)); + + ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count); + + for (i = 0; i < dsp_mgr->regs_max_count; i++) + dsp_mgr->regs[i].modified = 0; + + for (i = 0; i < dsp_mgr->instr_count; i++) + dsp_mgr->instr[i].modified = 0; + + for (j = 0; j < 2; j++) { + max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc); + for (i = 0; i < max; i++) { + if (j == 0) + dsp_mgr->itram_hwacc[i].modified = 0; + else + dsp_mgr->etram_hwacc[i].modified = 0; + } + } + + ld10k1_free_code_struct(&code); + + if (add_ctrl) + free(add_ctrl); + if (del_ids) + free(del_ids); + return 0; +} + + +int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size) +{ + emu10k1_fx8010_info_t info; + int i; + emu10k1_fx8010_code_t code; + emu10k1_fx8010_control_gpr_t *ctrl; + emu10k1_ctl_elem_id_t *ids; + emu10k1_fx8010_pcm_t ipcm; + + unsigned int *iptr; + + int err; + + if ((err = ld10k1_alloc_code_struct(&code)) < 0) + return err; + + /* setup tram size */ + if (tram_size >= 0 && snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) { + error("unable to setup tram"); + if (dsp_mgr->audigy) + error("You are probably user of audigy, audigy 2 and you not aplyed patch to enable tram"); + /* this is not fatal, but do not use tram */ + dsp_mgr->i_tram.size = 0; + dsp_mgr->e_tram.size = 0; + } else { + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_INFO, &info) < 0) { + error("unable to get info "); + ld10k1_free_code_struct(&code); + return LD10K1_ERR_DRIVER_INFO; + } + + dsp_mgr->i_tram.size = info.internal_tram_size; + dsp_mgr->e_tram.size = info.external_tram_size; + } + + /* get count of controls */ + code.gpr_list_control_count = 0; + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) { + error("unable to peek code"); + ld10k1_free_code_struct(&code); + return LD10K1_ERR_DRIVER_CODE_PEEK; + } + + ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total); + if (!ctrl) { + ld10k1_free_code_struct(&code); + return LD10K1_ERR_NO_MEM; + } + + code.gpr_list_control_count = code.gpr_list_control_total; + code.gpr_list_controls = ctrl; + + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = 0x0; + for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++) + code.tram_valid[i] = 0x0; + for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++) + code.code_valid[i] = 0x0;; + + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) { + error("unable to peek code"); + ld10k1_free_code_struct(&code); + free(ctrl); + return LD10K1_ERR_DRIVER_CODE_PEEK; + } + + + + /* new name */ + strcpy(code.name, LD10K1_SIGNATURE); + for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++) + code.gpr_valid[i] = ~0; + + for (i = 0; i < sizeof(code.gpr_valid) * 8; i++) { + code.gpr_map[i] = 0; + } + + ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total); + if (!ids) { + ld10k1_free_code_struct(&code); + free(ctrl); + return LD10K1_ERR_NO_MEM; + } + + code.gpr_del_control_count = code.gpr_list_control_total; + if (code.gpr_del_control_count) { + for (i = 0; i < code.gpr_del_control_count; i++) { + memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t)); + } + } + + free(ctrl); + + code.gpr_del_controls = ids; + code.gpr_list_control_count = 0; + code.gpr_add_control_count = 0; + code.gpr_list_control_count = 0; + + for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++) + code.tram_valid[i] = ~0; + for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++) + code.code_valid[i] = ~0; + + for (i = 0; i < sizeof(code.tram_valid) * 8; i++) { + code.tram_addr_map[i] = 0; + code.tram_data_map[i] = 0; + } + + for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2) + if (dsp_mgr->audigy) { + ld10k1_syntetize_instr(dsp_mgr->audigy, + 0x0f, + 0xc0, 0xc0, 0xcf, 0xc0, iptr); + } else { + ld10k1_syntetize_instr(dsp_mgr->audigy, + 0x06, + 0x40, 0x40, 0x40, 0x40, iptr); + } + + /* initialize i2s outputs on audigy */ + if (dsp_mgr->audigy) { + for (iptr = code.code, i = 0; audigy_must_init_output[i] > 0; i += 2, iptr += 2) + ld10k1_syntetize_instr(dsp_mgr->audigy, 0x00, + audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, iptr); + } + +#ifndef DEBUG_DRIVER + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) { + error("unable to poke code"); + ld10k1_free_code_struct(&code); + free(ids); + return LD10K1_ERR_DRIVER_CODE_POKE; + } +#endif + + free(ids); + + /* delete tram pcm dsp part */ + if (!dsp_mgr->audigy) { + for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) { + ipcm.substream = i; + ipcm.channels = 0; +#ifndef DEBUG_DRIVER + if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) { + error("unable to poke code"); + ld10k1_free_code_struct(&code); + return LD10K1_ERR_DRIVER_PCM_POKE; + } +#endif + } + } + + ld10k1_free_code_struct(&code); + return 0; +} + +void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + if (dsp_mgr->audigy) { + for (i = 0; audigy_must_init_output[i] > 0; i += 2) + audigy_must_init_output[i + 1] = 1; + } +} + +void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg) +{ + int i ; + if (dsp_mgr->audigy) { + for (i = 0; audigy_must_init_output[i] > 0; i += 2) { + if (audigy_must_init_output[i] == reg) { + audigy_must_init_output[i + 1] = 0; + return; + } + } + } +} + +void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code) +{ + int j; + + ld10k1_init_must_init_output(dsp_mgr); + for (j = 0; j < dsp_mgr->instr_count; j++) { + if (dsp_mgr->instr[j].used) + ld10k1_set_must_init_output(dsp_mgr, dsp_mgr->instr[j].arg[0]); + } + + int i; + int l; + int ioffset = dsp_mgr->instr_count - 1; + if (dsp_mgr->audigy) { + for (i = 0; audigy_must_init_output[i] > 0; i += 2) { + if (audigy_must_init_output[i + 1]) { + /* find free instruction slot */ + for (;ioffset >= 0; ioffset--) { + if (!dsp_mgr->instr[ioffset].used) { + ld10k1_instr_t *instr = &(dsp_mgr->instr[ioffset]); + ld10k1_syntetize_instr(dsp_mgr->audigy, + 0x0, + audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, + code->code + ioffset * 2); + instr->op_code = 0; + instr->arg[0] = audigy_must_init_output[i]; + for (l = 1; l < 4; l++) + instr->arg[l] = 0xc0; + set_bit(ioffset, code->code_valid); + dsp_mgr->instr[ioffset].used = 1; + ioffset--; + break; + } + } + + if (ioffset < 0) + return; + } + } + } +} diff --git a/ld10k1/src/ld10k1_driver.h b/ld10k1/src/ld10k1_driver.h new file mode 100644 index 0000000..2a3bc4d --- /dev/null +++ b/ld10k1/src/ld10k1_driver.h @@ -0,0 +1,28 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_DRIVER_H +#define __LD10K1_DRIVER_H + +int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr); +int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size); + +#endif /* __LD10K1_DRIVER_H */ diff --git a/ld10k1/src/ld10k1_dump.c b/ld10k1/src/ld10k1_dump.c new file mode 100644 index 0000000..f2167b0 --- /dev/null +++ b/ld10k1/src/ld10k1_dump.c @@ -0,0 +1,153 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "ld10k1.h" +#include "ld10k1_dump_file.h" +#include "ld10k1_dump.h" +#include "ld10k1_error.h" + +int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size) +{ + int dump_size = 0; + void *dump_file = NULL; + void *ptr = NULL; + ld10k1_dump_t *header = NULL; + ld10k1_ctl_dump_t *ctl = NULL; + int i, j; + ld10k1_ctl_list_item_t *item; + unsigned int *ival = NULL; + ld10k1_tram_dump_t *tram = NULL; + ld10k1_instr_dump_t *instr = NULL; + + dump_size += sizeof(ld10k1_dump_t); + dump_size += sizeof(ld10k1_ctl_dump_t) * dsp_mgr->ctl_list_count; + dump_size += sizeof(unsigned int) * dsp_mgr->regs_max_count; + dump_size += sizeof(ld10k1_tram_dump_t) * (dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc); + dump_size += sizeof(ld10k1_instr_dump_t) * dsp_mgr->instr_count; + + dump_file = malloc(dump_size); + if (!dump_file) + return LD10K1_ERR_NO_MEM; + + ptr = dump_file; + header = (ld10k1_dump_t *)ptr; + strcpy(header->signature, "LD10K1 DUMP 001"); + if (!dsp_mgr->audigy) + header->dump_type = DUMP_TYPE_LIVE; + else + header->dump_type = DUMP_TYPE_AUDIGY; + + header->tram_size = dsp_mgr->e_tram.size; + header->ctl_count = dsp_mgr->ctl_list_count; + header->gpr_count = dsp_mgr->regs_max_count; + header->tram_count = dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc; + header->instr_count = dsp_mgr->instr_count; + + /*printf("Size header%d\n", dump_size); + printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t), + header->ctl_count, sizeof(ld10k1_ctl_dump_t), + header->gpr_count, sizeof(unsigned int), + header->tram_count, sizeof(ld10k1_tram_dump_t), + header->instr_count, sizeof(ld10k1_instr_dump_t));*/ + + ptr += sizeof(ld10k1_dump_t); + /* ctls */ + for (item = dsp_mgr->ctl_list; item != NULL; item = item->next) { + ctl = (ld10k1_ctl_dump_t *)ptr; + strcpy(ctl->name, item->ctl.name); + ctl->index = item->ctl.index; + ctl->vcount = item->ctl.vcount; + ctl->count = item->ctl.count; + for (j = 0; j < 32; j++) { + ctl->gpr_idx[j] = item->ctl.gpr_idx[j]; + ctl->value[j] = item->ctl.value[j]; + } + ctl->min = item->ctl.min; + ctl->max = item->ctl.max; + ctl->translation = item->ctl.translation; + + ptr += sizeof(ld10k1_ctl_dump_t); + } + + /* regs */ + for (i = 0; i < dsp_mgr->regs_max_count; i++) { + ival = (unsigned int *) ptr; + *ival = dsp_mgr->regs[i].val; + ptr += sizeof(unsigned int); + } + + /* tram */ + for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) { + tram = (ld10k1_tram_dump_t *) ptr; + if (dsp_mgr->itram_hwacc[i].used) { + tram->type = dsp_mgr->itram_hwacc[i].op; + tram->addr = dsp_mgr->itram_hwacc[i].addr_val; + tram->data = dsp_mgr->itram_hwacc[i].data_val; + } else { + tram->type = 0; + tram->addr = 0; + tram->data = 0; + } + ptr += sizeof(ld10k1_tram_dump_t); + } + + for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) { + tram = (ld10k1_tram_dump_t *) ptr; + if (dsp_mgr->etram_hwacc[i].used) { + if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_READ) + tram->type = DUMP_TRAM_READ; + else if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_WRITE) + tram->type = DUMP_TRAM_WRITE; + else + tram->type = DUMP_TRAM_NULL; + tram->addr = dsp_mgr->etram_hwacc[i].addr_val; + tram->data = dsp_mgr->etram_hwacc[i].data_val; + } else { + tram->type = 0; + tram->addr = 0; + tram->data = 0; + } + ptr += sizeof(ld10k1_tram_dump_t); + } + + /* instr */ + for (i = 0; i < dsp_mgr->instr_count; i++) { + instr = (ld10k1_instr_dump_t *) ptr; + instr->used = dsp_mgr->instr[i].used; + instr->op = dsp_mgr->instr[i].op_code; + instr->arg[0] = dsp_mgr->instr[i].arg[0]; + instr->arg[1] = dsp_mgr->instr[i].arg[1]; + instr->arg[2] = dsp_mgr->instr[i].arg[2]; + instr->arg[3] = dsp_mgr->instr[i].arg[3]; + ptr += sizeof(ld10k1_instr_dump_t); + } + + *dump = dump_file; + *size = dump_size; + + return 0; +} diff --git a/ld10k1/src/ld10k1_dump.h b/ld10k1/src/ld10k1_dump.h new file mode 100644 index 0000000..f5e50ef --- /dev/null +++ b/ld10k1/src/ld10k1_dump.h @@ -0,0 +1,27 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_DUMP_H +#define __LD10K1_DUMP_H + +int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size); + +#endif /* __LD10K1_DUMP_H */ diff --git a/ld10k1/src/ld10k1_dump_file.h b/ld10k1/src/ld10k1_dump_file.h new file mode 100644 index 0000000..6a2a5fb --- /dev/null +++ b/ld10k1/src/ld10k1_dump_file.h @@ -0,0 +1,67 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_DUMP_FILE_H +#define __LD10K1_DUMP_FILE_H + +#define DUMP_TYPE_LIVE 0 +#define DUMP_TYPE_AUDIGY_OLD 1 +#define DUMP_TYPE_AUDIGY 2 + +typedef struct { + char signature[16]; /* LD10K1 DUMP 001 */ + int dump_type; + int tram_size; + int ctl_count; + int gpr_count; + int tram_count; + int instr_count; +} ld10k1_dump_t; + +#define DUMP_TRAM_NULL 0 +#define DUMP_TRAM_READ 1 +#define DUMP_TRAM_WRITE 2 + +typedef struct { + int type; + unsigned int addr; + unsigned int data; +} ld10k1_tram_dump_t; + +typedef struct { + int used; + unsigned int op; + unsigned int arg[4]; +} ld10k1_instr_dump_t; + +typedef struct { + char name[44]; + int index; + unsigned int vcount; /* count of GPR (1..32) */ + unsigned int count; /* count of GPR (1..32) */ + unsigned int gpr_idx[32]; /* GPR number(s) */ + unsigned int value[32]; + unsigned int min; /* minimum range */ + unsigned int max; /* maximum range */ + unsigned int translation; /* typ - 0 - bool, num 1 - enum */ +} ld10k1_ctl_dump_t; + +#endif /* __LD10K1_DUMP_FILE_H */ diff --git a/ld10k1/src/ld10k1_fnc.c b/ld10k1/src/ld10k1_fnc.c new file mode 100644 index 0000000..4bc1f55 --- /dev/null +++ b/ld10k1/src/ld10k1_fnc.c @@ -0,0 +1,2373 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ld10k1.h" +#include "ld10k1_fnc.h" +#include "ld10k1_fnc_int.h" +#include "ld10k1_driver.h" +#include "ld10k1_tram.h" +#include "ld10k1_error.h" + +char *ld10k1_dsp_mgr_name_new(char **where, const char *from); +int ld10k1_add_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl); +void ld10k1_del_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl); +int ld10k1_dsp_mgr_patch_unload(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int idx); +int ld10k1_get_used_index_for_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl, int **idxs, int *cnt); + +unsigned int ld10k1_resolve_named_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg); +unsigned int ld10k1_gpr_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res, + unsigned int usage, unsigned int val); +unsigned int ld10k1_gpr_dyn_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res); +unsigned int ld10k1_const_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_const_count, int *res_const_count, int *res_const, + int max_res_count, int *res_count, int *res, int const_val); + +void ld10k1_const_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg); +void ld10k1_const_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg); +void ld10k1_gpr_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg); +void ld10k1_gpr_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg); + +ld10k1_conn_point_t *ld10k1_conn_point_alloc(int simple); +void ld10k1_conn_point_free(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point); +int ld10k1_conn_point_set_to(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, int io); +void ld10k1_conn_point_unset(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point); +int ld10k1_conn_point_add(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io); +int ld10k1_conn_point_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io); + +int ld10k1_conn_point_get_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io); + +void ld10k1_conn_point_add_to_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point); +void ld10k1_conn_point_del_from_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point); +int ld10k1_gen_patch_id(ld10k1_dsp_mgr_t *dsp_mgr, int pnum); + +/* + * Tables + */ + +unsigned int hw_const[22 * 2] = +{ + 0x00000000, EMU10K1_REG_HW(0), + 0x00000001, EMU10K1_REG_HW(1), + 0x00000002, EMU10K1_REG_HW(2), + 0x00000003, EMU10K1_REG_HW(3), + 0x00000004, EMU10K1_REG_HW(4), + 0x00000008, EMU10K1_REG_HW(5), + 0x00000010, EMU10K1_REG_HW(6), + 0x00000020, EMU10K1_REG_HW(7), + 0x00000100, EMU10K1_REG_HW(8), + 0x00010000, EMU10K1_REG_HW(9), + 0x10000000, EMU10K1_REG_HW(11), + 0x20000000, EMU10K1_REG_HW(12), + 0x40000000, EMU10K1_REG_HW(13), + 0x80000000, EMU10K1_REG_HW(14), + 0x7fffffff, EMU10K1_REG_HW(15), + 0xffffffff, EMU10K1_REG_HW(16), + 0xfffffffe, EMU10K1_REG_HW(17), + 0xc0000000, EMU10K1_REG_HW(18), + 0x4f1bbcde, EMU10K1_REG_HW(19), + 0x5a7ef9db, EMU10K1_REG_HW(20), + 0x00100000, EMU10K1_REG_HW(21) +}; + +int ld10k1_dsp_mgr_init(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int tmp_gpr_count = 0; + int tmp_a_gpr_count = 0; + int tmp_itram_count = 0; + int tmp_etram_count = 0; + int tmp_op_count = 0; + int i, j; + + dsp_mgr->add_ctl_list = NULL; + dsp_mgr->add_list_count = 0; + + dsp_mgr->del_ctl_list = NULL; + dsp_mgr->del_list_count = 0; + + dsp_mgr->ctl_list = NULL; + dsp_mgr->ctl_list_count = 0; + + dsp_mgr->point_list = 0; + + if (dsp_mgr->audigy) { + tmp_itram_count = 0xC0; + tmp_etram_count = 0x100 - 0xC0; + tmp_op_count = 0x400; + tmp_a_gpr_count = 0x200; + } else { + tmp_itram_count = 0x80; + tmp_etram_count = 0xA0 - 0x80; + tmp_op_count = 0x200; + tmp_gpr_count = 0x100; + } + + dsp_mgr->instr_count = tmp_op_count; + dsp_mgr->instr_free = tmp_op_count; + + for (i = 0; i < tmp_op_count; i++) { + dsp_mgr->instr[i].used = 0; + dsp_mgr->instr[i].modified = 1; + dsp_mgr->instr[i].op_code = 0; + for (j = 0; j < 4; j++) + dsp_mgr->instr[i].arg[j] = 0; + } + + /* fx */ + for (i = 0; i < (dsp_mgr->audigy ? 0x40 : 0x10); i++) { + dsp_mgr->fxs[i].name = NULL; + dsp_mgr->fxs[i].point = NULL; + } + dsp_mgr->fx_count = dsp_mgr->audigy ? 0x40 : 0x10; + + /* input */ + for (i = 0; i < (dsp_mgr->audigy ? 0x20 : 0x10); i++) { + dsp_mgr->ins[i].name = NULL; + dsp_mgr->ins[i].point = NULL; + } + + dsp_mgr->in_count = dsp_mgr->audigy ? 0x20 : 0x10; + + /* output */ + for (i = 0; i < (dsp_mgr->audigy ? 0x40 : 0x20); i++) { + dsp_mgr->outs[i].name = NULL; + dsp_mgr->outs[i].point = NULL; + } + + dsp_mgr->out_count = dsp_mgr->audigy ? 0x40 : 0x20; + + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x00].name), "FX_PCM_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x01].name), "FX_PCM_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x02].name), "FX_PCM_Surr_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x03].name), "FX_PCM_Surr_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x04].name), "FX_MIDI_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x05].name), "FX_MIDI_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x06].name), "FX_Center"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x07].name), "FX_LFE"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x0c].name), "FX_MIDI_Reverb"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x0d].name), "FX_MIDI_Chorus"); + + if (dsp_mgr->audigy) { + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x08].name), "FX_PCM_Front_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x09].name), "FX_PCM_Front_Right"); + + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x14].name), "FX_Passthrough_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->fxs[0x15].name), "FX_Passthrough_Right"); + + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x00].name), "IN_AC97_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x01].name), "IN_AC97_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x02].name), "IN_Audigy_CD_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x03].name), "IN_Audigy_CD_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x04].name), "IN_Opt_IEC958_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x05].name), "IN_Opt_IEC958_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x08].name), "IN_Line_Mic_2_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x09].name), "IN_Line_Mic_2_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0a].name), "IN_ADC_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0b].name), "IN_ADC_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0c].name), "IN_Aux2_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0d].name), "IN_Aux2_Right"); + + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x00].name), "OUT_Dig_Front_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x01].name), "OUT_Dig_Front_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x02].name), "OUT_Dig_Center"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x03].name), "OUT_Dig_LEF"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x04].name), "OUT_Headphone_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x05].name), "OUT_Headphone_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x06].name), "OUT_Dig_Rear_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x07].name), "OUT_Dig_Rear_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x08].name), "OUT_Front_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x09].name), "OUT_Front_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0a].name), "OUT_Center"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0b].name), "OUT_LFE"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0e].name), "OUT_Rear_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0f].name), "OUT_Rear_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x10].name), "OUT_AC97_Front_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x11].name), "OUT_AC97_Front_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x16].name), "OUT_ADC_Caputre_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x17].name), "OUT_ADC_Capture_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x18].name), "OUT_Mic_Capture"); + } else { + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x00].name), "IN_AC97_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x01].name), "IN_AC97_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x02].name), "IN_TTL_IEC958_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x03].name), "IN_TTL_IEC958_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x04].name), "IN_Zoom_Video_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x05].name), "IN_Zoom_Video_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x06].name), "IN_Optical_IEC958_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x07].name), "IN_Optical_IEC958_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x08].name), "IN_Line_Mic_1_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x09].name), "IN_Line_Mic_1_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0a].name), "IN_Coax_IEC958_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0b].name), "IN_Coax_IEC958_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0c].name), "IN_Line_Mic_2_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->ins[0x0d].name), "IN_Line_Mic_2_Right"); + + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x00].name), "OUT_AC97_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x01].name), "OUT_AC97_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x02].name), "OUT_Opt_IEC958_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x03].name), "OUT_Opt_IEC958_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x04].name), "OUT_Center"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x05].name), "OUT_LFE"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x06].name), "OUT_Headphone_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x07].name), "OUT_Headphone_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x08].name), "OUT_Analog_Surr_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x09].name), "OUT_Analog_Surr_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0a].name), "OUT_PCM_Capture_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0b].name), "OUT_PCM_Capture_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0c].name), "OUT_MIC_Capture"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0d].name), "OUT_AC97_Surr_Left"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x0e].name), "OUT_AC97_Surr_Right"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x11].name), "OUT_AC97_Center"); + ld10k1_dsp_mgr_name_new(&(dsp_mgr->outs[0x12].name), "OUT_AC97_LFE"); + } + + dsp_mgr->regs_max_count = dsp_mgr->audigy ? tmp_a_gpr_count : tmp_gpr_count; + + /* constants */ + for (i = 0; i < 21; i++) { + dsp_mgr->consts[i].const_val = hw_const[i * 2]; + dsp_mgr->consts[i].gpr_idx = hw_const[i * 2 + 1]; + dsp_mgr->consts[i].hw = 1; + dsp_mgr->consts[i].ref = 1; + dsp_mgr->consts[i].used = 1; + } + + dsp_mgr->consts[21].const_val = dsp_mgr->audigy ? 0x00000800 : 0x00080000; + dsp_mgr->consts[21].gpr_idx = EMU10K1_REG_HW(10); + dsp_mgr->consts[21].hw = 1; + dsp_mgr->consts[21].used = 1; + dsp_mgr->consts[21].ref = 1; + dsp_mgr->consts_max_count = 22 + dsp_mgr->regs_max_count; + + /* gprs */ + for (i = 0; i < dsp_mgr->regs_max_count; i++) { + dsp_mgr->regs[i].used = 0; + dsp_mgr->regs[i].gpr_usage = GPR_USAGE_NONE; + dsp_mgr->regs[i].val = 0; + dsp_mgr->regs[i].ref = 0; + dsp_mgr->regs[i].modified = 1; + } + + dsp_mgr->patch_count = 0; + + for (i = 0; i < 0x100; i++) { + dsp_mgr->tram_acc[i].used = 0; + dsp_mgr->tram_acc[i].type = 0; + dsp_mgr->tram_acc[i].offset = 0; + dsp_mgr->tram_acc[i].hwacc = 0xFFFFFFFF; + dsp_mgr->tram_acc[i].grp = 0xFFFFFFFF; + + dsp_mgr->tram_grp[i].used = 0; + dsp_mgr->tram_grp[i].type = 0; + dsp_mgr->tram_grp[i].size = 0; + dsp_mgr->tram_grp[i].offset = 0; + dsp_mgr->tram_grp[i].req_pos = TRAM_POS_NONE; + dsp_mgr->tram_grp[i].pos = TRAM_POS_NONE; + } + + for (i = 0; i < 0x40; i++) { + dsp_mgr->etram_hwacc[i].used = 0; + dsp_mgr->etram_hwacc[i].op = 0; + dsp_mgr->etram_hwacc[i].modified = 1; + dsp_mgr->etram_hwacc[i].data_val = 0; + dsp_mgr->etram_hwacc[i].addr_val = 0; + } + + for (i = 0; i < 0xC0; i++) { + dsp_mgr->itram_hwacc[i].used = 0; + dsp_mgr->itram_hwacc[i].modified = 1; + dsp_mgr->itram_hwacc[i].data_val = 0; + dsp_mgr->itram_hwacc[i].addr_val = 0; + } + + dsp_mgr->max_tram_grp = dsp_mgr->max_tram_acc = tmp_itram_count + tmp_etram_count; + dsp_mgr->max_itram_hwacc = tmp_itram_count; + dsp_mgr->max_etram_hwacc = tmp_etram_count; + + dsp_mgr->i_tram.size = 0; + dsp_mgr->i_tram.max_hwacc = tmp_itram_count; + dsp_mgr->i_tram.hwacc = dsp_mgr->itram_hwacc; + dsp_mgr->i_tram.used_hwacc = 0; + + dsp_mgr->e_tram.size = 0; + dsp_mgr->e_tram.max_hwacc = tmp_etram_count; + dsp_mgr->e_tram.hwacc = dsp_mgr->etram_hwacc; + dsp_mgr->e_tram.used_hwacc = 0; + + dsp_mgr->patch_count = 0; + for (i = 0; i < EMU10K1_PATCH_MAX; i++) { + dsp_mgr->patch_ptr[i] = NULL; + dsp_mgr->patch_order[i] = 0xFFFFFFFF; + } + + return 0; +} + +void ld10k1_dsp_mgr_init_id_gen(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + + for (i = 0; i < EMU10K1_PATCH_MAX; i++) + dsp_mgr->patch_id_gens[i] = 0; +} + +void ld10k1_dsp_mgr_free(ld10k1_dsp_mgr_t *dsp_mgr) +{ + unsigned int i; + + for (i = 0; i < EMU10K1_PATCH_MAX; i++) { + if (dsp_mgr->patch_ptr[i]) + ld10k1_dsp_mgr_patch_unload(dsp_mgr, dsp_mgr->patch_ptr[i], i); + } + + ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count); + ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count); + ld10k1_del_all_controls_from_list(&(dsp_mgr->ctl_list), &dsp_mgr->ctl_list_count); + + /* FIXME - uvolnovanie point - asi netreba - su uvolnovane pri patch */ + for (i = 0; i < dsp_mgr->fx_count; i++) + if (dsp_mgr->fxs[i].name) + free(dsp_mgr->fxs[i].name); + + for (i = 0; i < dsp_mgr->in_count; i++) + if (dsp_mgr->ins[i].name) + free(dsp_mgr->ins[i].name); + + for (i = 0; i < dsp_mgr->out_count; i++) + if (dsp_mgr->outs[i].name) + free(dsp_mgr->outs[i].name); +} + +ld10k1_patch_t *ld10k1_dsp_mgr_patch_new(void) +{ + ld10k1_patch_t *np; + + np = (ld10k1_patch_t *)malloc(sizeof(ld10k1_patch_t)); + if (!np) + return NULL; + + np->patch_name = NULL; + np->id = 0; + + np->in_count = 0; + np->ins = NULL; + + np->out_count = 0; + np->outs = NULL; + + np->const_count = 0; + np->consts = NULL; + + np->sta_count = 0; + np->stas = NULL; + + np->dyn_count = 0; + np->dyns = NULL; + + np->hw_count = 0; + np->hws = NULL; + + np->tram_count = 0; + np->tram_grp = NULL; + + np->tram_acc_count = 0; + np->tram_acc = NULL; + + np->ctl_count = 0; + np->ctl = NULL; + + np->instr_count = 0; + np->instr_offset = 0; + np->instr = NULL; + + return np; +} + +void ld10k1_dsp_mgr_patch_free(ld10k1_patch_t *patch) +{ + int i; + + if (patch->patch_name) + free(patch->patch_name); + + for (i = 0; i < patch->in_count; i++) + if (patch->ins[i].name) + free(patch->ins[i].name); + + for (i = 0; i < patch->out_count; i++) + if (patch->outs[i].name) + free(patch->outs[i].name); + + if (patch->ins) + free(patch->ins); + + if (patch->outs) + free(patch->outs); + + if (patch->consts) + free(patch->consts); + + if (patch->stas) + free(patch->stas); + + if (patch->dyns) + free(patch->dyns); + + if (patch->hws) + free(patch->hws); + + if (patch->tram_grp) + free(patch->tram_grp); + + if (patch->tram_acc) + free(patch->tram_acc); + + if (patch->ctl) + free(patch->ctl); + + if (patch->instr) + free(patch->instr); + + free(patch); +} + +ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_in_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_in_out_t *ins; + + ins = (ld10k1_p_in_out_t *)malloc(sizeof(ld10k1_p_in_out_t) * count); + if (!ins) + return NULL; + + if (patch->ins) + free(patch->ins); + + memset(ins, 0, sizeof(ld10k1_p_in_out_t) * count); + + patch->ins = ins; + patch->in_count = count; + return ins; +} + +ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_out_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_in_out_t *outs; + + outs = (ld10k1_p_in_out_t *)malloc(sizeof(ld10k1_p_in_out_t) * count); + if (!outs) + return NULL; + + if (patch->outs) + free(patch->outs); + + memset(outs, 0, sizeof(ld10k1_p_in_out_t) * count); + + patch->outs = outs; + patch->out_count = count; + return outs; +} + +ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_const_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_const_sta_t *consts; + + consts = (ld10k1_p_const_sta_t *)malloc(sizeof(ld10k1_p_const_sta_t) * count); + if (!consts) + return NULL; + + if (patch->consts) + free(patch->consts); + + memset(consts, 0, sizeof(ld10k1_p_const_sta_t) * count); + + patch->consts = consts; + patch->const_count = count; + return consts; +} + +ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_sta_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_const_sta_t *stas; + + stas = (ld10k1_p_const_sta_t *)malloc(sizeof(ld10k1_p_const_sta_t) * count); + if (!stas) + return NULL; + + if (patch->stas) + free(patch->stas); + + memset(stas, 0, sizeof(ld10k1_p_const_sta_t) * count); + + patch->stas = stas; + patch->sta_count = count; + return stas; +} + +ld10k1_p_dyn_t *ld10k1_dsp_mgr_patch_dyn_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_dyn_t *dyns; + + dyns = (ld10k1_p_dyn_t *)malloc(sizeof(ld10k1_p_dyn_t) * count); + if (!dyns) + return NULL; + + if (patch->dyns) + free(patch->dyns); + + memset(dyns, 0, sizeof(ld10k1_p_dyn_t) * count); + + patch->dyns = dyns; + patch->dyn_count = count; + return dyns; +} + +ld10k1_p_hw_t *ld10k1_dsp_mgr_patch_hw_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_hw_t *hws; + + hws = (ld10k1_p_hw_t *)malloc(sizeof(ld10k1_p_hw_t) * count); + if (!hws) + return NULL; + + if (patch->hws) + free(patch->hws); + + memset(hws, 0, sizeof(ld10k1_p_hw_t) * count); + + patch->hws = hws; + patch->hw_count = count; + return hws; +} + +ld10k1_p_tram_grp_t *ld10k1_dsp_mgr_patch_tram_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_tram_grp_t *tram; + + tram = (ld10k1_p_tram_grp_t *)malloc(sizeof(ld10k1_p_tram_grp_t) * count); + if (!tram) + return NULL; + + if (patch->tram_grp) + free(patch->tram_grp); + + memset(tram, 0, sizeof(ld10k1_p_tram_grp_t) * count); + + patch->tram_grp = tram; + patch->tram_count = count; + return tram; +} + +ld10k1_p_tram_acc_t *ld10k1_dsp_mgr_patch_tram_acc_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_p_tram_acc_t *tram_acc; + + tram_acc = (ld10k1_p_tram_acc_t *)malloc(sizeof(ld10k1_p_tram_acc_t) * count); + if (!tram_acc) + return NULL; + + if (patch->tram_acc) + free(patch->tram_acc); + + memset(tram_acc, 0, sizeof(ld10k1_p_tram_acc_t) * count); + + patch->tram_acc = tram_acc; + patch->tram_acc_count = count; + return tram_acc; +} + +ld10k1_instr_t *ld10k1_dsp_mgr_patch_instr_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_instr_t *instr; + + instr = (ld10k1_instr_t *)malloc(sizeof(ld10k1_instr_t) * count); + if (!instr) + return NULL; + + if (patch->instr) + free(patch->instr); + + memset(instr, 0, sizeof(ld10k1_instr_t) * count); + + patch->instr = instr; + patch->instr_count = count; + return instr; +} + +ld10k1_ctl_t *ld10k1_dsp_mgr_patch_ctl_new(ld10k1_patch_t *patch, unsigned int count) +{ + ld10k1_ctl_t *ctl; + + ctl = (ld10k1_ctl_t *)malloc(sizeof(ld10k1_ctl_t) * count); + if (!ctl) + return NULL; + + if (patch->ctl) + free(patch->ctl); + + memset(ctl, 0, sizeof(ld10k1_ctl_t) * count); + + patch->ctl = ctl; + patch->ctl_count = count; + return ctl; +} + +char *ld10k1_dsp_mgr_name_new(char **where, const char *from) +{ + char *ns; + + ns = (char *)malloc(strlen(from) + 1); + if (!ns) + return NULL; + + if (*where) + free(*where); + + *where = ns; + strcpy(ns, from); + return ns; +} + +void ld10k1_dsp_mgr_op(ld10k1_instr_t *instr, unsigned int op, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4) +{ + instr->used = 1; + instr->modified = 1; + instr->op_code = op; + instr->arg[0] = arg1; + instr->arg[1] = arg2; + instr->arg[2] = arg3; + instr->arg[3] = arg4; +} + +int ld10k1_dsp_mgr_get_phys_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg) +{ + int idx = reg & 0xFFFFFFF; + + switch(EMU10K1_REG_TYPE_B(reg)) { + case EMU10K1_REG_TYPE_FX: + if (dsp_mgr->audigy) { + if (idx > 0x3F) + return -1; + else + return idx; + } else { + if (idx > 0x0F) + return -1; + else + return idx; + } + break; + case EMU10K1_REG_TYPE_INPUT: + if (dsp_mgr->audigy) { + if (idx > 0x1F) + return -1; + else + return idx + 0x40; + } else { + if (idx > 0x0F) + return -1; + else + return idx + 0x10; + } + break; + case EMU10K1_REG_TYPE_OUTPUT: + if (dsp_mgr->audigy) { + if (idx > 0x3F) + return -1; + else + return idx + 0x60; + } else { + if (idx > 0x1F) + return -1; + else + return idx + 0x20; + } + case EMU10K1_REG_TYPE_HW: + if (dsp_mgr->audigy) { + if (idx > 0x1F) + return -1; + else + return idx + 0xC0; + } else { + if (idx > 0x1F) + return -1; + else + return idx + 0x40; + } + case EMU10K1_REG_TYPE_TRAM_CTL: + if (dsp_mgr->audigy) { + if (idx > 0xFF) + return -1; + else + return idx + 0x10; + } else { + return -1; + } + case EMU10K1_REG_TYPE_TRAM_DATA: + if (dsp_mgr->audigy) { + if (idx > 0xFF) + return -1; + else + return idx + 0x200; + } else { + if (idx > 0xBF) + return -1; + else + return idx + 0x200; + } + case EMU10K1_REG_TYPE_TRAM_ADDR: + if (dsp_mgr->audigy) { + if (idx > 0xFF) + return -1; + else + return idx + 0x300; + } else { + if (idx > 0xBF) + return -1; + else + return idx + 0x300; + } + case EMU10K1_REG_TYPE_NORMAL: + if (dsp_mgr->audigy) { + if (idx > 0x1FF) + return -1; + else + return idx + 0x400; + } else { + if (idx > 0xFF) + return -1; + else + return idx + 0x100; + } + case EMU10K1_REG_TYPE_CONST: + if (idx > MAX_CONST_COUNT) + return -1; + else + return ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, dsp_mgr->consts[idx].gpr_idx); + default: + return -1; + } +} + +int ld10k1_dsp_mgr_get_phys_reg_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int reg) +{ + unsigned int ind_reg = 0; + unsigned int acc_idx = 0; + + ld10k1_conn_point_t *point; + + switch (EMU10K1_PREG_TYPE_B(reg)) { + case EMU10K1_PREG_TYPE_IN: + /*if (patch->ins[reg & 0xFFFFFFF].point) + ind_reg = patch->ins[reg & 0xFFFFFFF].point->con_gpr_idx; + else + ind_reg = EMU10K1_REG_HW(0); + break;*/ + if (patch->ins[reg & 0xFFFFFFF].point) { + point = patch->ins[reg & 0xFFFFFFF].point; + ind_reg = ld10k1_conn_point_get_reg(dsp_mgr, point, CON_IO_PIN, patch, reg & 0xFFFFFFF); + } else + ind_reg = EMU10K1_REG_HW(0); + break; + case EMU10K1_PREG_TYPE_OUT: + if (patch->outs[reg & 0xFFFFFFF].point) { + point = patch->outs[reg & 0xFFFFFFF].point; + + ind_reg = ld10k1_conn_point_get_reg(dsp_mgr, point, CON_IO_POUT, patch, reg & 0xFFFFFFF); + } else + ind_reg = EMU10K1_REG_HW(0); /* const 0 */ + break; + case EMU10K1_PREG_TYPE_CONST: + ind_reg = patch->consts[reg & 0xFFFFFFF].gpr_idx; + break; + case EMU10K1_PREG_TYPE_STA: + ind_reg = patch->stas[reg & 0xFFFFFFF].gpr_idx; + break; + case EMU10K1_PREG_TYPE_DYN: + ind_reg = patch->dyns[reg & 0xFFFFFFF].gpr_idx; + break; + case EMU10K1_PREG_TYPE_HW: + ind_reg = patch->hws[reg & 0xFFFFFFF].gpr_idx; + break; + case EMU10K1_PREG_TYPE_CTL: + ind_reg = patch->ctl[(reg & 0xFF00) >> 8].gpr_idx[reg & 0xFF]; + break; + case EMU10K1_PREG_TYPE_TRAM_DATA: + acc_idx = patch->tram_acc[reg & 0xFFFFFFF].acc_idx; + ind_reg = EMU10K1_REG_TRAM_DATA(dsp_mgr->tram_acc[acc_idx].hwacc); + break; + case EMU10K1_PREG_TYPE_TRAM_ADDR: + acc_idx = patch->tram_acc[reg & 0xFFFFFFF].acc_idx; + ind_reg = EMU10K1_REG_TRAM_ADDR(dsp_mgr->tram_acc[acc_idx].hwacc); + break; + default: + return -1; + } + + if (ind_reg) + return ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, ind_reg); + return -1; +} + +int ld10k1_dsp_mgr_actualize_instr(ld10k1_dsp_mgr_t *dsp_mgr) +{ + unsigned int i, j, k, l, m, z; + unsigned int instr_offset; + ld10k1_patch_t *tmpp; + ld10k1_instr_t *instr; + ld10k1_conn_point_t *tmp_point; + int allmodified = 0; + int found; + + instr_offset = 0; + + /* intruction actualization */ + for (i = 0; i < dsp_mgr->patch_count; i++) { + tmpp = dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]]; + + + for (m = 0; m < 3; m++) { + if (m == 0 || m == 2) { + /* get all owned points */ + for (j = 0; j < (m == 0 ? tmpp->in_count : tmpp->out_count); j++) { + allmodified = 0; + if (m == 0) + tmp_point = tmpp->ins[j].point; + else + tmp_point = tmpp->outs[j].point; + if (tmp_point && tmp_point->owner == tmpp && + ((m == 0 && tmp_point->position == INSERT_BEFORE_OWNER) || + (m == 2 && tmp_point->position == INSERT_AFTER_OWNER))) + { + /* check if not generated before */ + found = 0; + for (z = 0; z < j; z++) + if ((m == 0 && tmpp->ins[z].point == tmp_point) || + (m == 2 && tmpp->outs[z].point == tmp_point)) { + found = 1; + break; + } + /* if generated - continue */ + if (found) + continue; + + if (tmp_point->reserved_instr > 0 && tmp_point->out_instr_offset != instr_offset) + allmodified = 1; + + tmp_point->out_instr_offset = instr_offset; + /* copy instructions */ + for (k = 0; k < tmp_point->reserved_instr; k++) + if (allmodified || tmp_point->out_instr[k].modified) { + instr = &(dsp_mgr->instr[k + tmp_point->out_instr_offset]); + + instr->used = 1; + instr->modified = 1; + instr->op_code = tmp_point->out_instr[k].op_code; + for (l = 0; l < 4; l++) + instr->arg[l] = ld10k1_dsp_mgr_get_phys_reg(dsp_mgr, tmp_point->out_instr[k].arg[l]); + tmp_point->out_instr[k].modified = 0; + } + instr_offset += tmp_point->reserved_instr; + } + } + } else { + /* patch*/ + allmodified = 0; + if (tmpp->instr_offset != instr_offset) + allmodified = 1; + + tmpp->instr_offset = instr_offset; + + for (j = 0; j < tmpp->instr_count; j++) + if (allmodified || tmpp->instr[j].modified) { + instr = &(dsp_mgr->instr[j + tmpp->instr_offset]); + + instr->used = 1; + instr->modified = 1; + instr->op_code = tmpp->instr[j].op_code; + for (k = 0; k < 4; k++) + instr->arg[k] = ld10k1_dsp_mgr_get_phys_reg_for_patch(dsp_mgr, tmpp, tmpp->instr[j].arg[k]); + tmpp->instr[j].modified = 0; + } + instr_offset += tmpp->instr_count; + } + } + } + + for (j = instr_offset; j < dsp_mgr->instr_count; j++) { + if (dsp_mgr->instr[j].used) { + dsp_mgr->instr[j].modified = 1; + dsp_mgr->instr[j].used = 0; + } + } + return ld10k1_update_driver(dsp_mgr); +} + +int ld10k1_dsp_mgr_actualize_instr_for_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int reg) +{ + int j, k; + + for (j = 0; j < patch->instr_count; j++) + for (k = 0; k < 4; k++) + if (patch->instr[j].arg[k] == reg) { + patch->instr[j].modified = 1; + } + return 0; +} + +void ld10k1_dsp_mgr_actualize_order(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + + for (i = 0; i < dsp_mgr->patch_count; i++) + dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]]->order = i; +} + +int ld10k1_dsp_mgr_patch_load(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, int before, int *loaded) +{ + /* check if i can add patch */ + int pp, i, j; + int err; + + int res[MAX_GPR_COUNT]; + int res_count = 0; + int max_res_count = MAX_GPR_COUNT; + int const_res[MAX_CONST_COUNT]; + int const_res_count = 0; + int max_const_res_count = MAX_CONST_COUNT; + + unsigned int reserved; + + ld10k1_ctl_t tmp_ctl; + + ld10k1_dsp_tram_resolve_t tram_res; + + ld10k1_patch_t *tpatch; + + if (dsp_mgr->patch_count >= EMU10K1_PATCH_MAX) + return LD10K1_ERR_MAX_PATCH_COUNT; + + /* get patch number */ + for (i = 0, pp = -1; i < dsp_mgr->patch_count; i++) + if (dsp_mgr->patch_ptr[i] == NULL) + pp = i; + + if (pp < 0) + pp = dsp_mgr->patch_count; + + if (before > dsp_mgr->patch_count) + before = dsp_mgr->patch_count; + + /* static */ + for (i = 0; i < patch->sta_count; i++) { + reserved = ld10k1_gpr_reserve(dsp_mgr, max_res_count, &res_count, res, GPR_USAGE_NORMAL, patch->stas[i].const_val); + if (!reserved) + return LD10K1_ERR_NOT_FREE_REG; + patch->stas[i].gpr_idx = reserved; + } + + /* constant */ + for (i = 0; i < patch->const_count; i++) { + + /* try allocate */ + reserved = ld10k1_const_reserve(dsp_mgr, max_const_res_count, &const_res_count, const_res, + max_res_count, &res_count, res, patch->consts[i].const_val); + if (reserved == 0) + return LD10K1_ERR_NOT_FREE_REG; + patch->consts[i].gpr_idx = reserved; + } + + /* dynamic */ + for (i = 0; i < patch->dyn_count; i++) { + reserved = ld10k1_gpr_dyn_reserve(dsp_mgr, max_res_count, &res_count, res); + if (!reserved) + return LD10K1_ERR_NOT_FREE_REG; + patch->dyns[i].gpr_idx = reserved; + } + + /* hw */ + for (i = 0; i < patch->hw_count; i++) + patch->hws[i].gpr_idx = ld10k1_resolve_named_reg(dsp_mgr, patch->hws[i].reg_idx); + + /* ctl regs */ + for (i = 0; i < patch->ctl_count; i++) { + for (j = 0; j < patch->ctl[i].count; j++) { + reserved = ld10k1_gpr_reserve(dsp_mgr, max_res_count, &res_count, res, + GPR_USAGE_NORMAL, patch->ctl[i].value[j]); + if (!reserved) + return LD10K1_ERR_NOT_FREE_REG; + patch->ctl[i].gpr_idx[j] = reserved; + } + } + + if (dsp_mgr->instr_free < patch->instr_count) + return LD10K1_ERR_NOT_FREE_INSTR; + + /* tram */ + if (patch->tram_count > 0) + if ((err = ld10k1_tram_reserve_for_patch(dsp_mgr, patch, &tram_res)) < 0) + return err; + + for (i = 0; i < patch->ctl_count; i++) { + memcpy(&tmp_ctl, &(patch->ctl[i]), sizeof(ld10k1_ctl_t)); + /* resolve gpr_idx */ + for (j = 0; j < tmp_ctl.count; j++) + tmp_ctl.gpr_idx[j] = tmp_ctl.gpr_idx[j] & ~EMU10K1_REG_TYPE_MASK; + if ((err = ld10k1_add_control(dsp_mgr, &tmp_ctl)) < 0) { + for (j = 0; j < i - 1; j++) + ld10k1_del_control(dsp_mgr, &(patch->ctl[j])); + return err; + } + + /* copy index back */ + patch->ctl[i].index = tmp_ctl.index; + } + + if (patch->tram_count > 0) + if ((err = ld10k1_tram_alloc_for_patch(dsp_mgr, patch, &tram_res)) < 0) + return err; + + for (i = dsp_mgr->patch_count - 1; i >= before ; i--) + dsp_mgr->patch_order[i + 1] = dsp_mgr->patch_order[i]; + + dsp_mgr->patch_order[before] = pp; + dsp_mgr->patch_count++; + + dsp_mgr->patch_ptr[pp] = patch; + loaded[0] = pp; + + patch->id = ld10k1_gen_patch_id(dsp_mgr, pp); + loaded[1] = patch->id; + + /* allocate registers */ + for (i = 0; i < const_res_count; i++) + ld10k1_const_alloc(dsp_mgr, const_res[i]); + + for (i = 0; i < res_count; i++) + ld10k1_gpr_alloc(dsp_mgr, res[i]); + + /* actualize tram */ + if (patch->tram_count > 0) + for (i = 0; i < dsp_mgr->patch_count; i++) { + tpatch = dsp_mgr->patch_ptr[dsp_mgr->patch_order[i]]; + if (tpatch->tram_count) + ld10k1_tram_actualize_tram_for_patch(dsp_mgr, tpatch); + } + + dsp_mgr->instr_free -= patch->instr_count; + + ld10k1_dsp_mgr_actualize_order(dsp_mgr); + return ld10k1_dsp_mgr_actualize_instr(dsp_mgr); +} + +int ld10k1_dsp_mgr_patch_unload(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, unsigned int idx) +{ + unsigned int i,j ; + + /* free in registers */ + for (i = 0; i < patch->in_count; i++) + if (patch->ins[i].point) + ld10k1_conn_point_del(dsp_mgr, patch->ins[i].point, CON_IO_PIN, patch, i); + + /* free out registers */ + for (i = 0; i < patch->out_count; i++) + if (patch->outs[i].point) + ld10k1_conn_point_del(dsp_mgr, patch->outs[i].point, CON_IO_POUT, patch, i); + + /* free dyn registers */ + for (i = 0; i < patch->dyn_count; i++) + ld10k1_gpr_free(dsp_mgr, patch->dyns[i].gpr_idx); + + /* free sta registers */ + for (i = 0; i < patch->sta_count; i++) + ld10k1_gpr_free(dsp_mgr, patch->stas[i].gpr_idx); + + /* free const registers */ + for (i = 0; i < patch->const_count; i++) + ld10k1_const_free(dsp_mgr, patch->consts[i].gpr_idx); + + /* free ctl regs */ + for (i = 0; i < patch->ctl_count; i++) { + for (j = 0; j < patch->ctl[i].count; j++) { + ld10k1_gpr_free(dsp_mgr, patch->ctl[i].gpr_idx[j]); + } + } + + /* free controls */ + for (i = 0; i < patch->ctl_count; i++) + ld10k1_del_control(dsp_mgr, &(patch->ctl[i])); + + /* free tram */ + if (patch->tram_count > 0) + ld10k1_tram_free_tram_for_patch(dsp_mgr, patch); + + /* free from registers */ + for (i = 0; i < dsp_mgr->patch_count; i++) + if (dsp_mgr->patch_order[i] == idx) + for (;i < dsp_mgr->patch_count; i++) + dsp_mgr->patch_order[i] = dsp_mgr->patch_order[i + 1]; + dsp_mgr->patch_ptr[idx] = NULL; + + /* free from mem */ + ld10k1_dsp_mgr_patch_free(patch); + + /* decrement patch count */ + dsp_mgr->patch_count--; + dsp_mgr->instr_free += patch->instr_count; + + ld10k1_dsp_mgr_actualize_order(dsp_mgr); + /* actualize instructons */ + return ld10k1_dsp_mgr_actualize_instr(dsp_mgr); +} + +int ld10k1_patch_fnc_check_patch(ld10k1_dsp_mgr_t *dsp_mgr, + ld10k1_patch_t *new_patch) +{ + int i, j, k; + + /* check hw registers */ + for (i = 0; i < new_patch->hw_count; i++) { + if (!ld10k1_resolve_named_reg(dsp_mgr, new_patch->hws[i].reg_idx)) + return LD10K1_ERR_WRONG_REG_HW_INDEX; + } + + /* tram check */ + for (i = 0; i < new_patch->tram_count; i++) { + if (new_patch->tram_grp[i].grp_type != TRAM_GRP_DELAY && new_patch->tram_grp[i].grp_type != TRAM_GRP_TABLE) + return LD10K1_ERR_WRONG_TRAM_TYPE; + if (new_patch->tram_grp[i].grp_size < 0) + return LD10K1_ERR_WRONG_TRAM_SIZE; + if (new_patch->tram_grp[i].grp_pos != TRAM_POS_AUTO && + new_patch->tram_grp[i].grp_pos != TRAM_POS_INTERNAL && + new_patch->tram_grp[i].grp_pos != TRAM_POS_EXTERNAL) + return LD10K1_ERR_WRONG_TRAM_POS; + } + + /* tram access check */ + for (i = 0; i < new_patch->tram_acc_count; i++) { + /* type */ + if ((new_patch->tram_acc[i].acc_type & ~(TRAM_ACC_READ | TRAM_ACC_WRITE | TRAM_ACC_ZERO)) != 0) + return LD10K1_ERR_WRONG_TRAM_ACC_TYPE; + + if (((new_patch->tram_acc[i].acc_type & (TRAM_ACC_READ | TRAM_ACC_WRITE)) != TRAM_ACC_READ) && + ((new_patch->tram_acc[i].acc_type & (TRAM_ACC_READ | TRAM_ACC_WRITE)) != TRAM_ACC_WRITE)) + return LD10K1_ERR_WRONG_TRAM_ACC_TYPE; + + if (new_patch->tram_acc[i].grp < 0 && new_patch->tram_acc[i].grp >= new_patch->tram_count) + return LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE; + + if (new_patch->tram_acc[i].acc_offset < 0 || new_patch->tram_acc[i].acc_offset >= new_patch->tram_grp[new_patch->tram_acc[i].grp].grp_size) + return LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE; + } + + /* control check */ + for (i = 0; i < new_patch->ctl_count; i++) { + new_patch->ctl[i].name[43] = '\0'; + + if (new_patch->ctl[i].vcount > new_patch->ctl[i].count) + return LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE; + if (new_patch->ctl[i].count > MAX_CTL_GPR_COUNT) + return LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE; + + if (new_patch->ctl[i].min > new_patch->ctl[i].max) + return LD10K1_ERR_CTL_MIN_MAX_RANGE; + + if (new_patch->ctl[i].translation < 0 || new_patch->ctl[i].translation > EMU10K1_GPR_TRANSLATION_LAST) + return LD10K1_ERR_CTL_TRANLSLATION; + + for(j = 0; j < new_patch->ctl[i].count; j++) { + if (new_patch->ctl[i].value[j] < new_patch->ctl[i].min || new_patch->ctl[i].value[j] > new_patch->ctl[i].max) + return LD10K1_ERR_CTL_REG_VALUE; + } + } + + /* instruction check */ + for (i = 0; i < new_patch->instr_count; i++) { + if (new_patch->instr[i].op_code < 0 || new_patch->instr[i].op_code > iSKIP) + return LD10K1_ERR_INSTR_OPCODE; + + for (k = 0; k < 4; k++) { + int arg = new_patch->instr[i].arg[k]; + switch (EMU10K1_PREG_TYPE_B(arg)) { + case EMU10K1_PREG_TYPE_IN: + if ((arg & 0xFFFFFFF) >= new_patch->in_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_OUT: + if ((arg & 0xFFFFFFF) >= new_patch->out_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_CONST: + if ((arg & 0xFFFFFFF) >= new_patch->const_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_STA: + if ((arg & 0xFFFFFFF) >= new_patch->sta_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_DYN: + if ((arg & 0xFFFFFFF) >= new_patch->dyn_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_HW: + if ((arg & 0xFFFFFFF) >= new_patch->hw_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_CTL: + if ((((arg & 0xFF00) >> 8) >= new_patch->ctl_count) || + ((arg & 0xFF) >= new_patch->ctl[(arg & 0xFF00) >> 8].count)) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + case EMU10K1_PREG_TYPE_TRAM_DATA: + case EMU10K1_PREG_TYPE_TRAM_ADDR: + if ((arg & 0xFFFFFFF) >= new_patch->tram_acc_count) + return LD10K1_ERR_INSTR_ARG_INDEX; + break; + default: + return LD10K1_ERR_INSTR_ARG_INDEX; + } + } + } + + return 0; +} + +int ld10k1_patch_fnc_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_patch_del_t *patch_fnc) +{ + int err; + + if (patch_fnc->where >= 0 && patch_fnc->where < EMU10K1_PATCH_MAX) { + if (dsp_mgr->patch_ptr[patch_fnc->where]) { + if ((err = ld10k1_dsp_mgr_patch_unload(dsp_mgr, + dsp_mgr->patch_ptr[patch_fnc->where], + patch_fnc->where)) < 0) + return err; + else + return 0; + } else + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + } + else + return LD10K1_ERR_UNKNOWN_PATCH_NUM; +} + +int ld10k1_connection_fnc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_connection_t *connection_fnc, int *conn_id) +{ + ld10k1_patch_t *from_patch = NULL; + ld10k1_patch_t *to_patch = NULL; + ld10k1_conn_point_t *from_point = NULL; + ld10k1_conn_point_t *to_point = NULL; + ld10k1_conn_point_t *tmp_point = NULL; + int err; + + if (connection_fnc->what == FNC_CONNECTION_ADD) { + if (connection_fnc->from_type != CON_IO_PIN && + connection_fnc->from_type != CON_IO_POUT && + connection_fnc->from_type != CON_IO_FX && + connection_fnc->from_type != CON_IO_IN && + connection_fnc->from_type != CON_IO_OUT) + return LD10K1_ERR_CONNECTION; + if (connection_fnc->to_type != CON_IO_PIN && + connection_fnc->to_type != CON_IO_POUT && + connection_fnc->to_type != CON_IO_FX && + connection_fnc->to_type != CON_IO_IN && + connection_fnc->to_type != CON_IO_OUT) + return LD10K1_ERR_CONNECTION; + + /* first must be patch */ + if (connection_fnc->from_type != CON_IO_PIN && connection_fnc->from_type != CON_IO_POUT) + return LD10K1_ERR_CONNECTION; + + if (connection_fnc->from_type == CON_IO_PIN && + connection_fnc->to_type == CON_IO_OUT) + return LD10K1_ERR_CONNECTION; + if (connection_fnc->from_type == CON_IO_POUT && + (connection_fnc->to_type == CON_IO_FX || + connection_fnc->to_type == CON_IO_IN)) + return LD10K1_ERR_CONNECTION; + + if (connection_fnc->from_patch < 0 || connection_fnc->from_patch >= EMU10K1_PATCH_MAX) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + from_patch = dsp_mgr->patch_ptr[connection_fnc->from_patch]; + if (!from_patch) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + + if (connection_fnc->to_type == CON_IO_PIN || + connection_fnc->to_type == CON_IO_POUT) { + if (connection_fnc->to_patch < 0 || connection_fnc->to_patch >= EMU10K1_PATCH_MAX) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + to_patch = dsp_mgr->patch_ptr[connection_fnc->to_patch]; + if (!to_patch) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + } + else + to_patch = NULL; + + if (from_patch == to_patch) + return LD10K1_ERR_CONNECTION; + + if (connection_fnc->to_io < 0) + return LD10K1_ERR_CONNECTION; + if (connection_fnc->from_io < 0) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + if (connection_fnc->from_type == CON_IO_PIN) { + if (connection_fnc->from_io >= from_patch->in_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + from_point = from_patch->ins[connection_fnc->from_io].point; + } else { + if (connection_fnc->from_io >= from_patch->out_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + from_point = from_patch->outs[connection_fnc->from_io].point; + } + + switch (connection_fnc->to_type) { + case CON_IO_FX: + if (connection_fnc->to_io >= dsp_mgr->fx_count) + return LD10K1_ERR_CONNECTION; + to_point = dsp_mgr->fxs[connection_fnc->to_io].point; + break; + case CON_IO_IN: + if (connection_fnc->to_io >= dsp_mgr->in_count) + return LD10K1_ERR_CONNECTION; + to_point = dsp_mgr->ins[connection_fnc->to_io].point; + break; + case CON_IO_OUT: + if (connection_fnc->to_io >= dsp_mgr->out_count) + return LD10K1_ERR_CONNECTION; + to_point = dsp_mgr->outs[connection_fnc->to_io].point; + break; + case CON_IO_PIN: + if (connection_fnc->to_io >= to_patch->in_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + to_point = to_patch->ins[connection_fnc->to_io].point; + break; + case CON_IO_POUT: + if (connection_fnc->to_io >= to_patch->out_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + to_point = to_patch->outs[connection_fnc->to_io].point; + break; + } + + if (from_patch && to_patch) { + if (from_point == to_point) + if (from_point) + if (connection_fnc->multi || from_point->con_count == 2) + return 0; + if (!connection_fnc->multi || !to_point) { + if (!(tmp_point = ld10k1_conn_point_alloc(connection_fnc->simple))) + return LD10K1_ERR_NO_MEM; + if ((err = ld10k1_conn_point_set_to(dsp_mgr, tmp_point, 0, -1)) < 0) { + ld10k1_conn_point_free(dsp_mgr, tmp_point); + return err; + } + + /* reconnect to patch */ + if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->to_type, to_patch, connection_fnc->to_io)) < 0) { + ld10k1_conn_point_free(dsp_mgr, tmp_point); + return err; + } + } else + tmp_point = to_point; + + /* reconnect from patch */ + if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->from_type, from_patch, connection_fnc->from_io)) < 0) { + /* if point is allocated now this call can't fail */ + /* ld10k1_conn_point_free(dsp_mgr, tmp_point); */ + return err; + } + } else { + if (from_point == to_point && from_point) + return 0; + if (!to_point) { + if (!(tmp_point = ld10k1_conn_point_alloc(0))) + return LD10K1_ERR_NO_MEM; + if ((err = ld10k1_conn_point_set_to(dsp_mgr, tmp_point, connection_fnc->to_type, connection_fnc->to_io)) < 0) { + ld10k1_conn_point_free(dsp_mgr, tmp_point); + return err; + } + } else + tmp_point = to_point; + + /* reconnect from patch */ + if ((err = ld10k1_conn_point_add(dsp_mgr, tmp_point, connection_fnc->from_type, from_patch, connection_fnc->from_io)) < 0) { + /* if point is allocated now this call can't fail */ + /* ld10k1_conn_point_free(dsp_mgr, tmp_point); */ + return err; + } + } + + if (tmp_point->id <= 0) + tmp_point->id = ld10k1_gen_patch_id(dsp_mgr, connection_fnc->from_patch); + + *conn_id = tmp_point->id; + + ld10k1_dsp_mgr_actualize_instr(dsp_mgr); + return 0; + } if (connection_fnc->what == FNC_CONNECTION_DEL) { + if (connection_fnc->from_type != CON_IO_PIN && + connection_fnc->from_type != CON_IO_POUT) + return LD10K1_ERR_CONNECTION; + + if (connection_fnc->from_patch < 0 || connection_fnc->from_patch >= EMU10K1_PATCH_MAX) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + from_patch = dsp_mgr->patch_ptr[connection_fnc->from_patch]; + if (!from_patch) + return LD10K1_ERR_UNKNOWN_PATCH_NUM; + + if (connection_fnc->from_io < 0) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + + if (connection_fnc->from_type == CON_IO_PIN) { + if (connection_fnc->from_io >= from_patch->in_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + from_point = from_patch->ins[connection_fnc->from_io].point; + } else { + if (connection_fnc->from_io >= from_patch->out_count) + return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM; + from_point = from_patch->outs[connection_fnc->from_io].point; + } + + *conn_id = -1; + + if (!from_point) + return 0; + + if ((EMU10K1_REG_TYPE_B(from_point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL && from_point->con_count > 1) || + from_point->con_count > 0) + *conn_id = from_point->id; + + ld10k1_conn_point_del(dsp_mgr, from_point, connection_fnc->from_type, from_patch, connection_fnc->from_io); + + ld10k1_dsp_mgr_actualize_instr(dsp_mgr); + return 0; + } else + return LD10K1_ERR_CONNECTION_FNC; +} + +ld10k1_ctl_list_item_t *ld10k1_look_control_from_list(ld10k1_ctl_list_item_t *list, ld10k1_ctl_t *gctl) +{ + ld10k1_ctl_list_item_t *item; + + for (item = list; item != NULL; item = item->next) + if (strcmp(item->ctl.name, gctl->name) == 0 && item->ctl.index == gctl->index) + return item; + + return NULL; +} + +int ld10k1_add_control_to_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl) +{ + ld10k1_ctl_list_item_t *item; + + item = ld10k1_look_control_from_list(*list, gctl); + if (!item) { + item = (ld10k1_ctl_list_item_t *)malloc(sizeof(ld10k1_ctl_list_item_t)); + if (!item) + return LD10K1_ERR_NO_MEM; + + item->next = NULL; + + if (!*list) + /* empty */ + *list = item; + else { + /* add to begining */ + item->next = *list; + *list = item; + } + (*count)++; + } + + memcpy(&(item->ctl), gctl, sizeof(*gctl)); + + return 0; +} + +void ld10k1_del_control_from_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl) +{ + ld10k1_ctl_list_item_t *item; + ld10k1_ctl_list_item_t *item1; + + if (!*list) + return; + + item = ld10k1_look_control_from_list(*list, gctl); + if (!item) + return; + + if (*list == item) { + *list = item->next; + } else { + for (item1 = *list; item1->next != NULL; item1 = item1->next) + if (item1->next == item) { + item1->next = item->next; + break; + } + } + + free(item); + (*count)--; +} + +void ld10k1_del_all_controls_from_list(ld10k1_ctl_list_item_t **list, int *count) +{ + ld10k1_ctl_list_item_t *item; + ld10k1_ctl_list_item_t *item1; + + for (item = *list; item != NULL;) { + item1 = item->next; + free(item); + item = item1; + } + + *count = 0; + *list = NULL; +} + +int ld10k1_get_used_index_for_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl, int **idxs, int *cnt) +{ + int i; + ld10k1_ctl_list_item_t *item; + ld10k1_reserved_ctl_list_item_t *itemr; + int count; + int *index_list; + + count = 0; + i = 0; + + /* first get count */ + for (item = dsp_mgr->ctl_list; item != NULL; item = item->next) + if (strcmp(item->ctl.name, gctl->name) == 0) + count++; + + for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next) + if (strcmp(item->ctl.name, gctl->name) == 0) + count++; + + for (itemr = dsp_mgr->reserved_ctl_list; itemr != NULL; itemr = itemr->next) + if (strcmp(itemr->res_ctl.name, gctl->name) == 0) + count++; + + if (!count) { + *idxs = NULL; + *cnt = 0; + return 0; + } + + /* second get array */ + index_list = (int *)malloc(sizeof(int) * count); + if (!index_list) + return LD10K1_ERR_NO_MEM; + + for (item = dsp_mgr->ctl_list; item != NULL; item = item->next) + if (strcmp(item->ctl.name, gctl->name) == 0) + index_list[i++] = item->ctl.index; + + for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next) + if (strcmp(item->ctl.name, gctl->name) == 0) + index_list[i++] = item->ctl.index; + + for (itemr = dsp_mgr->reserved_ctl_list; itemr != NULL; itemr = itemr->next) + if (strcmp(itemr->res_ctl.name, gctl->name) == 0) + index_list[i++] = itemr->res_ctl.index; + + *idxs = index_list; + *cnt = count; + + return 0; +} + + +int ld10k1_add_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl) +{ + int err; + int *idxs; + int cnt; + int new_idx; + int i; + int found; + + new_idx = 0; + + /* check index */ + if (gctl->want_index < 0) { + /* find free index */ + if ((err = ld10k1_get_used_index_for_control(dsp_mgr, gctl, &idxs, &cnt)) < 0) + return err; + + while (new_idx < 1000) { + found = 0; + for (i = 0; i < cnt; i++) { + if (new_idx == idxs[i]) { + new_idx++; + found = 1; + break; + } + } + if (!found) { + gctl->index = new_idx; + break; + } + } + + if (idxs) + free(idxs); + + if (new_idx >= 1000) + return LD10K1_ERR_CTL_EXISTS; + } + else + gctl->index = gctl->want_index; + + /* is there control ??? */ + if (ld10k1_look_control_from_list(dsp_mgr->ctl_list, gctl)) + return LD10K1_ERR_CTL_EXISTS; + /* is for add ??? */ + if (ld10k1_look_control_from_list(dsp_mgr->add_ctl_list, gctl)) + return 0; + + /* add */ + return ld10k1_add_control_to_list(&(dsp_mgr->add_ctl_list), &(dsp_mgr->add_list_count), gctl); +} + +void ld10k1_del_control(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_ctl_t *gctl) +{ + /* is for add ??? */ + if (ld10k1_look_control_from_list(dsp_mgr->add_ctl_list, gctl)) { + ld10k1_del_control_from_list(&(dsp_mgr->add_ctl_list), &(dsp_mgr->add_list_count), gctl); + return; + } + + /* is for del ??? */ + if (ld10k1_look_control_from_list(dsp_mgr->del_ctl_list, gctl)) + return; + + /* delete ??? */ + if (ld10k1_look_control_from_list(dsp_mgr->ctl_list, gctl)) { + ld10k1_add_control_to_list(&(dsp_mgr->del_ctl_list), &(dsp_mgr->del_list_count), gctl); + return; + } + return; +} + +/* this will by usefull with modified as10k1 */ +unsigned int named_to_standard[] = +{ + /* FX buses */ + EMU10K1_NREG_FXBUS_PCM_LEFT, EMU10K1_REG_FX(0x00), EMU10K1_REG_FX(0x00), + EMU10K1_NREG_FXBUS_PCM_RIGHT, EMU10K1_REG_FX(0x01), EMU10K1_REG_FX(0x01), + EMU10K1_NREG_FXBUS_PCM_FRONT_LEFT, EMU10K1_REG_FX(0x08), EMU10K1_REG_FX(0x08), + EMU10K1_NREG_FXBUS_PCM_FRONT_RIGHT, EMU10K1_REG_FX(0x09), EMU10K1_REG_FX(0x09), + EMU10K1_NREG_FXBUS_PCM_REAR_LEFT, EMU10K1_REG_FX(0x02), EMU10K1_REG_FX(0x02), + EMU10K1_NREG_FXBUS_PCM_REAR_RIGHT, EMU10K1_REG_FX(0x03), EMU10K1_REG_FX(0x03), + EMU10K1_NREG_FXBUS_PCM_CENTER, EMU10K1_REG_FX(0x06), EMU10K1_REG_FX(0x06), + EMU10K1_NREG_FXBUS_PCM_LFE, EMU10K1_REG_FX(0x07), EMU10K1_REG_FX(0x07), + EMU10K1_NREG_FXBUS_MIDI_LEFT, EMU10K1_REG_FX(0x04), EMU10K1_REG_FX(0x04), + EMU10K1_NREG_FXBUS_MIDI_RIGHT, EMU10K1_REG_FX(0x05), EMU10K1_REG_FX(0x05), + EMU10K1_NREG_FXBUS_MIDI_REVERB, EMU10K1_REG_FX(0x0C), EMU10K1_REG_FX(0x0C), + EMU10K1_NREG_FXBUS_MIDI_CHORUS, EMU10K1_REG_FX(0x0D), EMU10K1_REG_FX(0x0D), + + EMU10K1_A_NREG_FXBUS_PT_LEFT, 0, EMU10K1_REG_FX(0x14), + EMU10K1_A_NREG_FXBUS_PT_RIGHT, 0, EMU10K1_REG_FX(0x15), + + /* inputs */ + EMU10K1_NREG_IN_AC97_LEFT, EMU10K1_REG_IN(0x00), EMU10K1_REG_IN(0x00), + EMU10K1_NREG_IN_AC97_RIGHT, EMU10K1_REG_IN(0x01), EMU10K1_REG_IN(0x01), + EMU10K1_NREG_IN_SPDIF_CD_LEFT, EMU10K1_REG_IN(0x02), EMU10K1_REG_IN(0x02), + EMU10K1_NREG_IN_SPDIF_CD_RIGHT, EMU10K1_REG_IN(0x03), EMU10K1_REG_IN(0x03), + EMU10K1_NREG_IN_SPDIF_OPT_LEFT, EMU10K1_REG_IN(0x06), EMU10K1_REG_IN(0x04), + EMU10K1_NREG_IN_SPDIF_OPT_RIGHT, EMU10K1_REG_IN(0x07), EMU10K1_REG_IN(0x05), + EMU10K1_NREG_IN_I2S_1_LEFT, EMU10K1_REG_IN(0x08), EMU10K1_REG_IN(0x08), + EMU10K1_NREG_IN_I2S_1_RIGHT, EMU10K1_REG_IN(0x09), EMU10K1_REG_IN(0x09), + EMU10K1_NREG_IN_I2S_2_LEFT, EMU10K1_REG_IN(0x0C), EMU10K1_REG_IN(0x0C), + EMU10K1_NREG_IN_I2S_2_RIGHT, EMU10K1_REG_IN(0x0D), EMU10K1_REG_IN(0x0D), + + EMU10K1_L_NREG_IN_SPDIF_COAX_LEFT, EMU10K1_REG_IN(0x0A), 0, + EMU10K1_L_NREG_IN_SPDIF_COAX_RIGHT, EMU10K1_REG_IN(0x0B), 0, + EMU10K1_L_NREG_IN_ZOOM_LEFT, EMU10K1_REG_IN(0x04), 0, + EMU10K1_L_NREG_IN_ZOOM_RIGHT, EMU10K1_REG_IN(0x05), 0, + EMU10K1_L_NREG_IN_LINE_1_LEFT, EMU10K1_REG_IN(0x08), 0, + EMU10K1_L_NREG_IN_LINE_1_RIGHT, EMU10K1_REG_IN(0x09), 0, + EMU10K1_L_NREG_IN_LINE_2_LEFT, EMU10K1_REG_IN(0x0C), 0, + EMU10K1_L_NREG_IN_LINE_2_RIGHT, EMU10K1_REG_IN(0x0D), 0, + + EMU10K1_A_NREG_IN_LINE_1_LEFT, 0, EMU10K1_REG_IN(0x0A), + EMU10K1_A_NREG_IN_LINE_1_RIGHT, 0, EMU10K1_REG_IN(0x0B), + EMU10K1_A_NREG_IN_LINE_2_LEFT, 0, EMU10K1_REG_IN(0x08), + EMU10K1_A_NREG_IN_LINE_2_RIGHT, 0, EMU10K1_REG_IN(0x09), + EMU10K1_A_NREG_IN_LINE_3_LEFT, 0, EMU10K1_REG_IN(0x0C), + EMU10K1_A_NREG_IN_LINE_3_RIGHT, 0, EMU10K1_REG_IN(0x0D), + + /* outputs */ + EMU10K1_NREG_OUT_FRONT_LEFT, EMU10K1_REG_OUT(0x00), EMU10K1_REG_OUT(0x08), + EMU10K1_NREG_OUT_FRONT_RIGHT, EMU10K1_REG_OUT(0x01), EMU10K1_REG_OUT(0x09), + EMU10K1_NREG_OUT_REAR_LEFT, EMU10K1_REG_OUT(0x08), EMU10K1_REG_OUT(0x0E), + EMU10K1_NREG_OUT_REAR_RIGHT, EMU10K1_REG_OUT(0x09), EMU10K1_REG_OUT(0x0F), + EMU10K1_NREG_OUT_CENTER, EMU10K1_REG_OUT(0x04), EMU10K1_REG_OUT(0x0A), + EMU10K1_NREG_OUT_LFE, EMU10K1_REG_OUT(0x05), EMU10K1_REG_OUT(0x0B), + EMU10K1_NREG_OUT_AC97_LEFT, EMU10K1_REG_OUT(0x00), EMU10K1_REG_OUT(0x10), + EMU10K1_NREG_OUT_AC97_RIGHT, EMU10K1_REG_OUT(0x01), EMU10K1_REG_OUT(0x11), + EMU10K1_NREG_OUT_ADC_LEFT, EMU10K1_REG_OUT(0x0A), EMU10K1_REG_OUT(0x16), + EMU10K1_NREG_OUT_ADC_RIGHT, EMU10K1_REG_OUT(0x0B), EMU10K1_REG_OUT(0x17), + EMU10K1_NREG_OUT_MIC, EMU10K1_REG_OUT(0x0C), EMU10K1_REG_OUT(0x18), + EMU10K1_NREG_OUT_HEADPHONE_LEFT, EMU10K1_REG_OUT(0x06), EMU10K1_REG_OUT(0x04), + EMU10K1_NREG_OUT_HEADPHONE_RIGHT, EMU10K1_REG_OUT(0x07), EMU10K1_REG_OUT(0x05), + + EMU10K1_L_NREG_OUT_OPT_LEFT, EMU10K1_REG_OUT(0x02), 0, + EMU10K1_L_NREG_OUT_OPT_RIGHT, EMU10K1_REG_OUT(0x03), 0, + + EMU10K1_A_NREG_OUT_D_FRONT_LEFT, 0, EMU10K1_REG_OUT(0x00), + EMU10K1_A_NREG_OUT_D_FRONT_RIGHT, 0, EMU10K1_REG_OUT(0x01), + EMU10K1_A_NREG_OUT_D_REAR_LEFT, 0, EMU10K1_REG_OUT(0x06), + EMU10K1_A_NREG_OUT_D_REAR_RIGHT, 0, EMU10K1_REG_OUT(0x07), + EMU10K1_A_NREG_OUT_D_CENTER, 0, EMU10K1_REG_OUT(0x02), + EMU10K1_A_NREG_OUT_D_LFE, 0, EMU10K1_REG_OUT(0x03), + + /* hardware */ + EMU10K1_NREG_CONST_00000000, EMU10K1_REG_HW(0x00), EMU10K1_REG_HW(0x00), + EMU10K1_NREG_CONST_00000001, EMU10K1_REG_HW(0x01), EMU10K1_REG_HW(0x01), + EMU10K1_NREG_CONST_00000002, EMU10K1_REG_HW(0x02), EMU10K1_REG_HW(0x02), + EMU10K1_NREG_CONST_00000003, EMU10K1_REG_HW(0x03), EMU10K1_REG_HW(0x03), + EMU10K1_NREG_CONST_00000004, EMU10K1_REG_HW(0x04), EMU10K1_REG_HW(0x04), + EMU10K1_NREG_CONST_00000008, EMU10K1_REG_HW(0x05), EMU10K1_REG_HW(0x05), + EMU10K1_NREG_CONST_00000010, EMU10K1_REG_HW(0x06), EMU10K1_REG_HW(0x06), + EMU10K1_NREG_CONST_00000020, EMU10K1_REG_HW(0x07), EMU10K1_REG_HW(0x07), + EMU10K1_NREG_CONST_00000100, EMU10K1_REG_HW(0x08), EMU10K1_REG_HW(0x08), + EMU10K1_NREG_CONST_00010000, EMU10K1_REG_HW(0x09), EMU10K1_REG_HW(0x09), + EMU10K1_L_NREG_CONST_00080000, EMU10K1_REG_HW(0x0A), 0, + EMU10K1_A_NREG_CONST_00000800, 0, EMU10K1_REG_HW(0x0A), + EMU10K1_NREG_CONST_10000000, EMU10K1_REG_HW(0x0B), EMU10K1_REG_HW(0x0B), + EMU10K1_NREG_CONST_20000000, EMU10K1_REG_HW(0x0C), EMU10K1_REG_HW(0x0C), + EMU10K1_NREG_CONST_40000000, EMU10K1_REG_HW(0x0D), EMU10K1_REG_HW(0x0D), + EMU10K1_NREG_CONST_80000000, EMU10K1_REG_HW(0x0E), EMU10K1_REG_HW(0x0E), + EMU10K1_NREG_CONST_7FFFFFFF, EMU10K1_REG_HW(0x0F), EMU10K1_REG_HW(0x0F), + EMU10K1_NREG_CONST_FFFFFFFF, EMU10K1_REG_HW(0x10), EMU10K1_REG_HW(0x10), + EMU10K1_NREG_CONST_FFFFFFFE, EMU10K1_REG_HW(0x11), EMU10K1_REG_HW(0x11), + EMU10K1_NREG_CONST_C0000000, EMU10K1_REG_HW(0x12), EMU10K1_REG_HW(0x12), + EMU10K1_NREG_CONST_4F1BBCDC, EMU10K1_REG_HW(0x13), EMU10K1_REG_HW(0x13), + EMU10K1_NREG_CONST_5A7EF9DB, EMU10K1_REG_HW(0x14), EMU10K1_REG_HW(0x14), + EMU10K1_NREG_CONST_00100000, EMU10K1_REG_HW(0x15), EMU10K1_REG_HW(0x15), + + EMU10K1_NREG_HW_ACCUM, EMU10K1_REG_HW(0x16), EMU10K1_REG_HW(0x16), + EMU10K1_NREG_HW_CCR, EMU10K1_REG_HW(0x17), EMU10K1_REG_HW(0x17), + EMU10K1_NREG_HW_NOISE1, EMU10K1_REG_HW(0x18), EMU10K1_REG_HW(0x18), + EMU10K1_NREG_HW_NOISE2, EMU10K1_REG_HW(0x19), EMU10K1_REG_HW(0x19), + EMU10K1_NREG_HW_IRQ, EMU10K1_REG_HW(0x1A), EMU10K1_REG_HW(0x1A), + EMU10K1_NREG_HW_DBAC, EMU10K1_REG_HW(0x1B), EMU10K1_REG_HW(0x1B), + EMU10K1_A_NREG_HW_DBACE, 0, EMU10K1_REG_HW(0x1D), + 0 +}; + +unsigned int ld10k1_resolve_named_reg(ld10k1_dsp_mgr_t *dsp_mgr, unsigned int reg) +{ + /* find named - better will be use of binary search */ + int i; + + i = 0; + while (named_to_standard[i]) { + if (named_to_standard[i] == reg) + return dsp_mgr->audigy ? named_to_standard[i + 2] : named_to_standard[i + 1]; + i += 3; + } + + return 0; +} + +unsigned int ld10k1_gpr_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res, + unsigned int usage, unsigned int val) +{ + int i, j; + if (*res_count >= max_res_count) + return 0; + + for (i = 0; i < dsp_mgr->regs_max_count; i++) { + if (!dsp_mgr->regs[i].used) { + /* check in reserved */ + for (j = 0; j < *res_count; j++) { + if (res[j] == i) + break; + } + + if (j >= *res_count) { + res[*res_count] = i; + (*res_count)++; + dsp_mgr->regs[i].gpr_usage = usage; + dsp_mgr->regs[i].val = val; + return EMU10K1_REG_NORMAL(i); + } + } + } + return 0; +} + +unsigned int ld10k1_gpr_dyn_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_count, int *res_count, int *res) +{ + int i, j; + if (*res_count >= max_res_count) + return 0; + + /* try find other dyn not reserved */ + for (i = 0; i < dsp_mgr->regs_max_count; i++) { + if (dsp_mgr->regs[i].used && dsp_mgr->regs[i].gpr_usage == GPR_USAGE_DYNAMIC) { + /* check in reserved */ + for (j = 0; j < *res_count; j++) { + if (res[j] == i) + break; + } + + if (j >= *res_count) { + res[*res_count] = i; + (*res_count)++; + dsp_mgr->regs[i].gpr_usage = GPR_USAGE_DYNAMIC; + dsp_mgr->regs[i].val = 0; + return EMU10K1_REG_NORMAL(i); + } + } + } + + /* not found - try normal */ + return ld10k1_gpr_reserve(dsp_mgr, max_res_count, res_count, res, GPR_USAGE_DYNAMIC, 0); +} + +void ld10k1_gpr_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg) +{ + int i = reg & 0x0FFFFFFF; + dsp_mgr->regs[i].ref++; + dsp_mgr->regs[i].modified = 1; + dsp_mgr->regs[i].used = 1; +} + +void ld10k1_gpr_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg) +{ + int i = reg & 0x0FFFFFFF; + dsp_mgr->regs[i].gpr_usage = GPR_USAGE_NONE; + dsp_mgr->regs[i].val = 0; + dsp_mgr->regs[i].ref--; + dsp_mgr->regs[i].modified = 1; + dsp_mgr->regs[i].used = 0; +} + +unsigned int ld10k1_const_reserve(ld10k1_dsp_mgr_t *dsp_mgr, int max_res_const_count, int *res_const_count, int *res_const, + int max_res_count, int *res_count, int *res, int const_val) +{ + int i, j; + int free_gpr; + + if (*res_const_count >= max_res_const_count) + return 0; + + /* check in reserved */ + for (i = 0; i < *res_const_count; i++) { + if (dsp_mgr->consts[res_const[i]].const_val == const_val) + return EMU10K1_REG_CONST(res_const[i]); + } + + /* check in all constants */ + for (i = 0; i < dsp_mgr->consts_max_count; i++) + if (dsp_mgr->consts[i].used && dsp_mgr->consts[i].const_val == const_val) { + /* add to reserved */ + res_const[*res_const_count] = i; + (*res_const_count)++; + return EMU10K1_REG_CONST(i); + } + + + /* try find other dyn not reserved */ + for (i = 0; i < dsp_mgr->consts_max_count; i++) { + if (!dsp_mgr->consts[i].used) { + /* there is free room */ + /* if in reserved continue */ + for (j = 0; j < *res_const_count; j++) { + if (res_const[j] == i) + break; + } + if (j < *res_const_count) + continue; + + free_gpr = ld10k1_gpr_reserve(dsp_mgr, max_res_count, res_count, res, GPR_USAGE_CONST, const_val); + if (!free_gpr) + return 0; + res_const[*res_const_count] = i; + (*res_const_count)++; + dsp_mgr->consts[i].gpr_idx = free_gpr; + dsp_mgr->consts[i].const_val = const_val; + dsp_mgr->consts[i].hw = 0; + return EMU10K1_REG_CONST(i); + } + } + + return 0; +} + +void ld10k1_const_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int reg) +{ + int i = reg & 0x0FFFFFFF; + dsp_mgr->consts[i].ref++; + if (!dsp_mgr->consts[i].used) { + /*ld10k1_gpr_free(dsp_mgr, dsp_mgr->consts[i].gpr_idx);*/ + dsp_mgr->consts[i].used = 1; + } +} + +void ld10k1_const_free(ld10k1_dsp_mgr_t *dsp_mgr, int reg) +{ + int i = reg & 0x0FFFFFFF; + dsp_mgr->consts[i].ref--; + if (dsp_mgr->consts[i].ref == 0) { + if (!dsp_mgr->consts[i].hw) + dsp_mgr->consts[i].used = 0; + } +} + +ld10k1_conn_point_t *ld10k1_conn_point_alloc(int simple) +{ + ld10k1_conn_point_t *tmp = (ld10k1_conn_point_t *)malloc(sizeof(ld10k1_conn_point_t)); + int i; + + if (!tmp) + return NULL; + + tmp->simple = simple; + tmp->id = 0; + + tmp->next = NULL; + tmp->con_count = 0; + tmp->con_gpr_idx = 0; + + tmp->reserved_gpr = 0; + tmp->reserved_instr = 0; + + tmp->out_instr_offset = 0; + + for (i = 0; i < MAX_CONN_PER_POINT; i++) { + tmp->type[i] = 0; + tmp->patch[i] = NULL; + tmp->io[i] = -1; + tmp->out_gpr_idx[i] = 0; + } + + tmp->owner = NULL; + tmp->position = INSERT_BEFORE_OWNER; + return tmp; +} + +void ld10k1_conn_point_free(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point) +{ + int i; + + point->owner = NULL; + + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] != 0) { + if (point->out_gpr_idx[i]) { + ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[i]); + point->out_gpr_idx[i] = 0; + } + + if (point->type[i] == CON_IO_PIN) { + point->patch[i]->ins[point->io[i]].point = NULL; + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[i], EMU10K1_PREG_IN(point->io[i])); + } else { + point->patch[i]->outs[point->io[i]].point = NULL; + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[i], EMU10K1_PREG_OUT(point->io[i])); + } + + point->con_count--; + + point->type[i] = 0; + point->patch[i] = NULL; + point->io[i] = -1; + } + + dsp_mgr->instr_free += point->reserved_instr; + point->reserved_instr = 0; + + ld10k1_conn_point_unset(dsp_mgr, point); +} + +void ld10k1_point_actualize_owner(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point) +{ + /* instructions should be alocated */ + int i; + int icount, iarg, iout; + + ld10k1_patch_t *tmp_owner = NULL; + + if (point->simple) + return; + + if (point->reserved_gpr > 0) { + if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL) { + /* patch reg */ + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == CON_IO_PIN) { + if (!tmp_owner) + tmp_owner = point->patch[i]; + else { + if (tmp_owner->order > point->patch[i]->order) + tmp_owner = point->patch[i]; + } + } + point->owner = tmp_owner; + point->position = INSERT_BEFORE_OWNER; + } else { + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == CON_IO_POUT) { + if (!tmp_owner) + tmp_owner = point->patch[i]; + else { + if (tmp_owner->order < point->patch[i]->order) + tmp_owner = point->patch[i]; + } + } + point->owner = tmp_owner; + point->position = INSERT_AFTER_OWNER; + } + + icount = 0; + iarg = 0; + iout = 0; + for (i = 0; i < MAX_CONN_PER_POINT; i++) { + if (point->out_gpr_idx[i] != 0) { + if (iarg == 0) { + point->out_instr[icount].used = 1; + point->out_instr[icount].modified = 1; + point->out_instr[icount].op_code = iACC3; + point->out_instr[icount].arg[0] = point->con_gpr_idx; + iarg++; + if (iout >= 3) { + point->out_instr[icount].arg[1] = point->con_gpr_idx; + iarg++; + } + } + point->out_instr[icount].arg[iarg++] = point->out_gpr_idx[i]; + + iout++; + if (iarg > 3) { + icount++; + iarg = 0; + } + } + } + + if (iarg > 0/* && iarg <= 3*/) + for (i = iarg; i < 4; i++) + point->out_instr[icount].arg[i] = EMU10K1_REG_HW(0); + } else { + point->owner = NULL; + point->position = INSERT_BEFORE_OWNER; + } +} + +int ld10k1_conn_point_set_to(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, int io) +{ + int reserved_tmp; + int reserved_tmp_count = 0; + unsigned int reserved; + + switch (type) { + case CON_IO_FX: + dsp_mgr->fxs[io].point = point; + point->con_gpr_idx = EMU10K1_REG_FX(io); + break; + case CON_IO_IN: + dsp_mgr->ins[io].point = point; + point->con_gpr_idx = EMU10K1_REG_IN(io); + break; + case CON_IO_OUT: + dsp_mgr->outs[io].point = point; + point->con_gpr_idx = EMU10K1_REG_OUT(io); + break; + default: + reserved = ld10k1_gpr_reserve(dsp_mgr, 1, &reserved_tmp_count, &reserved_tmp, GPR_USAGE_NORMAL, 0); + if (!reserved) + return LD10K1_ERR_NOT_FREE_REG; + ld10k1_gpr_alloc(dsp_mgr, reserved); + point->con_gpr_idx = reserved; + } + + /* FIXME - aktualizacia instrukcii */ + + + ld10k1_conn_point_add_to_list(dsp_mgr, point); + + return 0; +} + +void ld10k1_conn_point_unset(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point) +{ + int index = point->con_gpr_idx & ~EMU10K1_REG_TYPE_MASK; + switch (EMU10K1_REG_TYPE_B(point->con_gpr_idx)) { + case EMU10K1_REG_TYPE_FX: + dsp_mgr->fxs[index].point = NULL; + point->con_gpr_idx = 0; + break; + case EMU10K1_REG_TYPE_INPUT: + dsp_mgr->ins[index].point = NULL; + point->con_gpr_idx = 0; + break; + case EMU10K1_REG_TYPE_OUTPUT: + dsp_mgr->outs[index].point = NULL; + point->con_gpr_idx = 0; + break; + default: + ld10k1_gpr_free(dsp_mgr, point->con_gpr_idx); + point->con_gpr_idx = 0; + } + + ld10k1_conn_point_del_from_list(dsp_mgr, point); + + /* FIXME - aktualizacia instrukcii */ +} + +int ld10k1_conn_point_add(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io) +{ + int i, j; + int poutcount; + int allocgprcount = 0; + int allocinstrcount = 0; + unsigned int reserved[2]; + unsigned int res[2]; + int reservedcount = 0; + int usedreserved = 0; + + if (point->con_count >= MAX_CONN_PER_POINT) + return LD10K1_ERR_MAX_CON_PER_POINT; + + /* check pout count */ + if (!point->simple && type == CON_IO_POUT) { + poutcount = 0; + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == CON_IO_POUT) + poutcount++; + + if (poutcount > 0) { + if (poutcount < 2) { + allocgprcount = 2; + allocinstrcount = 1; + } else if (poutcount >= 2) { + allocgprcount = 1; + if ((poutcount - 3) % 2 == 0) { + allocinstrcount = 1; + } + } + + /* allocate instr */ + if (dsp_mgr->instr_free < allocinstrcount) + return LD10K1_ERR_NOT_FREE_INSTR; + + /* allocate gpr */ + for (i = 0; i < allocgprcount; i++) { + reserved[i] = ld10k1_gpr_reserve(dsp_mgr, 2, &reservedcount, res, GPR_USAGE_NORMAL, 0); + if (!reserved[i]) + return LD10K1_ERR_NOT_FREE_REG; + } + + for (i = 0; i < allocgprcount; i++) + ld10k1_gpr_alloc(dsp_mgr, reserved[i]); + } + } + + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == 0) { + point->type[i] = type; + point->patch[i] = patch; + point->io[i] = io; + point->out_gpr_idx[i] = 0; + + if (type == CON_IO_PIN) { + if (patch->ins[io].point) + ld10k1_conn_point_del(dsp_mgr, patch->ins[io].point, CON_IO_PIN, patch, io); + patch->ins[io].point = point; + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_IN(io)); + } else { + if (patch->outs[io].point) + ld10k1_conn_point_del(dsp_mgr, patch->outs[io].point, CON_IO_POUT, patch, io); + patch->outs[io].point = point; + + if (point->simple) + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io)); + else { + /* i is not used anymore */ + /* for all CON_IO_POUT where isn't reg add reserved */ + if (reservedcount > 0) { + for (j = 0; j < MAX_CONN_PER_POINT; j++) { + if (point->type[j] == CON_IO_POUT && point->out_gpr_idx[j] == 0) { + point->out_gpr_idx[j] = reserved[usedreserved++]; + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[j], EMU10K1_PREG_OUT(point->io[j])); + if (usedreserved >= reservedcount) + break; + } + } + } else + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io)); + + dsp_mgr->instr_free -= allocinstrcount; + point->reserved_gpr += reservedcount; + point->reserved_instr += allocinstrcount; + + if (reservedcount > 0) + ld10k1_point_actualize_owner(dsp_mgr, point); + } + } + + point->con_count++; + + return 0; + } + + return LD10K1_ERR_MAX_CON_PER_POINT; +} + +int ld10k1_conn_point_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io) +{ + int i, j; + int poutcount; + int inc, outc; + + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == type && point->patch[i] == patch && point->io[i] == io) { + point->type[i] = 0; + point->patch[i] = NULL; + point->io[i] = -1; + if (type == CON_IO_PIN) { + patch->ins[io].point = NULL; + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_IN(io)); + } else { + patch->outs[io].point = NULL; + if (!point->simple && point->out_gpr_idx[i]) { + ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[i]); + point->reserved_gpr--; + point->out_gpr_idx[i] = 0; + } + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, patch, EMU10K1_PREG_OUT(io)); + + if (!point->simple) { + /* get pout count */ + poutcount = 0; + for (i = 0; i < MAX_CONN_PER_POINT; i++) + if (point->type[i] == CON_IO_POUT) + poutcount++; + + if (poutcount > 0) { + if (poutcount < 2) { + /* free all gpr and instr */ + for (j = 0; j < MAX_CONN_PER_POINT; j++) + if (point->type[j] == CON_IO_POUT && point->out_gpr_idx[j]) { + ld10k1_dsp_mgr_actualize_instr_for_reg(dsp_mgr, point->patch[j], EMU10K1_PREG_OUT(point->io[j])); + ld10k1_gpr_free(dsp_mgr, point->out_gpr_idx[j]); + point->reserved_gpr--; + point->out_gpr_idx[j] = 0; + } + dsp_mgr->instr_free += point->reserved_instr; + point->reserved_instr -= point->reserved_instr; + } else if ((poutcount - 3) % 2 == 0) { + /* free 1 instruction */ + dsp_mgr->instr_free += 1; + point->reserved_instr -= 1; + } + } + ld10k1_point_actualize_owner(dsp_mgr, point); + } + } + point->con_count--; + + /* check in out count */ + outc = 0; + inc = 0; + for (j = 0; j < MAX_CONN_PER_POINT; j++) { + if (point->type[j] == CON_IO_POUT) + outc++; + else if (point->type[j] == CON_IO_PIN) + inc++; + } + + if ((EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL && point->con_count <= 1) || + point->con_count <= 0 || + ((outc <= 0 || inc <= 0) && EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL)) + ld10k1_conn_point_free(dsp_mgr, point); + + return 0; + } + return 0; +} + +int ld10k1_conn_point_get_reg(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point, int type, ld10k1_patch_t *patch, int io) +{ + unsigned int reg = 0; + int i; + + for (i = 0; i < MAX_CONN_PER_POINT; i++) { + if (point->patch[i] == patch && + point->type[i] == type && + point->io[i] == io) { + reg = point->out_gpr_idx[i]; + break; + } + } + if (reg == 0) + reg = point->con_gpr_idx; + return reg; +} + +int ld10k1_gen_patch_id(ld10k1_dsp_mgr_t *dsp_mgr, int pnum) +{ + int nid = 0; + + nid = dsp_mgr->patch_id_gens[pnum]++ | pnum << 16; + return nid; +} + +void ld10k1_conn_point_add_to_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point) +{ + if (dsp_mgr->point_list) + point->next = dsp_mgr->point_list; + else + point->next = NULL; + dsp_mgr->point_list = point; +} + +void ld10k1_conn_point_del_from_list(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_conn_point_t *point) +{ + ld10k1_conn_point_t *tmp = dsp_mgr->point_list; + + if (tmp == point) { + dsp_mgr->point_list = point->next; + point->next = NULL; + return; + } + + while (tmp) { + if (tmp->next == point) { + tmp->next = point->next; + point->next = NULL; + return; + } + tmp = tmp->next; + } +} diff --git a/ld10k1/src/ld10k1_fnc1.c b/ld10k1/src/ld10k1_fnc1.c new file mode 100644 index 0000000..651fcff --- /dev/null +++ b/ld10k1/src/ld10k1_fnc1.c @@ -0,0 +1,1507 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#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)); +} diff --git a/ld10k1/src/ld10k1_fnc1.h b/ld10k1/src/ld10k1_fnc1.h new file mode 100644 index 0000000..696abc8 --- /dev/null +++ b/ld10k1/src/ld10k1_fnc1.h @@ -0,0 +1,35 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_FNC1_H +#define __LD10K1_FNC1_H + +#include "comm.h" + +extern ld10k1_dsp_mgr_t dsp_mgr; + +int main_loop(comm_param *param, int audigy, const char *card_id, int tram_size, snd_ctl_t *ctlp); + +int send_response_ok(int conn_num); +int send_response_err(int conn_num, int err); +int send_response_wd(int conn_num, void *data, int data_size); + +#endif /* __LD10K1_FNC1_H */ diff --git a/ld10k1/src/ld10k1_fnc_int.h b/ld10k1/src/ld10k1_fnc_int.h new file mode 100644 index 0000000..b7e4af7 --- /dev/null +++ b/ld10k1/src/ld10k1_fnc_int.h @@ -0,0 +1,52 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_FNC_INT_H +#define __LD10K1_FNC_INT_H + +int ld10k1_dsp_mgr_init(ld10k1_dsp_mgr_t *dsp_mgr); +void ld10k1_dsp_mgr_init_id_gen(ld10k1_dsp_mgr_t *dsp_mgr); +void ld10k1_dsp_mgr_free(ld10k1_dsp_mgr_t *dsp_mgr); + +ld10k1_patch_t *ld10k1_dsp_mgr_patch_new(void); +void ld10k1_dsp_mgr_patch_free(ld10k1_patch_t *patch); +ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_in_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_out_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_const_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_sta_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_dyn_t *ld10k1_dsp_mgr_patch_dyn_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_hw_t *ld10k1_dsp_mgr_patch_hw_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_tram_grp_t *ld10k1_dsp_mgr_patch_tram_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_p_tram_acc_t *ld10k1_dsp_mgr_patch_tram_acc_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_instr_t *ld10k1_dsp_mgr_patch_instr_new(ld10k1_patch_t *patch, unsigned int count); +ld10k1_ctl_t *ld10k1_dsp_mgr_patch_ctl_new(ld10k1_patch_t *patch, unsigned int count); +char *ld10k1_dsp_mgr_name_new(char **where, const char *from); + +int ld10k1_dsp_mgr_patch_load(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, int before, int *loaded); +int ld10k1_patch_fnc_check_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *new_patch); +int ld10k1_patch_fnc_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_patch_del_t *patch_fnc); +int ld10k1_connection_fnc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_connection_t *connection_fnc, int *conn_id); + +void ld10k1_del_control_from_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl); +void ld10k1_del_all_controls_from_list(ld10k1_ctl_list_item_t **list, int *count); +int ld10k1_add_control_to_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl); + +#endif /* __LD10K1_FNC_INT_H */ diff --git a/ld10k1/src/ld10k1_mixer.c b/ld10k1/src/ld10k1_mixer.c new file mode 100644 index 0000000..772b98c --- /dev/null +++ b/ld10k1/src/ld10k1_mixer.c @@ -0,0 +1,97 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include + +#include "ld10k1.h" +#include "ld10k1_mixer.h" +#include "ld10k1_error.h" + +int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp) +{ + snd_ctl_elem_list_t *clist; + int count; + int i; + const char *ctl_name; + unsigned int ctl_index; + + ld10k1_reserved_ctl_list_item_t *res_ctl; + + dsp_mgr->reserved_ctl_list = NULL; + + snd_ctl_elem_list_alloca(&clist); + + if (snd_ctl_elem_list(ctlp, clist) < 0) + return LD10K1_ERR_NO_MEM; + + if ((count = snd_ctl_elem_list_get_count(clist)) < 0) + return LD10K1_ERR_NO_MEM; + + snd_ctl_elem_list_set_offset(clist, 0); + + if (snd_ctl_elem_list_alloc_space(clist, count) < 0) + return LD10K1_ERR_NO_MEM; + + if (snd_ctl_elem_list(ctlp, clist) < 0) { + snd_ctl_elem_list_free_space(clist); + return LD10K1_ERR_NO_MEM; + } + + for (i = 0; i < count; i++) { + snd_ctl_elem_id_t *id; + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_list_get_id(clist, i, id); + + ctl_name = snd_ctl_elem_id_get_name(id); + ctl_index = snd_ctl_elem_id_get_index(id); + + res_ctl = (ld10k1_reserved_ctl_list_item_t *)malloc(sizeof(ld10k1_reserved_ctl_list_item_t)); + if (!res_ctl) { + snd_ctl_elem_list_free_space(clist); + return LD10K1_ERR_NO_MEM; + } + + res_ctl->next = dsp_mgr->reserved_ctl_list; + dsp_mgr->reserved_ctl_list = res_ctl; + strncpy(res_ctl->res_ctl.name, ctl_name, 43); + res_ctl->res_ctl.name[43] = '\0'; + res_ctl->res_ctl.index = ctl_index; + } + + snd_ctl_elem_list_free_space(clist); + return 0; +} + +int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr) +{ + ld10k1_reserved_ctl_list_item_t *item; + ld10k1_reserved_ctl_list_item_t *item1; + + for (item = dsp_mgr->reserved_ctl_list; item != NULL;) { + item1 = item->next; + free(item); + item = item1; + } + + dsp_mgr->reserved_ctl_list = NULL; + return 0; +} + diff --git a/ld10k1/src/ld10k1_mixer.h b/ld10k1/src/ld10k1_mixer.h new file mode 100644 index 0000000..e1251bc --- /dev/null +++ b/ld10k1/src/ld10k1_mixer.h @@ -0,0 +1,28 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_MIXER_H +#define __LD10K1_MIXER_H + +int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp); +int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr); + +#endif /* __LD10K1_MIXER_H */ diff --git a/ld10k1/src/ld10k1_tram.c b/ld10k1/src/ld10k1_tram.c new file mode 100644 index 0000000..840f552 --- /dev/null +++ b/ld10k1/src/ld10k1_tram.c @@ -0,0 +1,481 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "ld10k1.h" +#include "ld10k1_fnc.h" +#include "ld10k1_tram.h" +#include "ld10k1_error.h" +#include + +int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res); +int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res); + +void ld10k1_tram_init_res(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res) +{ + res->isize = dsp_mgr->i_tram.size; + res->ifree = dsp_mgr->i_tram.size; + res->iacc_count = dsp_mgr->i_tram.max_hwacc; + res->iacc_free_count = dsp_mgr->i_tram.max_hwacc; + + res->esize = dsp_mgr->e_tram.size; + res->efree = dsp_mgr->e_tram.size; + res->eacc_count = dsp_mgr->e_tram.max_hwacc; + res->eacc_free_count = dsp_mgr->e_tram.max_hwacc; + + res->grp_free = res->iacc_free_count + res->eacc_free_count; + + res->item_count = 0; +} + +void ld10k1_tram_init_res_from_dsp_mgr(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res) +{ + /* throught all groups */ + int i; + for (i = 0; i < dsp_mgr->max_tram_grp; i++) { + if (dsp_mgr->tram_grp[i].used) { + /* get position */ + res->grp_free--; + switch (dsp_mgr->tram_grp[i].req_pos) { + case TRAM_POS_NONE: + case TRAM_POS_AUTO: + /* add to res */ + res->items[res->item_count].grp_idx = i; + res->items[res->item_count].grp_size = dsp_mgr->tram_grp[i].size; + res->items[res->item_count].grp_acc_count = dsp_mgr->tram_grp[i].acc_count; + res->items[res->item_count].res_value = 0; + res->items[res->item_count].pos = TRAM_POS_NONE; + res->item_count++; + break; + case TRAM_POS_INTERNAL: + /* decrease resources */ + res->ifree -= dsp_mgr->tram_grp[i].size; + res->iacc_free_count -= dsp_mgr->tram_grp[i].acc_count; + break; + case TRAM_POS_EXTERNAL: + res->efree -= dsp_mgr->tram_grp[i].size; + res->eacc_free_count -= dsp_mgr->tram_grp[i].acc_count; + break; + } + } + } +} + +int ld10k1_tram_acc_count_from_patch(ld10k1_patch_t *patch, int grp) +{ + int i, count; + + for (count = 0, i = 0; i < patch->tram_acc_count; i++) + if (patch->tram_acc[i].grp == grp) + count++; + + return count; +} + +int ld10k1_tram_init_res_from_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch) +{ + int i; + int acc_count; + + /* through all groups */ + for (i = 0; i < patch->tram_count; i++) { + if (res->grp_free <= 0) + return LD10K1_ERR_TRAM_FULL_GRP; + /* get acc count */ + acc_count = ld10k1_tram_acc_count_from_patch(patch, i); + if (acc_count <= 0) + continue; + /* get position */ + switch (patch->tram_grp[i].grp_pos) { + case TRAM_POS_NONE: + case TRAM_POS_AUTO: + /* add to res */ + res->items[res->item_count].grp_idx = -i - 1; + res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size; + res->items[res->item_count].grp_acc_count = acc_count; + res->items[res->item_count].res_value = 0; + res->items[res->item_count].pos = TRAM_POS_NONE; + res->item_count++; + break; + case TRAM_POS_INTERNAL: + /* decrease resources */ + if (res->ifree < patch->tram_grp[i].grp_size) + return LD10K1_ERR_ITRAM_FULL; + if (res->iacc_free_count < acc_count) + return LD10K1_ERR_ITRAM_FULL_ACC; + res->ifree -= patch->tram_grp[i].grp_size; + res->iacc_free_count -= acc_count; + break; + case TRAM_POS_EXTERNAL: + /* decrease resources */ + if (res->efree < patch->tram_grp[i].grp_size) + return LD10K1_ERR_ETRAM_FULL; + if (res->eacc_free_count < acc_count) + return LD10K1_ERR_ETRAM_FULL_ACC; + res->efree -= patch->tram_grp[i].grp_size; + res->eacc_free_count -= acc_count; + break; + } + } + return 0; +} + +int ld10k1_tram_init_res_from_patch_copy(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch) +{ + /* throught all groups */ + int i; + int acc_count; + + for (i = 0; i < patch->tram_count; i++) { + /* get acc count */ + acc_count = ld10k1_tram_acc_count_from_patch(patch, i); + /* get position */ + if (patch->tram_grp[i].grp_pos == TRAM_POS_INTERNAL || + patch->tram_grp[i].grp_pos == TRAM_POS_EXTERNAL) { + + res->items[res->item_count].grp_idx = -i - 1; + res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size; + res->items[res->item_count].grp_acc_count = acc_count; + res->items[res->item_count].pos = patch->tram_grp[i].grp_pos; + res->items[res->item_count].res_value = 0; + res->item_count++; + } + } + return 0; +} + +int ld10k1_tram_calc_res_value(ld10k1_dsp_tram_resolve_t *res) +{ + /* res_value is calculated as grp_size / acc_count */ + int i; + for (i = 0; i < res->item_count; i++) + res->items[i].res_value = res->items[i].grp_size / res->items[i].grp_acc_count; + return 0; +} + +static int ld10k1_tram_sort_res_compare(const void *item1, const void *item2) +{ + ld10k1_dsp_tram_resolve_item_t *i1 = (ld10k1_dsp_tram_resolve_item_t *)item1; + ld10k1_dsp_tram_resolve_item_t *i2 = (ld10k1_dsp_tram_resolve_item_t *)item2; + + if (i1->res_value == i2->res_value) + return 0; + else if (i1->res_value > i2->res_value) + return 1; + else + return -1; +} + +int ld10k1_tram_sort_res(ld10k1_dsp_tram_resolve_t *res) +{ + qsort(res->items, res->item_count, sizeof(ld10k1_dsp_tram_resolve_item_t), ld10k1_tram_sort_res_compare); + return 0; +} + +int ld10k1_tram_resolve_res(ld10k1_dsp_tram_resolve_t *res) +{ + int i; + for (i = 0; i < res->item_count; i++) { + /* first try internal tram then external tram */ + if (res->items[i].grp_size <= res->ifree && + res->items[i].grp_acc_count <= res->iacc_free_count) { + /* put it into itram */ + res->ifree -= res->items[i].grp_size; + res->iacc_free_count -= res->items[i].grp_acc_count; + res->items[i].pos = TRAM_POS_INTERNAL; + } else if (res->items[i].grp_size <= res->efree && + res->items[i].grp_acc_count <= res->eacc_free_count) { + /* put it into etram */ + res->efree -= res->items[i].grp_size; + res->eacc_free_count -= res->items[i].grp_acc_count; + res->items[i].pos = TRAM_POS_EXTERNAL; + } else + return LD10K1_ERR_TRAM_FULL; + } + return 0; +} + +int ld10k1_tram_grp_alloc(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + for (i = 0; i < dsp_mgr->max_tram_grp; i++) { + if (!dsp_mgr->tram_grp[i].used) { + dsp_mgr->tram_grp[i].used = 1; + return i; + } + } + return LD10K1_ERR_TRAM_FULL_GRP; +} + +void ld10k1_tram_grp_free(ld10k1_dsp_mgr_t *dsp_mgr, int grp) +{ + dsp_mgr->tram_grp[grp].used = 0; +} + +int ld10k1_tram_acc_alloc(ld10k1_dsp_mgr_t *dsp_mgr) +{ + int i; + for (i = 0; i < dsp_mgr->max_tram_acc; i++) { + if (!dsp_mgr->tram_acc[i].used) { + dsp_mgr->tram_acc[i].used = 1; + return i; + } + } + return LD10K1_ERR_TRAM_FULL_ACC; +} + +void ld10k1_tram_acc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc) +{ + dsp_mgr->tram_acc[acc].used = 0; +} + +int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res) +{ + int err; + + ld10k1_tram_init_res(dsp_mgr, res); + ld10k1_tram_init_res_from_dsp_mgr(dsp_mgr, res); + + if ((err = ld10k1_tram_init_res_from_patch(dsp_mgr, res, patch)) < 0) + return err; + + ld10k1_tram_calc_res_value(res); + ld10k1_tram_sort_res(res); + + if ((err = ld10k1_tram_resolve_res(res)) < 0) + return err; + + ld10k1_tram_init_res_from_patch_copy(dsp_mgr, res, patch); + + return 0; +} + +int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res) +{ + int i; + int grp; + int acc; + + /* allocate tram grp and acc for patch */ + for (i = 0; i < patch->tram_count; i++) { + grp = ld10k1_tram_grp_alloc(dsp_mgr); + patch->tram_grp[i].grp_idx = grp; + dsp_mgr->tram_grp[grp].type = patch->tram_grp[i].grp_type; + dsp_mgr->tram_grp[grp].size = patch->tram_grp[i].grp_size; + } + + for (i = 0; i < res->item_count; i++) { + if (res->items[i].grp_idx < 0) { + res->items[i].grp_idx = patch->tram_grp[-(res->items[i].grp_idx + 1)].grp_idx; + dsp_mgr->tram_grp[res->items[i].grp_idx].pos = TRAM_POS_NONE; + dsp_mgr->tram_grp[res->items[i].grp_idx].acc_count = res->items[i].grp_acc_count; + } + } + + for (i = 0; i < patch->tram_acc_count; i++) { + acc = ld10k1_tram_acc_alloc(dsp_mgr); + patch->tram_acc[i].acc_idx = acc; + dsp_mgr->tram_acc[acc].type = patch->tram_acc[i].acc_type; + dsp_mgr->tram_acc[acc].offset = patch->tram_acc[i].acc_offset; + dsp_mgr->tram_acc[acc].grp = patch->tram_grp[patch->tram_acc[i].grp].grp_idx; + } + + ld10k1_tram_res_alloc_hwacc(dsp_mgr, res); + ld10k1_tram_realloc_space(dsp_mgr, res); + return 0; +} + +int ld10k1_tram_hwacc_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int external) +{ + int i; + + if (!external) { + for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) { + if (!dsp_mgr->itram_hwacc[i].used) { + dsp_mgr->itram_hwacc[i].used = 1; + dsp_mgr->i_tram.used_hwacc++; + return i; + } + } + } else { + for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) { + if (!dsp_mgr->etram_hwacc[i].used) { + dsp_mgr->etram_hwacc[i].used = 1; + dsp_mgr->e_tram.used_hwacc++; + return i + dsp_mgr->max_itram_hwacc; + } + } + } + return LD10K1_ERR_TRAM_FULL_ACC; +} + +void ld10k1_tram_hwacc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc) +{ + if (acc < dsp_mgr->max_itram_hwacc) { + dsp_mgr->itram_hwacc[acc].used = 0; + dsp_mgr->itram_hwacc[acc].addr_val = 0; + dsp_mgr->itram_hwacc[acc].data_val = 0; + dsp_mgr->itram_hwacc[acc].modified = 1; + dsp_mgr->i_tram.used_hwacc--; + } else { + int nacc = acc - dsp_mgr->max_itram_hwacc; + dsp_mgr->etram_hwacc[nacc].used = 0; + dsp_mgr->etram_hwacc[nacc].used = 0; + dsp_mgr->etram_hwacc[nacc].addr_val = 0; + dsp_mgr->etram_hwacc[nacc].data_val = 0; + dsp_mgr->etram_hwacc[nacc].modified = 1; + dsp_mgr->e_tram.used_hwacc--; + } +} + +void ld10k1_tram_actualize_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int op, unsigned int addr, unsigned int data) +{ + if (acc < dsp_mgr->max_itram_hwacc) { + dsp_mgr->itram_hwacc[acc].op = op; + dsp_mgr->itram_hwacc[acc].addr_val = addr; + dsp_mgr->itram_hwacc[acc].data_val = data; + dsp_mgr->itram_hwacc[acc].modified = 1; + } else { + int nacc = acc - dsp_mgr->max_itram_hwacc; + dsp_mgr->etram_hwacc[nacc].op = op; + dsp_mgr->etram_hwacc[nacc].addr_val = addr; + dsp_mgr->etram_hwacc[nacc].data_val = data; + dsp_mgr->etram_hwacc[nacc].modified = 1; + } +} + +void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data) +{ + int nacc; + + if (acc < dsp_mgr->max_itram_hwacc) { + *addr = dsp_mgr->itram_hwacc[acc].addr_val; + *data = dsp_mgr->itram_hwacc[acc].data_val; + } else { + nacc = acc - dsp_mgr->max_itram_hwacc; + *addr = dsp_mgr->etram_hwacc[nacc].addr_val; + *data = dsp_mgr->etram_hwacc[nacc].data_val; + } +} + +int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res) +{ + int i, j; + int grp_idx; + int hwacc; + + /* free hw acc - where pos changed */ + for (i = 0; i < res->item_count; i++) { + grp_idx = res->items[i].grp_idx; + if (dsp_mgr->tram_grp[grp_idx].pos != TRAM_POS_NONE && + dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) { + for (j = 0; j < dsp_mgr->max_tram_acc; j++) + if (dsp_mgr->tram_acc[j].used && + dsp_mgr->tram_acc[j].grp == grp_idx) + ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[j].hwacc); + dsp_mgr->tram_grp[grp_idx].pos = TRAM_POS_NONE; + } + } + + /* now allocate */ + for (i = 0; i < res->item_count; i++) { + grp_idx = res->items[i].grp_idx; + if (dsp_mgr->tram_grp[grp_idx].pos == TRAM_POS_NONE && + dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) { + dsp_mgr->tram_grp[grp_idx].pos = res->items[i].pos; + for (j = 0; j < dsp_mgr->max_tram_acc; j++) + if (dsp_mgr->tram_acc[j].used && + dsp_mgr->tram_acc[j].grp == grp_idx) { + hwacc = ld10k1_tram_hwacc_alloc(dsp_mgr, res->items[i].pos == TRAM_POS_EXTERNAL ? 1 : 0); + dsp_mgr->tram_acc[j].hwacc = hwacc; + } + } + } + return 0; +} + +int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res) +{ + int itram_size = res->isize; + int etram_size = res->esize; + int i; + + /* allocate from end */ + for (i = 0; i < dsp_mgr->max_tram_grp; i++) + if (dsp_mgr->tram_grp[i].used) { + if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) { + itram_size -= dsp_mgr->tram_grp[i].size; + dsp_mgr->tram_grp[i].offset = itram_size; + } else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) { + etram_size -= dsp_mgr->tram_grp[i].size; + dsp_mgr->tram_grp[i].offset = etram_size; + } + } + + return 0; +} + + +int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch) +{ + int i; + int grp_idx; + int acc_idx; + int tram_op; + + /* for all patch accs */ + for (i = 0; i < patch->tram_acc_count; i++) { + grp_idx = patch->tram_grp[patch->tram_acc[i].grp].grp_idx; + acc_idx = patch->tram_acc[i].acc_idx; + tram_op = 0; + + if (dsp_mgr->tram_acc[acc_idx].type == TRAM_ACC_WRITE) + tram_op = TRAM_OP_WRITE; + else + tram_op = TRAM_OP_READ; + + ld10k1_tram_actualize_hwacc(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc, + tram_op, dsp_mgr->tram_grp[grp_idx].offset + patch->tram_acc[i].acc_offset, 0); + } + return 0; +} + +int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch) +{ + int i; + int acc_idx; + int grp_idx; + + /* free all patch accs */ + for (i = 0; i < patch->tram_acc_count; i++) { + acc_idx = patch->tram_acc[i].acc_idx; + ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc); + ld10k1_tram_acc_free(dsp_mgr, acc_idx); + } + + /* free all patch grps */ + for (i = 0; i < patch->tram_count; i++) { + grp_idx = patch->tram_grp[i].grp_idx; + ld10k1_tram_grp_free(dsp_mgr, grp_idx); + } + + return 0; +} + diff --git a/ld10k1/src/ld10k1_tram.h b/ld10k1/src/ld10k1_tram.h new file mode 100644 index 0000000..380f8e0 --- /dev/null +++ b/ld10k1/src/ld10k1_tram.h @@ -0,0 +1,53 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LD10K1_TRAM_H +#define __LD10K1_TRAM_H + +typedef struct { + int grp_idx; + unsigned int grp_size; + unsigned int grp_acc_count; + unsigned int res_value; + unsigned int pos; +} ld10k1_dsp_tram_resolve_item_t; + +typedef struct { + int isize; + int ifree; + int iacc_count; + int iacc_free_count; + int esize; + int efree; + int eacc_count; + int eacc_free_count; + int grp_free; + int item_count; + ld10k1_dsp_tram_resolve_item_t items[MAX_TRAM_COUNT]; +} ld10k1_dsp_tram_resolve_t; + +int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res); +int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res); +int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch); +void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data); +int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch); + +#endif /* __LD10K1_TRAM_H */ diff --git a/ld10k1/src/liblo10k1.c b/ld10k1/src/liblo10k1.c new file mode 100644 index 0000000..c8e0f94 --- /dev/null +++ b/ld10k1/src/liblo10k1.c @@ -0,0 +1,1168 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include "comm.h" +#include "ld10k1_fnc.h" +#include "ld10k1_error.h" +#include "liblo10k1.h" +#include "liblo10k1ef.h" +#include "liblo10k1lf.h" +#include "ld10k1_debug.h" +#include "config.h" + +int send_request_check(int conn_num, int op, void *data, int data_size) +{ + int opr, sizer; + int err; + + if ((err = send_request(conn_num, op, data, data_size)) < 0) + return err; + + if ((err = receive_response(conn_num, &opr, &sizer)) < 0) + return err; + + return 0; +} + +int send_msg_data_check(int conn_num, void *data, int data_size) +{ + int opr, sizer; + int err; + + if ((err = send_msg_data(conn_num, data, data_size)) < 0) + return err; + + if ((err = receive_response(conn_num, &opr, &sizer)) < 0) + return err; + + return 0; +} + +int receive_response_data_check(int conn_num, void *data, int idata_size) +{ + int err; + int op, data_size; + + if ((err = receive_response(conn_num, &op, &data_size)) < 0) + return err; + + if (op == FNC_ERR) + return LD10K1_ERR_PROTOCOL; + if (data_size != idata_size) + return LD10K1_ERR_PROTOCOL; + + if ((err = receive_msg_data(conn_num, data, data_size)) < 0) + return err; + + /* receive check */ + if ((err = receive_response(conn_num, &op, &data_size)) < 0) + return err; + + return 0; +} + +void liblo10k1_connection_init(liblo10k1_connection_t *conn) +{ + *conn = 0; +} + +int liblo10k1_connect(liblo10k1_param *param, liblo10k1_connection_t *conn) +{ + int err; + + param->server = 0; + *conn = setup_comm(param); + if (*conn < 0) + return LD10K1_ERR_COMM_CONN; + if ((err = connect_comm(*conn, param)) < 0) { + free_comm(*conn); + *conn = 0; + return err; + } + return 0; +} + +int liblo10k1_disconnect(liblo10k1_connection_t *conn) +{ + send_request(*conn, FNC_CLOSE_CONN, NULL, 0); + free_comm(*conn); + *conn = 0; + return 0; +} + +int liblo10k1_is_open(liblo10k1_connection_t *conn) +{ + return *conn != 0; +} + +int liblo10k1_patch_set_in_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_pio_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_pio_t *)malloc(sizeof(liblo10k1_dsp_pio_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_pio_t) * count); + } + + p->in_count = count; + if (p->ins) + free(p->ins); + p->ins = tmp; + return 0; +} + +int liblo10k1_patch_set_out_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_pio_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_pio_t *)malloc(sizeof(liblo10k1_dsp_pio_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_pio_t) * count); + } + + p->out_count = count; + if (p->outs) + free(p->outs); + p->outs = tmp; + return 0; +} + +int liblo10k1_patch_set_const_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_cs_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_cs_t *)malloc(sizeof(liblo10k1_dsp_cs_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_cs_t) * count); + } + + p->const_count = count; + if (p->consts) + free(p->consts); + p->consts = tmp; + return 0; +} + +int liblo10k1_patch_set_sta_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_cs_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_cs_t *)malloc(sizeof(liblo10k1_dsp_cs_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_cs_t) * count); + } + + p->sta_count = count; + if (p->stas) + free(p->stas); + p->stas = tmp; + return 0; +} + +int liblo10k1_patch_set_dyn_count(liblo10k1_dsp_patch_t *p, int count) +{ + p->dyn_count = count; + return 0; +} + +int liblo10k1_patch_set_hw_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_hw_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_hw_t *)malloc(sizeof(liblo10k1_dsp_hw_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_hw_t) * count); + } + + p->hw_count = count; + if (p->hws) + free(p->hws); + p->hws = tmp; + return 0; +} + +int liblo10k1_patch_set_tram_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_tram_grp_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_tram_grp_t *)malloc(sizeof(liblo10k1_dsp_tram_grp_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_tram_grp_t) * count); + } + + p->tram_count = count; + if (p->tram) + free(p->tram); + p->tram = tmp; + return 0; +} + +int liblo10k1_patch_set_tram_acc_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_tram_acc_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_tram_acc_t *)malloc(sizeof(liblo10k1_dsp_tram_acc_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_tram_acc_t) * count); + } + + p->tram_acc_count = count; + if (p->tram_acc) + free(p->tram_acc); + p->tram_acc = tmp; + return 0; +} + +int liblo10k1_patch_set_ctl_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_ctl_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_ctl_t *)malloc(sizeof(liblo10k1_dsp_ctl_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_ctl_t) * count); + } + + p->ctl_count = count; + if (p->ctl) + free(p->ctl); + p->ctl = tmp; + return 0; +} + +int liblo10k1_patch_set_instr_count(liblo10k1_dsp_patch_t *p, int count) +{ + liblo10k1_dsp_instr_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_instr_t *)malloc(sizeof(liblo10k1_dsp_instr_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_dsp_instr_t) * count); + } + + p->instr_count = count; + if (p->instr) + free(p->instr); + p->instr = tmp; + return 0; +} + +liblo10k1_dsp_patch_t *liblo10k1_patch_alloc(int in_count, int out_count, int const_count, int sta_count, int dyn_count, int hw_count, int tram_count, int tram_acc_count, int ctl_count, int instr_count) +{ + liblo10k1_dsp_patch_t *np; + int en = 0; + + np = (liblo10k1_dsp_patch_t *)malloc(sizeof(liblo10k1_dsp_patch_t)); + if (!np) + return NULL; + + np->patch_name[0] ='\0'; + np->ins = NULL; + np->outs = NULL; + np->consts = NULL; + np->stas = NULL; + np->hws = NULL; + np->tram = NULL; + np->tram_acc = NULL; + np->ctl = NULL; + np->instr = NULL; + + if ((en = liblo10k1_patch_set_dyn_count(np, dyn_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_in_count(np, in_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_out_count(np, out_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_const_count(np, const_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_sta_count(np, sta_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_hw_count(np, hw_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_tram_count(np, tram_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_tram_acc_count(np, tram_acc_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_ctl_count(np, ctl_count)) < 0) + goto error; + if ((en = liblo10k1_patch_set_instr_count(np, instr_count)) < 0) + goto error; + return np; +error: + liblo10k1_patch_free(np); + return NULL; +} + +void liblo10k1_patch_free(liblo10k1_dsp_patch_t *patch) +{ + liblo10k1_patch_set_in_count(patch, 0); + liblo10k1_patch_set_out_count(patch, 0); + liblo10k1_patch_set_const_count(patch, 0); + liblo10k1_patch_set_dyn_count(patch, 0); + liblo10k1_patch_set_sta_count(patch, 0); + liblo10k1_patch_set_hw_count(patch, 0); + liblo10k1_patch_set_tram_count(patch, 0); + liblo10k1_patch_set_tram_acc_count(patch, 0); + liblo10k1_patch_set_ctl_count(patch, 0); + liblo10k1_patch_set_instr_count(patch, 0); + + free(patch); +} + +int liblo10k1_patch_load(liblo10k1_connection_t *conn, liblo10k1_dsp_patch_t *patch, int before, int *loaded, int *loaded_id) +{ + int err; + ld10k1_fnc_patch_add_t patch_fnc; + int tmpres[2]; + + strncpy(patch_fnc.patch.patch_name, patch->patch_name, sizeof(patch_fnc.patch.patch_name) - 1); + patch_fnc.patch.patch_name[sizeof(patch_fnc.patch.patch_name) - 1] = '\0'; + + patch_fnc.patch.in_count = patch->in_count; + patch_fnc.patch.out_count = patch->out_count; + patch_fnc.patch.const_count = patch->const_count; + patch_fnc.patch.static_count = patch->sta_count; + patch_fnc.patch.dynamic_count = patch->dyn_count; + patch_fnc.patch.hw_count = patch->hw_count; + patch_fnc.patch.tram_count = patch->tram_count; + patch_fnc.patch.tram_acc_count = patch->tram_acc_count; + patch_fnc.patch.ctl_count = patch->ctl_count; + patch_fnc.patch.instr_count = patch->instr_count; + + /* patch */ + /* add */ + patch_fnc.where = before; + if ((err = send_request_check(*conn, FNC_PATCH_ADD, &patch_fnc, sizeof(ld10k1_fnc_patch_add_t))) < 0) + return err; + + /* in */ + if (patch->in_count) + if ((err = send_msg_data_check(*conn, patch->ins, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count)) < 0) + return err; + + /* out */ + if (patch->out_count) + if ((err = send_msg_data_check(*conn, patch->outs, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count)) < 0) + return err; + + /* const */ + if (patch->const_count) + if ((err = send_msg_data_check(*conn, patch->consts, sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count)) < 0) + return err; + + /* sta */ + if (patch->sta_count) + if ((err = send_msg_data_check(*conn, patch->stas, sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count)) < 0) + return err; + + /* hw */ + if (patch->hw_count) + if ((err = send_msg_data_check(*conn, patch->hws, sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count)) < 0) + return err; + + if (patch->tram_count) + /* tram groups */ + if ((err = send_msg_data_check(*conn, patch->tram, sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count)) < 0) + return err; + + if (patch->tram_acc_count) + /* tram access */ + if ((err = send_msg_data_check(*conn, patch->tram_acc, sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count)) < 0) + return err; + + if (patch->ctl_count) + /* ctls */ + if ((err = send_msg_data_check(*conn, patch->ctl, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count)) < 0) + return err; + + /* instr */ + if ((err = send_msg_data_check(*conn, patch->instr, sizeof(ld10k1_dsp_instr_t) * patch->instr_count)) < 0) + return err; + + if ((err = receive_response_data_check(*conn, tmpres, sizeof(tmpres))) < 0) + return err; + + if (loaded) + *loaded = tmpres[0]; + if (loaded_id) + *loaded_id = tmpres[1]; + + return 0; +} + +int liblo10k1_debug(liblo10k1_connection_t *conn, int deb, void (*prn_fnc)(char *)) +{ + int err; + ld10k1_fnc_debug_t debug_info; + char debug_line[1000]; + int opr, sizer; + + /* add */ + debug_info.what = deb; + + if ((err = send_request(*conn, FNC_DEBUG, &debug_info, sizeof(ld10k1_fnc_debug_t))) < 0) + return err; + + while (1) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE) + break; + + if (sizer < (int)sizeof(debug_line)) { + if ((err = receive_msg_data(*conn, &debug_line, sizer)) < 0) + return err; + } else + return LIBLO10K1_ERR_DEBUG; + (*prn_fnc)(debug_line); + } + + /* not checked */ + return receive_response(*conn, &opr, &sizer); +} + +int liblo10k1_patch_unload(liblo10k1_connection_t *conn, int patch_num) +{ + ld10k1_fnc_patch_del_t patch_fnc; + + patch_fnc.where = patch_num; + + return send_request_check(*conn, FNC_PATCH_DEL, &patch_fnc, sizeof(ld10k1_fnc_patch_del_t)); +} + +int liblo10k1_dsp_init(liblo10k1_connection_t *conn) +{ + return send_request_check(*conn, FNC_DSP_INIT, NULL, 0); +} + +static int liblo10k1_find_any(liblo10k1_connection_t *conn, int op, int patch, char *name, int *out) +{ + ld10k1_fnc_name_t name_info; + int err; + int idx = -1; + + name_info.patch_num = patch; + name_info.gpr = -1; + + strncpy(name_info.name, name, sizeof(name_info.name) - 1); + name_info.name[sizeof(name_info.name) - 1] = '\0'; + + if ((err = send_request(*conn, op, &name_info, sizeof(ld10k1_fnc_name_t))) < 0) + return err; + + if ((err = receive_response_data_check(*conn, &idx, sizeof(idx))) < 0) + return err; + + *out = idx; + return 0; +} + +int liblo10k1_find_patch(liblo10k1_connection_t *conn, char *patch_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_PATCH_FIND, -1, patch_name, out); +} + +int liblo10k1_find_fx(liblo10k1_connection_t *conn, char *fx_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_FX_FIND, -1, fx_name, out); +} + +int liblo10k1_find_in(liblo10k1_connection_t *conn, char *in_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_IN_FIND, -1, in_name, out); +} + +int liblo10k1_find_out(liblo10k1_connection_t *conn, char *out_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_OUT_FIND, -1, out_name, out); +} + +int liblo10k1_find_patch_in(liblo10k1_connection_t *conn, int patch_num, char *patch_in_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_PATCH_IN_FIND, patch_num, patch_in_name, out); +} + +int liblo10k1_find_patch_out(liblo10k1_connection_t *conn, int patch_num, char *patch_out_name, int *out) +{ + return liblo10k1_find_any(conn, FNC_PATCH_OUT_FIND, patch_num, patch_out_name, out); +} + +int liblo10k1_con_add(liblo10k1_connection_t *conn, int multi, int simple, int from_type, int from_patch, int from_io, int to_type, int to_patch, int to_io, int *ci) +{ + ld10k1_fnc_connection_t connection_fnc; + int err; + int conn_id; + + connection_fnc.what = FNC_CONNECTION_ADD; + connection_fnc.multi = multi; + connection_fnc.simple = simple; + connection_fnc.from_type = from_type; + connection_fnc.from_patch = from_patch; + connection_fnc.from_io = from_io; + connection_fnc.to_type = to_type; + connection_fnc.to_patch = to_patch; + connection_fnc.to_io = to_io; + + if ((err = send_request(*conn, FNC_CONNECTION_ADD, &connection_fnc, sizeof(ld10k1_fnc_connection_t))) < 0) + return err; + + if ((err = receive_response_data_check(*conn, &conn_id, sizeof(conn_id))) < 0) + return err; + + if (ci) + *ci = conn_id; + return 0; +} + +int liblo10k1_con_del(liblo10k1_connection_t *conn, int type, int patch, int io, int *ci) +{ + ld10k1_fnc_connection_t connection_fnc; + int err; + int conn_id; + + connection_fnc.what = FNC_CONNECTION_DEL; + connection_fnc.from_type = type; + connection_fnc.from_patch = patch; + connection_fnc.from_io = io; + connection_fnc.to_type = -1; + connection_fnc.to_patch = -1; + connection_fnc.to_io = -1; + + if ((err = send_request(*conn, FNC_CONNECTION_DEL, &connection_fnc, sizeof(ld10k1_fnc_connection_t))) < 0) + return err; + + if ((err = receive_response_data_check(*conn, &conn_id, sizeof(conn_id))) < 0) + return err; + + if (ci) + *ci = conn_id; + return 0; +} + +static int liblo10k1_rename_any(liblo10k1_connection_t *conn, int op, int patch_num, int gpr_num, char *name) +{ + ld10k1_fnc_name_t name_info; + + name_info.patch_num = patch_num; + name_info.gpr = gpr_num; + + strncpy(name_info.name, name, sizeof(name_info.name) - 1); + name_info.name[sizeof(name_info.name) - 1] = '\0'; + + return send_request_check(*conn, op, &name_info, sizeof(ld10k1_fnc_name_t)); +} + +int liblo10k1_rename_patch(liblo10k1_connection_t *conn, int patch_num, char *patch_name) +{ + return liblo10k1_rename_any(conn, FNC_PATCH_RENAME, patch_num, -1, patch_name); +} + +int liblo10k1_rename_patch_in(liblo10k1_connection_t *conn, int patch_num, int in, char *patch_in_name) +{ + return liblo10k1_rename_any(conn, FNC_PATCH_IN_RENAME, patch_num, in, patch_in_name); +} + +int liblo10k1_rename_patch_out(liblo10k1_connection_t *conn, int patch_num, int out, char *patch_out_name) +{ + return liblo10k1_rename_any(conn, FNC_PATCH_OUT_RENAME, patch_num, out, patch_out_name); +} + +int liblo10k1_rename_fx(liblo10k1_connection_t *conn, int fx, char *fx_name) +{ + return liblo10k1_rename_any(conn, FNC_FX_RENAME, -1, fx, fx_name); +} + +int liblo10k1_rename_in(liblo10k1_connection_t *conn, int in, char *in_name) +{ + return liblo10k1_rename_any(conn, FNC_IN_RENAME, -1, in, in_name); +} + +int liblo10k1_rename_out(liblo10k1_connection_t *conn, int out, char *out_name) +{ + return liblo10k1_rename_any(conn, FNC_OUT_RENAME, -1, out, out_name); +} + +int liblo10k1_get_io(liblo10k1_connection_t *conn, int op, int io_num, liblo10k1_get_io_t *out); +int liblo10k1_get_pio(liblo10k1_connection_t *conn, int op, int patch_num, int io_num, liblo10k1_get_io_t *out); + +int liblo10k1_get_fx(liblo10k1_connection_t *conn, int fx_num, liblo10k1_get_io_t *out) +{ + return liblo10k1_get_io(conn, FNC_GET_FX, fx_num, out); +} + +int liblo10k1_get_in(liblo10k1_connection_t *conn, int in_num, liblo10k1_get_io_t *out) +{ + return liblo10k1_get_io(conn, FNC_GET_IN, in_num, out); +} + +int liblo10k1_get_out(liblo10k1_connection_t *conn, int out_num, liblo10k1_get_io_t *out) +{ + return liblo10k1_get_io(conn, FNC_GET_OUT, out_num, out); +} + +int liblo10k1_get_pin(liblo10k1_connection_t *conn, int patch_num, int in_num, liblo10k1_get_io_t *out) +{ + return liblo10k1_get_pio(conn, FNC_GET_PIN, patch_num, in_num, out); +} + +int liblo10k1_get_pout(liblo10k1_connection_t *conn, int patch_num, int out_num, liblo10k1_get_io_t *out) +{ + return liblo10k1_get_pio(conn, FNC_GET_POUT, patch_num, out_num, out); +} + +int liblo10k1_get_io(liblo10k1_connection_t *conn, int op, int io_num, liblo10k1_get_io_t *out) +{ + int err; + + if ((err = send_request(*conn, op, &io_num, sizeof(int))) < 0) + return err; + + if ((err = receive_response_data_check(*conn, out, sizeof(liblo10k1_get_io_t))) < 0) + return err; + + return 0; +} + +int liblo10k1_get_pio(liblo10k1_connection_t *conn, int op, int patch_num, int io_num, liblo10k1_get_io_t *out) +{ + int tmp_num[2]; + int err; + + tmp_num[0] = patch_num; + tmp_num[1] = io_num; + + if ((err = send_request(*conn, op, tmp_num, sizeof(int) * 2)) < 0) + return err; + + if ((err = receive_response_data_check(*conn, out, sizeof(liblo10k1_get_io_t))) < 0) + return err; + + return 0; +} + +int liblo10k1_get_io_count(liblo10k1_connection_t *conn, int op, int *out); +int liblo10k1_get_pio_count(liblo10k1_connection_t *conn, int op, int patch_num, int *out); + +int liblo10k1_get_fx_count(liblo10k1_connection_t *conn, int *out) +{ + return liblo10k1_get_io_count(conn, FNC_GET_FX_COUNT, out); +} + +int liblo10k1_get_in_count(liblo10k1_connection_t *conn, int *out) +{ + return liblo10k1_get_io_count(conn, FNC_GET_IN_COUNT, out); +} + +int liblo10k1_get_out_count(liblo10k1_connection_t *conn, int *out) +{ + return liblo10k1_get_io_count(conn, FNC_GET_OUT_COUNT, out); +} + +int liblo10k1_get_pin_count(liblo10k1_connection_t *conn, int patch_num, int *out) +{ + return liblo10k1_get_pio_count(conn, FNC_GET_PIN_COUNT, patch_num, out); +} + +int liblo10k1_get_pout_count(liblo10k1_connection_t *conn, int patch_num, int *out) +{ + return liblo10k1_get_pio_count(conn, FNC_GET_POUT_COUNT, patch_num, out); +} + +int liblo10k1_get_io_count(liblo10k1_connection_t *conn, int op, int *out) +{ + int err; + + if ((err = send_request(*conn, op, 0, 0)) < 0) + return err; + + if ((err = receive_response_data_check(*conn, out, sizeof(int))) < 0) + return err; + + return 0; +} + +int liblo10k1_get_pio_count(liblo10k1_connection_t *conn, int op, int patch_num, int *out) +{ + int err; + + if ((err = send_request(*conn, op, &patch_num, sizeof(int))) < 0) + return err; + + if ((err = receive_response_data_check(*conn, out, sizeof(int))) < 0) + return err; + + return 0; +} + +int liblo10k1_get_patches_info(liblo10k1_connection_t *conn, liblo10k1_patches_info_t **out, int *count) +{ + liblo10k1_patches_info_t *info; + int opr, sizer; + int err; + + *out = NULL; + *count = 0; + info = NULL; + + if ((err = send_request(*conn, FNC_GET_PATCHES_INFO, 0, 0)) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + *count = sizer / sizeof(liblo10k1_patches_info_t); + if (sizer > 0) { + info = (liblo10k1_patches_info_t *)receive_msg_data_malloc(*conn, sizer); + if (!info) + return LD10K1_ERR_NO_MEM; + } + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) { + free(info); + return err; + } + + *out = info; + return 0; +} + +int liblo10k1_patch_get(liblo10k1_connection_t *conn, int patch_num, liblo10k1_dsp_patch_t **opatch) +{ + liblo10k1_dsp_patch_t *patch; + int err; + + ld10k1_dsp_patch_t tmp_patch; + int opr, sizer; + + + if ((err = send_request(*conn, FNC_GET_PATCH, &patch_num, sizeof(patch_num))) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE) + return LD10K1_ERR_PROTOCOL; + + if ((err = receive_msg_data(*conn, &tmp_patch, sizeof(tmp_patch))) < 0) + return err; + + /* alloc patch */ + patch = liblo10k1_patch_alloc(tmp_patch.in_count, tmp_patch.out_count, tmp_patch.const_count, tmp_patch.static_count, tmp_patch.dynamic_count, tmp_patch.hw_count, tmp_patch.tram_count, tmp_patch.tram_acc_count, tmp_patch.ctl_count, tmp_patch.instr_count); + if (!patch) + return LD10K1_ERR_NO_MEM; + + strcpy(patch->patch_name, tmp_patch.patch_name); + + /* ins */ + if (patch->in_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->in_count * sizeof(ld10k1_dsp_p_in_out_t)) + goto err_protocol; + + patch->ins = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->ins) + goto err_nomem; + } + + /* outs */ + if (patch->out_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->out_count * sizeof(ld10k1_dsp_p_in_out_t)) + goto err_protocol; + + patch->outs = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->outs) + goto err_nomem; + } + + /* consts */ + if (patch->const_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->const_count * sizeof(ld10k1_dsp_p_const_static_t)) + goto err_protocol; + + patch->consts = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->consts) + goto err_nomem; + } + + /* stas */ + if (patch->sta_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->sta_count * sizeof(ld10k1_dsp_p_const_static_t)) + goto err_protocol; + + patch->stas = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->stas) + goto err_nomem; + } + + /* hws */ + if (patch->hw_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->hw_count * sizeof(ld10k1_dsp_p_hw_t)) + goto err_protocol; + + patch->hws = (ld10k1_dsp_p_hw_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->hws) + goto err_nomem; + } + + /* ctls */ + if (patch->ctl_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->ctl_count * sizeof(liblo10k1_dsp_ctl_t)) + goto err_protocol; + + patch->ctl = (liblo10k1_dsp_ctl_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->ctl) + goto err_nomem; + } + + /* tram grp */ + if (patch->tram_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->tram_count * sizeof(liblo10k1_dsp_tram_grp_t)) + goto err_protocol; + + patch->tram = (liblo10k1_dsp_tram_grp_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->tram) + goto err_nomem; + } + + /* tram acc */ + if (patch->tram_acc_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->tram_acc_count * sizeof(liblo10k1_dsp_tram_acc_t)) + goto err_protocol; + + patch->tram_acc = (liblo10k1_dsp_tram_acc_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->tram_acc) + goto err_nomem; + } + + /* instr */ + if (patch->instr_count) { + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (opr != FNC_CONTINUE || (unsigned int)sizer != patch->instr_count * sizeof(liblo10k1_dsp_instr_t)) + goto err_protocol; + + patch->instr = (liblo10k1_dsp_instr_t *)receive_msg_data_malloc(*conn, sizer); + if (!patch->instr) + goto err_nomem; + } + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) { + liblo10k1_patch_free(patch); + return err; + } + + *opatch = patch; + return 0; +err_nomem: + liblo10k1_patch_free(patch); + return LD10K1_ERR_NO_MEM; + +err_protocol: + liblo10k1_patch_free(patch); + return LD10K1_ERR_PROTOCOL; +} + +int liblo10k1_dump(liblo10k1_connection_t *conn, void **out, int *size) +{ + int opr, sizer; + int err; + void *dump = NULL; + + if ((err = send_request(*conn, FNC_DUMP, 0, 0)) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + *size = sizer; + if (sizer > 0) { + dump = receive_msg_data_malloc(*conn, sizer); + if (!dump) + return LD10K1_ERR_NO_MEM; + } + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) { + free(dump); + return err; + } + + *out = dump; + return 0; +} + +int liblo10k1_check_version(liblo10k1_connection_t *conn) +{ + int opr, sizer; + int err; + ld10k1_fnc_version_t ver; + + if ((err = send_request(*conn, FNC_VERSION, 0, 0)) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (sizer == sizeof(ver)) { + if ((err = receive_msg_data(*conn, &ver, sizer)) < 0) + return err; + } + else + return LD10K1_ERR_WRONG_VER; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (strcmp(ver.ld10k1_version, VERSION) == 0) + return 0; + else + return LD10K1_ERR_WRONG_VER; +} + +int liblo10k1_get_points_info(liblo10k1_connection_t *conn, int **out, int *count) +{ + int *info; + int opr, sizer; + int err; + + info = NULL; + + if ((err = send_request(*conn, FNC_GET_POINTS_INFO, 0, 0)) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + *count = sizer / sizeof(int); + if (sizer > 0) { + info = (int *)receive_msg_data_malloc(*conn, sizer); + if (!info) + return LD10K1_ERR_NO_MEM; + } + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) { + free(info); + return err; + } + + *out = info; + return 0; +} + +int liblo10k1_get_point_info(liblo10k1_connection_t *conn, int point_id, liblo10k1_point_info_t *out) +{ + int opr, sizer; + int err; + + if ((err = send_request(*conn, FNC_GET_POINT_INFO, &point_id, sizeof(point_id))) < 0) + return err; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + if (sizer != sizeof(liblo10k1_point_info_t)) + return LD10K1_ERR_PROTOCOL; + if ((err = receive_msg_data(*conn, out, sizer)) < 0) + return LD10K1_ERR_PROTOCOL; + + if ((err = receive_response(*conn, &opr, &sizer)) < 0) + return err; + + return 0; +} + +int liblo10k1_get_dsp_info(liblo10k1_connection_t *conn, liblo10k1_dsp_info_t *info) +{ + int err; + + if ((err = send_request(*conn, FNC_GET_DSP_INFO, NULL, 0)) < 0) + return err; + + if ((err = receive_response_data_check(*conn, info, sizeof(liblo10k1_dsp_info_t))) < 0) + return err; + + return 0; +} + +struct errmsg_t +{ + int errnum; + char *errmsg; +}; + +struct errmsg_t error_text[] = +{ + {LD10K1_ERR_UNKNOWN, "Unknown error"}, + {LD10K1_ERR_COMM_READ, "Error in read from socket"}, + {LD10K1_ERR_COMM_WRITE, "Error in write to socket"}, + {LD10K1_ERR_UNKNOWN_PATCH_NUM, "Wrong parameter - patch with this num doesn't exists"}, + {LD10K1_ERR_PROTOCOL, "ld10k1 is expecting more or less data as it got"}, + {LD10K1_ERR_COMM_CONN, "Error in socket connect"}, + +/* add patch */ + {LD10K1_ERR_PROTOCOL_IN_COUNT, "Wrong in registers count"}, + {LD10K1_ERR_PROTOCOL_OUT_COUNT, "Wrong out registers count"}, + {LD10K1_ERR_PROTOCOL_CONST_COUNT, "Wrong const registers count"}, + {LD10K1_ERR_PROTOCOL_STATIC_COUNT, "Wrong static registers count"}, + {LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT, "Wrong dynamic registers count"}, + {LD10K1_ERR_PROTOCOL_HW_COUNT, "Wrong hw registers count"}, + {LD10K1_ERR_PROTOCOL_TRAM_COUNT, "Wrong tram count"}, + {LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT, "Wrong tram access registers count"}, + {LD10K1_ERR_PROTOCOL_CTL_COUNT, "Wrong controls count"}, + {LD10K1_ERR_PROTOCOL_INSTR_COUNT, "Wrong instructions count"}, + +/* driver */ + {LD10K1_ERR_DRIVER_CODE_POKE, "Unable to poke code"}, + {LD10K1_ERR_DRIVER_INFO, "Unable to get info"}, + {LD10K1_ERR_DRIVER_CODE_PEEK, "Unable to peek code"}, + {LD10K1_ERR_DRIVER_PCM_POKE, "Unable to poke pcm"}, + +/* tram */ + {LD10K1_ERR_ITRAM_FULL, "Not enought free itram"}, + {LD10K1_ERR_ETRAM_FULL, "Not enought free etram"}, + {LD10K1_ERR_TRAM_FULL, "Not enought free tram"}, + {LD10K1_ERR_TRAM_FULL_GRP, "Not enought free tram group"}, + + {LD10K1_ERR_ITRAM_FULL_ACC, "Not enought free itram acc"}, + {LD10K1_ERR_ETRAM_FULL_ACC, "Not enought free etram acc"}, + {LD10K1_ERR_TRAM_FULL_ACC, "Not enought free tram acc"}, + + {LD10K1_ERR_MAX_CON_PER_POINT, "Maximum connections per point reached"}, + +/* others */ + {LD10K1_ERR_NO_MEM, "Not enought free mem"}, + {LD10K1_ERR_MAX_PATCH_COUNT, "Max patch count excesed"}, + {LD10K1_ERR_NOT_FREE_REG, "There is not free reg"}, + {LD10K1_ERR_NOT_FREE_INSTR, "There is no free instruction slot"}, + +/* patch chceck */ + {LD10K1_ERR_WRONG_REG_HW_INDEX, "Loaded patch has wrong hw index"}, + {LD10K1_ERR_WRONG_TRAM_POS, "Loaded patch has wrong tram position"}, + + {LD10K1_ERR_WRONG_TRAM_TYPE, "Loaded patch has wrong tram type"}, + {LD10K1_ERR_WRONG_TRAM_SIZE, "Loaded patch has wrong tram size"}, + {LD10K1_ERR_WRONG_TRAM_ACC_TYPE, "Loaded patch has wrong tram acc type"}, + + {LD10K1_ERR_TRAM_GRP_OUT_OF_RANGE, "Loaded patch has tram gpr index out of range"}, + {LD10K1_ERR_TRAM_ACC_OUT_OF_RANGE, "Loaded patch has tram acc index out of range"}, + + {LD10K1_ERR_CTL_VCOUNT_OUT_OF_RANGE, "Loaded patch has wrong count of visible gpr for control"}, + {LD10K1_ERR_CTL_COUNT_OUT_OF_RANGE, "Loaded patch has wrong count of gpr for control"}, + + {LD10K1_ERR_CTL_MIN_MAX_RANGE, "Loaded patch has wrong min, max range for control"}, + {LD10K1_ERR_CTL_TRANLSLATION, "Loaded patch has wrong translation function for control"}, + {LD10K1_ERR_CTL_REG_INDEX, "Loaded patch has wrong gpr index for control"}, + {LD10K1_ERR_CTL_REG_VALUE, "Loaded patch has wrong initial value for control"}, + + {LD10K1_ERR_INSTR_OPCODE, "Loaded patch has wrong instruction opcode"}, + {LD10K1_ERR_INSTR_ARG_INDEX, "Loaded patch has wrong argument for instruction"}, + + {LD10K1_ERR_UNKNOWN_REG_NUM, "There isn't register with this reg number"}, + {LD10K1_ERR_UNKNOWN_PATCH_REG_NUM, "There isn't patch register with this reg number for patch"}, + + {LD10K1_ERR_CONNECTION, "Couldn't connect patch to io"}, + {LD10K1_ERR_CONNECTION_FNC, "Not supported connect/disconnect function"}, + + {LD10K1_ERR_CTL_EXISTS, "Can't add control because there is one with same name"}, + + {LD10K1_ERR_PATCH_RENAME, "Couldn't rename patch"}, + {LD10K1_ERR_PATCH_REG_RENAME, "Couldn't rename patch register"}, + {LD10K1_ERR_REG_RENAME, "Couldn't rename register"}, + {LD10K1_ERR_WRONG_VER, "Wrong ld10k1 version"}, + {LD10K1_ERR_UNKNOWN_POINT, "Unknown point"}, + + /* errors from liblo10k1ef */ + {LD10K1_EF_ERR_OPEN, "Can not open file"}, + {LD10K1_EF_ERR_STAT, "Can not stat file"}, + {LD10K1_EF_ERR_SIZE, "Wrong file size"}, + {LD10K1_EF_ERR_READ, "Can not read file"}, + {LD10K1_EF_ERR_SIGNATURE, "Wrong file signature"}, + {LD10K1_EF_ERR_FORMAT, "Wrong file format"}, + + {LD10K1_EF_ERR_TRANSFORM_CTL, "Can not transform control"}, + {LD10K1_EF_ERR_TRANSFORM, "Can not transform effect"}, + {LD10K1_EF_ERR_TRANSFORM_TRANS, "Wrong control translation"}, + + /* errors from liblo10k1lf */ + {LD10K1_LF_ERR_OPEN, "Can not open file"}, + {LD10K1_LF_ERR_WRITE, "Can not write file"}, + {LD10K1_LF_ERR_READ, "Can not read file"}, + {LD10K1_LF_ERR_SIGNATURE, "Wrong file signature"}, + {LD10K1_LF_ERR_PART_TYPE, "Wrong part type"}, + {LD10K1_LF_ERR_PART_SIZE, "Wrong part size"}, + {LD10K1_LF_ERR_VERSION, "Wrong file version"}, + {LD10K1_LF_ERR_FILE_TYPE, "Wrong file type"}, + + {0, ""} +}; + +char *liblo10k1_error_str(int error) +{ + int i; + + for (i = 0; error_text[i].errnum != 0; i++) + if (error_text[i].errnum == error) + return error_text[i].errmsg; + return "Error msg not specified in liblo10k1"; +} diff --git a/ld10k1/src/liblo10k1ef.c b/ld10k1/src/liblo10k1ef.c new file mode 100644 index 0000000..0a3cfdb --- /dev/null +++ b/ld10k1/src/liblo10k1ef.c @@ -0,0 +1,1099 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#include "ld10k1_error.h" +#include "ld10k1_fnc.h" +#include "comm.h" +#include "liblo10k1.h" +#include "liblo10k1ef.h" + +liblo10k1_emu_patch_t *liblo10k1_emu_new_patch() +{ + liblo10k1_emu_patch_t *tmp = (liblo10k1_emu_patch_t *)malloc(sizeof(liblo10k1_emu_patch_t)); + + if (!tmp) + return NULL; + memset(tmp, 0, sizeof(liblo10k1_emu_patch_t)); + + return tmp; +} + +void liblo10k1_emu_free_patch(liblo10k1_emu_patch_t *p) +{ + liblo10k1_emu_patch_set_in_count(p, 0); + liblo10k1_emu_patch_set_out_count(p, 0); + liblo10k1_emu_patch_set_dyn_count(p, 0); + liblo10k1_emu_patch_set_sta_count(p, 0); + liblo10k1_emu_patch_set_ctl_count(p, 0); + liblo10k1_emu_patch_set_con_count(p, 0); + liblo10k1_emu_patch_set_lookup_count(p, 0); + liblo10k1_emu_patch_set_delay_count(p, 0); + liblo10k1_emu_patch_set_instr_count(p, 0); + + free(p); +} + +int liblo10k1_emu_patch_set_in_count(liblo10k1_emu_patch_t *p, int count) +{ + unsigned int *tmp = NULL; + + if (count > 0) { + tmp = (unsigned int *)malloc(sizeof(unsigned int)*count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(unsigned int) * count); + } + + p->in_count = count; + if (p->ins) + free(p->ins); + p->ins = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_out_count(liblo10k1_emu_patch_t *p, int count) +{ + unsigned int *tmp = NULL; + + if (count > 0) { + tmp = (unsigned int *)malloc(sizeof(unsigned int)*count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(unsigned int) * count); + } + + p->out_count = count; + if (p->outs) + free(p->outs); + p->outs = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_dyn_count(liblo10k1_emu_patch_t *p, int count) +{ + unsigned int *tmp = NULL; + + if (count > 0) { + tmp = (unsigned int *)malloc(sizeof(unsigned int)*count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(unsigned int) * count); + } + + p->dyn_count = count; + if (p->dyns) + free(p->dyns); + p->dyns = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_sta_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_sc_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_emu_sc_t *)malloc(sizeof(liblo10k1_emu_sc_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_sc_t)*count); + } + + p->sta_count = count; + if (p->stas) + free(p->stas); + p->stas = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_ctl_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_ctl_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_emu_ctl_t *)malloc(sizeof(liblo10k1_emu_ctl_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_ctl_t)*count); + } + + p->ctl_count = count; + if (p->ctls) + free(p->ctls); + p->ctls = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_con_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_sc_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_emu_sc_t *)malloc(sizeof(liblo10k1_emu_sc_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_sc_t)*count); + } + + p->con_count = count; + if (p->cons) + free(p->cons); + p->cons = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_line_count(liblo10k1_emu_tram_t *t, int write, int count) +{ + liblo10k1_emu_tram_line_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_emu_tram_line_t *)malloc(sizeof(liblo10k1_emu_tram_line_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_tram_line_t)*count); + } + + if (write) { + t->write_line_count = count; + if (t->write_lines) + free(t->write_lines); + t->write_lines = tmp; + } else { + t->read_line_count = count; + if (t->read_lines) + free(t->read_lines); + t->read_lines = tmp; + } + return 0; +} + +int liblo10k1_emu_patch_set_lookup_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_tram_t *tmp = NULL; + int i; + + if (count > 0) { + tmp = (liblo10k1_emu_tram_t *)malloc(sizeof(liblo10k1_emu_tram_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_tram_t)*count); + } + + if (p->tram_lookups) { + for (i = 0; i < p->tram_lookup_count; i++) { + liblo10k1_emu_patch_set_line_count(&(p->tram_lookups[i]), 0, 0); + liblo10k1_emu_patch_set_line_count(&(p->tram_lookups[i]), 1, 0); + } + free(p->tram_lookups); + } + p->tram_lookup_count = count; + p->tram_lookups = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_delay_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_tram_t *tmp = NULL; + int i; + + if (count > 0) { + tmp = (liblo10k1_emu_tram_t *)malloc(sizeof(liblo10k1_emu_tram_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_tram_t)*count); + } + + if (p->tram_delays) { + for (i = 0; i < p->tram_delay_count; i++) { + liblo10k1_emu_patch_set_line_count(&(p->tram_delays[i]), 0, 0); + liblo10k1_emu_patch_set_line_count(&(p->tram_delays[i]), 1, 0); + } + free(p->tram_delays); + } + p->tram_delay_count = count; + p->tram_delays = tmp; + return 0; +} + +int liblo10k1_emu_patch_set_instr_count(liblo10k1_emu_patch_t *p, int count) +{ + liblo10k1_emu_instr_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_emu_instr_t *)malloc(sizeof(liblo10k1_emu_instr_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + memset(tmp, 0, sizeof(liblo10k1_emu_instr_t)*count); + } + + p->instr_count = count; + if (p->instrs) + free(p->instrs); + p->instrs = tmp; + return 0; +} + +static int read_byte(char *patch_data, int size, int *pos, unsigned char *out) +{ + if (*pos < size) { + *out = patch_data[*pos]; + (*pos)++; + return 0; + } else + return LD10K1_EF_ERR_FORMAT; +} + +static int read_ushort(char *patch_data, int size, int *pos, unsigned short *out) +{ + if (*pos + 1 < size) { + *out = *((unsigned short *)(patch_data + *pos)); + *(pos) += 2; + return 0; + } else + return LD10K1_EF_ERR_FORMAT; +} + +static int read_uint(char *patch_data, int size, int *pos, unsigned int *out) +{ + if (*pos + 3 < size) { + *out = *((unsigned int *)(patch_data + *pos)); + (*pos) += 4; + return 0; + } else + return LD10K1_EF_ERR_FORMAT; +} + +static int read_string(char *patch_data, int size, int *pos, char *out, int ssize) +{ + if (*pos + ssize - 1 < size) { + strncpy(out, &(patch_data[*pos]), ssize - 1); + out[ssize - 1] = '\0'; + (*pos) += ssize; + return 0; + } else + return LD10K1_EF_ERR_FORMAT; +} + +int liblo10k1_emu_load_patch(char *file_name, liblo10k1_emu_patch_t **p) +{ + struct stat patch_stat; + char *patch_data; + FILE *patch_file; + liblo10k1_emu_patch_t *new_patch = NULL; + unsigned int i, j, z, k; + int en = 0; + + int file_pos = 0; + int file_size = 0; + + unsigned char byte_tmp; + unsigned short ushort_tmp; + + liblo10k1_emu_tram_t *tmp_tram; + liblo10k1_emu_tram_line_t *tmp_tram_lines; + + unsigned int part1, part2; + + if (!(patch_file = fopen(file_name, "r"))) + return LD10K1_EF_ERR_OPEN; + + /* first load patch to mem */ + if (stat(file_name, &patch_stat)) + return LD10K1_EF_ERR_STAT; + + /* minimal patch len is 57 */ + if (patch_stat.st_size < 57 || patch_stat.st_size > 1000000) + return LD10K1_EF_ERR_SIZE; + + file_size = patch_stat.st_size; + + patch_data = (char *)malloc(patch_stat.st_size); + if (!patch_data) + return LD10K1_ERR_NO_MEM; + + if (fread(patch_data, patch_stat.st_size, 1, patch_file) != 1) { + fclose(patch_file); + en = LD10K1_EF_ERR_READ; + goto err; + } else + fclose(patch_file); + + /* signature check */ + if (strncmp(patch_data, "EMU10K1 FX8010 1", 16) != 0) { + en = LD10K1_EF_ERR_SIGNATURE; + goto err; + } + + new_patch = liblo10k1_emu_new_patch(); + if (!new_patch) { + en = LD10K1_ERR_NO_MEM; + goto err; + } + + /* next patch name */ + strncpy(new_patch->patch_name, &(patch_data[16]), 31); + new_patch->patch_name[31] = '\0'; + + /* registers */ + file_pos = 32+16; + + /* in count */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if (byte_tmp >= 32) { + en = LD10K1_EF_ERR_FORMAT; + goto err; + } + + if ((en = liblo10k1_emu_patch_set_in_count(new_patch, byte_tmp)) < 0 || + (en = liblo10k1_emu_patch_set_out_count(new_patch, byte_tmp)) < 0) + goto err; + + /* read in gprs */ + for (i = 0; i < new_patch->in_count; i++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->ins[i] = byte_tmp; + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->outs[i] = byte_tmp; + } + + /* read dyn gprs */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_dyn_count(new_patch, byte_tmp)) < 0) + goto err; + + for (i = 0; i < new_patch->dyn_count; i++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->dyns[i] = byte_tmp; + } + + /* read sta gprs */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_sta_count(new_patch, byte_tmp)) < 0) + goto err; + + for (i = 0; i < new_patch->sta_count; i++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->stas[i].sc = byte_tmp; + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->stas[i].sc_val))) < 0) + goto err; + } + + /* read ctl gprs */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_ctl_count(new_patch, byte_tmp)) < 0) + goto err; + + for (i = 0; i < new_patch->ctl_count; i++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->ctls[i].ctl = byte_tmp; + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val))) < 0) + goto err; + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val_min))) < 0) + goto err; + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->ctls[i].ctl_val_max))) < 0) + goto err; + if ((en = read_string(patch_data, file_size, &file_pos, new_patch->ctls[i].ctl_name, 32)) < 0) + goto err; + } + + /* read const gprs */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_con_count(new_patch, byte_tmp)) < 0) + goto err; + + for (i = 0; i < new_patch->con_count; i++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + new_patch->cons[i].sc = byte_tmp; + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->cons[i].sc_val))) < 0) + goto err; + } + + /* read tram lookup gprs */ + for (z = 0; z < 2; z++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if (z) { + if ((en = liblo10k1_emu_patch_set_delay_count(new_patch, byte_tmp)) < 0) + goto err; + } else { + if ((en = liblo10k1_emu_patch_set_lookup_count(new_patch, byte_tmp)) < 0) + goto err; + } + + for (i = 0; i < (z ? new_patch->tram_delay_count : new_patch->tram_lookup_count); i++) { + /* size */ + if (z) { + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->tram_delays[i].size))) < 0) + goto err; + tmp_tram = new_patch->tram_delays + i; + } else { + if ((en = read_uint(patch_data, file_size, &file_pos, &(new_patch->tram_lookups[i].size))) < 0) + goto err; + tmp_tram = new_patch->tram_lookups + i; + } + + for (k = 0; k < 2; k++) { + /* read lines */ + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_line_count(tmp_tram, k, byte_tmp)) < 0) + goto err; + + if (k) + tmp_tram_lines = tmp_tram->write_lines; + else + tmp_tram_lines = tmp_tram->read_lines; + + for (j = 0; j < (k ? tmp_tram->write_line_count : tmp_tram->read_line_count); j++) { + if ((en = read_byte(patch_data, file_size, &file_pos, &byte_tmp)) < 0) + goto err; + + tmp_tram_lines[j].line = byte_tmp; + + if ((en = read_uint(patch_data, file_size, &file_pos, &(tmp_tram_lines[j].line_size))) < 0) + goto err; + } + } + } + } + + /* instruction lines */ + if ((en = read_ushort(patch_data, file_size, &file_pos, &ushort_tmp)) < 0) + goto err; + + if ((en = liblo10k1_emu_patch_set_instr_count(new_patch, ushort_tmp)) < 0) + goto err; + + for (i = 0; i < new_patch->instr_count; i++) { + if ((en = read_uint(patch_data, file_size, &file_pos, &part1)) < 0) + goto err; + if ((en = read_uint(patch_data, file_size, &file_pos, &part2)) < 0) + goto err; + + /* fill instr */ + new_patch->instrs[i].arg[2] = part1 >> 10; + new_patch->instrs[i].arg[3] = part1 & 0x3FF; + new_patch->instrs[i].op = part2 >> 20; + new_patch->instrs[i].arg[0] = (part2 >> 10) & 0x3FF; + new_patch->instrs[i].arg[1] = part2 & 0x3FF; + } + + *p = new_patch; + + if (patch_data) + free(patch_data); + return 0; +err: + if (patch_data) + free(patch_data); + if (new_patch) + liblo10k1_emu_free_patch(new_patch); + return en; +} + +typedef struct +{ + unsigned int gpr; + unsigned int ld_gpr; +} used_gpr_t; + + +static int check_if_used(used_gpr_t *gprs, int count, unsigned int gpr) +{ + int i; + for (i = 0; i < count; i++) { + if (gprs[i].gpr == gpr) + return i; + } + return -1; +} + +static char *default_in_names[] = +{ + "IL", + "IR", + "IRL", + "IRR", + "IC", + "ILFE" +}; + +static char *default_out_names[] = +{ + "OL", + "OR", + "ORL", + "ORR", + "OC", + "OLFE" +}; + +int liblo10k1_patch_find_ctl_by_name(liblo10k1_dsp_patch_t *p, char *ctl_name) +{ + int i; + for (i = 0; i < p->ctl_count; i++) + if (strcmp(p->ctl[i].name, ctl_name) == 0) + return i; + return -1; +} + +int liblo10k1_patch_ctl_set_trans(liblo10k1_dsp_patch_t *p, int idx, int trans) +{ + int i; + switch (trans) { + case EMU10K1_GPR_TRANSLATION_NONE: + break; + case EMU10K1_GPR_TRANSLATION_TABLE100: + if (p->ctl[idx].min != 0 && p->ctl[idx].max != 100) + return LD10K1_EF_ERR_TRANSFORM_TRANS; + break; + case EMU10K1_GPR_TRANSLATION_BASS: + case EMU10K1_GPR_TRANSLATION_TREBLE: + if (p->ctl[idx].min != 0 && p->ctl[idx].max != 0xFFFFFFFF) + return LD10K1_EF_ERR_TRANSFORM_TRANS; + if (p->ctl[idx].count != 5) + return LD10K1_EF_ERR_TRANSFORM_TRANS; + break; + case EMU10K1_GPR_TRANSLATION_ONOFF: + if (p->ctl[idx].min != 0 && p->ctl[idx].max != 1) + return LD10K1_EF_ERR_TRANSFORM_TRANS; + break; + } + for (i = 0; i < p->ctl[idx].count; i++) + if (p->ctl[idx].value[i] < p->ctl[idx].min || p->ctl[idx].value[i] > p->ctl[idx].max) + return LD10K1_EF_ERR_TRANSFORM_TRANS; + p->ctl[idx].translation = trans; + return 0; +} + +int liblo10k1_patch_ctl_set_vcount(liblo10k1_dsp_patch_t *p, int idx, int vc) +{ + if (p->ctl[idx].count < vc) + return LD10K1_EF_ERR_TRANSFORM_CTL; + p->ctl[idx].vcount = vc; + return 0; +} + +int liblo10k1_patch_ctl_set_index(liblo10k1_dsp_patch_t *p, int idx, int i) +{ + p->ctl[idx].index = i; + return 0; +} + +int liblo10k1_patch_ctl_set_value(liblo10k1_dsp_patch_t *p, int idx, int vi, int val) +{ + if (p->ctl[idx].count < vi) + return LD10K1_EF_ERR_TRANSFORM_CTL; + if (val < p->ctl[idx].min || val > p->ctl[idx].max) + return LD10K1_EF_ERR_TRANSFORM_CTL; + p->ctl[idx].value[vi] = val; + return 0; +} + +int liblo10k1_emu_transform_patch(liblo10k1_emu_patch_t *ep, liblo10k1_ctl_transform_t *tctl, int tctl_count, liblo10k1_dsp_patch_t **lp) +{ + used_gpr_t used_gpr[0x400]; + int used_gpr_count = 0; + int i, j, k; + int gpr; + int tmp_cnt; + int idx; + int en = 0; + int io_name_map[6]; + int transformed; + liblo10k1_dsp_ctl_t *tmp_nctl; + liblo10k1_emu_ctl_t *tmp_octl; + int const_count, hw_count; /*int ctl_transform_map[256];*/ + liblo10k1_dsp_patch_t *np = NULL; + liblo10k1_emu_tram_t *tram_tmp; + liblo10k1_dsp_tram_acc_t *tram_nacc; + liblo10k1_emu_tram_line_t *tram_line; + int val, addhw, addconst; + + /* for all instruction get used gpr list */ + for (i = 0; i < ep->instr_count; i++) { + for (j = 0; j < 4; j++) { + gpr = ep->instrs[i].arg[j]; + for (k = 0; k < used_gpr_count; k++) + if (gpr == used_gpr[k].gpr) + break; + + if (k < used_gpr_count) + continue; + + used_gpr[used_gpr_count].gpr = gpr; + used_gpr[used_gpr_count].ld_gpr = 0; + used_gpr_count++; + } + } + + np = liblo10k1_patch_alloc(0, 0, 0, 0, 0, 0, 0, 0, 0, ep->instr_count); + if (!np) + return LD10K1_ERR_NO_MEM; + + /* set patch name */ + strcpy(np->patch_name, ep->patch_name); + + /* in gprs */ + tmp_cnt = 0; + for (i = 0; i < ep->in_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->ins[i] + 0x100); + if (idx >= 0) { + used_gpr[idx].ld_gpr = EMU10K1_PREG_IN(tmp_cnt); + if (i < 6) + io_name_map[i] = tmp_cnt; + tmp_cnt++; + } else { + if (i < 6) + io_name_map[i] = -1; + } + } + + if ((en = liblo10k1_patch_set_in_count(np, tmp_cnt)) < 0) + goto err; + + /* set in name */ + if (ep->in_count == 2 || /* stereo */ + ep->in_count == 4 || /* 4 channel */ + ep->in_count == 6) { /* 5.1 */ + for (i = 0; i < ep->in_count; i++) { + if (io_name_map[i] >= 0) + strcpy(np->ins[io_name_map[i]].name, default_in_names[i]); + } + } + + /* out gprs */ + tmp_cnt = 0; + for (i = 0; i < ep->out_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->outs[i] + 0x100); + if (idx >= 0) { + used_gpr[idx].ld_gpr = EMU10K1_PREG_OUT(tmp_cnt); + if (i < 6) + io_name_map[i] = tmp_cnt; + tmp_cnt++; + } else { + if (i < 6) + io_name_map[i] = -1; + } + } + + if ((en = liblo10k1_patch_set_out_count(np, tmp_cnt)) < 0) + goto err; + + /* set out name */ + if (ep->out_count == 2 || /* stereo */ + ep->out_count == 4 || /* 4 channel */ + ep->out_count == 6) { /* 5.1 */ + for (i = 0; i < ep->out_count; i++) { + if (io_name_map[i] >= 0) + strcpy(np->outs[io_name_map[i]].name, default_out_names[i]); + } + } + + /* dyn regs */ + tmp_cnt = 0; + for (i = 0; i < ep->dyn_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->dyns[i] + 0x100); + if (idx >= 0) { + used_gpr[idx].ld_gpr = EMU10K1_PREG_DYN(tmp_cnt); + tmp_cnt++; + } + } + + if ((en = liblo10k1_patch_set_dyn_count(np, tmp_cnt)) < 0) + goto err; + + /* sta regs */ + tmp_cnt = 0; + for (i = 0; i < ep->sta_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->stas[i].sc + 0x100); + if (idx >= 0) { + used_gpr[idx].ld_gpr = EMU10K1_PREG_STA(tmp_cnt); + tmp_cnt++; + } + } + + if ((en = liblo10k1_patch_set_sta_count(np, tmp_cnt)) < 0) + goto err; + + /* sta regs - initilization */ + tmp_cnt = 0; + for (i = 0; i < ep->sta_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->stas[i].sc + 0x100); + if (idx >= 0) { + np->stas[tmp_cnt].const_val = ep->stas[i].sc_val; + tmp_cnt++; + } + } + + /* FIXME - ak je niektoty ctl pouzity v tctl viackrat tak to zblbne */ + /* ctls regs */ + /* first get count of ctls */ + tmp_cnt = 0; + for (i = 0; i < tctl_count; i++) + tmp_cnt += tctl[i].emu_ctl_count; + + if ((en = liblo10k1_patch_set_ctl_count(np, ep->ctl_count - tmp_cnt + tctl_count)) < 0) + goto err; + + tmp_cnt = 0; + for (i = 0; i < ep->ctl_count; i++) { + tmp_octl = &(ep->ctls[i]); + /* find if transformed */ + transformed = 0; + for (j = 0; j < tctl_count; j++) { + for (k = 0; k < tctl[j].emu_ctl_count; k++) { + if (i == tctl[j].emu_ctls[k]) { + /* it is transformed */ + tmp_nctl = &(np->ctl[j]); + if (strcmp(tmp_nctl->name, "") != 0) { + /* initialized - check min, max */ + if (tmp_octl->ctl_val_min != tmp_nctl->min || + tmp_octl->ctl_val_max != tmp_nctl->max) { + en = LD10K1_EF_ERR_TRANSFORM_CTL; + goto err; + } + + tmp_nctl->value[k] = tmp_octl->ctl_val; + } else { + /* initialize it */ + strcpy(tmp_nctl->name, tctl[j].ctl_name); + tmp_nctl->index = -1; + tmp_nctl->vcount = tctl[j].emu_ctl_count;/*1;*/ + tmp_nctl->count = tctl[j].emu_ctl_count;/*1;*/ + tmp_nctl->value[k] = tmp_octl->ctl_val; + tmp_nctl->min = tmp_octl->ctl_val_min; + tmp_nctl->max = tmp_octl->ctl_val_max; + tmp_nctl->translation = EMU10K1_GPR_TRANSLATION_NONE; + } + + idx = check_if_used(used_gpr, used_gpr_count, tmp_octl->ctl + 0x100); + if (idx >= 0) + used_gpr[idx].ld_gpr = EMU10K1_PREG_CTL(j, k); + + transformed = 1; + break; + } + } + if (transformed) + break; + } + + if (transformed) + continue; + /* not transformed */ + tmp_nctl = &(np->ctl[tmp_cnt + tctl_count]); + + strcpy(tmp_nctl->name, tmp_octl->ctl_name); + tmp_nctl->index = -1; + tmp_nctl->vcount = 1; + tmp_nctl->count = 1; + tmp_nctl->value[0] = tmp_octl->ctl_val; + tmp_nctl->min = tmp_octl->ctl_val_min; + tmp_nctl->max = tmp_octl->ctl_val_max; + tmp_nctl->translation = EMU10K1_GPR_TRANSLATION_NONE; + + idx = check_if_used(used_gpr, used_gpr_count, tmp_octl->ctl + 0x100); + if (idx >= 0) + used_gpr[idx].ld_gpr = EMU10K1_PREG_CTL(tmp_cnt + tctl_count, 0); + + tmp_cnt++; + + if (tmp_cnt > np->ctl_count) { + en = LD10K1_EF_ERR_TRANSFORM_CTL; + goto err; + } + } + + if (tmp_cnt + tctl_count < np->ctl_count) { + en = LD10K1_EF_ERR_TRANSFORM_CTL; + goto err; + } + + /* tram */ + if ((en = liblo10k1_patch_set_tram_count(np, ep->tram_lookup_count + ep->tram_delay_count)) < 0) + goto err; + + tmp_cnt = 0; + for (i = 0; i < ep->tram_lookup_count + ep->tram_delay_count; i++) { + if (i < ep->tram_lookup_count) + tram_tmp = &(ep->tram_lookups[i]); + else + tram_tmp = &(ep->tram_delays[i - ep->tram_lookup_count]); + + tmp_cnt += tram_tmp->read_line_count + tram_tmp->write_line_count; + np->tram[i].grp_type = i < ep->tram_lookup_count ? TRAM_GRP_TABLE : TRAM_GRP_DELAY; + np->tram[i].grp_size = tram_tmp->size; + np->tram[i].grp_pos = TRAM_POS_AUTO; + } + + /* tram acc */ + if ((en = liblo10k1_patch_set_tram_acc_count(np, tmp_cnt)) < 0) + goto err; + + tmp_cnt = 0; + for (i = 0; i < ep->tram_lookup_count + ep->tram_delay_count; i++) { + if (i < ep->tram_lookup_count) + tram_tmp = &(ep->tram_lookups[i]); + else + tram_tmp = &(ep->tram_delays[i - ep->tram_lookup_count]); + + for (k = 0; k < 2; k++) { + for (j = 0; j < (k ? tram_tmp->write_line_count : tram_tmp->read_line_count); j++) { + if (k) + tram_line = &(tram_tmp->write_lines[j]); + else + tram_line = &(tram_tmp->read_lines[j]); + + tram_nacc = &(np->tram_acc[tmp_cnt]); + + tram_nacc->grp = i; + tram_nacc->acc_offset = tram_line->line_size; + tram_nacc->acc_type = k ? TRAM_ACC_WRITE : TRAM_ACC_READ; + + idx = check_if_used(used_gpr, used_gpr_count, tram_line->line + 0x200); + if (idx >= 0) + used_gpr[idx].ld_gpr = EMU10K1_PREG_TRAM_DATA(tmp_cnt); + + idx = check_if_used(used_gpr, used_gpr_count, tram_line->line + 0x300); + if (idx >= 0) + used_gpr[idx].ld_gpr = EMU10K1_PREG_TRAM_ADDR(tmp_cnt); + + tmp_cnt++; + } + } + } + + /* const and hw */ + const_count = 0; + hw_count = 0; + + for (i = 0; i < used_gpr_count; i++) { + gpr = used_gpr[i].gpr; + + if (gpr < 0x40) + hw_count++; + else if (gpr < 0x56) + const_count++; + else if (gpr < 0x5C) + hw_count++; + } + + /* const regs */ + tmp_cnt = 0; + for (i = 0; i < ep->con_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->cons[i].sc + 0x100); + if (idx >= 0) { + used_gpr[idx].ld_gpr = EMU10K1_PREG_CONST(tmp_cnt); + tmp_cnt++; + } + } + + /* consts */ + if ((en = liblo10k1_patch_set_const_count(np, const_count + tmp_cnt)) < 0) + goto err; + + const_count = tmp_cnt; + + /* const regs - initilization */ + tmp_cnt = 0; + for (i = 0; i < ep->con_count; i++) { + idx = check_if_used(used_gpr, used_gpr_count, ep->cons[i].sc + 0x100); + if (idx >= 0) { + np->consts[tmp_cnt].const_val = ep->cons[i].sc_val; + tmp_cnt++; + } + } + + /* hw */ + if ((en = liblo10k1_patch_set_hw_count(np, hw_count)) < 0) + goto err; + + hw_count = 0; + for (i = 0; i < used_gpr_count; i++) { + gpr = used_gpr[i].gpr; + addconst = 0; + addhw = 0; + + if (gpr < 0x40) { + /* fx */ + addhw = 1; + if (gpr < 0x10) + val = EMU10K1_REG_FX(gpr); + else if (gpr < 0x20) + val = EMU10K1_REG_IN(gpr - 0x10); + else + val = EMU10K1_REG_OUT(gpr - 0x20); + } else { + switch (gpr) { + case 0x40: + addconst = 1; val = 0x00000000; + break; + case 0x41: + addconst = 1; val = 0x00000001; + break; + case 0x42: + addconst = 1; val = 0x00000002; + break; + case 0x43: + addconst = 1; val = 0x00000003; + break; + case 0x44: + addconst = 1; val = 0x00000004; + break; + case 0x45: + addconst = 1; val = 0x00000008; + break; + case 0x46: + addconst = 1; val = 0x00000010; + break; + case 0x47: + addconst = 1; val = 0x00000020; + break; + case 0x48: + addconst = 1; val = 0x00000100; + break; + case 0x49: + addconst = 1; val = 0x00010000; + break; + case 0x4A: + addconst = 1; val = 0x00080000; + break; + case 0x4B: + addconst = 1; val = 0x10000000; + break; + case 0x4C: + addconst = 1; val = 0x20000000; + break; + case 0x4D: + addconst = 1; val = 0x40000000; + break; + case 0x4E: + addconst = 1; val = 0x80000000; + break; + case 0x4F: + addconst = 1; val = 0x7FFFFFFF; + break; + case 0x50: + addconst = 1; val = 0xFFFFFFFF; + break; + case 0x51: + addconst = 1; val = 0xFFFFFFFE; + break; + case 0x52: + addconst = 1; val = 0xC0000000; + break; + case 0x53: + addconst = 1; val = 0x4F1BBCDC; + break; + case 0x54: + addconst = 1; val = 0x5A7EF9DB; + break; + case 0x55: + addconst = 1; val = 0x00100000; + break; + case 0x56: + addhw = 1; val = EMU10K1_NREG_HW_ACCUM; + break; + case 0x57: + addhw = 1; val = EMU10K1_NREG_HW_CCR; + break; + case 0x58: + addhw = 1; val = EMU10K1_NREG_HW_NOISE1; + break; + case 0x59: + addhw = 1; val = EMU10K1_NREG_HW_NOISE2; + break; + case 0x5A: + addhw = 1; val = EMU10K1_NREG_HW_IRQ; + break; + case 0x5B: + addhw = 1; val = EMU10K1_NREG_HW_DBAC; + break; + default: + if (gpr < 0x100) { + en = LD10K1_EF_ERR_TRANSFORM; + goto err; + } + break; + } + } + + if (addhw) { + np->hws[hw_count].hw_val = val; + used_gpr[i].ld_gpr = EMU10K1_PREG_HW(hw_count); + hw_count++; + } else if (addconst) { + np->consts[const_count].const_val = val; + used_gpr[i].ld_gpr = EMU10K1_PREG_CONST(const_count); + const_count++; + } + } + + /* instrs */ + if ((en = liblo10k1_patch_set_instr_count(np, ep->instr_count)) < 0) + goto err; + + for (i = 0; i < ep->instr_count; i++) { + np->instr[i].op_code = ep->instrs[i].op; + for (j = 0; j < 4; j++) { + gpr = ep->instrs[i].arg[j]; + + idx = check_if_used(used_gpr, used_gpr_count, gpr); + if (!used_gpr[idx].ld_gpr) { + en = LD10K1_EF_ERR_TRANSFORM; + goto err; + } + + np->instr[i].arg[j] = used_gpr[idx].ld_gpr; + } + } + + *lp = np; + return 0; +err: + if (np) + liblo10k1_patch_free(np); + return en; +} + diff --git a/ld10k1/src/liblo10k1lf.c b/ld10k1/src/liblo10k1lf.c new file mode 100644 index 0000000..3cb1ffc --- /dev/null +++ b/ld10k1/src/liblo10k1lf.c @@ -0,0 +1,1388 @@ +/* + * EMU10k1 loader lib + * Copyright (c) 2003,2004 by Peter Zubaj + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include "version.h" +#include "ld10k1.h" +#include "ld10k1_fnc.h" +#include "ld10k1_error.h" +#include "comm.h" +#include "liblo10k1.h" +#include "liblo10k1lf.h" + +#define CREATER_MAJOR LD10K1_LIB_MAJOR +#define CREATER_MINOR LD10K1_LIB_MINOR +#define CREATER_SUBMINOR LD10K1_LIB_SUBMINOR + +#define FILE_MAJOR 0 +#define FILE_MINOR 1 +#define FILE_SUBMINOR 0 + +#define READER_MAJOR 0 +#define READER_MINOR 1 +#define READER_SUBMINOR 7 + +#define LD10K1_FILE_SIGNATURE "LD10K1 NATIVE EFFECT FILE " + +int liblo10k1lf_save_dsp_setup(liblo10k1_file_dsp_setup_t *c, FILE *file); + +int liblo10k1lf_save_file_header(FILE *file, unsigned int ft); +int liblo10k1lf_save_file_info(FILE *file, liblo10k1_file_info_t *fi); +int liblo10k1lf_save_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, void *data); +int liblo10k1lf_find_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part); +int liblo10k1lf_find_part_il(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, int il, liblo10k1_file_part_t *part); + +int liblo10k1lf_save_dsp_config(liblo10k1_file_dsp_setup_t *c, char *file_name, liblo10k1_file_info_t *fi) +{ + FILE *file = NULL; + int err; + + file = fopen(file_name, "w"); + if (!file) + return LD10K1_LF_ERR_OPEN; + + if ((err = liblo10k1lf_save_file_header(file, LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP)) < 0) + goto err; + + if ((err = liblo10k1lf_save_file_info(file, fi)) < 0) + goto err; + + if ((err = liblo10k1lf_save_dsp_setup(c, file)) < 0) + goto err; + + fclose(file); + return 0; +err: + fclose(file); + return err; +} + +int liblo10k1lf_save_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, void *data) +{ + liblo10k1_file_part_t part; + + memset(&part, 0, sizeof(part)); + part.part_type = part_type; + part.part_id = part_id; + part.part_length = part_length; + + if (fwrite(&part, sizeof(liblo10k1_file_part_t), 1, file) != 1) + return LD10K1_LF_ERR_WRITE; + + if (part_length > 0) + if (fwrite(data, part_length, 1, file) != 1) + return LD10K1_LF_ERR_WRITE; + return 0; +} + +int liblo10k1lf_save_file_header(FILE *file, unsigned int ft) +{ + liblo10k1_file_header_t fhdr; + liblo10k1_file_part_info_t file_info; + int err; + + strcpy(fhdr.signature, LD10K1_FILE_SIGNATURE); + memset(fhdr.reserved, 0, sizeof(fhdr.reserved)); + + if (fwrite(&fhdr, sizeof(liblo10k1_file_header_t), 1, file) != 1) + return LD10K1_LF_ERR_WRITE; + + memset(&file_info, 0, sizeof(file_info)); + + file_info.file_type = ft; + + file_info.file_version_major = FILE_MAJOR; + file_info.file_version_minor = FILE_MINOR; + file_info.file_version_subminor = FILE_SUBMINOR; /* file version = 0.0.1 */ + + file_info.minimal_reader_version_major = READER_MAJOR; + file_info.minimal_reader_version_minor = READER_MINOR; + file_info.minimal_reader_version_subminor = READER_SUBMINOR; /* minimal reader version = 0.1.7 */ + + file_info.creater_version_major = CREATER_MAJOR; + file_info.creater_version_minor = CREATER_MINOR; + file_info.creater_version_subminor = CREATER_SUBMINOR; /* creater version = 0.1.7 */ + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_INFO, sizeof(file_info), &file_info)) < 0) + return err; + return 0; +} + +int liblo10k1lf_save_string_info(FILE *file, int id, char *str) +{ + int str_len; + int err; + + if (str) + str_len = strlen(str) + 1; + else + str_len = 0; + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, id, str_len, str)) < 0) + return err; + return 0; +} + +int liblo10k1lf_load_string_info(FILE *file, int id, char **str) +{ + char *tmp; + int err; + liblo10k1_file_part_t part; + + if ((err = liblo10k1lf_find_part_il(file, LD10K1_FP_TYPE_NORMAL, id, 0, 1, &part)) < 0) + return err; + + tmp = NULL; + if (part.part_length > 0) { + tmp = (char *)malloc(part.part_length); + if (!tmp) + return LD10K1_ERR_NO_MEM; + + if (fread(tmp, part.part_length, 1, file) != 1) { + free(tmp); + return LD10K1_LF_ERR_READ; + } + } + + if (*str) + free(*str); + *str = tmp; + return 0; +} + +int liblo10k1lf_save_file_info(FILE *file, liblo10k1_file_info_t *fi) +{ + int err; + + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_NAME, fi->name)) < 0) + return err; + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_DESC, fi->desc)) < 0) + return err; + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_CREATER, fi->creater)) < 0) + return err; + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_AUTHOR, fi->author)) < 0) + return err; + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_COPYRIGHT, fi->copyright)) < 0) + return err; + if ((err = liblo10k1lf_save_string_info(file, LD10K1_FP_FILE_INFO_LICENCE, fi->license)) < 0) + return err; + return 0; +} + +int liblo10k1lf_load_file_info(FILE *file, liblo10k1_file_info_t **fi) +{ + int err; + + liblo10k1_file_info_t *i = liblo10k1lf_file_info_alloc(); + + if (!i) + return LD10K1_ERR_NO_MEM; + + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_NAME, &(i->name))) < 0) + goto err; + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_DESC, &(i->desc))) < 0) + goto err; + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_CREATER, &(i->creater))) < 0) + goto err; + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_AUTHOR, &(i->author))) < 0) + goto err; + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_COPYRIGHT, &(i->copyright))) < 0) + goto err; + if ((err = liblo10k1lf_load_string_info(file, LD10K1_FP_FILE_INFO_LICENCE, &(i->license))) < 0) + goto err; + + *fi = i; + return 0; +err: + if (i) + liblo10k1lf_file_info_free(i); + return err; +} + +int liblo10k1lf_save_io(liblo10k1_get_io_t *ios, int count, int ptl, int pt, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_get_io_t), &(ios[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_pio(liblo10k1_dsp_pio_t *ios, int count, int ptl, int pt, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_dsp_pio_t), &(ios[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_cs(liblo10k1_dsp_cs_t *css, int count, int ptl, int pt, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, ptl, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, pt, sizeof(liblo10k1_dsp_cs_t), &(css[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, ptl, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_hw(liblo10k1_dsp_hw_t *hws, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_HW_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_HW, sizeof(liblo10k1_dsp_hw_t), &(hws[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_HW_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_tram(liblo10k1_dsp_tram_grp_t *trams, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_TRAM_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_TRAM, sizeof(liblo10k1_dsp_tram_grp_t), &(trams[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_TRAM_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_tram_acc(liblo10k1_dsp_tram_acc_t *tram_accs, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_TRAM_ACC_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_TRAM_ACC, sizeof(liblo10k1_dsp_tram_acc_t), &(tram_accs[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_TRAM_ACC_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_ctl(liblo10k1_dsp_ctl_t *ctls, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_CTL_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_CTL, sizeof(liblo10k1_dsp_ctl_t), &(ctls[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_CTL_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_instr(liblo10k1_dsp_instr_t *instrs, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_INSTR_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_INSTR, sizeof(liblo10k1_dsp_instr_t), &(instrs[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_INSTR_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_points(liblo10k1_point_info_t *points, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_POINT_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_POINT, sizeof(liblo10k1_point_info_t), &(points[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_POINT_LIST, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_patch(liblo10k1_dsp_patch_t *p, FILE *file) +{ + int err; + liblo10k1_file_patch_info_t pinfo; + + /* io list start */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_PATCH, 0, NULL)) < 0) + return err; + + /* patch info */ + strcpy(pinfo.patch_name, p->patch_name); + pinfo.in_count = p->in_count; + pinfo.out_count = p->out_count; + pinfo.const_count = p->const_count; + pinfo.sta_count = p->sta_count; + pinfo.dyn_count = p->dyn_count; + pinfo.hw_count = p->hw_count; + pinfo.tram_count = p->tram_count; + pinfo.tram_acc_count = p->tram_acc_count; + pinfo.ctl_count = p->ctl_count; + pinfo.instr_count = p->instr_count; + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_PATCH_INFO, sizeof(liblo10k1_file_patch_info_t), &pinfo)) < 0) + return err; + + /* pins */ + if ((err = liblo10k1lf_save_pio(p->ins, p->in_count, LD10K1_FP_PIN_LIST, LD10K1_FP_PIO, file)) < 0) + return err; + /* pouts */ + if ((err = liblo10k1lf_save_pio(p->outs, p->out_count, LD10K1_FP_POUT_LIST, LD10K1_FP_PIO, file)) < 0) + return err; + /* consts */ + if ((err = liblo10k1lf_save_cs(p->consts, p->const_count, LD10K1_FP_CONST_LIST, LD10K1_FP_CS, file)) < 0) + return err; + /* stas */ + if ((err = liblo10k1lf_save_cs(p->stas, p->sta_count, LD10K1_FP_STA_LIST, LD10K1_FP_CS, file)) < 0) + return err; + /* hws */ + if ((err = liblo10k1lf_save_hw(p->hws, p->hw_count, file)) < 0) + return err; + /* trams */ + if ((err = liblo10k1lf_save_tram(p->tram, p->tram_count, file)) < 0) + return err; + /* tram_accs */ + if ((err = liblo10k1lf_save_tram_acc(p->tram_acc, p->tram_acc_count, file)) < 0) + return err; + /* ctls */ + if ((err = liblo10k1lf_save_ctl(p->ctl, p->ctl_count, file)) < 0) + return err; + /* instrs */ + if ((err = liblo10k1lf_save_instr(p->instr, p->instr_count, file)) < 0) + return err; + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_PATCH, 0, NULL)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_save_dsp_setup(liblo10k1_file_dsp_setup_t *c, FILE *file) +{ + liblo10k1_file_part_dsp_setup_t setup; + int err; + int i; + + setup.dsp_type = c->dsp_type; + setup.fx_count = c->fx_count; + setup.in_count = c->in_count; + setup.out_count = c->out_count; + setup.patch_count = c->patch_count; + setup.point_count = c->point_count; + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_NORMAL, LD10K1_FP_DSP_SETUP, sizeof(setup), &setup)) < 0) + return err; + + /* save fx */ + if ((err = liblo10k1lf_save_io(c->fxs, c->fx_count, LD10K1_FP_FX_LIST, LD10K1_FP_FX, file)) < 0) + return err; + + /* save in */ + if ((err = liblo10k1lf_save_io(c->ins, c->in_count, LD10K1_FP_IN_LIST, LD10K1_FP_IN, file)) < 0) + return err; + + /* save out */ + if ((err = liblo10k1lf_save_io(c->outs, c->out_count, LD10K1_FP_OUT_LIST, LD10K1_FP_OUT, file)) < 0) + return err; + + /* save patches */ + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_START, LD10K1_FP_PATCH_LIST, 0, NULL)) < 0) + return err; + + for (i = 0; i < c->patch_count; i++) { + if ((err = liblo10k1lf_save_patch(c->patches[i], file)) < 0) + return err; + } + + if ((err = liblo10k1lf_save_part(file, LD10K1_FP_TYPE_END, LD10K1_FP_PATCH_LIST, 0, NULL)) < 0) + return err; + + /* save points */ + if ((err = liblo10k1lf_save_points(c->points, c->point_count, file)) < 0) + return err; + + return 0; +} + +liblo10k1_file_dsp_setup_t *liblo10k1lf_dsp_config_alloc() +{ + liblo10k1_file_dsp_setup_t *tmp = (liblo10k1_file_dsp_setup_t *)malloc(sizeof(liblo10k1_file_dsp_setup_t)); + + memset(tmp, 0, sizeof(liblo10k1_file_dsp_setup_t)); + + return tmp; +} + +void liblo10k1lf_dsp_config_free(liblo10k1_file_dsp_setup_t *c) +{ + int i; + + if (c->fxs) + free(c->fxs); + if (c->ins) + free(c->ins); + if (c->outs) + free(c->outs); + if (c->patches) { + for (i = 0; i < c->patch_count; i++) { + if (c->patches[i]) + liblo10k1_patch_free(c->patches[i]); + } + free(c->patches); + } + if (c->points) + free(c->points); +} + +int liblo10k1lf_dsp_config_set_fx_count(liblo10k1_file_dsp_setup_t *c, int count) +{ + liblo10k1_get_io_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + } + + if (c->fxs) + free(c->fxs); + + c->fx_count = count; + c->fxs = tmp; + return 0; +} + +int liblo10k1lf_dsp_config_set_in_count(liblo10k1_file_dsp_setup_t *c, int count) +{ + liblo10k1_get_io_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + } + + if (c->ins) + free(c->ins); + + c->in_count = count; + c->ins = tmp; + return 0; +} + +int liblo10k1lf_dsp_config_set_out_count(liblo10k1_file_dsp_setup_t *c, int count) +{ + liblo10k1_get_io_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_get_io_t *)malloc(sizeof(liblo10k1_get_io_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + } + + if (c->outs) + free(c->outs); + + c->out_count = count; + c->outs = tmp; + return 0; +} + +int liblo10k1lf_dsp_config_set_patch_count(liblo10k1_file_dsp_setup_t *c, int count) +{ + int i; + /* alloc patches list */ + liblo10k1_dsp_patch_t **tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_dsp_patch_t **)malloc(sizeof(liblo10k1_dsp_patch_t *) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + + memset(tmp, 0, sizeof(liblo10k1_dsp_patch_t *) * count); + } + + if (c->patches) { + for (i = 0; i < c->patch_count; i++) { + if (c->patches[i]) + liblo10k1_patch_free(c->patches[i]); + } + free(c->patches); + } + + c->patch_count = count; + c->patches = tmp; + return 0; +} + +int liblo10k1lf_dsp_config_set_point_count(liblo10k1_file_dsp_setup_t *c, int count) +{ + liblo10k1_point_info_t *tmp = NULL; + + if (count > 0) { + tmp = (liblo10k1_point_info_t *)malloc(sizeof(liblo10k1_point_info_t) * count); + if (!tmp) + return LD10K1_ERR_NO_MEM; + + memset(tmp, 0, sizeof(liblo10k1_point_info_t) * count); + } + + if (c->points) + free(c->points); + + c->point_count = count; + c->points = tmp; + return 0; +} + +int liblo10k1lf_get_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t **setup) +{ + liblo10k1_dsp_info_t info; + int err; + int i, j, k; + + liblo10k1_file_dsp_setup_t *s; + liblo10k1_patches_info_t *plist; + int pcount; + int tmp; + + int *points; + + plist = NULL; + points = NULL; + s = liblo10k1lf_dsp_config_alloc(); + if (!s) + return LD10K1_ERR_NO_MEM; + + /* get dsp type */ + if ((err = liblo10k1_get_dsp_info(conn, &info)) < 0) + return err; + + s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K1; + if (info.chip_type == CHIP_LIVE) + s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K1; + else if (info.chip_type == CHIP_AUDIGY) + s->dsp_type = LD10K1_FP_INFO_DSP_TYPE_EMU10K2; + + /* now get everything what is needed */ + if ((err = liblo10k1_get_fx_count(conn, &tmp)) < 0) + goto err; + + if ((err = liblo10k1lf_dsp_config_set_fx_count(s, tmp)) < 0) + goto err; + + for (i = 0; i < s->fx_count; i++) { + if ((err = liblo10k1_get_fx(conn, i, &(s->fxs[i]))) < 0) + goto err; + } + + if ((err = liblo10k1_get_in_count(conn, &tmp)) < 0) + goto err; + + if ((err = liblo10k1lf_dsp_config_set_in_count(s, tmp)) < 0) + goto err; + + for (i = 0; i < s->in_count; i++) { + if ((err = liblo10k1_get_in(conn, i, &(s->ins[i]))) < 0) + goto err; + } + + if ((err = liblo10k1_get_out_count(conn, &tmp)) < 0) + goto err; + + if ((err = liblo10k1lf_dsp_config_set_out_count(s, tmp)) < 0) + goto err; + + for (i = 0; i < s->out_count; i++) { + if ((err = liblo10k1_get_out(conn, i, &(s->outs[i]))) < 0) + goto err; + } + + if ((err = liblo10k1_get_patches_info(conn, &plist, &pcount)) < 0) + goto err; + + /* alloc patches list */ + if ((err = liblo10k1lf_dsp_config_set_patch_count(s, pcount)) < 0) + goto err; + + for (i = 0; i < s->patch_count; i++) { + if ((err = liblo10k1_patch_get(conn, plist[i].patch_num, &(s->patches[i]))) < 0) + goto err; + } + + if ((err = liblo10k1_get_points_info(conn, &points, &pcount)) < 0) + goto err; + + if ((err = liblo10k1lf_dsp_config_set_point_count(s, pcount)) < 0) + goto err; + + for (i = 0; i < s->point_count; i++) { + if ((err = liblo10k1_get_point_info(conn, points[i], &(s->points[i]))) < 0) + goto err; + + /* id to patch index */ + for (j = 0; j < s->points[i].conn_count;j++) { + if (s->points[i].patch[j] >= 0) { + for (k = 0; k < s->patch_count; k++) { + if (plist[k].id == s->points[i].patch[j]) { + s->points[i].patch[j] = k; + break; + } + } + + if (s->points[i].patch[j] != k) { + err = LD10K1_ERR_UNKNOWN_PATCH_NUM; + goto err; + } + } + } + } + + free(plist); + free(points); + + *setup = s; + return 0; +err: + if (plist) + free(plist); + if (points) + free(points); + + liblo10k1lf_dsp_config_free(s); + return err; +} + +int liblo10k1lf_put_dsp_config(liblo10k1_connection_t *conn, liblo10k1_file_dsp_setup_t *setup) +{ + int err; + int i, j; + int loaded_id; + int loaded; + int *trans_nums; + + int tin_type, tout_type; + int tin, tout; + int tpin, tpout; + + int pnum; + + tin_type = 0; + tout_type = 0; + tin = 0; + tout = 0; + tpin = 0; + tpout = 0; + + /* first initialize dsp */ + if ((err = liblo10k1_dsp_init(conn)) < 0) + return err; + + for (i = 0; i < setup->fx_count; i++) { + if ((err = liblo10k1_rename_fx(conn, i, setup->fxs[i].name)) < 0) + return err; + } + + for (i = 0; i < setup->in_count; i++) { + if ((err = liblo10k1_rename_in(conn, i, setup->ins[i].name)) < 0) + return err; + } + + for (i = 0; i < setup->out_count; i++) { + if ((err = liblo10k1_rename_out(conn, i, setup->outs[i].name)) < 0) + return err; + } + + if (setup->patch_count <= 0) + return 0; + + trans_nums = (int *)malloc(sizeof(int) * setup->patch_count); + if (!trans_nums) + return LD10K1_ERR_NO_MEM; + + memset(trans_nums, 0, sizeof(int) * setup->patch_count); + + /* load all patches - remember ids */ + for (i = 0; i < setup->patch_count; i++) { + if ((err = liblo10k1_patch_load(conn, setup->patches[i], -1, &loaded, &loaded_id)) < 0) + goto err; + trans_nums[i] = loaded; + } + + /* connect all connections */ + for (i = 0; i < setup->point_count; i++) { + if (setup->points[i].type == CON_IO_NORMAL) { + /* find first pin */ + for (j = 0; j < setup->points[i].conn_count;j++) + if (!setup->points[i].io_type[j]) { + tin_type = CON_IO_PIN; + tin = setup->points[i].io[j]; + tpin = setup->points[i].patch[j]; + if (tpin >= 0) + tpin = trans_nums[tpin]; + break; + } + + /* find first pout */ + for (j = 0; j < setup->points[i].conn_count;j++) + if (setup->points[i].io_type[j]) { + tout_type = CON_IO_POUT; + tout = setup->points[i].io[j]; + tpout = setup->points[i].patch[j]; + if (tpout >= 0) + tpout = trans_nums[tpout]; + break; + } + + for (j = 0; j < setup->points[i].conn_count; j++) { + pnum = setup->points[i].patch[j]; + if (pnum >= 0) + pnum = trans_nums[pnum]; + if (!setup->points[i].io_type[j]) { + if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi, + setup->points[i].simple, CON_IO_PIN, pnum, setup->points[i].io[j], + tout_type, tpout, tout, NULL)) < 0) + goto err; + } else { + if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi, + setup->points[i].simple, CON_IO_POUT, pnum, setup->points[i].io[j], + tin_type, tpin, tin, NULL)) < 0) + goto err; + } + } + } else { + tin_type = tout_type = setup->points[i].type; + tin = tout = setup->points[i].io_idx; + tpin = tpout = -1; + + for (j = 0; j < setup->points[i].conn_count; j++) { + pnum = setup->points[i].patch[j]; + if (pnum >= 0) + pnum = trans_nums[pnum]; + if ((err = liblo10k1_con_add(conn, j == 0 ? 0 : setup->points[i].multi, + setup->points[i].simple, setup->points[i].io_type[j] ? CON_IO_POUT : CON_IO_PIN, pnum, setup->points[i].io[j], + tin_type, tpin, tin, NULL)) < 0) + goto err; + } + } + } + + return 0; +err: + if (trans_nums) + free(trans_nums); + return err; +} + +int liblo10k1lf_skip_part(FILE *file, liblo10k1_file_part_t *part) +{ + char tmp_char; + int i; + int err; + int found_end_part = 0; + + if (part->part_type == LD10K1_FP_TYPE_NORMAL) { + /* read all data */ + for (i = 0; i < part->part_length; i++) + if (fread(&tmp_char, 1, 1, file) != 1) + return LD10K1_LF_ERR_READ; + } else if (part->part_type == LD10K1_FP_TYPE_END) { + return 0; + } else { + while (!found_end_part) { + /* read next part */ + if (fread(part, sizeof(liblo10k1_file_part_t), 1, file) != 1) + return LD10K1_LF_ERR_READ; + + /* check type & id */ + if (part->part_type == LD10K1_FP_TYPE_END) + found_end_part = 1; + else { + if ((err = liblo10k1lf_skip_part(file, part)) < 0) + return err; + } + } + } + return 0; +} + +int liblo10k1lf_find_part_il(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, int il, liblo10k1_file_part_t *part) +{ + int err; + while (1) { + if (fread(part, sizeof(liblo10k1_file_part_t), 1, file) != 1) + return LD10K1_LF_ERR_READ; + + /* check type & id */ + if (part->part_type == part_type && part->part_id == part_id) { + if (part->part_type == LD10K1_FP_TYPE_NORMAL) { + if (il || part->part_length == part_length) + return 0; + else + return LD10K1_LF_ERR_PART_SIZE; + } else { + if (part->part_length != 0) + return LD10K1_LF_ERR_PART_SIZE; + else + return 0; + } + } else { + if ((err = liblo10k1lf_skip_part(file, part)) < 0) + return err; + } + } +} + +int liblo10k1lf_find_part(FILE *file, unsigned int part_type, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part) +{ + return liblo10k1lf_find_part_il(file, part_type, part_id, part_length, 0, part); +} + +int liblo10k1lf_find_part_ws(FILE *file, unsigned int part_id, unsigned int part_length, liblo10k1_file_part_t *part) +{ + return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_NORMAL, part_id, part_length, part); +} + +int liblo10k1lf_find_part_start(FILE *file, unsigned int part_id) +{ + liblo10k1_file_part_t part; + return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_START, part_id, 0, &part); +} + +int liblo10k1lf_find_part_end(FILE *file, unsigned int part_id) +{ + liblo10k1_file_part_t part; + return liblo10k1lf_find_part(file, LD10K1_FP_TYPE_END, part_id, 0, &part); +} + +int liblo10k1lf_find_load_part_ws(FILE *file, unsigned int part_id, unsigned int part_length, void *where) +{ + int err; + liblo10k1_file_part_t part; + + if ((err = liblo10k1lf_find_part_ws(file, part_id, part_length, &part)) < 0) + return err; + + if (fread(where, part_length, 1, file) != 1) + return LD10K1_LF_ERR_READ; + + return 0; +} + +int liblo10k1lf_can_load_file(FILE *file, unsigned int ft) +{ + liblo10k1_file_header_t fhdr; + liblo10k1_file_part_info_t file_info; + int err; + + if (fread(&fhdr, sizeof(liblo10k1_file_header_t), 1, file) != 1) + return LD10K1_LF_ERR_READ; + + /* check signature */ + if (strcmp(fhdr.signature, LD10K1_FILE_SIGNATURE) != 0) + return LD10K1_LF_ERR_SIGNATURE; + + /* now load file info part & check version */ + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_INFO, sizeof(file_info), &file_info)) < 0) + return err; + + if (file_info.minimal_reader_version_major > CREATER_MAJOR) + return LD10K1_LF_ERR_VERSION; + + if (file_info.minimal_reader_version_major == CREATER_MAJOR && + file_info.minimal_reader_version_minor > CREATER_MINOR) + return LD10K1_LF_ERR_VERSION; + + if (file_info.minimal_reader_version_major == CREATER_MAJOR && + file_info.minimal_reader_version_minor == CREATER_MINOR && + file_info.minimal_reader_version_subminor > CREATER_SUBMINOR) + return LD10K1_LF_ERR_VERSION; + + /* check file type */ + if (file_info.file_type != ft) + return LD10K1_LF_ERR_FILE_TYPE; + + return 0; +} + +int liblo10k1lf_load_io(liblo10k1_get_io_t *ios, int count, int ptl, int pt, FILE *file) +{ + int i, err; + + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, pt, sizeof(liblo10k1_get_io_t), &(ios[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_points(liblo10k1_point_info_t *points, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_POINT_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_POINT, sizeof(liblo10k1_point_info_t), &(points[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_POINT_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_pio(liblo10k1_dsp_pio_t *ios, int count, int ptl, int pt, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, pt, sizeof(liblo10k1_dsp_pio_t), &(ios[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_cs(liblo10k1_dsp_cs_t *css, int count, int ptl, int pt, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, ptl)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, pt, sizeof(liblo10k1_dsp_cs_t), &(css[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, ptl)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_hw(liblo10k1_dsp_hw_t *hws, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_HW_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_HW, sizeof(liblo10k1_dsp_hw_t), &(hws[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_HW_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_tram(liblo10k1_dsp_tram_grp_t *trams, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_TRAM_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_TRAM, sizeof(liblo10k1_dsp_tram_grp_t), &(trams[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_TRAM_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_tram_acc(liblo10k1_dsp_tram_acc_t *tram_accs, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_TRAM_ACC_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_TRAM_ACC, sizeof(liblo10k1_dsp_tram_acc_t), &(tram_accs[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_TRAM_ACC_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_ctl(liblo10k1_dsp_ctl_t *ctls, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_CTL_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_CTL, sizeof(liblo10k1_dsp_ctl_t), &(ctls[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_CTL_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_instr(liblo10k1_dsp_instr_t *instrs, int count, FILE *file) +{ + int i, err; + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_INSTR_LIST)) < 0) + return err; + + for (i = 0; i < count; i++) { + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_INSTR, sizeof(liblo10k1_dsp_instr_t), &(instrs[i]))) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_INSTR_LIST)) < 0) + return err; + + return 0; +} + +int liblo10k1lf_load_patch(liblo10k1_dsp_patch_t **p, FILE *file) +{ + int err; + liblo10k1_file_patch_info_t pinfo; + liblo10k1_dsp_patch_t *patch = NULL; + + /* io list start */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_PATCH)) < 0) + return err; + + /* patch info */ + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_PATCH_INFO, sizeof(liblo10k1_file_patch_info_t), &pinfo)) < 0) + return err; + + patch = liblo10k1_patch_alloc(pinfo.in_count, pinfo.out_count, pinfo.const_count, pinfo.sta_count, pinfo.dyn_count, + pinfo.hw_count, pinfo.tram_count, pinfo.tram_acc_count, pinfo.ctl_count, pinfo.instr_count); + if (!patch) { + err = LD10K1_ERR_NO_MEM; + goto err; + } + + strcpy(patch->patch_name, pinfo.patch_name); + + /* pins */ + if ((err = liblo10k1lf_load_pio(patch->ins, patch->in_count, LD10K1_FP_PIN_LIST, LD10K1_FP_PIO, file)) < 0) + return err; + /* pouts */ + if ((err = liblo10k1lf_load_pio(patch->outs, patch->out_count, LD10K1_FP_POUT_LIST, LD10K1_FP_PIO, file)) < 0) + return err; + /* consts */ + if ((err = liblo10k1lf_load_cs(patch->consts, patch->const_count, LD10K1_FP_CONST_LIST, LD10K1_FP_CS, file)) < 0) + return err; + /* stas */ + if ((err = liblo10k1lf_load_cs(patch->stas, patch->sta_count, LD10K1_FP_STA_LIST, LD10K1_FP_CS, file)) < 0) + return err; + /* hws */ + if ((err = liblo10k1lf_load_hw(patch->hws, patch->hw_count, file)) < 0) + return err; + /* trams */ + if ((err = liblo10k1lf_load_tram(patch->tram, patch->tram_count, file)) < 0) + return err; + /* tram_accs */ + if ((err = liblo10k1lf_load_tram_acc(patch->tram_acc, patch->tram_acc_count, file)) < 0) + return err; + /* ctls */ + if ((err = liblo10k1lf_load_ctl(patch->ctl, patch->ctl_count, file)) < 0) + return err; + /* instrs */ + if ((err = liblo10k1lf_load_instr(patch->instr, patch->instr_count, file)) < 0) + return err; + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_PATCH)) < 0) + return err; + + *p = patch; + return 0; +err: + if (patch) + liblo10k1_patch_free(patch); + return err; +} + +int liblo10k1lf_load_dsp_setup(liblo10k1_file_dsp_setup_t **c, FILE *file) +{ + liblo10k1_file_part_dsp_setup_t setup; + int err; + int i; + + liblo10k1_file_dsp_setup_t *cfg; + + if ((err = liblo10k1lf_find_load_part_ws(file, LD10K1_FP_DSP_SETUP, sizeof(setup), &setup)) < 0) + return err; + + cfg = liblo10k1lf_dsp_config_alloc(); + + cfg->dsp_type = setup.dsp_type; + + /* alloc space */ + if ((err = liblo10k1lf_dsp_config_set_fx_count(cfg, setup.fx_count)) < 0) + goto err; + if ((err = liblo10k1lf_dsp_config_set_in_count(cfg, setup.in_count)) < 0) + goto err; + if ((err = liblo10k1lf_dsp_config_set_out_count(cfg, setup.out_count)) < 0) + goto err; + if ((err = liblo10k1lf_dsp_config_set_patch_count(cfg, setup.patch_count)) < 0) + goto err; + if ((err = liblo10k1lf_dsp_config_set_point_count(cfg, setup.point_count)) < 0) + goto err; + + /* load fx */ + if ((err = liblo10k1lf_load_io(cfg->fxs, cfg->fx_count, LD10K1_FP_FX_LIST, LD10K1_FP_FX, file)) < 0) + return err; + + /* load in */ + if ((err = liblo10k1lf_load_io(cfg->ins, cfg->in_count, LD10K1_FP_IN_LIST, LD10K1_FP_IN, file)) < 0) + return err; + + /* load out */ + if ((err = liblo10k1lf_load_io(cfg->outs, cfg->out_count, LD10K1_FP_OUT_LIST, LD10K1_FP_OUT, file)) < 0) + return err; + + /* load patches */ + if ((err = liblo10k1lf_find_part_start(file, LD10K1_FP_PATCH_LIST)) < 0) + return err; + + for (i = 0; i < cfg->patch_count; i++) { + if ((err = liblo10k1lf_load_patch(&(cfg->patches[i]), file)) < 0) + return err; + } + + if ((err = liblo10k1lf_find_part_end(file, LD10K1_FP_PATCH_LIST)) < 0) + return err; + + + /* load points */ + if ((err = liblo10k1lf_load_points(cfg->points, cfg->point_count, file)) < 0) + return err; + + *c = cfg; + return 0; +err: + if (cfg) + liblo10k1lf_dsp_config_free(cfg); + return err; +} + +int liblo10k1lf_load_dsp_config(liblo10k1_file_dsp_setup_t **c, char *file_name, liblo10k1_file_info_t **fi) +{ + FILE *file = NULL; + int err; + + liblo10k1_file_info_t *i = NULL; + + file = fopen(file_name, "r"); + if (!file) + return LD10K1_LF_ERR_OPEN; + + if ((err = liblo10k1lf_can_load_file(file, LD10K1_FP_INFO_FILE_TYPE_DSP_SETUP)) < 0) + goto err; + + if ((err = liblo10k1lf_load_file_info(file, &i)) < 0) + goto err; + + if ((err = liblo10k1lf_load_dsp_setup(c, file)) < 0) + goto err; + + *fi = i; + fclose(file); + return 0; +err: + if (i) + liblo10k1lf_file_info_free(i); + fclose(file); + return err; +} + +liblo10k1_file_info_t *liblo10k1lf_file_info_alloc() +{ + liblo10k1_file_info_t *tmp = (liblo10k1_file_info_t *)malloc(sizeof(liblo10k1_file_info_t)); + if (tmp) + memset(tmp, 0, sizeof(liblo10k1_file_info_t)); + return tmp; +} + +void liblo10k1lf_file_info_free(liblo10k1_file_info_t *fi) +{ + if (fi->name) + free(fi->name); + if (fi->desc) + free(fi->desc); + if (fi->creater) + free(fi->creater); + if (fi->author) + free(fi->author); + if (fi->copyright) + free(fi->copyright); + if (fi->license) + free(fi->license); +} + +int liblo10k1lf_save_dsp_patch(liblo10k1_dsp_patch_t *p, char *file_name, liblo10k1_file_info_t *fi) +{ + FILE *file = NULL; + int err; + + file = fopen(file_name, "w"); + if (!file) + return LD10K1_LF_ERR_OPEN; + + if ((err = liblo10k1lf_save_file_header(file, LD10K1_FP_INFO_FILE_TYPE_PATCH)) < 0) + goto err; + + if ((err = liblo10k1lf_save_file_info(file, fi)) < 0) + goto err; + + if ((err = liblo10k1lf_save_patch(p, file)) < 0) + goto err; + + fclose(file); + return 0; +err: + fclose(file); + return err; +} + +int liblo10k1lf_load_dsp_patch(liblo10k1_dsp_patch_t **p, char *file_name, liblo10k1_file_info_t **fi) +{ + FILE *file = NULL; + int err; + + liblo10k1_file_info_t *i = NULL; + + file = fopen(file_name, "r"); + if (!file) + return LD10K1_LF_ERR_OPEN; + + if ((err = liblo10k1lf_can_load_file(file, LD10K1_FP_INFO_FILE_TYPE_PATCH)) < 0) + goto err; + + if ((err = liblo10k1lf_load_file_info(file, &i)) < 0) + goto err; + + if ((err = liblo10k1lf_load_patch(p, file)) < 0) + goto err; + + *fi = i; + fclose(file); + return 0; +err: + if (i) + liblo10k1lf_file_info_free(i); + fclose(file); + return err; +} diff --git a/ld10k1/src/lo10k1.c b/ld10k1/src/lo10k1.c new file mode 100644 index 0000000..a52945d --- /dev/null +++ b/ld10k1/src/lo10k1.c @@ -0,0 +1,1737 @@ +/* + * EMU10k1 loader + * + * Copyright (c) 2003,2004 by Peter Zubaj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#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; +}