Input SDL plugin. Compile and run on the OpenPandora. Include config for Pandora...
authorptitSeb <sebastien.chev@gmail.com>
Tue, 24 Sep 2013 19:34:56 +0000 (21:34 +0200)
committerptitSeb <sebastien.chev@gmail.com>
Tue, 24 Sep 2013 19:34:56 +0000 (21:34 +0200)
21 files changed:
source/mupen64plus-input-sdl/AUTHORS [new file with mode: 0644]
source/mupen64plus-input-sdl/COPYING [new file with mode: 0644]
source/mupen64plus-input-sdl/INSTALL [new file with mode: 0644]
source/mupen64plus-input-sdl/LICENSES [new file with mode: 0644]
source/mupen64plus-input-sdl/README [new file with mode: 0644]
source/mupen64plus-input-sdl/RELEASE [new file with mode: 0644]
source/mupen64plus-input-sdl/data/InputAutoCfg.ini [new file with mode: 0644]
source/mupen64plus-input-sdl/projects/msvc11/mupen64plus-input-sdl.vcxproj [new file with mode: 0644]
source/mupen64plus-input-sdl/projects/msvc8/mupen64plus-input-sdl.vcproj [new file with mode: 0644]
source/mupen64plus-input-sdl/projects/unix/Makefile [new file with mode: 0755]
source/mupen64plus-input-sdl/src/autoconfig.c [new file with mode: 0644]
source/mupen64plus-input-sdl/src/autoconfig.h [new file with mode: 0644]
source/mupen64plus-input-sdl/src/config.c [new file with mode: 0644]
source/mupen64plus-input-sdl/src/config.h [new file with mode: 0644]
source/mupen64plus-input-sdl/src/osal_dynamiclib.h [new file with mode: 0644]
source/mupen64plus-input-sdl/src/osal_dynamiclib_unix.c [new file with mode: 0644]
source/mupen64plus-input-sdl/src/osal_dynamiclib_win32.c [new file with mode: 0644]
source/mupen64plus-input-sdl/src/osal_preproc.h [new file with mode: 0644]
source/mupen64plus-input-sdl/src/plugin.c [new file with mode: 0644]
source/mupen64plus-input-sdl/src/plugin.h [new file with mode: 0644]
source/mupen64plus-input-sdl/src/version.h [new file with mode: 0644]

diff --git a/source/mupen64plus-input-sdl/AUTHORS b/source/mupen64plus-input-sdl/AUTHORS
new file mode 100644 (file)
index 0000000..afcbe3e
--- /dev/null
@@ -0,0 +1,4 @@
+Original author: Gregor Anich <blight>
+
+Subsequent authors: many people from the Mupen64Plus team have worked on this code.
+
diff --git a/source/mupen64plus-input-sdl/COPYING b/source/mupen64plus-input-sdl/COPYING
new file mode 100644 (file)
index 0000000..60549be
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/source/mupen64plus-input-sdl/INSTALL b/source/mupen64plus-input-sdl/INSTALL
new file mode 100644 (file)
index 0000000..9319528
--- /dev/null
@@ -0,0 +1,26 @@
+Mupen64Plus-Input-SDL INSTALL
+-----------------------------
+
+This text file was written to explain the installation process of the
+Mupen64Plus-Input-SDL module.
+
+If this module is part of a Mupen64Plus source code bundle, the user should run
+the "m64p_install.sh" script in the root of the unzipped bundle to install all
+of the included modules in the bundle.
+
+If this module is a standalone source code release, you should build the library
+from source code and install it via the makefile, like this:
+
+$ cd projects/unix
+$ make all
+$ sudo make install
+
+If you want to build the Mupen64Plus-Input-SDL module for installation in a
+home folder for a single user, you may build it like this (replacing
+<my-folder> with your desired local installation path):
+
+$ cd projects/unix
+$ make all
+$ make install LIBDIR=<my-folder>
+
+
diff --git a/source/mupen64plus-input-sdl/LICENSES b/source/mupen64plus-input-sdl/LICENSES
new file mode 100644 (file)
index 0000000..0d30700
--- /dev/null
@@ -0,0 +1,369 @@
+Mupen64Plus-input-sdl LICENSE
+-----------------------------
+
+Mupen64Plus-input-sdl is licensed under the GNU General Public License version 2.
+
+The authors of Mupen64Plus-input-sdl are:
+  * Richard Goedeken (Richard42)
+  * Sven Eckelmann (ecsv)
+  * John Chadwick (NMN)
+  * James Hood (Ebenblues)
+  * Scott Gorman (okaygo)
+  * Scott Knauert (Tillin9)
+  * Jesse Dean (DarkJezter)
+  * Louai Al-Khanji (slougi)
+  * Bob Forder (orbitaldecay)
+  * Jason Espinosa (hasone)
+  * HyperHacker
+  * and others.
+
+Mupen64Plus is based on GPL-licensed source code from Mupen64 v0.5, originally written by:
+  * Hacktarux
+  * Dave2001
+  * Zilmar
+  * Gregor Anich (Blight)
+  * Juha Luotio (JttL)
+  * and others.
+
+                   GNU GENERAL PUBLIC LICENSE  
+                      Version 2, June 1991  
+  
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+                          675 Mass Ave, Cambridge, MA 02139, 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  
+
+
+       Appendix: How to Apply These Terms to Your New Programs  
+  
+  If you develop a new program, and you want it to be of the greatest  
+possible use to the public, the best way to achieve this is to make it  
+free software which everyone can redistribute and change under these terms.  
+  
+  To do so, attach the following notices to the program.  It is safest  
+to attach them to the start of each source file to most effectively  
+convey the exclusion of warranty; and each file should have at least  
+the "copyright" line and a pointer to where the full notice is found.  
+  
+    <one line to give the program's name and a brief idea of what it does.>  
+    Copyright (C) 19yy  <name of author>  
+  
+    This program is free software; you can redistribute it and/or modify  
+    it under the terms of the GNU General Public License as published by  
+    the Free Software Foundation; either version 2 of the License, or  
+    (at your option) any later version.  
+  
+    This program is distributed in the hope that it will be useful,  
+    but WITHOUT ANY WARRANTY; without even the implied warranty of  
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
+    GNU General Public License for more details.  
+  
+    You should have received a copy of the GNU General Public License  
+    along with this program; if not, write to the Free Software  
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy name of author  
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.  
+    This is free software, and you are welcome to redistribute it  
+    under certain conditions; type `show c' for details.  
+  
+The hypothetical commands `show w' and `show c' should show the appropriate  
+parts of the General Public License.  Of course, the commands you use may  
+be called something other than `show w' and `show c'; they could even be  
+mouse-clicks or menu items--whatever suits your program.  
+  
+You should also get your employer (if you work as a programmer) or your  
+school, if any, to sign a "copyright disclaimer" for the program, if  
+necessary.  Here is a sample; alter the names:  
+  
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program  
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.  
+  
+  <signature of Ty Coon>, 1 April 1989  
+  Ty Coon, President of Vice  
+  
+This General Public License does not permit incorporating your program into  
+proprietary programs.  If your program is a subroutine library, you may  
+consider it more useful to permit linking proprietary applications with the  
+library.  If this is what you want to do, use the GNU Library General  
+Public License instead of this License.
+
diff --git a/source/mupen64plus-input-sdl/README b/source/mupen64plus-input-sdl/README
new file mode 100644 (file)
index 0000000..e9e049a
--- /dev/null
@@ -0,0 +1,146 @@
+===============================================================================
+-------------------------------------------------------------------------------
+Mupen64plus-input-sdl README                                               v2.0
+-------------------------------------------------------------------------------
+===============================================================================
+
+The latest documentation for this plugin can be found in wiki format at:
+
+https://code.google.com/p/mupen64plus/wiki/KeyboardSetup
+https://code.google.com/p/mupen64plus/wiki/ControllerSetup
+
+The format and usage of this plugin's "mupen64plus.cfg" configuration options
+can be found at:
+
+http://mupen64plus.retrouprising.com/mediawiki/index.php?title=Mupen64Plus_Plugin_Parameters#Input-SDL
+
+-------------------------------------------------------------------------------
+Notes about usage of SDL input plugin:
+-------------------------------------------------------------------------------
+
+ - If one of the enabled controllers has the "mouse" general-purpose config parameters set
+   to True, the plugin will hide the mouse cursor and 'grab' the mouse pointer.  The user
+   may press the Left Control and Alt keys together to toggle the mouse cursor on and off.
+ - If X/Y analog axes are mapped to keys, a plain keypress will simulate the joystick
+   being pressed all the way to the edge.  To decrease the amount of simulated joystick
+   deflection, the user may press Right Control, Right Shift, or Right Ctrl+Right Shift.
+
+-------------------------------------------------------------------------------
+Notes for supported joysticks for auto-configuration:
+-------------------------------------------------------------------------------
+
+1. Jess Tech Rumble Pad (Saitek Rumble)
+The left D-pad is mapped to the D-pad; The joystick is mapped to the left joystick of the gamepad; the C buttons are mapped to the gampad's right joystick. Start button is mapped to start; the A-button is mapped to the lowest button on the gamepad's right front; the B-button to the left button (buttons marked 3 and 1 on my gamepad). The L and R buttons are mapped to the lower left and right rear triggers; the Z button is mapped to the left upper rear trigger. All other buttons are unused. 
+
+2. Logitech Dual Action gamepad, Logitech Cordless Rumblepad 2:
+The digital pad maps to the N64 d-pad.  The left analog stick maps to the N64 analog stick.
+The right analog stick maps to the C-buttons,  and the buttons 2 and 1 map to A and B.
+Button 4 is the Z trigger, and the top shoulder buttons map to the left and right N64 triggers.
+Button 10 is the start button.
+The bottom shoulder buttons select the memory pack or rumble pak.
+
+3. Logitech Logitech(R) Precision(TM) Gamepad, Gravis GamePad Pro USB
+I came up with what I see as one of the few decent configurations (SSB aside) since it allows access to everything but the dpad.
+A is L1, B is R1, Z is L2, R is R2, L is select. C buttons are the four buttons, and the dpad acts as the joystick. Not the most orthodox, but it works well.
+
+4. Microsoft X-Box 360 pad:
+C button U (up) and C button R (right) are assigned to the Y and B buttons.
+All 4 C buttons are assigned to the U and V axis (including the already configured up and right C buttons).
+The Z button has been assigned to the left trigger and switching the rumble on and off can be done with the right trigger.
+Because there are no other buttons left I decided to use the button click behavior of the left joystick to switch Mempak on and off.
+
+5. MP-8866 Dual USB Joypad:
+This is a USB adapter for PlayStation controllers (2).
+
+D-Pad:    hat(0)
+L-Stick:  x:0, y:1
+R-Stick:  x:2, y:3
+Triangle: button(0)
+Circle:   button(1)
+Cross:    button(2)
+Square:   button(3)
+L2:       button(4)
+R2:       button(5)
+L1:       button(6)
+R1:       button(7)
+Start:    button(8)
+Select:   button(9)
+L3:       button(10)
+R3:       button(11)
+Note:  This is when analog mode is selected. If analog is off then D-Pad becomes axes 0/1 and both sticks are disabled (including L3/R3).
+
+6. N64 controller:
+All controls are mapped to their proper place on the N64 controller with an Adaptoid or custom hardware with Gamecon driver.
+Rumble and Memory packs can be selected with the 'r' and 'm' keys, respectively.
+
+7. Playstation 3 Controller:
+Left analog stick - analog stick
+Right analog stick - C-pad
+D-Pad - D-Pad
+Cross - A
+Square - B
+L1 / R1 - L / R
+L2 - Z
+Start - Start
+
+8. SAITEK P880:
+The gamepad doesnt have enough keys to real assign all buttons. The second 
+analog stick can be used as button by pushing him insight.
+
+General Configuration:
+Digital Pad was used as N64 digital pad, First analog stick was used as N64 
+Analog stick. The red button was used as N64 Start button. L and R was used 
+for N64 L and R. Second analog stick axes was used for N64 C buttons and 
+second "analog stick button" was used for C-down. The first column of keys was 
+used for A and B and the second and third row was used for C-Buttons - except 
+for the Button next to the A button which would be C-Down but got the Z 
+button.
+
+9. Xbox Gamepad (userspace driver)
+I created an Input Config for a Xbox 360 controller running with
+xboxdrv on a Linux system (http://pingus.seul.org/~grumbel/xboxdrv/).
+
+Z = Left shoulder button
+L = Left shoulder trigger
+A = A Button
+B = X Button
+
+everything else should be obvious.
+
+Unfortunately, you will also have to make some configuration to
+xboxdrv to make this work properly. xboxdrv has to be started with the
+following config file. The "-as-button" options make sure that the D-
+Pad and Trigger are emulated as buttons and the deadzone options make
+the C buttons work much better.
+The guide=KEY_ESC allows you to quit the emulator by pressing the
+guide key on the controller. This is obviously just nice-to-have and
+not actually neccessary for the config to work.
+
+[xboxdrv]
+silent=true
+trigger-as-button=true
+dpad-as-button=true
+
+[ui-buttonmap]
+guide=KEY_ESC
+
+[axismap]
+x2^deadzone:27000
+y2^deadzone:27000
+
+10. Saitek Cyborg V.3 Rumble Pad (aka Saitek PS2700)
+Honestly, it's one of the best pads that I've used in a long time, so thought I'd contribute this quick config. Basically, Dpad and Analog sticks are unchanged, C-buttons are mapped to the right analog stick, L-R triggers are L1 and R1, Z is mapped to R2, A + B are mapped to X and Square, respectively, start is mapped to the Home button, and Triangle, Square, L2, Start, Select, and the Analog triggers are unused, since it's not intuitive to use them for what's left.
+
+11. Default Keyboard interface:
+Analog Pad is "Arrow Keys"
+C Up/Left/Down/Right are "I", "J", "K", "L"
+DPad Up/Left/Down/Right are "W", "A", "S", "D"
+Z trig is "z" key
+L and R trigs are "x" and "c"
+Start is "Enter" ("Return")
+A is "left shift"
+B is "left control"
+Select Mempack = ","
+Select Rumblepack = "."
+
+
diff --git a/source/mupen64plus-input-sdl/RELEASE b/source/mupen64plus-input-sdl/RELEASE
new file mode 100644 (file)
index 0000000..49a935f
--- /dev/null
@@ -0,0 +1,158 @@
+SDL Input plugin for Mupen64Plus
+--------------------------------
+
+Mupen64Plus-input-sdl v2.0 - July 4, 2013
+-----------------------------------------
+ - re-write auto-configuration logic to be more user friendly.  Add new 'mode' parameter.
+ - support for 6 new joysticks
+ - work-around for buggy xboxdrv which results in no rumble
+ - bugfix: crash when rumble used with controller #4
+ - support to build against SDL2
+ - Project files for Visual Studio 2012
+ - Makefile changes
+   - add support for PowerPC and MinGW32 builds
+   - add cross-compiling support to build Win32 executables (MXE) under Linux
+
+Mupen64Plus-input-sdl v1.99.5 - March 10, 2012
+-------------------------------------------------
+ - Improved input setup behavior (auto-config) to make some use cases more friendly
+ - Updated input plugin for new Mupen64plus 2.0 API versioning scheme
+ - Added version number to SDL Input plugin parameters
+ - Add new parameter for mouse sensitivity, handle mouse movement differently so mouse is easier to use as controller
+ - New auto-configuration for controllers:
+   - raphnet technologies GC/N64 usb converter
+   - Logitech Chillstream Controller
+   - Jess Tech Colour Rumble
+   - Xbox 360 linux userspace driver
+   - Generic X-Box pad
+   - Saitek P2900 Wireless Pad
+   - Jess Tech USB 4-Axis 12-Button Gamepad
+ - bugfix: #392 - when switching between rumble pak and memory pak, simulate removing the pack, waiting 1 second, then inserting the new one
+ - bugfix: #424 - problem with USB devices supporting multiple controllers per device
+ - bugfix: #409 - PS3 controller not auto-detected in Gentoo when connected via bluetooth
+ - bugfix: correctly handle USB devices with multiple game pads, from Peter Helbing
+ - makefile fixes and improvements
+
+Mupen64Plus-input-sdl v1.99.4 - November 22, 2010
+-------------------------------------------------
+ - Bugfix: Do configuration during PluginStart(), so GUI will see defaults (auto-configured) the first time it is run
+ - Move axis value reducers to right shift and right ctrl, to avoid conflict with A/B buttons
+ - New feature: extra deadzone parameter in axis() config parameter clause when mapping an analog joystick axis to an N64 button
+ - many new joystick auto-configurations
+ - makefile fixes and improvements
+
+Mupen64Plus-input-sdl v1.99.3 - February 13, 2010
+-------------------------------------------------
+ - New feature: auto-configuration uses an .ini file instead of hard-coding the controllers in the source code
+ - New controller auto-configurations:
+   - Original X-Box (and compatible clones)
+   - HuiJia USB GamePad
+   - USB Human(2p) Interface Device
+ - sync with core<-->plugin API change for RomOpen()
+ - Bugfix: controller pak was fixed at startup, switching b/w mempak and rumblepak did not work
+ - Bugfix: Xbox 360 and PS3 controllers need slightly different names under OSX
+ - Makefile improvements:
+   - plugin must be linked with CC instead of LD because 'sdl-config --libs' can give "-Wl,-rpath"
+   - added OS type GNU/kFreeBSD
+
+Mupen64Plus-input-sdl v1.99.2 - January 6, 2010
+-------------------------------------------------
+ - new feature: added MSVC8 project file, minor code refactoring for VC compatibility
+ - added auto-configuration for:
+   - Xbox 360 Wireless Receiver
+   - PS3 controller
+   - Jess Tech Dual Analog Pad
+ - Makefile improvements:
+   - throw error if OS/CPU not supported
+   - use DESTDIR in install/uninstall paths
+   - Allow user-specified CC/CXX/LD paths
+
+Mupen64Plus-input-sdl v1.99.1 - December 14, 2009
+-------------------------------------------------
+ - New feature: Joystick/Keyboard auto-configuration
+ - New feature: deadzone and peak analog joystick values are now configurable
+ - Converted to new Mupen64Plus 2.0 API
+ - Refactored build system to separate source and object files
+ - Major code cleanup: mouse movement and analog axis code was terrible, removed non-standard data types
+ - Improved debug messages
+ - bugfix: mapping the X/Y analog sticks to keypresses didnt work
+ - bugfix: LeftCtrl-LeftAlt key command when mouse is enabled to now toggles between grabbing and releasing the mouse pointer
+
+Mupen64Plus Pre-2.0
+-------------------
+ - numerous fixes and enhancements were made to this code during the mupen64plus project before v2.0
+
+Original Blight Changelog
+-------------------------
+
+0.0.10:
+ - when the keyboard is used to control an axis left shift and left control can be 
+   pressed to change the axis movement. shift reduces the movement by 25%, control 
+   reduces it by 50%, control and shift together reduce the movement by 75%
+ - when the mouse is used left ctrl + left alt can be used to release the mouse, 
+   clicking into the window will grab the mouse again.
+
+0.0.9:
+ - import new version of SDL_tff (2.0.7)
+ - when the keyboard is used to control an axis left shift can be pressed to change 
+   the axis movement to 25% of the original value
+
+0.0.8-b:
+ - fixed bug which didn't put analog axis back into default position when a key
+   which was assigned to it was pressed and released again
+
+0.0.8:
+ - fixed a stupid bug which disabled analog axis
+
+0.0.7-b:
+ - sdl config dialog: input event queue is flushed before a 
+   button/whatever is assigned
+
+0.0.7: mouse support!
+ - mouse support (x and y axis automatically mapped to analog stick,
+   mouse buttons mapable onto n64 buttons)
+
+0.0.6:
+ - keyboard and gamepad can be used at the same time (the keyboard will work always,
+   even if you choose another device. if you want to use only the keyboard select
+   keyboard as device
+
+0.0.5:
+ - sdl about dialog
+ - fixed config routine (incorrectly read X- axis)
+ - fixed small sdl config dialog drawing bug
+ - corrected config dialog c button labels
+
+0.0.4: joystick hat support
+ - fixed a segfault when the rom was closed
+ - less axis sensibility when assigning a new mapping (changed from 10 to 50 percent)
+ - less sensibility for axis mapped to buttons (changed from 10 to 20 percent)
+ - it's possible to clear assignments and cancel an assignment
+ - joystick hat support (mapable to axis and buttons)
+ - fixed some bugs in the input reading function
+ - fixed all compiler warnings
+
+0.0.3:
+ - no more need for the SDL_image library
+ - no longer link against gtk library
+
+0.0.2-2:
+ - fixed a bug which didn't allow to assign anything to a pad button
+
+0.0.2-1:                       *BROKEN*
+ - help for the SDL gui
+
+0.0.2: new SDL config dialog!  *BROKEN*
+ - fixed a bug where it wouldn't open the joystick device if you change the controller
+ - sdl config dialog
+ - some other lil' fixes
+
+0.0.1: made some small fixes
+ - now it's possible to map an axis (i.e. X Axis +) to a button (i.e.  DPAD_UP)
+ - configuration is saved and displayed for all devices
+ - changed the config dialog a bit (bigger text entries, bigger device combo)
+ - new config file format
+
+0.0.1b: initial version
+ - should work :-)
+
diff --git a/source/mupen64plus-input-sdl/data/InputAutoCfg.ini b/source/mupen64plus-input-sdl/data/InputAutoCfg.ini
new file mode 100644 (file)
index 0000000..6d67e45
--- /dev/null
@@ -0,0 +1,953 @@
+; InputAutoCfg.ini for Mupen64Plus SDL Input plugin
+
+[Keyboard]
+plugged = True
+plugin = 2
+mouse = False
+DPad R = key(100)
+DPad L = key(97)
+DPad D = key(115)
+DPad U = key(119)
+Start = key(13)
+Z Trig = key(122)
+B Button = key(306)
+A Button = key(304)
+C Button R = key(108)
+C Button L = key(106)
+C Button D = key(107)
+C Button U = key(105)
+R Trig = key(99)
+L Trig = key(120)
+Mempak switch = key(44)
+Rumblepak switch = key(46)
+X Axis = key(276,275)
+Y Axis = key(273,274)
+
+; Boom Smart Joy Converter
+[HID 6666:0667]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(13)
+DPad L = button(15)
+DPad D = button(14)
+DPad U = button(12)
+Start = button(11)
+Z Trig = button(10)
+B Button = button(4)
+A Button = button(5)
+C Button R = button(1)
+C Button L = button(3)
+C Button D = button(2)
+C Button U = button(0)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Cyborg V.3 Rumble Pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = axis(4+)
+DPad L = axis(4-)
+DPad D = axis(5+)
+DPad U = axis(5-)
+Start = button(12)
+Z Trig = button(7)
+B Button = button(0)
+A Button = button(1)
+C Button R = button(8) axis(2+)
+C Button L = button(3) axis(2-)
+C Button D = button(2) axis(3+)
+C Button U = button(9) axis(3-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[DragonRise Inc. Generic USB Joystick]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = key(275) axis(0+)
+DPad L = key(276) axis(0-)
+DPad D = key(274) axis(1+)
+DPad U = key(273) axis(1-)
+Start = button(9)
+Z Trig = button(4)
+B Button = button(3)
+A Button = button(2)
+C Button R = button(7) axis(3+)
+C Button L = button(6) axis(3-)
+C Button D = button(1) axis(4+)
+C Button U = button(0) axis(4-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+) 
+
+; FuSa is a homebrew program which allows a PSP to be used as a gamepad
+[FuSa FuSa GamePad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R =
+DPad L =
+DPad D =
+DPad U =
+Start = button(7)
+Z Trig = button(4)
+B Button = button(2)
+A Button = button(0)
+C Button R = hat(0 Right)
+C Button L = hat(0 Left)
+C Button D = hat(0 Down)
+C Button U = hat(0 Up)
+R Trig = button(5)
+L Trig = button(3)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Gasia Co.,Ltd PS(R) Gamepad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = key(275) axis(0+) hat(0 Right)
+DPad L = key(276) axis(0-)
+DPad D = key(274) axis(1+) hat(0 Down)
+DPad U = key(273) axis(1-)
+Start = button(9)
+Z Trig = button(6)
+B Button = button(3)
+A Button = button(2)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch = button(1)
+Rumblepak switch = button(0)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+; raphnet technologies USB converter (http://www.raphnet-tech.com/)
+[GC/N64_USB]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(13)
+DPad L = button(12)
+DPad D = button(11)
+DPad U = button(10)
+Start = button(3)
+Z Trig = button(2)
+B Button = button(1)
+A Button = button(0)
+C Button R = button(7)
+C Button L = button(6)
+C Button D = button(5)
+C Button U = button(4)
+R Trig = button(9)
+L Trig = button(8)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[GreenAsia Inc. USB Joystick]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(1)
+B Button = button(3)
+A Button = button(2)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(2+)
+C Button U = axis(2-)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Jess Tech Dual Analog Pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(7)
+B Button = button(0)
+A Button = button(2)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(2+)
+C Button U = axis(2-)
+R Trig = button(6)
+L Trig = button(4)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Jess Tech Colour Rumble Pad]
+plugged = True
+plugin = 1
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(4)
+B Button = button(0)
+A Button = button(2)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(2+)
+C Button U = axis(2-)
+R Trig = button(7)
+L Trig = button(5)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Jess Tech USB 4-Axis 12-Button Gamepad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(4)
+Z Trig = button(5)
+B Button = button(8)
+A Button = button(9)
+C Button R = button(1)
+C Button L = button(3)
+C Button D = button(2)
+C Button U = button(0)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+; X-box controllers and compatible clones
+[Logitech Chillstream Controller]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(7)
+Z Trig = axis(2+)
+B Button = button(2)
+A Button = button(0)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(4+)
+C Button U = axis(4-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch = button(6)
+Rumblepak switch = button(8)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Logitech Cordless Rumblepad 2]
+[Logitech Cordless RumblePad 2]
+[Logitech RumblePad 2 USB]
+[Logitech Dual Action]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = axis(4+) hat(0 Right)
+DPad L = axis(4-) hat(0 Left)
+DPad D = axis(5+) hat(0 Down)
+DPad U = axis(5-) hat(0 Up)
+Start = button(9)
+Z Trig = button(6)
+B Button = button(0)
+A Button = button(1)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch = button(8)
+Rumblepak switch = button(7)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Logitech Logitech(R) Precision(TM) Gamepad]
+[Gravis GamePad Pro USB]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 100,100
+AnalogPeak = 32768,32768
+DPad R = axis(0+)
+DPad L = axis(0-)
+DPad D = axis(1+)
+Dpad U = axis(1-)
+Start = button(9)
+Z Trig = button(6)
+B Button = button(5)
+A Button = button(4)
+C Button R = button(2)
+C Button L = button(0)
+C Button D = button(1)
+C Button U = button(3)
+R Trig = button(7)
+L Trig = button(8)
+Mempack switch =
+Rumblepak Switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Logitech WingMan Action Pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(13)
+DPad L = button(15)
+DPad D = button(14)
+DPad U = button(12)
+Start = button(8)
+Z Trig = button(6)
+B Button = button(3)
+A Button = button(0)
+C Button R = button(2)
+C Button L = button(4)
+C Button D = button(1)
+C Button U = button(5)
+R Trig = button(7)
+L Trig =
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Mega World USB Game Controllers]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(7)
+B Button = button(0)
+A Button = button(2)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(2+)
+C Button U = axis(2-)
+R Trig = button(6)
+L Trig = button(4)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[MP-8866 Dual USB Joypad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(8)
+Z Trig = button(6)
+B Button = button(3)
+A Button = button(2)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = button(7)
+L Trig = button(4)
+Mempak switch = button(10)
+Rumblepak switch = button(11)
+Y Axis = axis(1-,1+)
+X Axis = axis(0-,0+)
+
+[Microsoft X-Box 360 pad]
+[Win32: Controller (XBOX 360 For Windows)]
+[Win32: XBOX 360 For Windows (Controller)]
+[Win32: XBOX 360 For Windows]
+[Xbox 360 Wireless Receiver]
+[OSX: Wireless 360 Controller]
+[OSX: Controller]
+[Linux: Xbox Gamepad (userspace driver)]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(7)
+Z Trig = axis(2+)
+B Button = button(2)
+A Button = button(0)
+C Button R = axis(4+)
+C Button L = axis(4-) button(3)
+C Button D = axis(3+) button(1)
+C Button U = axis(3-)
+R Trig = button(5) axis(2-)
+L Trig = button(4)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[N64 controller]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(0)
+B Button = button(2)
+A Button = button(1)
+C Button R = button(4)
+C Button L = button(5)
+C Button D = button(3)
+C Button U = button(6)
+R Trig = button(8)
+L Trig = button(7)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[PC Game Controller]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(8)
+B Button = button(4)
+A Button = button(5)
+C Button R = button(1)
+C Button L = button(3)
+C Button D = button(2)
+C Button U = button(0)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[SAITEK P880]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(10)
+Z Trig = button(3)
+B Button = button(0)
+A Button = button(2)
+C Button R = button(5) axis(3+)
+C Button L = button(1) axis(3-)
+C Button D = button(9) axis(2+)
+C Button U = button(4) axis(2-)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Saitek P990 Dual Analog Pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(5)
+Z Trig = button(4)
+B Button = button(0)
+A Button = button(1)
+C Button R = button(8) axis(3+)
+C Button L = button(3) axis(3-)
+C Button D = button(2) axis(2+)
+C Button U = button(9) axis(2-)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = button(11)
+Rumblepak switch = axis(10+)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Saitek P2900 Wireless Pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = axis(4+)
+DPad L = axis(4-)
+DPad D = axis(5+)
+DPad U = axis(5-)
+Start = button(6)
+Z Trig = button(7)
+B Button = button(0)
+A Button = button(1)
+C Button R = button(8) axis(3+)
+C Button L = button(3) axis(3-)
+C Button D = button(2) axis(2+)
+C Button U = button(9) axis(2-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch = button(11)
+Rumblepak switch = axis(10+)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Thrustmaster Dual Trigger 3-in-1]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(3)
+B Button = button(0)
+A Button = button(1)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(5+)
+C Button U = axis(5-)
+R Trig = button(5)
+L Trig = button(4)
+Mempak switch = button(6)
+Rumblepak switch = button(7)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[THRUSTMASTER Firestorm Dual Power 2]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(5)
+Z Trig = button(8)
+B Button = button(1)
+A Button = button(0)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = button(6)
+L Trig = button(4)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Twin USB Joystick]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(9)
+Z Trig = button(4)
+B Button = button(6)
+A Button = button(7)
+C Button R = button(1)
+C Button L = button(3)
+C Button D = button(2)
+C Button U = button(0)
+R Trig = button(5)
+L Trig = button(11)
+Mempak switch =
+Rumblepak switch =
+Y Axis = axis(1-,1+)
+X Axis = axis(0-,0+)
+
+[PLAYSTATION(R)3 Controller]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(5)
+DPad L = button(7)
+DPad D = button(6)
+DPad U = button(4)
+Start = button(3)
+Z Trig = button(8)
+B Button = button(15)
+A Button = button(14)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = button(11)
+L Trig = button(10)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[WiseGroup.,Ltd TigerGame XBOX+PS2+GC Game Controller Adapter]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(9)
+DPad L = button(8)
+DPad D = button(10)
+DPad U = button(11)
+Start = button(7)
+Z Trig = button(6)
+B Button = button(1)
+A Button = button(0)
+C Button R = axis(2+)
+C Button L = axis(2-)
+C Button D = axis(3+)
+C Button U = axis(3-)
+R Trig = axis(4+)
+L Trig = axis(5+)
+Mempak switch =
+Rumblepak switch =
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[Wish Technologies Adaptoid]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = button(13)
+DPad L = button(12)
+DPad D = button(11)
+DPad U = button(10)
+Start = button(8)
+Z Trig = button(9)
+B Button = button(3)
+A Button = button(0)
+C Button R = button(2)
+C Button L = button(4)
+C Button D = button(1)
+C Button U = button(5)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = 
+Rumblepak switch = 
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+; X-box controllers and compatible clones
+[Microsoft X-Box pad v1 (US)]
+[Microsoft X-Box pad v2 (US)]
+[Microsoft X-Box pad (Japan)]
+[Microsoft Xbox Controller S]
+[Thrustmaster, Inc. Controller]
+[Logitech Xbox Cordless Controller]
+[Logitech Compact Controller for Xbox]
+[Mad Catz Controller (unverified)]
+[InterAct 'PowerPad Pro' X-Box pad (Germany)]
+[Mad Catz Control Pad]
+[Mad Catz LumiCON]
+[Mad Catz Control Pad Pro]
+[Mad Catz MicroCON]
+[Mad Catz Lynx Wireless Controller]
+[Zeroplus Xbox Controller]
+[Pelican Eclipse PL-2023]
+[Zeroplus Xbox Controller]
+[Radica Gamester Controller]
+[Radica Games Jtech Controller]
+[Logic3 Freebird wireless Controller]
+[Eclipse wireless Controller]
+[Edge wireless Controller]
+[SmartJoy Frag Xpad/PS2 adaptor]
+[Joytech Advanced Controller]
+[BigBen XBMiniPad Controller]
+[Joytech Wireless Advanced Controller]
+[Chinese-made Xbox Controller]
+[Generic X-Box pad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 4096,4096
+AnalogPeak = 32768,32768
+DPad R = hat(0 Right)
+DPad L = hat(0 Left)
+DPad D = hat(0 Down)
+DPad U = hat(0 Up)
+Start = button(6)
+Z Trig = button(7)
+B Button = button(1)
+A Button = button(0)
+C Button R = axis(3+)
+C Button L = axis(3-)
+C Button D = axis(4+)
+C Button U = axis(4-)
+R Trig = axis(5+)
+L Trig = axis(2+)
+Mempak switch = button(5)
+Rumblepak switch = button(2)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+[OSX: USB GamePad]
+; this is a 2-port USB device.  The Right port is controller #1, the Left port is #2
+; this is the "MayFlash" adapter, aka HuiJia.  The OSX driver seems to have a
+; different button mapping
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 2500,2500
+AnalogPeak = 20000,20000
+DPad R = button(13)
+DPad L = button(15)
+DPad D = button(14)
+DPad U = button(12)
+Start = button(9)
+Z Trig = button(8)
+B Button = button(2)
+A Button = button(1)
+C Button R = axis(1-)
+C Button L = axis(1+)
+C Button D = axis(0+)
+C Button U = axis(0-)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(2-,2+)
+Y Axis = axis(3-,3+)
+__NextController:
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 2500,2500
+AnalogPeak = 20000,20000
+DPad R = button(29)
+DPad L = button(31)
+DPad D = button(30)
+DPad U = button(28)
+Start = button(25)
+Z Trig = button(24)
+B Button = button(18)
+A Button = button(17)
+C Button R = axis(5-)
+C Button L = axis(5+)
+C Button D = axis(4+)
+C Button U = axis(4-)
+R Trig = button(23)
+L Trig = button(22)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(6-,6+)
+Y Axis = axis(7-,7+)
+
+[HuiJia USB GamePad]
+plugged = True
+plugin = 2
+mouse = False
+AnalogDeadzone = 100,100
+AnalogPeak = 20000,20000
+DPad R = button(13)
+DPad L = button(15)
+DPad D = button(14)
+DPad U = button(12)
+Start = button(9)
+Z Trig = button(8)
+B Button = button(2)
+A Button = button(1)
+C Button R = axis(3-)
+C Button L = axis(3+)
+C Button D = axis(2+)
+C Button U = axis(2-)
+R Trig = button(7)
+L Trig = button(6)
+Mempak switch = key(109)
+Rumblepak switch = key(114)
+X Axis = axis(0-,0+)
+Y Axis = axis(1-,1+)
+
+; Asikgame - Super Dual Box (with two PS2 gamepads connected)
+; this is a 2-port USB device. The Right port is controller #1, the Left port is #2
+[USB Human(2p) Interface Device]
+plugged = True
+plugin = 2
+mouse = False
+DPad R= axis(2+)
+DPad L= axis(2-)
+DPad D= axis(5+)
+DPad U= axis(5-)
+Start= button(0)
+Z Trig= button(1)
+B Button= button(3)
+A Button= button(2)
+C Button R= hat(0 Right)
+C Button L= hat(0 Left)
+C Button D= hat(0 Down)
+C Button U= hat(0 Up)
+R Trig= button(5)
+L Trig= button(4)
+Mempak switch= button(9)
+Rumblepak switch= button(8)
+Y Axis= axis(1-,1+)
+X Axis= axis(0-,0+)
+__NextController:
+plugged = True
+plugin = 2
+mouse = False
+DPad R= axis(6+)
+DPad L= axis(6-)
+DPad D= axis(7+)
+DPad U= axis(7-)
+Start= button(12)
+Z Trig= button(13)
+B Button= button(15)
+A Button= button(14)
+C Button R= hat(1 Right)
+C Button L= hat(1 Left)
+C Button D= hat(1 Down)
+C Button U= hat(1 Up)
+R Trig= button(17)
+L Trig= button(16)
+Mempak switch= button(21)
+Rumblepak switch= button(20)
+Y Axis= axis(4-,4+)
+X Axis= axis(3-,3+)
+
+#Pandora dual nub support, the hat is in fact "nub1"
+[nub0]
+plugged = True
+plugin = 2
+mouse = False
+DPad R = key(275)
+DPad L = key(276)
+DPad D = key(274)
+DPad U = key(273)
+#Start is Start
+Start= key(308)
+Z Trig= key(303)
+#B button = (X) = 281 = SDLK_PAGEDWN
+B Button= key(278)
+#A button = (A) = 278 = SDLK_HOME (279 = (B))
+A Button= key(281)
+R Trig= key(305)
+#L trigger is (B) (P = 111)
+L Trig= key(279)
+Y Axis= axis(1-,1+)
+X Axis= axis(0-,0+)
+# K=107 , Backspace=8
+C Button R = key(8)
+# J = 106, 9 = 57
+C Button L = key(57)
+# M = 109 , (Y) = 280
+C Button D = key(280)
+# I = 105 , 0 = 48
+C Button U = key(48)
+#C Button R = hat(0 Right)
+#C Button L = hat(0 Left)
+#C Button D = hat(0 Down)
+#C Button U = hat(0 Up)
+# default value here
+Mempak switch = key(44)
+Rumblepak switch = key(46)
diff --git a/source/mupen64plus-input-sdl/projects/msvc11/mupen64plus-input-sdl.vcxproj b/source/mupen64plus-input-sdl/projects/msvc11/mupen64plus-input-sdl.vcxproj
new file mode 100644 (file)
index 0000000..3be7d99
--- /dev/null
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{7F3178D0-0E2E-471B-9160-69F0354F9DE9}</ProjectGuid>
+    <RootNamespace>mupen64plusinputsdl</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+    <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\autoconfig.c" />
+    <ClCompile Include="..\..\src\config.c" />
+    <ClCompile Include="..\..\src\osal_dynamiclib_win32.c" />
+    <ClCompile Include="..\..\src\plugin.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\autoconfig.h" />
+    <ClInclude Include="..\..\src\config.h" />
+    <ClInclude Include="..\..\src\osal_dynamiclib.h" />
+    <ClInclude Include="..\..\src\osal_preproc.h" />
+    <ClInclude Include="..\..\src\plugin.h" />
+    <ClInclude Include="..\..\src\version.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/source/mupen64plus-input-sdl/projects/msvc8/mupen64plus-input-sdl.vcproj b/source/mupen64plus-input-sdl/projects/msvc8/mupen64plus-input-sdl.vcproj
new file mode 100644 (file)
index 0000000..75f290e
--- /dev/null
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+       ProjectType="Visual C++"
+       Version="8.00"
+       Name="mupen64plus-input-sdl"
+       ProjectGUID="{7F3178D0-0E2E-471B-9160-69F0354F9DE9}"
+       RootNamespace="mupen64plusinputsdl"
+       Keyword="Win32Proj"
+       >
+       <Platforms>
+               <Platform
+                       Name="Win32"
+               />
+       </Platforms>
+       <ToolFiles>
+       </ToolFiles>
+       <Configurations>
+               <Configuration
+                       Name="Debug|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
+                       ConfigurationType="2"
+                       CharacterSet="2"
+                       >
+                       <Tool
+                               Name="VCPreBuildEventTool"
+                       />
+                       <Tool
+                               Name="VCCustomBuildTool"
+                       />
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"
+                       />
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"
+                       />
+                       <Tool
+                               Name="VCMIDLTool"
+                       />
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               Optimization="0"
+                               AdditionalIncludeDirectories="..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include"
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE"
+                               MinimalRebuild="true"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
+                               UsePrecompiledHeader="0"
+                               WarningLevel="3"
+                               Detect64BitPortabilityProblems="false"
+                               DebugInformationFormat="4"
+                       />
+                       <Tool
+                               Name="VCManagedResourceCompilerTool"
+                       />
+                       <Tool
+                               Name="VCResourceCompilerTool"
+                       />
+                       <Tool
+                               Name="VCPreLinkEventTool"
+                       />
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib"
+                               LinkIncremental="2"
+                               GenerateDebugInformation="true"
+                               SubSystem="2"
+                               TargetMachine="1"
+                       />
+                       <Tool
+                               Name="VCALinkTool"
+                       />
+                       <Tool
+                               Name="VCManifestTool"
+                       />
+                       <Tool
+                               Name="VCXDCMakeTool"
+                       />
+                       <Tool
+                               Name="VCBscMakeTool"
+                       />
+                       <Tool
+                               Name="VCFxCopTool"
+                       />
+                       <Tool
+                               Name="VCAppVerifierTool"
+                       />
+                       <Tool
+                               Name="VCWebDeploymentTool"
+                       />
+                       <Tool
+                               Name="VCPostBuildEventTool"
+                       />
+               </Configuration>
+               <Configuration
+                       Name="Release|Win32"
+                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                       IntermediateDirectory="$(ConfigurationName)"
+                       ConfigurationType="2"
+                       CharacterSet="2"
+                       WholeProgramOptimization="1"
+                       >
+                       <Tool
+                               Name="VCPreBuildEventTool"
+                       />
+                       <Tool
+                               Name="VCCustomBuildTool"
+                       />
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"
+                       />
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"
+                       />
+                       <Tool
+                               Name="VCMIDLTool"
+                       />
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               AdditionalIncludeDirectories="..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include"
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE"
+                               RuntimeLibrary="2"
+                               UsePrecompiledHeader="0"
+                               WarningLevel="3"
+                               Detect64BitPortabilityProblems="false"
+                               DebugInformationFormat="3"
+                               CompileAs="0"
+                       />
+                       <Tool
+                               Name="VCManagedResourceCompilerTool"
+                       />
+                       <Tool
+                               Name="VCResourceCompilerTool"
+                       />
+                       <Tool
+                               Name="VCPreLinkEventTool"
+                       />
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib"
+                               LinkIncremental="1"
+                               GenerateDebugInformation="true"
+                               SubSystem="2"
+                               OptimizeReferences="2"
+                               EnableCOMDATFolding="2"
+                               TargetMachine="1"
+                       />
+                       <Tool
+                               Name="VCALinkTool"
+                       />
+                       <Tool
+                               Name="VCManifestTool"
+                       />
+                       <Tool
+                               Name="VCXDCMakeTool"
+                       />
+                       <Tool
+                               Name="VCBscMakeTool"
+                       />
+                       <Tool
+                               Name="VCFxCopTool"
+                       />
+                       <Tool
+                               Name="VCAppVerifierTool"
+                       />
+                       <Tool
+                               Name="VCWebDeploymentTool"
+                       />
+                       <Tool
+                               Name="VCPostBuildEventTool"
+                       />
+               </Configuration>
+       </Configurations>
+       <References>
+       </References>
+       <Files>
+               <Filter
+                       Name="Source Files"
+                       Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+                       >
+                       <File
+                               RelativePath="..\..\src\autoconfig.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\config.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\osal_dynamiclib_win32.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\plugin.c"
+                               >
+                       </File>
+               </Filter>
+               <Filter
+                       Name="Header Files"
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+                       >
+                       <File
+                               RelativePath="..\..\src\autoconfig.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\config.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\osal_dynamiclib.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\osal_preproc.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\plugin.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\version.h"
+                               >
+                       </File>
+               </Filter>
+       </Files>
+       <Globals>
+       </Globals>
+</VisualStudioProject>
diff --git a/source/mupen64plus-input-sdl/projects/unix/Makefile b/source/mupen64plus-input-sdl/projects/unix/Makefile
new file mode 100755 (executable)
index 0000000..61a5a87
--- /dev/null
@@ -0,0 +1,330 @@
+#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+# *   Mupen64plus-input-sdl - Makefile                                      *
+# *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+# *   Copyright (C) 2007-2009 Richard Goedeken                              *
+# *                                                                         *
+# *   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.,                                       *
+# *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+# Makefile for SDL Input plugin in Mupen64plus
+
+# detect operating system
+UNAME ?= $(shell uname -s)
+OS := NONE
+ifeq ("$(UNAME)","Linux")
+  OS = LINUX
+  SO_EXTENSION = so
+  SHARED = -shared
+endif
+ifeq ("$(UNAME)","linux")
+  OS = LINUX
+  SO_EXTENSION = so
+  SHARED = -shared
+endif
+ifneq ("$(filter GNU hurd,$(UNAME))","")
+  OS = LINUX
+  SO_EXTENSION = so
+  SHARED = -shared
+endif
+ifeq ("$(UNAME)","Darwin")
+  OS = OSX
+  SO_EXTENSION = dylib
+  SHARED = -bundle
+endif
+ifeq ("$(UNAME)","FreeBSD")
+  OS = FREEBSD
+  SO_EXTENSION = so
+  SHARED = -shared
+endif
+ifeq ("$(UNAME)","OpenBSD")
+  OS = FREEBSD
+  SO_EXTENSION = so
+  SHARED = -shared
+  $(warning OS type "$(UNAME)" not officially supported.')
+endif
+ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","")
+  OS = LINUX
+  SO_EXTENSION = so
+  SHARED = -shared
+endif
+ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW")
+  OS = MINGW
+  SO_EXTENSION = dll
+  SHARED = -shared
+  PIC = 0
+endif
+ifeq ("$(OS)","NONE")
+  $(error OS type "$(UNAME)" not supported.  Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
+endif
+
+# detect system architecture
+HOST_CPU ?= $(shell uname -m)
+NO_ASM ?= 1
+CPU := NONE
+ifneq ("$(filter x86_64 amd64,$(HOST_CPU))","")
+  CPU := X86
+  ifeq ("$(BITS)", "32")
+    ARCH_DETECTED := 64BITS_32
+    PIC ?= 0
+  else
+    ARCH_DETECTED := 64BITS
+    PIC ?= 1
+  endif
+endif
+ifneq ("$(filter pentium i%86,$(HOST_CPU))","")
+  CPU := X86
+  ARCH_DETECTED := 32BITS
+  PIC ?= 0
+endif
+ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","")
+  CPU := PPC
+  ARCH_DETECTED := 32BITS
+  BIG_ENDIAN := 1
+  PIC ?= 1
+  $(warning Architecture "$(HOST_CPU)" not officially supported.')
+endif
+ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","")
+  CPU := PPC
+  ARCH_DETECTED := 64BITS
+  BIG_ENDIAN := 1
+  PIC ?= 1
+  $(warning Architecture "$(HOST_CPU)" not officially supported.')
+endif
+ifneq ("$(filter arm%,$(HOST_CPU))","")
+  ifeq ("$(filter arm%b,$(HOST_CPU))","")
+    CPU := ARM
+    ARCH_DETECTED := 32BITS
+    PIC ?= 1
+    CFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -mtune=cortex-a8 -fsigned-char
+    $(warning Architecture "$(HOST_CPU)" not officially supported.')
+  endif
+endif
+ifeq ("$(CPU)","NONE")
+  $(error CPU type "$(HOST_CPU)" not supported.  Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
+endif
+
+# base CFLAGS, LDLIBS, and LDFLAGS
+OPTFLAGS ?= -O3
+WARNFLAGS ?= -Wall
+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -D_GNU_SOURCE=1
+LDFLAGS += $(SHARED)
+
+# Since we are building a shared library, we must compile with -fPIC on some architectures
+# On 32-bit x86 systems we do not want to use -fPIC because we don't have to and it has a big performance penalty on this arch
+ifeq ($(PIC), 1)
+  CFLAGS += -fPIC
+else
+  CFLAGS += -fno-PIC
+endif
+
+ifeq ($(BIG_ENDIAN), 1)
+  CFLAGS += -DM64P_BIG_ENDIAN
+endif
+
+# tweak flags for 32-bit build on 64-bit system
+ifeq ($(ARCH_DETECTED), 64BITS_32)
+  CFLAGS += -m32
+  LDFLAGS += -Wl,-m,elf_i386
+endif
+
+# set special flags per-system
+ifeq ($(OS), FREEBSD)
+  ifeq ($(ARCH_DETECTED), 64BITS_32)
+    $(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386)
+  endif
+endif
+ifeq ($(OS), LINUX)
+  LDLIBS += -ldl
+endif
+ifeq ($(OS), OSX)
+  # Select the proper SDK
+  # Also, SDKs are stored in a different location since XCode 4.3
+  OSX_SDK ?= $(shell sw_vers -productVersion | cut -f1 -f2 -d .)
+  OSX_XCODEMAJ = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f1 -d .)
+  OSX_XCODEMIN = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f2 -d .)
+  OSX_XCODEGE43 = $(shell echo "`expr $(OSX_XCODEMAJ) \>= 4``expr $(OSX_XCODEMIN) \>= 3`")
+  ifeq ($(OSX_XCODEGE43), 11)
+    OSX_SYSROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
+  else
+    OSX_SYSROOT := /Developer/SDKs
+  endif
+
+  ifeq ($(CPU), X86)
+    ifeq ($(ARCH_DETECTED), 64BITS)
+      CFLAGS += -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
+      LDLIBS += -ldl
+    else
+      CFLAGS += -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
+      LDLIBS += -ldl -read_only_relocs suppress
+    endif
+  endif
+endif
+
+# test for presence of SDL
+ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined)
+  SDL_CONFIG = $(CROSS_COMPILE)sdl-config
+  ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),)
+    $(error No SDL development libraries found!)
+  endif
+  SDL_CFLAGS  += $(shell $(SDL_CONFIG) --cflags)
+  SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs)
+endif
+CFLAGS += $(SDL_CFLAGS)
+LDLIBS += $(SDL_LDLIBS)
+
+# set mupen64plus core API header path
+ifneq ("$(APIDIR)","")
+  CFLAGS += "-I$(APIDIR)"
+else
+  TRYDIR = ../../../mupen64plus-core/src/api
+  ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
+    CFLAGS += -I$(TRYDIR)
+  else
+    TRYDIR = /usr/local/include/mupen64plus
+    ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
+      CFLAGS += -I$(TRYDIR)
+    else
+      TRYDIR = /usr/include/mupen64plus
+      ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","")
+        CFLAGS += -I$(TRYDIR)
+      else
+        $(error Mupen64Plus API header files not found! Use makefile parameter APIDIR to force a location.)
+      endif
+    endif
+  endif
+endif
+
+# reduced compile output when running make without V=1
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+    Q_CC = @echo '    CC  '$@;
+    Q_LD = @echo '    LD  '$@;
+endif
+endif
+
+# set base program pointers and flags
+CC        = $(CROSS_COMPILE)gcc
+CXX       = $(CROSS_COMPILE)g++
+RM       ?= rm -f
+INSTALL  ?= install
+MKDIR ?= mkdir -p
+COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+
+# set special flags for given Makefile parameters
+ifeq ($(DEBUG),1)
+  CFLAGS += -g
+  INSTALL_STRIP_FLAG ?= 
+else
+  ifneq ($(OS),OSX)
+    INSTALL_STRIP_FLAG ?= -s
+  endif
+endif
+ifeq ($(PLUGINDBG), 1)
+  CFLAGS += -D_DEBUG
+endif
+
+# set installation options
+ifeq ($(PREFIX),)
+  PREFIX := /usr/local
+endif
+ifeq ($(SHAREDIR),)
+  SHAREDIR := $(PREFIX)/share/mupen64plus
+endif
+ifeq ($(LIBDIR),)
+  LIBDIR := $(PREFIX)/lib
+endif
+ifeq ($(PLUGINDIR),)
+  PLUGINDIR := $(LIBDIR)/mupen64plus
+endif
+
+SRCDIR = ../../src
+OBJDIR = _obj$(POSTFIX)
+
+# list of source files to compile
+SOURCE = \
+       $(SRCDIR)/plugin.c \
+       $(SRCDIR)/autoconfig.c \
+       $(SRCDIR)/config.c
+
+ifeq ($(OS),MINGW)
+SOURCE += $(SRCDIR)/osal_dynamiclib_win32.c
+else
+SOURCE += $(SRCDIR)/osal_dynamiclib_unix.c
+endif
+
+# generate a list of object files build, make a temporary directory for them
+OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(filter %.c, $(SOURCE)))
+OBJDIRS = $(dir $(OBJECTS))
+$(shell $(MKDIR) $(OBJDIRS))
+
+# build targets
+TARGET = mupen64plus-input-sdl$(POSTFIX).$(SO_EXTENSION)
+
+targets:
+       @echo "Mupen64Plus-input-sdl makefile. "
+       @echo "  Targets:"
+       @echo "    all           == Build Mupen64Plus SDL input plugin"
+       @echo "    clean         == remove object files"
+       @echo "    rebuild       == clean and re-build all"
+       @echo "    install       == Install Mupen64Plus SDL input plugin"
+       @echo "    uninstall     == Uninstall Mupen64Plus SDL input plugin"
+       @echo "  Options:"
+       @echo "    BITS=32       == build 32-bit binaries on 64-bit machine"
+       @echo "    APIDIR=path   == path to find Mupen64Plus Core headers"
+       @echo "    OPTFLAGS=flag == compiler optimization (default: -O3 -flto)"
+       @echo "    WARNFLAGS=flag == compiler warning levels (default: -Wall)"
+       @echo "    PIC=(1|0)     == Force enable/disable of position independent code"
+       @echo "    POSTFIX=name  == String added to the name of the the build (default: '')"
+       @echo "  Install Options:"
+       @echo "    PREFIX=path   == install/uninstall prefix (default: /usr/local)"
+       @echo "    SHAREDIR=path == path to install shared data files (default: PREFIX/share/mupen64plus)"
+       @echo "    LIBDIR=path   == library prefix (default: PREFIX/lib)"
+       @echo "    PLUGINDIR=path == path to install plugin libraries (default: LIBDIR/mupen64plus)"
+       @echo "    DESTDIR=path  == path to prepend to all installation paths (only for packagers)"
+       @echo "  Debugging Options:"
+       @echo "    DEBUG=1       == add debugging symbols"
+       @echo "    PLUGINDBG=1   == print extra debugging information while running"
+       @echo "    V=1           == show verbose compiler output"
+
+all: $(TARGET)
+
+install: $(TARGET)
+       $(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)"
+       $(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)"
+       $(INSTALL) -d "$(DESTDIR)$(SHAREDIR)"
+       $(INSTALL) -m 0644 "../../data/InputAutoCfg.ini" "$(DESTDIR)$(SHAREDIR)"
+
+uninstall:
+       $(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)"
+       $(RM) "$(DESTDIR)$(SHAREDIR)/InputAutoCfg.ini"
+
+clean:
+       $(RM) -r $(OBJDIR) $(TARGET)
+
+rebuild: clean all
+
+# build dependency files
+CFLAGS += -MD
+-include $(OBJECTS:.o=.d)
+
+# standard build rules
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+       $(COMPILE.c) -o $@ $<
+
+$(TARGET): $(OBJECTS)
+       $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+.PHONY: all clean install uninstall targets
diff --git a/source/mupen64plus-input-sdl/src/autoconfig.c b/source/mupen64plus-input-sdl/src/autoconfig.c
new file mode 100644 (file)
index 0000000..f21aef0
--- /dev/null
@@ -0,0 +1,337 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - autoconfig.c                                  *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009-2013 Richard Goedeken                              *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <string.h>
+
+#include "m64p_types.h"
+#include "m64p_config.h"
+#include "osal_preproc.h"
+#include "autoconfig.h"
+#include "plugin.h"
+
+/* local definitions */
+#define INI_FILE_NAME "InputAutoCfg.ini"
+typedef struct {
+    m64p_handle pSrc;
+    m64p_handle pDst;
+} SCopySection;
+
+/* local functions */
+static char *StripSpace(char *pIn)
+{
+    char *pEnd = pIn + strlen(pIn) - 1;
+
+    while (*pIn == ' ' || *pIn == '\t' || *pIn == '\r' || *pIn == '\n')
+        pIn++;
+
+    while (pIn <= pEnd && (*pEnd == ' ' || *pEnd == '\t' || *pEnd == '\r' || *pEnd == '\n'))
+        *pEnd-- = 0;
+
+    return pIn;
+}
+
+static void CopyParamCallback(void * context, const char *ParamName, m64p_type ParamType)
+{
+    SCopySection *pCpyContext = (SCopySection *) context;
+    int paramInt;
+    float paramFloat;
+    char paramString[1024];
+
+    // handle the parameter copy depending upon type
+    switch (ParamType)
+    {
+        case M64TYPE_INT:
+        case M64TYPE_BOOL:
+            if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, &paramInt, sizeof(int)) == M64ERR_SUCCESS)
+                ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, &paramInt);
+            break;
+        case M64TYPE_FLOAT:
+            if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, &paramFloat, sizeof(float)) == M64ERR_SUCCESS)
+                ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, &paramFloat);
+            break;
+        case M64TYPE_STRING:
+            if (ConfigGetParameter(pCpyContext->pSrc, ParamName, ParamType, paramString, 1024) == M64ERR_SUCCESS)
+                ConfigSetParameter(pCpyContext->pDst, ParamName, ParamType, paramString);
+            break;
+        default:
+            // this should never happen
+            DebugMessage(M64MSG_ERROR, "Unknown source parameter type %i in copy callback", (int) ParamType);
+            return;
+    }
+}
+
+/* global functions */
+int auto_copy_inputconfig(const char *pccSourceSectionName, const char *pccDestSectionName, const char *sdlJoyName)
+{
+    SCopySection cpyContext;
+
+    if (ConfigOpenSection(pccSourceSectionName, &cpyContext.pSrc) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't open source config section '%s' for copying", pccSourceSectionName);
+        return 0;
+    }
+
+    if (ConfigOpenSection(pccDestSectionName, &cpyContext.pDst) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't open destination config section '%s' for copying", pccDestSectionName);
+        return 0;
+    }
+
+    // set the 'name' parameter
+    if (sdlJoyName != NULL)
+    {
+        if (ConfigSetParameter(cpyContext.pDst, "name", M64TYPE_STRING, sdlJoyName) != M64ERR_SUCCESS)
+        {
+            DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: Couldn't set 'name' parameter to '%s' in section '%s'", sdlJoyName, pccDestSectionName);
+            return 0;
+        }
+    }
+
+    // the copy gets done by the callback function
+    if (ConfigListParameters(cpyContext.pSrc, (void *) &cpyContext, CopyParamCallback) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_ERROR, "auto_copy_inputconfig: parameter list copy failed");
+        return 0;
+    }
+
+    return 1;
+}
+
+int auto_set_defaults(int iDeviceIdx, const char *joySDLName)
+{
+    FILE *pfIn;
+    m64p_handle pConfig = NULL;
+    const char *CfgFilePath = ConfigGetSharedDataFilepath(INI_FILE_NAME);
+    enum { E_NAME_SEARCH, E_NAME_FOUND, E_PARAM_READ } eParseState;
+    char *pchIni, *pchNextLine, *pchCurLine;
+    long iniLength;
+    int ControllersFound = 0;
+
+    /* if we couldn't get a name (no joystick plugged in to given port), then return with a failure */
+    if (joySDLName == NULL)
+        return 0;
+    /* if we couldn't find the shared data file, dump an error and return */
+    if (CfgFilePath == NULL || strlen(CfgFilePath) < 1)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't find config file '%s'", INI_FILE_NAME);
+        return 0;
+    }
+
+    /* read the input auto-config .ini file */
+    pfIn = fopen(CfgFilePath, "rb");
+    if (pfIn == NULL)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't open config file '%s'", CfgFilePath);
+        return 0;
+    }
+    fseek(pfIn, 0L, SEEK_END);
+    iniLength = ftell(pfIn);
+    fseek(pfIn, 0L, SEEK_SET);
+    pchIni = (char *) malloc(iniLength + 1);
+    if (pchIni == NULL)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't allocate %li bytes for config file '%s'", iniLength, CfgFilePath);
+        fclose(pfIn);
+        return 0;
+    }
+    if (fread(pchIni, 1, iniLength, pfIn) != iniLength)
+    {
+        DebugMessage(M64MSG_ERROR, "File read failed for %li bytes of config file '%s'", iniLength, CfgFilePath);
+        free(pchIni);
+        fclose(pfIn);
+        return 0;
+    }
+    fclose(pfIn);
+    pchIni[iniLength] = 0;
+
+    /* parse the INI file, line by line */
+    pchNextLine = pchIni;
+    eParseState = E_NAME_SEARCH;
+    while (pchNextLine != NULL && *pchNextLine != 0)
+    {
+        char *pivot = NULL;
+        /* set up character pointers */
+        pchCurLine = pchNextLine;
+        pchNextLine = strchr(pchNextLine, '\n');
+        if (pchNextLine != NULL)
+            *pchNextLine++ = 0;
+        pchCurLine = StripSpace(pchCurLine);
+
+        /* handle blank/comment lines */
+        if (strlen(pchCurLine) < 1 || *pchCurLine == ';' || *pchCurLine == '#')
+            continue;
+
+        /* handle section (joystick name in ini file) */
+        if (*pchCurLine == '[' && pchCurLine[strlen(pchCurLine)-1] == ']')
+        {
+            char Word[64];
+            char *wordPtr;
+            int  joyFound = 1;
+
+            if (eParseState == E_PARAM_READ)
+            {
+                /* we've finished parsing all parameters for the discovered input device */
+                free(pchIni);
+                return ControllersFound;
+            }
+            else if (eParseState == E_NAME_FOUND)
+            {
+                /* this is an equivalent device name to the one we're looking for (and found); keep looking for parameters */
+                continue;
+            }
+            /* we need to look through the device name word by word to see if it matches the joySDLName that we're looking for */ 
+            pchCurLine[strlen(pchCurLine)-1] = 0;
+            wordPtr = StripSpace(pchCurLine + 1);
+            /* first, if there is a preceding system name in this .ini device name, and the system matches, then strip out */
+#if defined(__unix__)
+            if (strncmp(wordPtr, "Unix:", 5) == 0)
+                wordPtr = StripSpace(wordPtr + 5);
+#endif
+#if defined(__linux__)
+            if (strncmp(wordPtr, "Linux:", 6) == 0)
+                wordPtr = StripSpace(wordPtr + 6);
+#endif
+#if defined(__APPLE__)
+            if (strncmp(wordPtr, "OSX:", 4) == 0)
+                wordPtr = StripSpace(wordPtr + 4);
+#endif
+#if defined(WIN32)
+            if (strncmp(wordPtr, "Win32:", 6) == 0)
+                wordPtr = StripSpace(wordPtr + 6);
+#endif
+            /* search in the .ini device name for all the words in the joystick name.  If any are missing, then this is not the right joystick model */
+            while (wordPtr != NULL && strlen(wordPtr) > 0)
+            {
+                char *nextSpace = strchr(wordPtr, ' ');
+                if (nextSpace == NULL)
+                {
+                    strncpy(Word, wordPtr, 63);
+                    Word[63] = 0;
+                    wordPtr = NULL;
+                }
+                else
+                {
+                    int length = (int) (nextSpace - wordPtr);
+                    if (length > 63) length = 63;
+                    strncpy(Word, wordPtr, length);
+                    Word[length] = 0;
+                    wordPtr = nextSpace + 1;
+                }
+                if (strcasestr(joySDLName, Word) == NULL)
+                    joyFound = 0;
+            }
+            /* if we found the right joystick, then open up the core config section to store parameters and set the 'device' param */
+            if (joyFound)
+            {
+                char SectionName[32];
+                sprintf(SectionName, "AutoConfig%i", ControllersFound);
+                if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
+                {
+                    DebugMessage(M64MSG_ERROR, "auto_set_defaults(): Couldn't open config section '%s'", SectionName);
+                    free(pchIni);
+                    return 0;
+                }
+                eParseState = E_NAME_FOUND;
+                ControllersFound++;
+                ConfigSetParameter(pConfig, "device", M64TYPE_INT, &iDeviceIdx);
+            }
+            continue;
+        }
+
+        /* handle parameters */
+        pivot = strchr(pchCurLine, '=');
+        if (pivot != NULL)
+        {
+            /* if we haven't found the correct section yet, just skip this */
+            if (eParseState == E_NAME_SEARCH)
+                continue;
+            eParseState = E_PARAM_READ;
+            /* otherwise, store this parameter in the current active joystick config */
+            *pivot++ = 0;
+            pchCurLine = StripSpace(pchCurLine);
+            pivot = StripSpace(pivot);
+            if (strcasecmp(pchCurLine, "plugin") == 0 || strcasecmp(pchCurLine, "device") == 0)
+            {
+                int iVal = atoi(pivot);
+                ConfigSetParameter(pConfig, pchCurLine, M64TYPE_INT, &iVal);
+            }
+            else if (strcasecmp(pchCurLine, "plugged") == 0 || strcasecmp(pchCurLine, "mouse") == 0)
+            {
+                int bVal = (strcasecmp(pivot, "true") == 0);
+                ConfigSetParameter(pConfig, pchCurLine, M64TYPE_BOOL, &bVal);
+            }
+            else
+            {
+                ConfigSetParameter(pConfig, pchCurLine, M64TYPE_STRING, pivot);
+            }
+            continue;
+        }
+
+        /* handle keywords */
+        if (pchCurLine[strlen(pchCurLine)-1] == ':')
+        {
+            /* if we haven't found the correct section yet, just skip this */
+            if (eParseState == E_NAME_SEARCH)
+                continue;
+            /* otherwise parse the keyword */
+            if (strcmp(pchCurLine, "__NextController:") == 0)
+            {
+                char SectionName[32];
+                /* if there are no more N64 controller spaces left, then exit */
+                if (ControllersFound == 4)
+                {
+                    free(pchIni);
+                    return ControllersFound;
+                }
+                /* otherwise go to the next N64 controller */
+                sprintf(SectionName, "AutoConfig%i", ControllersFound);
+                if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
+                {
+                    DebugMessage(M64MSG_ERROR, "auto_set_defaults(): Couldn't open config section '%s'", SectionName);
+                    free(pchIni);
+                    return ControllersFound;
+                }
+                ControllersFound++;
+                ConfigSetParameter(pConfig, "device", M64TYPE_INT, &iDeviceIdx);
+            }
+            else
+            {
+                DebugMessage(M64MSG_ERROR, "Unknown keyword '%s' in %s", pchCurLine, INI_FILE_NAME);
+            }
+            continue;
+        }
+
+        /* unhandled line in .ini file */
+        DebugMessage(M64MSG_ERROR, "Invalid line in %s: '%s'", INI_FILE_NAME, pchCurLine);
+    }
+
+    if (eParseState == E_PARAM_READ)
+    {
+        /* we've finished parsing all parameters for the discovered input device, which is the last in the .ini file */
+        free(pchIni);
+        return ControllersFound;
+    }
+
+    free(pchIni);
+    return 0;
+}
+
+
diff --git a/source/mupen64plus-input-sdl/src/autoconfig.h b/source/mupen64plus-input-sdl/src/autoconfig.h
new file mode 100644 (file)
index 0000000..cfdb5c7
--- /dev/null
@@ -0,0 +1,29 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - autoconfig.h                                  *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef __AUTOCONFIG_H__
+#define __AUTOCONFIG_H__
+
+extern int auto_copy_inputconfig(const char *pccSourceSectionName, const char *pccDestSectionName, const char *sdlJoyName);
+extern int auto_set_defaults(int iDeviceIdx, const char *joySDLName);
+
+#endif /* __AUTOCONFIG_H__ */
+
diff --git a/source/mupen64plus-input-sdl/src/config.c b/source/mupen64plus-input-sdl/src/config.c
new file mode 100644 (file)
index 0000000..1a6fa55
--- /dev/null
@@ -0,0 +1,799 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - config.c                                      *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009-2013 Richard Goedeken                              *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <SDL.h>
+
+#define M64P_PLUGIN_PROTOTYPES 1
+#include "m64p_types.h"
+#include "m64p_plugin.h"
+#include "m64p_config.h"
+
+#include "osal_preproc.h"
+#include "autoconfig.h"
+#include "plugin.h"
+
+#include "config.h"
+
+#define HAT_POS_NAME( hat )         \
+       ((hat == SDL_HAT_UP) ? "Up" :        \
+       ((hat == SDL_HAT_DOWN) ? "Down" :    \
+       ((hat == SDL_HAT_LEFT) ? "Left" :    \
+       ((hat == SDL_HAT_RIGHT) ? "Right" :  \
+         "None"))))
+
+typedef enum {
+    E_MODE_MANUAL = 0,
+    E_MODE_NAMED_AUTO,
+    E_MODE_FULL_AUTO
+ } eModeType;
+
+static const char *button_names[] = {
+    "DPad R",       // R_DPAD
+    "DPad L",       // L_DPAD
+    "DPad D",       // D_DPAD
+    "DPad U",       // U_DPAD
+    "Start",        // START_BUTTON
+    "Z Trig",       // Z_TRIG
+    "B Button",     // B_BUTTON
+    "A Button",     // A_BUTTON
+    "C Button R",   // R_CBUTTON
+    "C Button L",   // L_CBUTTON
+    "C Button D",   // D_CBUTTON
+    "C Button U",   // U_CBUTTON
+    "R Trig",       // R_TRIG
+    "L Trig",       // L_TRIG
+    "Mempak switch",
+    "Rumblepak switch",
+    "X Axis",       // X_AXIS
+    "Y Axis"        // Y_AXIS
+};
+
+/* static functions */
+static int get_hat_pos_by_name( const char *name )
+{
+    if( !strcasecmp( name, "up" ) )
+        return SDL_HAT_UP;
+    if( !strcasecmp( name, "down" ) )
+        return SDL_HAT_DOWN;
+    if( !strcasecmp( name, "left" ) )
+        return SDL_HAT_LEFT;
+    if( !strcasecmp( name, "right" ) )
+        return SDL_HAT_RIGHT;
+    DebugMessage(M64MSG_WARNING, "get_hat_pos_by_name(): direction '%s' unknown", name);
+    return -1;
+}
+
+static void clear_controller(int iCtrlIdx)
+{
+    int b;
+
+    controller[iCtrlIdx].device = DEVICE_NO_JOYSTICK;
+    controller[iCtrlIdx].control->Present = 0;
+    controller[iCtrlIdx].control->RawData = 0;
+    controller[iCtrlIdx].control->Plugin = PLUGIN_NONE;
+    for( b = 0; b < 16; b++ )
+    {
+        controller[iCtrlIdx].button[b].button = -1;
+        controller[iCtrlIdx].button[b].key = SDL_SCANCODE_UNKNOWN;
+        controller[iCtrlIdx].button[b].axis = -1;
+        controller[iCtrlIdx].button[b].axis_deadzone = -1;
+        controller[iCtrlIdx].button[b].hat = -1;
+        controller[iCtrlIdx].button[b].hat_pos = -1;
+        controller[iCtrlIdx].button[b].mouse = -1;
+    }
+    for( b = 0; b < 2; b++ )
+    {
+        controller[iCtrlIdx].mouse_sens[b] = 2.0;
+        controller[iCtrlIdx].axis_deadzone[b] = 4096;
+        controller[iCtrlIdx].axis_peak[b] = 32768;
+        controller[iCtrlIdx].axis[b].button_a = controller[iCtrlIdx].axis[b].button_b = -1;
+        controller[iCtrlIdx].axis[b].key_a = controller[iCtrlIdx].axis[b].key_b = SDL_SCANCODE_UNKNOWN;
+        controller[iCtrlIdx].axis[b].axis_a = -1;
+        controller[iCtrlIdx].axis[b].axis_dir_a = 1;
+        controller[iCtrlIdx].axis[b].axis_b = -1;
+        controller[iCtrlIdx].axis[b].axis_dir_b = 1;
+        controller[iCtrlIdx].axis[b].hat = -1;
+        controller[iCtrlIdx].axis[b].hat_pos_a = -1;
+        controller[iCtrlIdx].axis[b].hat_pos_b = -1;
+    }
+}
+
+static const char * get_sdl_joystick_name(int iCtrlIdx)
+{
+    static char JoyName[256];
+    const char *joySDLName;
+    int joyWasInit = SDL_WasInit(SDL_INIT_JOYSTICK);
+    
+    /* initialize the joystick subsystem if necessary */
+    if (!joyWasInit)
+        if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
+        {
+            DebugMessage(M64MSG_ERROR, "Couldn't init SDL joystick subsystem: %s", SDL_GetError() );
+            return NULL;
+        }
+
+    /* get the name of the corresponding joystick */
+    joySDLName = SDL_JoystickName(iCtrlIdx);
+
+    /* copy the name to our local string */
+    if (joySDLName != NULL)
+    {
+        strncpy(JoyName, joySDLName, 255);
+        JoyName[255] = 0;
+    }
+
+    /* quit the joystick subsystem if necessary */
+    if (!joyWasInit)
+        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+
+    /* if the SDL function had an error, then return NULL, otherwise return local copy of joystick name */
+    if (joySDLName == NULL)
+        return NULL;
+    else
+        return JoyName;
+}
+
+static int get_sdl_num_joysticks(void)
+{
+    int numJoysticks = 0;
+    int joyWasInit = SDL_WasInit(SDL_INIT_JOYSTICK);
+    
+    /* initialize the joystick subsystem if necessary */
+    if (!joyWasInit)
+        if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
+        {
+            DebugMessage(M64MSG_ERROR, "Couldn't init SDL joystick subsystem: %s", SDL_GetError() );
+            return 0;
+        }
+
+    /* get thenumber of joysticks */
+    numJoysticks = SDL_NumJoysticks();
+
+    /* quit the joystick subsystem if necessary */
+    if (!joyWasInit)
+        SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+
+    return numJoysticks;
+}
+
+/////////////////////////////////////
+// load_controller_config()
+// return value: 1 = OK
+//               0 = fail: couldn't open config section
+
+static int load_controller_config(const char *SectionName, int i, int sdlDeviceIdx)
+{
+    m64p_handle pConfig;
+    char input_str[256], value1_str[16], value2_str[16];
+    const char *config_ptr;
+    int j;
+
+    /* Open the configuration section for this controller */
+    if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't open config section '%s'", SectionName);
+        return 0;
+    }
+
+    /* set SDL device number */
+    controller[i].device = sdlDeviceIdx;
+
+    /* throw warnings if 'plugged' or 'plugin' are missing */
+    if (ConfigGetParameter(pConfig, "plugged", M64TYPE_BOOL, &controller[i].control->Present, sizeof(int)) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_WARNING, "missing 'plugged' parameter from config section %s. Setting to 1 (true).", SectionName);
+        controller[i].control->Present = 1;
+    }
+    if (ConfigGetParameter(pConfig, "plugin", M64TYPE_INT, &controller[i].control->Plugin, sizeof(int)) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_WARNING, "missing 'plugin' parameter from config section %s. Setting to 1 (none).", SectionName);
+        controller[i].control->Plugin = PLUGIN_NONE;
+    }
+    /* load optional parameters */
+    ConfigGetParameter(pConfig, "mouse", M64TYPE_BOOL, &controller[i].mouse, sizeof(int));
+    if (ConfigGetParameter(pConfig, "MouseSensitivity", M64TYPE_STRING, input_str, 256) == M64ERR_SUCCESS)
+    {
+        if (sscanf(input_str, "%f,%f", &controller[i].mouse_sens[0], &controller[i].mouse_sens[1]) != 2)
+            DebugMessage(M64MSG_WARNING, "parsing error in MouseSensitivity parameter for controller %i", i + 1);
+    }
+    if (ConfigGetParameter(pConfig, "AnalogDeadzone", M64TYPE_STRING, input_str, 256) == M64ERR_SUCCESS)
+    {
+        if (sscanf(input_str, "%i,%i", &controller[i].axis_deadzone[0], &controller[i].axis_deadzone[1]) != 2)
+            DebugMessage(M64MSG_WARNING, "parsing error in AnalogDeadzone parameter for controller %i", i + 1);
+    }
+    if (ConfigGetParameter(pConfig, "AnalogPeak", M64TYPE_STRING, input_str, 256) == M64ERR_SUCCESS)
+    {
+        if (sscanf(input_str, "%i,%i", &controller[i].axis_peak[0], &controller[i].axis_peak[1]) != 2)
+            DebugMessage(M64MSG_WARNING, "parsing error in AnalogPeak parameter for controller %i", i + 1);
+    }
+    /* load configuration for all the digital buttons */
+    for (j = 0; j < X_AXIS; j++)
+    {
+        if (ConfigGetParameter(pConfig, button_names[j], M64TYPE_STRING, input_str, 256) != M64ERR_SUCCESS)
+        {
+            DebugMessage(M64MSG_WARNING, "missing config key '%s' for controller %i button %i", button_names[j], i+1, j);
+            continue;
+        }
+        if ((config_ptr = strstr(input_str, "key")) != NULL)
+            if (sscanf(config_ptr, "key(%i)", (int *) &controller[i].button[j].key) != 1)
+                DebugMessage(M64MSG_WARNING, "parsing error in key() parameter of button '%s' for controller %i", button_names[j], i + 1);
+        if ((config_ptr = strstr(input_str, "button")) != NULL)
+            if (sscanf(config_ptr, "button(%i)", &controller[i].button[j].button) != 1)
+                DebugMessage(M64MSG_WARNING, "parsing error in button() parameter of button '%s' for controller %i", button_names[j], i + 1);
+        if ((config_ptr = strstr(input_str, "axis")) != NULL)
+        {
+            char chAxisDir;
+            if (sscanf(config_ptr, "axis(%d%c,%d", &controller[i].button[j].axis, &chAxisDir, &controller[i].button[j].axis_deadzone) != 3 &&
+                sscanf(config_ptr, "axis(%i%c", &controller[i].button[j].axis, &chAxisDir) != 2)
+                DebugMessage(M64MSG_WARNING, "parsing error in axis() parameter of button '%s' for controller %i", button_names[j], i + 1);
+            controller[i].button[j].axis_dir = (chAxisDir == '+' ? 1 : (chAxisDir == '-' ? -1 : 0));
+        }
+        if ((config_ptr = strstr(input_str, "hat")) != NULL)
+        {
+            char *lastchar = NULL;
+            if (sscanf(config_ptr, "hat(%i %15s", &controller[i].button[j].hat, value1_str) != 2)
+                DebugMessage(M64MSG_WARNING, "parsing error in hat() parameter of button '%s' for controller %i", button_names[j], i + 1);
+            value1_str[15] = 0;
+            /* chop off the last character of value1_str if it is the closing parenthesis */
+            lastchar = &value1_str[strlen(value1_str) - 1];
+            if (lastchar > value1_str && *lastchar == ')') *lastchar = 0;
+            controller[i].button[j].hat_pos = get_hat_pos_by_name(value1_str);
+        }
+        if ((config_ptr = strstr(input_str, "mouse")) != NULL)
+            if (sscanf(config_ptr, "mouse(%i)", &controller[i].button[j].mouse) != 1)
+                DebugMessage(M64MSG_WARNING, "parsing error in mouse() parameter of button '%s' for controller %i", button_names[j], i + 1);
+    }
+    /* load configuration for the 2 analog joystick axes */
+    for (j = X_AXIS; j <= Y_AXIS; j++)
+    {
+        int axis_idx = j - X_AXIS;
+        if (ConfigGetParameter(pConfig, button_names[j], M64TYPE_STRING, input_str, 256) != M64ERR_SUCCESS)
+        {
+            DebugMessage(M64MSG_WARNING, "missing config key '%s' for controller %i axis %i", button_names[j], i+1, axis_idx);
+            continue;
+        }
+        if ((config_ptr = strstr(input_str, "key")) != NULL)
+            if (sscanf(config_ptr, "key(%i,%i)", (int *) &controller[i].axis[axis_idx].key_a, (int *) &controller[i].axis[axis_idx].key_b) != 2)
+                DebugMessage(M64MSG_WARNING, "parsing error in key() parameter of axis '%s' for controller %i", button_names[j], i + 1);
+        if ((config_ptr = strstr(input_str, "button")) != NULL)
+            if (sscanf(config_ptr, "button(%i,%i)", &controller[i].axis[axis_idx].button_a, &controller[i].axis[axis_idx].button_b) != 2)
+                DebugMessage(M64MSG_WARNING, "parsing error in button() parameter of axis '%s' for controller %i", button_names[j], i + 1);
+        if ((config_ptr = strstr(input_str, "axis")) != NULL)
+        {
+            char chAxisDir1, chAxisDir2;
+            if (sscanf(config_ptr, "axis(%i%c,%i%c)", &controller[i].axis[axis_idx].axis_a, &chAxisDir1,
+                                                      &controller[i].axis[axis_idx].axis_b, &chAxisDir2) != 4)
+                DebugMessage(M64MSG_WARNING, "parsing error in axis() parameter of axis '%s' for controller %i", button_names[j], i + 1);
+            controller[i].axis[axis_idx].axis_dir_a = (chAxisDir1 == '+' ? 1 : (chAxisDir1 == '-' ? -1 : 0));
+            controller[i].axis[axis_idx].axis_dir_b = (chAxisDir2 == '+' ? 1 : (chAxisDir2 == '-' ? -1 : 0));
+        }
+        if ((config_ptr = strstr(input_str, "hat")) != NULL)
+        {
+            char *lastchar = NULL;
+            if (sscanf(config_ptr, "hat(%i %15s %15s", &controller[i].axis[axis_idx].hat, value1_str, value2_str) != 3)
+                DebugMessage(M64MSG_WARNING, "parsing error in hat() parameter of axis '%s' for controller %i", button_names[j], i + 1);
+            value1_str[15] = value2_str[15] = 0;
+            /* chop off the last character of value2_str if it is the closing parenthesis */
+            lastchar = &value2_str[strlen(value2_str) - 1];
+            if (lastchar > value2_str && *lastchar == ')') *lastchar = 0;
+            controller[i].axis[axis_idx].hat_pos_a = get_hat_pos_by_name(value1_str);
+            controller[i].axis[axis_idx].hat_pos_b = get_hat_pos_by_name(value2_str);
+        }
+    }
+
+    return 1;
+}
+
+static void init_controller_config(int iCtrlIdx, const char *pccDeviceName, eModeType mode)
+{
+    m64p_handle pConfig;
+    char SectionName[32], Param[32], ParamString[128];
+    int j;
+
+    /* Delete the configuration section for this controller, so we can use SetDefaults and save the help comments also */
+    sprintf(SectionName, "Input-SDL-Control%i", iCtrlIdx + 1);
+    ConfigDeleteSection(SectionName);
+    /* Open the configuration section for this controller (create a new one) */
+    if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't open config section '%s'", SectionName);
+        return;
+    }
+
+    /* save the general controller parameters */
+    ConfigSetDefaultFloat(pConfig, "version", CONFIG_VERSION, "Mupen64Plus SDL Input Plugin config parameter version number.  Please don't change this version number.");
+    ConfigSetDefaultInt(pConfig, "mode", (int) mode, "Controller configuration mode: 0=Fully Manual, 1=Auto with named SDL Device, 2=Fully automatic");
+    ConfigSetDefaultInt(pConfig, "device", controller[iCtrlIdx].device, "Specifies which joystick is bound to this controller: -1=No joystick, 0 or more= SDL Joystick number");
+    ConfigSetDefaultString(pConfig, "name", pccDeviceName, "SDL joystick name (or Keyboard)");
+    ConfigSetDefaultBool(pConfig, "plugged", controller[iCtrlIdx].control->Present, "Specifies whether this controller is 'plugged in' to the simulated N64");
+    ConfigSetDefaultInt(pConfig, "plugin", controller[iCtrlIdx].control->Plugin, "Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 5=Rumble pak");
+    ConfigSetDefaultBool(pConfig, "mouse", controller[iCtrlIdx].mouse, "If True, then mouse buttons may be used with this controller");
+
+    sprintf(Param, "%.2f,%.2f", controller[iCtrlIdx].mouse_sens[0], controller[iCtrlIdx].mouse_sens[1]);
+    ConfigSetDefaultString(pConfig, "MouseSensitivity", Param, "Scaling factor for mouse movements.  For X, Y axes.");
+    sprintf(Param, "%i,%i", controller[iCtrlIdx].axis_deadzone[0], controller[iCtrlIdx].axis_deadzone[1]);
+    ConfigSetDefaultString(pConfig, "AnalogDeadzone", Param, "The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0.  For X, Y axes.");
+    sprintf(Param, "%i,%i", controller[iCtrlIdx].axis_peak[0], controller[iCtrlIdx].axis_peak[1]);
+    ConfigSetDefaultString(pConfig, "AnalogPeak", Param, "An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80).  For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value");
+
+    /* save configuration for all the digital buttons */
+    for (j = 0; j < X_AXIS; j++ )
+    {
+        const char *Help;
+        int len = 0;
+        ParamString[0] = 0;
+        if (controller[iCtrlIdx].button[j].key > 0)
+        {
+            sprintf(Param, "key(%i) ", controller[iCtrlIdx].button[j].key);
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].button[j].button >= 0)
+        {
+            sprintf(Param, "button(%i) ", controller[iCtrlIdx].button[j].button);
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].button[j].axis >= 0)
+        {
+            if (controller[iCtrlIdx].button[j].axis_deadzone >= 0)
+                sprintf(Param, "axis(%i%c,%i) ", controller[iCtrlIdx].button[j].axis, (controller[iCtrlIdx].button[j].axis_dir == -1) ? '-' : '+',
+                        controller[iCtrlIdx].button[j].axis_deadzone);
+            else
+                sprintf(Param, "axis(%i%c) ", controller[iCtrlIdx].button[j].axis, (controller[iCtrlIdx].button[j].axis_dir == -1) ? '-' : '+');
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].button[j].hat >= 0)
+        {
+            sprintf(Param, "hat(%i %s) ", controller[iCtrlIdx].button[j].hat, HAT_POS_NAME(controller[iCtrlIdx].button[j].hat_pos));
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].button[j].mouse >= 0)
+        {
+            sprintf(Param, "mouse(%i) ", controller[iCtrlIdx].button[j].mouse);
+            strcat(ParamString, Param);
+        }
+        if (j == 0)
+            Help = "Digital button configuration mappings";
+        else
+            Help = NULL;
+        /* if last character is a space, chop it off */
+        len = strlen(ParamString);
+        if (len > 0 && ParamString[len-1] == ' ')
+            ParamString[len-1] = 0;
+        ConfigSetDefaultString(pConfig, button_names[j], ParamString, Help);
+    }
+
+    /* save configuration for the 2 analog axes */
+    for (j = 0; j < 2; j++ )
+    {
+        const char *Help;
+        int len = 0;
+        ParamString[0] = 0;
+        if (controller[iCtrlIdx].axis[j].key_a > 0 && controller[iCtrlIdx].axis[j].key_b > 0)
+        {
+            sprintf(Param, "key(%i,%i) ", controller[iCtrlIdx].axis[j].key_a, controller[iCtrlIdx].axis[j].key_b);
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].axis[j].button_a >= 0 && controller[iCtrlIdx].axis[j].button_b >= 0)
+        {
+            sprintf(Param, "button(%i,%i) ", controller[iCtrlIdx].axis[j].button_a, controller[iCtrlIdx].axis[j].button_b);
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].axis[j].axis_a >= 0 && controller[iCtrlIdx].axis[j].axis_b >= 0)
+        {
+            sprintf(Param, "axis(%i%c,%i%c) ", controller[iCtrlIdx].axis[j].axis_a, (controller[iCtrlIdx].axis[j].axis_dir_a <= 0) ? '-' : '+',
+                                               controller[iCtrlIdx].axis[j].axis_b, (controller[iCtrlIdx].axis[j].axis_dir_b <= 0) ? '-' : '+' );
+            strcat(ParamString, Param);
+        }
+        if (controller[iCtrlIdx].axis[j].hat >= 0)
+        {
+            sprintf(Param, "hat(%i %s %s) ", controller[iCtrlIdx].axis[j].hat,
+                                             HAT_POS_NAME(controller[iCtrlIdx].axis[j].hat_pos_a),
+                                             HAT_POS_NAME(controller[iCtrlIdx].axis[j].hat_pos_b));
+            strcat(ParamString, Param);
+        }
+        if (j == 0)
+            Help = "Analog axis configuration mappings";
+        else
+            Help = NULL;
+        /* if last character is a space, chop it off */
+        len = strlen(ParamString);
+        if (len > 0 && ParamString[len-1] == ' ')
+            ParamString[len-1] = 0;
+        ConfigSetDefaultString(pConfig, button_names[X_AXIS + j], ParamString, Help);
+    }
+
+}
+
+static int setup_auto_controllers(int bPreConfig, int n64CtrlStart, int sdlCtrlIdx, const char *sdlJoyName, eModeType ControlMode[], eModeType OrigControlMode[], char DeviceName[][256])
+{
+    char SectionName[32];
+    int ActiveControllers = 0;
+    int j;
+
+    /* create auto-config section(s) for this joystick (if this joystick is in the InputAutoConfig.ini) */
+    int ControllersFound = auto_set_defaults(sdlCtrlIdx, sdlJoyName);
+    if (ControllersFound == 0)
+        return 0;
+
+    /* copy the auto-config settings to the controller config section, and load our plugin joystick config from this */
+    sprintf(SectionName, "Input-SDL-Control%i", n64CtrlStart + 1);
+    if (OrigControlMode[n64CtrlStart] == E_MODE_FULL_AUTO)
+        auto_copy_inputconfig("AutoConfig0", SectionName, sdlJoyName);
+    else
+        auto_copy_inputconfig("AutoConfig0", SectionName, NULL);  // don't overwrite 'name' parameter if original mode was "named auto"
+    if (load_controller_config("AutoConfig0", n64CtrlStart, sdlCtrlIdx) > 0)
+    {
+        if (!bPreConfig)
+            DebugMessage(M64MSG_INFO, "N64 Controller #%i: Using auto-config with SDL joystick %i ('%s')", n64CtrlStart+1, sdlCtrlIdx, sdlJoyName);
+        ActiveControllers++;
+        ConfigSaveSection(SectionName);
+    }
+    else
+    {
+        if (!bPreConfig)
+            DebugMessage(M64MSG_ERROR, "Autoconfig data invalid for SDL joystick '%s'", sdlJoyName);
+    }
+    ConfigDeleteSection("AutoConfig0");
+
+    /* we have to handle the unfortunate case of a USB device mapping more than > 1 controller */
+    if (ControllersFound > 1)
+    {
+        for (j = 1; j < ControllersFound; j++)
+        {
+            char AutoSectionName[32];
+            sprintf(AutoSectionName, "AutoConfig%i", j);
+            /* if this would be > 4th controller, then just delete the auto-config */
+            if (n64CtrlStart + j >= 4)
+            {
+                ConfigDeleteSection(AutoSectionName);
+                continue;
+            }
+            /* look for another N64 controller that is in AUTO mode */
+            if (ControlMode[n64CtrlStart+j] == E_MODE_FULL_AUTO ||
+                (ControlMode[n64CtrlStart+j] == E_MODE_NAMED_AUTO && strncmp(DeviceName[n64CtrlStart+j], sdlJoyName, 255) == 0))
+            {
+                sprintf(SectionName, "Input-SDL-Control%i", n64CtrlStart + j + 1);
+                /* load our plugin joystick settings from the autoconfig */
+                if (load_controller_config(AutoSectionName, n64CtrlStart+j, sdlCtrlIdx) > 0)
+                {
+                    /* copy the auto-config settings to the controller config section */
+                    if (OrigControlMode[n64CtrlStart+j] == E_MODE_FULL_AUTO)
+                        auto_copy_inputconfig(AutoSectionName, SectionName, sdlJoyName);
+                    else
+                        auto_copy_inputconfig(AutoSectionName, SectionName, NULL);  // don't overwrite 'name' parameter if original mode was "named auto"
+                    if (!bPreConfig)
+                        DebugMessage(M64MSG_INFO, "N64 Controller #%i: Using auto-config with SDL joystick %i ('%s')", n64CtrlStart+j+1, sdlCtrlIdx, sdlJoyName);
+                    ActiveControllers++;
+                    ConfigSaveSection(SectionName);
+                    /* set the local controller mode to Manual so that we won't re-configure this controller in the next loop */
+                    ControlMode[n64CtrlStart+j] = E_MODE_MANUAL;
+                }
+                else
+                {
+                    if (!bPreConfig)
+                        DebugMessage(M64MSG_ERROR, "Autoconfig data invalid for SDL device '%s'", sdlJoyName);
+                }
+                /* delete the autoconfig section */
+                ConfigDeleteSection(AutoSectionName);
+            }
+        }
+    }
+
+    return ActiveControllers;
+}
+
+/* global functions */
+
+/* There are 4 special section parameters: version, mode, device, and name.  There are also 24 regular
+ * parameters: plugged, plugin, mouse, MouseSensitivity, DPad R/L/D/U, Start, Z/L/R Trigger, A/B button,
+ * C Button R/L/D/U, Mempak/Rumblepak switch, X/Y Axis, AnalogDeadzone, AnalogPeak.
+ *
+ * The N64 controller configuration behavior is regulated by the 'mode' parameter.  If this parameter is
+ * 0 (Fully Manual), then all configuration data is loaded and parsed without changes or autoconfig from
+ * the configuration section.  Any errors or warnings are printed.  If the mode parameter is 1 (Auto with
+ * named SDL Device), then the code below searches through the available SDL joysticks for one which
+ * matches with the 'name' parameter in the config section.  If a match is found, then the corresponding
+ * autoconfig is loaded and the regular parameters from the config section are updated with the
+ * autoconfig'ed settings.  If the mode parameter is 2 (Fully Auto), then the code below searches through
+ * all available detected SDL joysticks to try and find an autoconfig for each.  If an autoconfig match is
+ * found, then it is loaded and all config parameters (including device, name, and the regular parameters)
+ * are updated.
+ *
+ * This function is called with bPreConfig=true from the PluginStartup() function.  The purpose of this
+ * call is to load the 4 configuration sections with autoconfig data if necessary for a GUI front-end.
+ * When we are called with bPreConfig=true, we should only print warning/error messages and not info/status.
+ * This function is also called right before running the ROM game from InitiateControllers() with
+ * bPreConfig=false.  We should only print informational messages here, because we do not want to duplicate
+ * console output with the console-ui front-end (since the PluginStart() and InitiateControllers()
+ * functions are called in quick sequence from the console-ui).
+ */
+  
+void load_configuration(int bPreConfig)
+{
+    char SectionName[32];
+    int joy_plugged = 0;
+    int n64CtrlIdx, sdlCtrlIdx, j;
+    int sdlNumDevUsed = 0;
+    int sdlDevicesUsed[4];
+    eModeType OrigControlMode[4], ControlMode[4];
+    int ControlDevice[4];
+    char DeviceName[4][256];
+    int ActiveControllers = 0;
+    int sdlNumJoysticks = get_sdl_num_joysticks();
+    float fVersion = 0.0f;
+    const char *sdl_name;
+    int ControllersFound = 0;
+
+    /* tell user how many SDL joysticks are available */
+    if (!bPreConfig)
+        DebugMessage(M64MSG_INFO, "%i SDL joysticks were found.", sdlNumJoysticks);
+
+    /* loop through 4 N64 controllers, initializing and validating special section parameters */
+    for (n64CtrlIdx=0; n64CtrlIdx < 4; n64CtrlIdx++)
+    {
+        m64p_handle pConfig;
+        /* reset the controller configuration */
+        clear_controller(n64CtrlIdx);
+
+        /* Open the configuration section for this controller */
+        sprintf(SectionName, "Input-SDL-Control%i", n64CtrlIdx + 1);
+        if (ConfigOpenSection(SectionName, &pConfig) != M64ERR_SUCCESS)
+        {
+            // this should never happen
+            DebugMessage(M64MSG_ERROR, "Couldn't open config section '%s'.  Aborting...", SectionName);
+            return;
+        }
+        /* Check version number, and if it doesn't match: delete the config section */
+        fVersion = 0.0f;
+        if (ConfigGetParameter(pConfig, "version", M64TYPE_FLOAT, &fVersion, sizeof(float)) != M64ERR_SUCCESS || ((int) fVersion) != ((int) CONFIG_VERSION))
+        {
+            DebugMessage(M64MSG_WARNING, "Missing or incompatible config section '%s'. Clearing.", SectionName);
+            ConfigDeleteSection(SectionName);
+            // set local controller default parameters
+            OrigControlMode[n64CtrlIdx] = ControlMode[n64CtrlIdx] = E_MODE_FULL_AUTO;
+            ControlDevice[n64CtrlIdx] = DEVICE_NO_JOYSTICK;
+            DeviceName[n64CtrlIdx][0] = 0;
+            // write blank config for GUI front-ends
+            init_controller_config(n64CtrlIdx, "", E_MODE_FULL_AUTO);
+            // save it to the file too
+            ConfigSaveSection(SectionName);
+        }
+        else
+        {
+            if (ConfigGetParameter(pConfig, "mode", M64TYPE_INT, &OrigControlMode[n64CtrlIdx], sizeof(int)) != M64ERR_SUCCESS ||
+                (int) OrigControlMode[n64CtrlIdx] < 0 || (int) OrigControlMode[n64CtrlIdx] > 2)
+            {
+                if (!bPreConfig)
+                    DebugMessage(M64MSG_WARNING, "Missing or invalid 'mode' parameter in config section '%s'.  Setting to 2 (Fully Auto)", SectionName);
+                OrigControlMode[n64CtrlIdx] = E_MODE_FULL_AUTO;
+            }
+            ControlMode[n64CtrlIdx] = OrigControlMode[n64CtrlIdx];
+            if (ConfigGetParameter(pConfig, "device", M64TYPE_INT, &ControlDevice[n64CtrlIdx], sizeof(int)) != M64ERR_SUCCESS)
+            {
+                if (!bPreConfig)
+                    DebugMessage(M64MSG_WARNING, "Missing 'device' parameter in config section '%s'.  Setting to -1 (No joystick)", SectionName);
+                ControlDevice[n64CtrlIdx] = DEVICE_NO_JOYSTICK;
+            }
+            if (ConfigGetParameter(pConfig, "name", M64TYPE_STRING, DeviceName[n64CtrlIdx], 256) != M64ERR_SUCCESS)
+            {
+                DeviceName[n64CtrlIdx][0] = 0;
+            }
+        }
+    }
+
+    /* loop through 4 N64 controllers and set up those in Fully Manual mode */
+    for (n64CtrlIdx=0; n64CtrlIdx < 4; n64CtrlIdx++)
+    {
+        if (ControlMode[n64CtrlIdx] != E_MODE_MANUAL)
+            continue;
+        /* load the stored configuration (disregard any errors) */
+        sprintf(SectionName, "Input-SDL-Control%i", n64CtrlIdx + 1);
+        load_controller_config(SectionName, n64CtrlIdx, ControlDevice[n64CtrlIdx]);
+        /* if this config uses an SDL joystick, mark it as used */
+        if (ControlDevice[n64CtrlIdx] == DEVICE_NO_JOYSTICK)
+        {
+            if (!bPreConfig)
+                DebugMessage(M64MSG_INFO, "N64 Controller #%i: Using manual config with no SDL joystick (keyboard/mouse only)", n64CtrlIdx+1);
+        }
+        else
+        {
+            sdlDevicesUsed[sdlNumDevUsed++] = ControlDevice[n64CtrlIdx];
+            if (!bPreConfig)
+                DebugMessage(M64MSG_INFO, "N64 Controller #%i: Using manual config for SDL joystick %i", n64CtrlIdx+1, ControlDevice[n64CtrlIdx]);
+        }
+        ActiveControllers++;
+    }
+
+    /* now loop through again, setting up those in Named Auto mode */
+    for (n64CtrlIdx=0; n64CtrlIdx < 4; n64CtrlIdx++)
+    {
+        if (ControlMode[n64CtrlIdx] != E_MODE_NAMED_AUTO)
+            continue;
+        /* if name is empty, then use full auto mode instead */
+        if (DeviceName[n64CtrlIdx][0] == 0)
+        {
+            ControlMode[n64CtrlIdx] = E_MODE_FULL_AUTO;
+            continue;
+        }
+        sprintf(SectionName, "Input-SDL-Control%i", n64CtrlIdx + 1);
+        /* if user is looking for a keyboard, set that up */
+        if (strcasecmp(DeviceName[n64CtrlIdx], "Keyboard") == 0)
+        {
+            auto_set_defaults(DEVICE_NO_JOYSTICK, "Keyboard");
+            if (load_controller_config("AutoConfig0", n64CtrlIdx, DEVICE_NO_JOYSTICK) > 0)
+            {
+                if (!bPreConfig)
+                    DebugMessage(M64MSG_INFO, "N64 Controller #%i: Using auto-config for keyboard", n64CtrlIdx+1);
+                /* copy the auto-config settings to the controller config section */
+                auto_copy_inputconfig("AutoConfig0", SectionName, "Keyboard");
+                ActiveControllers++;
+                ConfigSaveSection(SectionName);
+            }
+            else
+            {
+                DebugMessage(M64MSG_ERROR, "Autoconfig keyboard setup invalid");
+            }
+            ConfigDeleteSection("AutoConfig0");
+            continue;
+        }
+        /* search for an unused SDL device with the matching name */
+        for (sdlCtrlIdx=0; sdlCtrlIdx < sdlNumJoysticks; sdlCtrlIdx++)
+        {
+            /* check if this one is in use */
+            int deviceAlreadyUsed = 0;
+            for (j = 0; j < sdlNumDevUsed; j++)
+            {
+                if (sdlDevicesUsed[j] == sdlCtrlIdx)
+                    deviceAlreadyUsed = 1;
+            }
+            if (deviceAlreadyUsed)
+                continue;
+            /* check if the name matches */
+            sdl_name = get_sdl_joystick_name(sdlCtrlIdx);
+            if (sdl_name != NULL && strncmp(DeviceName[n64CtrlIdx], sdl_name, 255) == 0)
+            {
+                /* set up one or more controllers for this SDL device, if present in InputAutoConfig.ini */
+                int ControllersFound = setup_auto_controllers(bPreConfig, n64CtrlIdx, sdlCtrlIdx, sdl_name, ControlMode, OrigControlMode, DeviceName);
+                if (ControllersFound == 0)
+                {
+                    // error: no auto-config found for this SDL device
+                    DebugMessage(M64MSG_ERROR, "No auto-config found for joystick named '%s' in InputAutoConfig.ini", sdl_name);
+                    // mark this device as being used just so we don't complain about it again
+                    sdlDevicesUsed[sdlNumDevUsed++] = sdlCtrlIdx;
+                    // quit looking for SDL joysticks which match the name, because there's no valid autoconfig for that name.
+                    // this controller will be unused; skip to the next one
+                    break;
+                }
+                /* mark this sdl device as used */
+                sdlDevicesUsed[sdlNumDevUsed++] = sdlCtrlIdx;
+                ActiveControllers += ControllersFound;
+                break;
+            }
+        }
+        /* if we didn't find a match for this joystick name, then set the controller to fully auto */
+        if (sdlCtrlIdx == sdlNumJoysticks)
+        {
+            if (!bPreConfig)
+                DebugMessage(M64MSG_WARNING, "N64 Controller #%i: No SDL joystick found matching name '%s'.  Using full auto mode.", n64CtrlIdx+1, DeviceName[n64CtrlIdx]);
+            ControlMode[n64CtrlIdx] = E_MODE_FULL_AUTO;
+        }
+    }
+
+    /* Final loop through N64 controllers, setting up those in Full Auto mode */
+    for (n64CtrlIdx=0; n64CtrlIdx < 4; n64CtrlIdx++)
+    {
+        if (ControlMode[n64CtrlIdx] != E_MODE_FULL_AUTO)
+            continue;
+        sprintf(SectionName, "Input-SDL-Control%i", n64CtrlIdx + 1);
+        /* search for an unused SDL device */
+        for (sdlCtrlIdx=0; sdlCtrlIdx < sdlNumJoysticks; sdlCtrlIdx++)
+        {
+            /* check if this one is in use */
+            int deviceAlreadyUsed = 0;
+            for (j = 0; j < sdlNumDevUsed; j++)
+            {
+                if (sdlDevicesUsed[j] == sdlCtrlIdx)
+                    deviceAlreadyUsed = 1;
+            }
+            if (deviceAlreadyUsed)
+                continue;
+            /* set up one or more controllers for this SDL device, if present in InputAutoConfig.ini */
+            sdl_name = get_sdl_joystick_name(sdlCtrlIdx);
+            ControllersFound = setup_auto_controllers(bPreConfig, n64CtrlIdx, sdlCtrlIdx, sdl_name, ControlMode, OrigControlMode, DeviceName);
+            if (!bPreConfig && ControllersFound == 0)
+            {
+                // error: no auto-config found for this SDL device
+                DebugMessage(M64MSG_ERROR, "No auto-config found for joystick named '%s' in InputAutoConfig.ini", sdl_name);
+                // mark this device as being used just so we don't complain about it again
+                sdlDevicesUsed[sdlNumDevUsed++] = sdlCtrlIdx;
+                // keep trying more SDL devices to see if we can auto-config one for this N64 controller
+                continue;
+            }
+            /* mark this sdl device as used */
+            sdlDevicesUsed[sdlNumDevUsed++] = sdlCtrlIdx;
+            ActiveControllers += ControllersFound;
+            break;
+        }
+        /* if this N64 controller was not activated, set device to -1 */
+        if (sdlCtrlIdx == sdlNumJoysticks)
+        {
+            m64p_handle section;
+            if (ConfigOpenSection(SectionName, &section) == M64ERR_SUCCESS)
+            {
+                const int iNoDevice = -1;
+                ConfigSetParameter(section, "device", M64TYPE_INT, &iNoDevice);
+                if (OrigControlMode[n64CtrlIdx] == E_MODE_FULL_AUTO)
+                    ConfigSetParameter(section, "name", M64TYPE_STRING, "");
+                ConfigSaveSection(SectionName);
+            }
+        }
+    }
+
+    /* fallback to keyboard if no controllers were configured */
+    if (ActiveControllers == 0)
+    {
+        if (!bPreConfig)
+            DebugMessage(M64MSG_INFO, "N64 Controller #1: Forcing default keyboard configuration");
+        auto_set_defaults(DEVICE_NO_JOYSTICK, "Keyboard");
+        if (load_controller_config("AutoConfig0", 0, DEVICE_NO_JOYSTICK) > 0)
+        {
+            /* copy the auto-config settings to the controller config section */
+            if (OrigControlMode[0] == E_MODE_FULL_AUTO)
+                auto_copy_inputconfig("AutoConfig0", "Input-SDL-Control1", "Keyboard");
+            else
+                auto_copy_inputconfig("AutoConfig0", "Input-SDL-Control1", NULL);  // don't overwrite 'name' parameter
+            ActiveControllers++;
+            ConfigSaveSection("Input-SDL-Control1");
+        }
+        else
+        {
+            DebugMessage(M64MSG_ERROR, "Autoconfig keyboard setup invalid");
+        }
+        ConfigDeleteSection("AutoConfig0");
+    }
+
+    /* see how many joysticks are plugged in */
+    joy_plugged = 0;
+    for (j = 0; j < 4; j++)
+    {
+        if (controller[j].control->Present)
+            joy_plugged++;
+    }
+
+    /* print out summary info message */
+    if (!bPreConfig)
+    {
+        if (joy_plugged > 0)
+        {
+            DebugMessage(M64MSG_INFO, "%i controller(s) found, %i plugged in and usable in the emulator", ActiveControllers, joy_plugged);
+        }
+        else
+        {
+            if (ActiveControllers == 0)
+                DebugMessage(M64MSG_WARNING, "No joysticks/controllers found");
+            else
+                DebugMessage(M64MSG_WARNING, "%i controllers found, but none were 'plugged in'", ActiveControllers);
+        }
+    }
+
+}
+
+
diff --git a/source/mupen64plus-input-sdl/src/config.h b/source/mupen64plus-input-sdl/src/config.h
new file mode 100644 (file)
index 0000000..31921f8
--- /dev/null
@@ -0,0 +1,30 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - config.h                                      *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#define CONFIG_VERSION 2.00
+
+extern void load_configuration(int bPreConfig);
+
+#endif /* __CONFIG_H__ */
+
diff --git a/source/mupen64plus-input-sdl/src/osal_dynamiclib.h b/source/mupen64plus-input-sdl/src/osal_dynamiclib.h
new file mode 100644 (file)
index 0000000..daef154
--- /dev/null
@@ -0,0 +1,30 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-core - osal/dynamiclib.h                                  *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#if !defined(OSAL_DYNAMICLIB_H)
+#define OSAL_DYNAMICLIB_H
+
+#include "m64p_types.h"
+
+void *     osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName);
+
+#endif /* #define OSAL_DYNAMICLIB_H */
+
diff --git a/source/mupen64plus-input-sdl/src/osal_dynamiclib_unix.c b/source/mupen64plus-input-sdl/src/osal_dynamiclib_unix.c
new file mode 100644 (file)
index 0000000..b3b7ba5
--- /dev/null
@@ -0,0 +1,37 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-core - osal/dynamiclib_unix.c                             *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include "m64p_types.h"
+#include "osal_dynamiclib.h"
+
+void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
+{
+    if (pccProcedureName == NULL)
+        return NULL;
+
+    return dlsym(LibHandle, pccProcedureName);
+}
+
+
diff --git a/source/mupen64plus-input-sdl/src/osal_dynamiclib_win32.c b/source/mupen64plus-input-sdl/src/osal_dynamiclib_win32.c
new file mode 100644 (file)
index 0000000..685d717
--- /dev/null
@@ -0,0 +1,74 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-ui-console - osal_dynamiclib_win32.c                      *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "m64p_types.h"
+#include "osal_dynamiclib.h"
+
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
+{
+    if (pLibHandle == NULL || pccLibraryPath == NULL)
+        return M64ERR_INPUT_ASSERT;
+
+    *pLibHandle = LoadLibrary(pccLibraryPath);
+
+    if (*pLibHandle == NULL)
+    {
+        char *pchErrMsg;
+        DWORD dwErr = GetLastError(); 
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
+        fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg);
+        LocalFree(pchErrMsg);
+        return M64ERR_INPUT_NOT_FOUND;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
+{
+    if (pccProcedureName == NULL)
+        return NULL;
+
+    return GetProcAddress(LibHandle, pccProcedureName);
+}
+
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
+{
+    int rval = FreeLibrary(LibHandle);
+
+    if (rval == 0)
+    {
+        char *pchErrMsg;
+        DWORD dwErr = GetLastError(); 
+        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
+        fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg);
+        LocalFree(pchErrMsg);
+        return M64ERR_INTERNAL;
+    }
+
+    return M64ERR_SUCCESS;
+}
diff --git a/source/mupen64plus-input-sdl/src/osal_preproc.h b/source/mupen64plus-input-sdl/src/osal_preproc.h
new file mode 100644 (file)
index 0000000..37c7dc4
--- /dev/null
@@ -0,0 +1,33 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus - osal_preproc.h                                          *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *   Copyright (C) 2002 Hacktarux                                          *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* this header file is for system-dependent #defines, #includes, and typedefs */
+
+#if !defined(OSAL_PREPROC_H)
+#define OSAL_PREPROC_H
+
+#if defined(WIN32)
+  #define strcasestr strstr
+  #define strcasecmp _stricmp
+#endif // WIN32
+
+#endif // OSAL_PREPROC_H
diff --git a/source/mupen64plus-input-sdl/src/plugin.c b/source/mupen64plus-input-sdl/src/plugin.c
new file mode 100644 (file)
index 0000000..26b1814
--- /dev/null
@@ -0,0 +1,928 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - plugin.c                                      *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2008-2011 Richard Goedeken                              *
+ *   Copyright (C) 2008 Tillin9                                            *
+ *   Copyright (C) 2002 Blight                                             *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <SDL.h>
+
+#define M64P_PLUGIN_PROTOTYPES 1
+#include "m64p_types.h"
+#include "m64p_plugin.h"
+#include "m64p_common.h"
+#include "m64p_config.h"
+
+#include "plugin.h"
+#include "config.h"
+#include "version.h"
+#include "osal_dynamiclib.h"
+
+#ifdef __linux__
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <linux/input.h>
+#endif /* __linux__ */
+
+#include <errno.h>
+
+/* defines for the force feedback rumble support */
+#ifdef __linux__
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define OFF(x)  ((x)%BITS_PER_LONG)
+#define BIT(x)  (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
+#endif //__linux__
+
+/* definitions of pointers to Core config functions */
+ptr_ConfigOpenSection      ConfigOpenSection = NULL;
+ptr_ConfigDeleteSection    ConfigDeleteSection = NULL;
+ptr_ConfigSaveSection      ConfigSaveSection = NULL;
+ptr_ConfigListParameters   ConfigListParameters = NULL;
+ptr_ConfigSaveFile         ConfigSaveFile = NULL;
+ptr_ConfigSetParameter     ConfigSetParameter = NULL;
+ptr_ConfigGetParameter     ConfigGetParameter = NULL;
+ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
+ptr_ConfigSetDefaultInt    ConfigSetDefaultInt = NULL;
+ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat = NULL;
+ptr_ConfigSetDefaultBool   ConfigSetDefaultBool = NULL;
+ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
+ptr_ConfigGetParamInt      ConfigGetParamInt = NULL;
+ptr_ConfigGetParamFloat    ConfigGetParamFloat = NULL;
+ptr_ConfigGetParamBool     ConfigGetParamBool = NULL;
+ptr_ConfigGetParamString   ConfigGetParamString = NULL;
+
+ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
+ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath = NULL;
+ptr_ConfigGetUserDataPath       ConfigGetUserDataPath = NULL;
+ptr_ConfigGetUserCachePath      ConfigGetUserCachePath = NULL;
+
+/* global data definitions */
+SController controller[4];   // 4 controllers
+
+/* static data definitions */
+static void (*l_DebugCallback)(void *, int, const char *) = NULL;
+static void *l_DebugCallContext = NULL;
+static int l_PluginInit = 0;
+
+static unsigned short button_bits[] = {
+    0x0001,  // R_DPAD
+    0x0002,  // L_DPAD
+    0x0004,  // D_DPAD
+    0x0008,  // U_DPAD
+    0x0010,  // START_BUTTON
+    0x0020,  // Z_TRIG
+    0x0040,  // B_BUTTON
+    0x0080,  // A_BUTTON
+    0x0100,  // R_CBUTTON
+    0x0200,  // L_CBUTTON
+    0x0400,  // D_CBUTTON
+    0x0800,  // U_CBUTTON
+    0x1000,  // R_TRIG
+    0x2000,  // L_TRIG
+    0x4000,  // Mempak switch
+    0x8000   // Rumblepak switch
+};
+
+static int romopen = 0;         // is a rom opened
+
+static unsigned char myKeyState[SDL_NUM_SCANCODES];
+
+#ifdef __linux__
+static struct ff_effect ffeffect[4];
+static struct ff_effect ffstrong[4];
+static struct ff_effect ffweak[4];
+#endif //__linux__
+
+/* Global functions */
+void DebugMessage(int level, const char *message, ...)
+{
+  char msgbuf[1024];
+  va_list args;
+
+  if (l_DebugCallback == NULL)
+      return;
+
+  va_start(args, message);
+  vsprintf(msgbuf, message, args);
+
+  (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
+
+  va_end(args);
+}
+
+static CONTROL temp_core_controlinfo[4];
+
+/* Mupen64Plus plugin functions */
+EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
+                                   void (*DebugCallback)(void *, int, const char *))
+{
+    ptr_CoreGetAPIVersions CoreAPIVersionFunc;
+    
+    int i, ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
+
+    if (l_PluginInit)
+        return M64ERR_ALREADY_INIT;
+
+    /* first thing is to set the callback function for debug info */
+    l_DebugCallback = DebugCallback;
+    l_DebugCallContext = Context;
+
+    /* attach and call the CoreGetAPIVersions function, check Config API version for compatibility */
+    CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
+    if (CoreAPIVersionFunc == NULL)
+    {
+        DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");
+        return M64ERR_INCOMPATIBLE;
+    }
+    
+    (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
+    if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000) || ConfigAPIVersion < CONFIG_API_VERSION)
+    {
+        DebugMessage(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
+                VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    /* Get the core config function pointers from the library handle */
+    ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
+    ConfigDeleteSection = (ptr_ConfigDeleteSection) osal_dynlib_getproc(CoreLibHandle, "ConfigDeleteSection");
+    ConfigSaveFile = (ptr_ConfigSaveFile) osal_dynlib_getproc(CoreLibHandle, "ConfigSaveFile");
+    ConfigSaveSection = (ptr_ConfigSaveSection) osal_dynlib_getproc(CoreLibHandle, "ConfigSaveSection");
+    ConfigListParameters = (ptr_ConfigListParameters) osal_dynlib_getproc(CoreLibHandle, "ConfigListParameters");
+    ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
+    ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
+    ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
+    ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
+    ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
+    ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
+    ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
+    ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
+    ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
+    ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
+
+    ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
+    ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
+    ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
+    ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
+
+    if (!ConfigOpenSection || !ConfigDeleteSection || !ConfigSaveFile || !ConfigSaveSection || !ConfigSetParameter || !ConfigGetParameter ||
+        !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
+        !ConfigGetParamInt   || !ConfigGetParamFloat   || !ConfigGetParamBool   || !ConfigGetParamString ||
+        !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
+    {
+        DebugMessage(M64MSG_ERROR, "Couldn't connect to Core configuration functions");
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    /* reset controllers */
+    memset(controller, 0, sizeof(SController) * 4);
+    for (i = 0; i < SDL_NUM_SCANCODES; i++)
+    {
+        myKeyState[i] = 0;
+    }
+    /* set CONTROL struct pointers to the temporary static array */
+    /* this small struct is used to tell the core whether each controller is plugged in, and what type of pak is connected */
+    /* we only need it so that we can call load_configuration below, to auto-config for a GUI front-end */
+    for (i = 0; i < 4; i++)
+        controller[i].control = temp_core_controlinfo + i;
+
+    /* read plugin config from core config database, auto-config if necessary and update core database */
+    load_configuration(1);
+
+    l_PluginInit = 1;
+    return M64ERR_SUCCESS;
+}
+
+EXPORT m64p_error CALL PluginShutdown(void)
+{
+    if (!l_PluginInit)
+        return M64ERR_NOT_INIT;
+
+    /* reset some local variables */
+    l_DebugCallback = NULL;
+    l_DebugCallContext = NULL;
+
+    l_PluginInit = 0;
+    return M64ERR_SUCCESS;
+}
+
+EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
+{
+    /* set version info */
+    if (PluginType != NULL)
+        *PluginType = M64PLUGIN_INPUT;
+
+    if (PluginVersion != NULL)
+        *PluginVersion = PLUGIN_VERSION;
+
+    if (APIVersion != NULL)
+        *APIVersion = INPUT_PLUGIN_API_VERSION;
+    
+    if (PluginNamePtr != NULL)
+        *PluginNamePtr = PLUGIN_NAME;
+
+    if (Capabilities != NULL)
+    {
+        *Capabilities = 0;
+    }
+                    
+    return M64ERR_SUCCESS;
+}
+
+/* Helper function to handle the SDL keys */
+static void
+doSdlKeys(unsigned char* keystate)
+{
+    int c, b, axis_val, axis_max_val;
+    static int grabmouse = 1, grabtoggled = 0;
+
+    axis_max_val = 80;
+    if (keystate[SDL_SCANCODE_RCTRL])
+        axis_max_val -= 40;
+    if (keystate[SDL_SCANCODE_RSHIFT])
+        axis_max_val -= 20;
+
+    for( c = 0; c < 4; c++ )
+    {
+        for( b = 0; b < 16; b++ )
+        {
+            if( controller[c].button[b].key == SDL_SCANCODE_UNKNOWN || ((int) controller[c].button[b].key) < 0)
+                continue;
+            if( keystate[controller[c].button[b].key] )
+                controller[c].buttons.Value |= button_bits[b];
+        }
+        for( b = 0; b < 2; b++ )
+        {
+            // from the N64 func ref: The 3D Stick data is of type signed char and in
+            // the range between 80 and -80. (32768 / 409 = ~80.1)
+            if( b == 0 )
+                axis_val = controller[c].buttons.X_AXIS;
+            else
+                axis_val = -controller[c].buttons.Y_AXIS;
+
+            if( controller[c].axis[b].key_a != SDL_SCANCODE_UNKNOWN && ((int) controller[c].axis[b].key_a) > 0)
+                if( keystate[controller[c].axis[b].key_a] )
+                    axis_val = -axis_max_val;
+            if( controller[c].axis[b].key_b != SDL_SCANCODE_UNKNOWN && ((int) controller[c].axis[b].key_b) > 0)
+                if( keystate[controller[c].axis[b].key_b] )
+                    axis_val = axis_max_val;
+
+            if( b == 0 )
+                controller[c].buttons.X_AXIS = axis_val;
+            else
+                controller[c].buttons.Y_AXIS = -axis_val;
+        }
+        if (controller[c].mouse)
+        {
+            if (keystate[SDL_SCANCODE_LCTRL] && keystate[SDL_SCANCODE_LALT])
+            {
+                if (!grabtoggled)
+                {
+                    grabtoggled = 1;
+                    grabmouse = !grabmouse;
+                    // grab/ungrab mouse
+#if SDL_VERSION_ATLEAST(2,0,0)
+#warning SDL mouse grabbing not yet supported with SDL 2.0
+#else
+                    SDL_WM_GrabInput( grabmouse ? SDL_GRAB_ON : SDL_GRAB_OFF );
+#endif
+                    SDL_ShowCursor( grabmouse ? 0 : 1 );
+                }
+            }
+            else grabtoggled = 0;
+        }
+    }
+}
+
+static unsigned char DataCRC( unsigned char *Data, int iLenght )
+{
+    unsigned char Remainder = Data[0];
+
+    int iByte = 1;
+    unsigned char bBit = 0;
+
+    while( iByte <= iLenght )
+    {
+        int HighBit = ((Remainder & 0x80) != 0);
+        Remainder = Remainder << 1;
+
+        Remainder += ( iByte < iLenght && Data[iByte] & (0x80 >> bBit )) ? 1 : 0;
+
+        Remainder ^= (HighBit) ? 0x85 : 0;
+
+        bBit++;
+        iByte += bBit/8;
+        bBit %= 8;
+    }
+
+    return Remainder;
+}
+
+/******************************************************************
+  Function: ControllerCommand
+  Purpose:  To process the raw data that has just been sent to a
+            specific controller.
+  input:    - Controller Number (0 to 3) and -1 signalling end of
+              processing the pif ram.
+            - Pointer of data to be processed.
+  output:   none
+
+  note:     This function is only needed if the DLL is allowing raw
+            data, or the plugin is set to raw
+
+            the data that is being processed looks like this:
+            initilize controller: 01 03 00 FF FF FF
+            read controller:      01 04 01 FF FF FF FF
+*******************************************************************/
+EXPORT void CALL ControllerCommand(int Control, unsigned char *Command)
+{
+    unsigned char *Data = &Command[5];
+
+    if (Control == -1)
+        return;
+
+    switch (Command[2])
+    {
+        case RD_GETSTATUS:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Get status");
+#endif
+            break;
+        case RD_READKEYS:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Read keys");
+#endif
+            break;
+        case RD_READPAK:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Read pak");
+#endif
+            if (controller[Control].control->Plugin == PLUGIN_RAW)
+            {
+                unsigned int dwAddress = (Command[3] << 8) + (Command[4] & 0xE0);
+
+                if(( dwAddress >= 0x8000 ) && ( dwAddress < 0x9000 ) )
+                    memset( Data, 0x80, 32 );
+                else
+                    memset( Data, 0x00, 32 );
+
+                Data[32] = DataCRC( Data, 32 );
+            }
+            break;
+        case RD_WRITEPAK:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Write pak");
+#endif
+            if (controller[Control].control->Plugin == PLUGIN_RAW)
+            {
+                unsigned int dwAddress = (Command[3] << 8) + (Command[4] & 0xE0);
+              if (dwAddress == PAK_IO_RUMBLE && *Data)
+                    DebugMessage(M64MSG_VERBOSE, "Triggering rumble pack.");
+#ifdef __linux__
+                struct input_event play;
+                if( dwAddress == PAK_IO_RUMBLE && controller[Control].event_joystick != 0)
+                {
+                    if( *Data )
+                    {
+                        play.type = EV_FF;
+                        play.code = ffeffect[Control].id;
+                        play.value = 1;
+
+                        if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
+                            perror("Error starting rumble effect");
+
+                    }
+                    else
+                    {
+                        play.type = EV_FF;
+                        play.code = ffeffect[Control].id;
+                        play.value = 0;
+
+                        if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
+                            perror("Error stopping rumble effect");
+                    }
+                }
+#endif //__linux__
+                Data[32] = DataCRC( Data, 32 );
+            }
+            break;
+        case RD_RESETCONTROLLER:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Reset controller");
+#endif
+            break;
+        case RD_READEEPROM:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Read eeprom");
+#endif
+            break;
+        case RD_WRITEEPROM:
+#ifdef _DEBUG
+            DebugMessage(M64MSG_INFO, "Write eeprom");
+#endif
+            break;
+        }
+}
+
+/******************************************************************
+  Function: GetKeys
+  Purpose:  To get the current state of the controllers buttons.
+  input:    - Controller Number (0 to 3)
+            - A pointer to a BUTTONS structure to be filled with
+            the controller state.
+  output:   none
+*******************************************************************/
+EXPORT void CALL GetKeys( int Control, BUTTONS *Keys )
+{
+    static int mousex_residual = 0;
+    static int mousey_residual = 0;
+    int b, axis_val;
+    SDL_Event event;
+    unsigned char mstate;
+
+    // Handle keyboard input first
+    doSdlKeys(SDL_GetKeyboardState(NULL));
+    doSdlKeys(myKeyState);
+
+    // read joystick state
+    SDL_JoystickUpdate();
+
+    if( controller[Control].device >= 0 )
+    {
+        for( b = 0; b < 16; b++ )
+        {
+            if( controller[Control].button[b].button >= 0 )
+                if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].button[b].button ) )
+                    controller[Control].buttons.Value |= button_bits[b];
+
+            if( controller[Control].button[b].axis >= 0 )
+            {
+                int deadzone = controller[Control].button[b].axis_deadzone;
+                axis_val = SDL_JoystickGetAxis( controller[Control].joystick, controller[Control].button[b].axis );
+                if (deadzone < 0)
+                    deadzone = 6000; /* default */
+                if( (controller[Control].button[b].axis_dir < 0) && (axis_val <= -deadzone) )
+                    controller[Control].buttons.Value |= button_bits[b];
+                else if( (controller[Control].button[b].axis_dir > 0) && (axis_val >= deadzone) )
+                    controller[Control].buttons.Value |= button_bits[b];
+            }
+
+            if( controller[Control].button[b].hat >= 0 )
+            {
+                if( controller[Control].button[b].hat_pos > 0 )
+                    if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].button[b].hat ) & controller[Control].button[b].hat_pos )
+                        controller[Control].buttons.Value |= button_bits[b];
+            }
+        }
+        for( b = 0; b < 2; b++ )
+        {
+            /* from the N64 func ref: The 3D Stick data is of type signed char and in the range between -80 and +80 */
+            int deadzone = controller[Control].axis_deadzone[b];
+            int range = controller[Control].axis_peak[b] - controller[Control].axis_deadzone[b];
+            /* skip this axis if the deadzone/peak values are invalid */
+            if (deadzone < 0 || range < 1)
+                continue;
+
+            if( b == 0 )
+                axis_val = controller[Control].buttons.X_AXIS;
+            else
+                axis_val = -controller[Control].buttons.Y_AXIS;
+
+            if( controller[Control].axis[b].axis_a >= 0 )  /* up and left for N64 */
+            {
+                int joy_val = SDL_JoystickGetAxis(controller[Control].joystick, controller[Control].axis[b].axis_a);
+                int axis_dir = controller[Control].axis[b].axis_dir_a;
+                if (joy_val * axis_dir > deadzone)
+                    axis_val = -((abs(joy_val) - deadzone) * 80 / range);
+                if (axis_val < -80)
+                    axis_val = -80;
+            }
+            if( controller[Control].axis[b].axis_b >= 0 ) /* down and right for N64 */
+            {
+                int joy_val = SDL_JoystickGetAxis(controller[Control].joystick, controller[Control].axis[b].axis_b);
+                int axis_dir = controller[Control].axis[b].axis_dir_b;
+                if (joy_val * axis_dir > deadzone)
+                    axis_val = ((abs(joy_val) - deadzone) * 80 / range);
+                if (axis_val > 80)
+                    axis_val = 80;
+            }
+            if( controller[Control].axis[b].hat >= 0 )
+            {
+                if( controller[Control].axis[b].hat_pos_a >= 0 )
+                    if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].axis[b].hat ) & controller[Control].axis[b].hat_pos_a )
+                        axis_val = -80;
+                if( controller[Control].axis[b].hat_pos_b >= 0 )
+                    if( SDL_JoystickGetHat( controller[Control].joystick, controller[Control].axis[b].hat ) & controller[Control].axis[b].hat_pos_b )
+                        axis_val = 80;
+            }
+
+            if( controller[Control].axis[b].button_a >= 0 )
+                if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].axis[b].button_a ) )
+                    axis_val = -80;
+            if( controller[Control].axis[b].button_b >= 0 )
+                if( SDL_JoystickGetButton( controller[Control].joystick, controller[Control].axis[b].button_b ) )
+                    axis_val = 80;
+
+            if( b == 0 )
+                controller[Control].buttons.X_AXIS = axis_val;
+            else
+                controller[Control].buttons.Y_AXIS = -axis_val;
+        }
+    }
+
+    // process mouse events
+    mstate = SDL_GetMouseState( NULL, NULL );
+    for( b = 0; b < 16; b++ )
+    {
+        if( controller[Control].button[b].mouse < 1 )
+            continue;
+        if( mstate & SDL_BUTTON(controller[Control].button[b].mouse) )
+            controller[Control].buttons.Value |= button_bits[b];
+    }
+
+    if (controller[Control].mouse)
+    {
+#if SDL_VERSION_ATLEAST(2,0,0)
+#warning SDL mouse grabbing not yet supported with SDL 2.0
+#else
+        if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON)
+        {
+            SDL_PumpEvents();
+#if SDL_VERSION_ATLEAST(1,3,0)
+            while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) == 1)
+#else
+            while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION)) == 1)
+#endif
+            {
+                if (event.motion.xrel)
+                {
+                    mousex_residual += (int) (event.motion.xrel * controller[Control].mouse_sens[0]);
+                }
+                if (event.motion.yrel)
+                {
+                    mousey_residual += (int) (event.motion.yrel * controller[Control].mouse_sens[1]);
+                }
+            }
+        }
+        else
+#endif
+        {
+            mousex_residual = 0;
+            mousey_residual = 0;
+        }
+        axis_val = mousex_residual;
+        if (axis_val < -80)
+            axis_val = -80;
+        else if (axis_val > 80)
+            axis_val = 80;
+        controller[Control].buttons.X_AXIS = axis_val;
+        axis_val = mousey_residual;
+        if (axis_val < -80)
+            axis_val = -80;
+        else if (axis_val > 80)
+            axis_val = 80;
+        controller[Control].buttons.Y_AXIS = -axis_val;
+        /* the mouse x/y values decay exponentially */
+        mousex_residual = (mousex_residual * 224) / 256;
+        mousey_residual = (mousey_residual * 224) / 256;
+    }
+
+#ifdef _DEBUG
+    DebugMessage(M64MSG_VERBOSE, "Controller #%d value: 0x%8.8X", Control, *(int *)&controller[Control].buttons );
+#endif
+    *Keys = controller[Control].buttons;
+
+    /* handle mempack / rumblepak switching (only if rumble is active on joystick) */
+#ifdef __linux__
+    if (controller[Control].event_joystick != 0)
+    {
+        struct input_event play;
+        static unsigned int SwitchPackTime[4] = {0, 0, 0, 0}, SwitchPackType[4] = {0, 0, 0, 0};
+        // when the user switches packs, we should mimick the act of removing 1 pack, and then inserting another 1 second later
+        if (controller[Control].buttons.Value & button_bits[14])
+        {
+            SwitchPackTime[Control] = SDL_GetTicks();         // time at which the 'switch pack' command was given
+            SwitchPackType[Control] = PLUGIN_MEMPAK;          // type of new pack to insert
+            controller[Control].control->Plugin = PLUGIN_NONE;// remove old pack
+            play.type = EV_FF;
+            play.code = ffweak[Control].id;
+            play.value = 1;
+            if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
+                perror("Error starting rumble effect");
+        }
+        if (controller[Control].buttons.Value & button_bits[15])
+        {
+            SwitchPackTime[Control] = SDL_GetTicks();         // time at which the 'switch pack' command was given
+            SwitchPackType[Control] = PLUGIN_RAW;             // type of new pack to insert
+            controller[Control].control->Plugin = PLUGIN_NONE;// remove old pack
+            play.type = EV_FF;
+            play.code = ffstrong[Control].id;
+            play.value = 1;
+            if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1)
+                perror("Error starting rumble effect");
+        }
+        // handle inserting new pack if the time has arrived
+        if (SwitchPackTime[Control] != 0 && (SDL_GetTicks() - SwitchPackTime[Control]) >= 1000)
+        {
+            controller[Control].control->Plugin = SwitchPackType[Control];
+            SwitchPackTime[Control] = 0;
+        }
+    }
+#endif /* __linux__ */
+
+    controller[Control].buttons.Value = 0;
+}
+
+static void InitiateRumble(int cntrl)
+{
+#ifdef __linux__
+    DIR* dp;
+    struct dirent* ep;
+    unsigned long features[4];
+    char temp[128];
+    char temp2[128];
+    int iFound = 0;
+
+    controller[cntrl].event_joystick = 0;
+
+    sprintf(temp,"/sys/class/input/js%d/device", controller[cntrl].device);
+    dp = opendir(temp);
+
+    if(dp==NULL)
+        return;
+
+    while ((ep=readdir(dp)))
+        {
+        if (strncmp(ep->d_name, "event",5)==0)
+            {
+            sprintf(temp, "/dev/input/%s", ep->d_name);
+            iFound = 1;
+            break;
+            }
+        else if(strncmp(ep->d_name,"input:event", 11)==0)
+            {
+            sscanf(ep->d_name, "input:%s", temp2);
+            sprintf(temp, "/dev/input/%s", temp2);
+            iFound = 1;
+            break;
+            }
+        else if(strncmp(ep->d_name,"input:input", 11)==0)
+            {
+            strcat(temp, "/");
+            strcat(temp, ep->d_name);
+            closedir (dp);
+            dp = opendir(temp);
+            if(dp==NULL)
+                return;
+            }
+       }
+
+    closedir(dp);
+
+    if (!iFound)
+    {
+        DebugMessage(M64MSG_WARNING, "Couldn't find input event for rumble support.");
+        return;
+    }
+
+    controller[cntrl].event_joystick = open(temp, O_RDWR);
+    if(controller[cntrl].event_joystick==-1)
+        {
+        DebugMessage(M64MSG_WARNING, "Couldn't open device file '%s' for rumble support.", temp);
+        controller[cntrl].event_joystick = 0;
+        return;
+        }
+
+    if(ioctl(controller[cntrl].event_joystick, EVIOCGBIT(EV_FF, sizeof(unsigned long) * 4), features)==-1)
+        {
+        DebugMessage(M64MSG_WARNING, "Linux kernel communication failed for force feedback (rumble).\n");
+        controller[cntrl].event_joystick = 0;
+        return;
+        }
+
+    if(!test_bit(FF_RUMBLE, features))
+        {
+        DebugMessage(M64MSG_WARNING, "No rumble supported on N64 joystick #%i", cntrl + 1);
+        controller[cntrl].event_joystick = 0;
+        return;
+        }
+
+    ffeffect[cntrl].type = FF_RUMBLE;
+    ffeffect[cntrl].id = -1;
+    ffeffect[cntrl].u.rumble.strong_magnitude = 0xFFFF;
+    ffeffect[cntrl].u.rumble.weak_magnitude = 0xFFFF;
+    ffeffect[cntrl].replay.length = 0x7fff;             // hack: xboxdrv is buggy and doesn't support infinite replay.
+                                                        // when xboxdrv is fixed (https://github.com/Grumbel/xboxdrv/issues/47),
+                                                        // please remove this
+
+    ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffeffect[cntrl]);
+
+    ffstrong[cntrl].type = FF_RUMBLE;
+    ffstrong[cntrl].id = -1;
+    ffstrong[cntrl].u.rumble.strong_magnitude = 0xFFFF;
+    ffstrong[cntrl].u.rumble.weak_magnitude = 0x0000;
+    ffstrong[cntrl].replay.length = 500;
+    ffstrong[cntrl].replay.delay = 0;
+
+    ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffstrong[cntrl]);
+
+    ffweak[cntrl].type = FF_RUMBLE;
+    ffweak[cntrl].id = -1;
+    ffweak[cntrl].u.rumble.strong_magnitude = 0x0000;
+    ffweak[cntrl].u.rumble.weak_magnitude = 0xFFFF;
+    ffweak[cntrl].replay.length = 500;
+    ffweak[cntrl].replay.delay = 0;
+
+    ioctl(controller[cntrl].event_joystick, EVIOCSFF, &ffweak[cntrl]);
+
+    DebugMessage(M64MSG_INFO, "Rumble activated on N64 joystick #%i", cntrl + 1);
+#endif /* __linux__ */
+}
+
+/******************************************************************
+  Function: InitiateControllers
+  Purpose:  This function initialises how each of the controllers
+            should be handled.
+  input:    - The handle to the main window.
+            - A controller structure that needs to be filled for
+              the emulator to know how to handle each controller.
+  output:   none
+*******************************************************************/
+EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo)
+{
+    int i;
+
+    // reset controllers
+    memset( controller, 0, sizeof( SController ) * 4 );
+    for ( i = 0; i < SDL_NUM_SCANCODES; i++)
+    {
+        myKeyState[i] = 0;
+    }
+    // set our CONTROL struct pointers to the array that was passed in to this function from the core
+    // this small struct tells the core whether each controller is plugged in, and what type of pak is connected
+    for (i = 0; i < 4; i++)
+        controller[i].control = ControlInfo.Controls + i;
+
+    // read configuration
+    load_configuration(0);
+
+    for( i = 0; i < 4; i++ )
+    {
+        // test for rumble support for this joystick
+        InitiateRumble(i);
+        // if rumble not supported, switch to mempack
+        if (controller[i].control->Plugin == PLUGIN_RAW && controller[i].event_joystick == 0)
+            controller[i].control->Plugin = PLUGIN_MEMPAK;
+    }
+
+    DebugMessage(M64MSG_INFO, "%s version %i.%i.%i initialized.", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION));
+}
+
+/******************************************************************
+  Function: ReadController
+  Purpose:  To process the raw data in the pif ram that is about to
+            be read.
+  input:    - Controller Number (0 to 3) and -1 signalling end of
+              processing the pif ram.
+            - Pointer of data to be processed.
+  output:   none
+  note:     This function is only needed if the DLL is allowing raw
+            data.
+*******************************************************************/
+EXPORT void CALL ReadController(int Control, unsigned char *Command)
+{
+#ifdef _DEBUG
+    if (Command != NULL)
+        DebugMessage(M64MSG_INFO, "Raw Read (cont=%d):  %02X %02X %02X %02X %02X %02X", Control,
+                     Command[0], Command[1], Command[2], Command[3], Command[4], Command[5]);
+#endif
+}
+
+/******************************************************************
+  Function: RomClosed
+  Purpose:  This function is called when a rom is closed.
+  input:    none
+  output:   none
+*******************************************************************/
+EXPORT void CALL RomClosed(void)
+{
+    int i;
+
+    // close joysticks
+    for( i = 0; i < 4; i++ )
+        if( controller[i].joystick )
+        {
+            SDL_JoystickClose( controller[i].joystick );
+            controller[i].joystick = NULL;
+        }
+
+    // quit SDL joystick subsystem
+    SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
+
+    // release/ungrab mouse
+#if SDL_VERSION_ATLEAST(2,0,0)
+#warning SDL mouse grabbing not yet supported with SDL 2.0
+#else
+    SDL_WM_GrabInput( SDL_GRAB_OFF );
+#endif
+    SDL_ShowCursor( 1 );
+
+    romopen = 0;
+}
+
+/******************************************************************
+  Function: RomOpen
+  Purpose:  This function is called when a rom is open. (from the
+            emulation thread)
+  input:    none
+  output:   none
+*******************************************************************/
+EXPORT int CALL RomOpen(void)
+{
+    int i;
+
+    // init SDL joystick subsystem
+    if( !SDL_WasInit( SDL_INIT_JOYSTICK ) )
+        if( SDL_InitSubSystem( SDL_INIT_JOYSTICK ) == -1 )
+        {
+            DebugMessage(M64MSG_ERROR, "Couldn't init SDL joystick subsystem: %s", SDL_GetError() );
+            return 0;
+        }
+
+    // open joysticks
+    for( i = 0; i < 4; i++ )
+        if( controller[i].device >= 0 )
+        {
+            controller[i].joystick = SDL_JoystickOpen( controller[i].device );
+            if( controller[i].joystick == NULL )
+                DebugMessage(M64MSG_WARNING, "Couldn't open joystick for controller #%d: %s", i + 1, SDL_GetError() );
+        }
+        else
+            controller[i].joystick = NULL;
+
+    // grab mouse
+    if (controller[0].mouse || controller[1].mouse || controller[2].mouse || controller[3].mouse)
+    {
+#if SDL_VERSION_ATLEAST(2,0,0)
+#warning SDL mouse grabbing not yet supported with SDL 2.0
+#else
+        SDL_ShowCursor( 0 );
+        if (SDL_WM_GrabInput( SDL_GRAB_ON ) != SDL_GRAB_ON)
+        {
+            DebugMessage(M64MSG_WARNING, "Couldn't grab input! Mouse support won't work!");
+        }
+#endif
+    }
+
+    romopen = 1;
+    return 1;
+}
+
+/******************************************************************
+  Function: SDL_KeyDown
+  Purpose:  To pass the SDL_KeyDown message from the emulator to the
+            plugin.
+  input:    keymod and keysym of the SDL_KEYDOWN message.
+  output:   none
+*******************************************************************/
+EXPORT void CALL SDL_KeyDown(int keymod, int keysym)
+{
+    myKeyState[keysym] = 1;
+}
+
+/******************************************************************
+  Function: SDL_KeyUp
+  Purpose:  To pass the SDL_KeyUp message from the emulator to the
+            plugin.
+  input:    keymod and keysym of the SDL_KEYUP message.
+  output:   none
+*******************************************************************/
+EXPORT void CALL SDL_KeyUp(int keymod, int keysym)
+{
+    myKeyState[keysym] = 0;
+}
+
diff --git a/source/mupen64plus-input-sdl/src/plugin.h b/source/mupen64plus-input-sdl/src/plugin.h
new file mode 100644 (file)
index 0000000..f5e7bfd
--- /dev/null
@@ -0,0 +1,175 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - plugin.h                                      *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2008-2009 Richard Goedeken                              *
+ *   Copyright (C) 2008 Tillin9                                            *
+ *   Copyright (C) 2002 Blight                                             *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef __PLUGIN_H__
+#define __PLUGIN_H__
+
+#include <SDL.h>
+#if ! SDL_VERSION_ATLEAST(1,3,0)
+
+#define SDL_GetKeyboardState SDL_GetKeyState
+#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN
+#define SDL_NUM_SCANCODES SDLK_LAST
+#define SDL_SCANCODE_RCTRL SDLK_RCTRL
+#define SDL_SCANCODE_RSHIFT SDLK_RSHIFT
+#define SDL_SCANCODE_LCTRL SDLK_LCTRL
+#define SDL_SCANCODE_LALT SDLK_LALT
+#define SDL_Scancode SDLKey
+
+#endif
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+
+static inline const char* _SDL_JoystickName(int device_index)
+{
+    SDL_Joystick *joystick;
+    const char *name;
+    static char JoyName[256];
+
+    joystick = SDL_JoystickOpen(device_index);
+    if (!joystick)
+        return NULL;
+
+    name = SDL_JoystickName(joystick);
+    if (name)
+    {
+        strncpy(JoyName, name, 255);
+        JoyName[255] = 0;
+    }
+    SDL_JoystickClose(joystick);
+
+    return JoyName;
+}
+
+#define SDL_JoystickName(device_index) _SDL_JoystickName(device_index)
+
+#endif
+
+#define M64P_PLUGIN_PROTOTYPES 1
+#include "m64p_plugin.h"
+#include "m64p_config.h"
+
+#define DEVICE_NO_JOYSTICK  (-1)
+
+// Some stuff from n-rage plugin
+#define RD_GETSTATUS        0x00        // get status
+#define RD_READKEYS         0x01        // read button values
+#define RD_READPAK          0x02        // read from controllerpack
+#define RD_WRITEPAK         0x03        // write to controllerpack
+#define RD_RESETCONTROLLER  0xff        // reset controller
+#define RD_READEEPROM       0x04        // read eeprom
+#define RD_WRITEEPROM       0x05        // write eeprom
+
+#define PAK_IO_RUMBLE       0xC000      // the address where rumble-commands are sent to
+
+enum EButton
+{
+    R_DPAD          = 0,
+    L_DPAD,
+    D_DPAD,
+    U_DPAD,
+    START_BUTTON,
+    Z_TRIG,
+    B_BUTTON,
+    A_BUTTON,
+    R_CBUTTON,
+    L_CBUTTON,
+    D_CBUTTON,
+    U_CBUTTON,
+    R_TRIG,
+    L_TRIG,
+    MEMPAK,
+    RUMBLEPAK,
+    X_AXIS,
+    Y_AXIS,
+    NUM_BUTTONS
+};
+
+typedef struct
+{
+    int button;         // button index; -1 if notassigned
+    SDL_Scancode key;   // sdl keysym; SDL_SCANCODE_UNKNOWN if not assigned
+    int axis, axis_dir; // aixs + direction (i.e. 0, 1 = X Axis +; 0, -1 = X Axis -); -1 if notassigned
+    int axis_deadzone;  // -1 for default, or >= 0 for custom value
+    int hat, hat_pos;   // hat + hat position; -1 if not assigned
+    int mouse;          // mouse button
+} SButtonMap;
+
+typedef struct
+{
+    int button_a, button_b;         // up/down or left/right; -1 if not assigned
+    SDL_Scancode key_a, key_b;      // up/down or left/right; SDL_SCANCODE_UNKNOWN if not assigned
+    int axis_a, axis_b;             // axis index; -1 if not assigned
+    int axis_dir_a, axis_dir_b;     // direction (1 = X+, 0, -1 = X-)
+    int hat, hat_pos_a, hat_pos_b;  // hat + hat position up/down and left/right; -1 if not assigned
+} SAxisMap;
+
+typedef struct
+{
+    CONTROL *control;               // pointer to CONTROL struct in Core library
+    BUTTONS buttons;
+
+    // mappings
+    SButtonMap    button[16];       // 14 buttons; in the order of EButton + mempak/rumblepak switches
+    SAxisMap      axis[2];          // 2 axis
+    int           device;           // joystick device; -1 = keyboard; -2 = none
+    int           mouse;            // mouse enabled: 0 = no; 1 = yes
+    SDL_Joystick *joystick;         // SDL joystick device
+    int           event_joystick;   // the /dev/input/eventX device for force feeback
+    int           axis_deadzone[2]; // minimum absolute value before analog movement is recognized
+    int           axis_peak[2];     // highest analog value returned by SDL, used for scaling
+    float         mouse_sens[2];    // mouse sensitivity
+} SController;
+
+/* global data definitions */
+extern SController controller[4];   // 4 controllers
+
+/* global function definitions */
+extern void DebugMessage(int level, const char *message, ...);
+
+/* declarations of pointers to Core config functions */
+extern ptr_ConfigListSections     ConfigListSections;
+extern ptr_ConfigOpenSection      ConfigOpenSection;
+extern ptr_ConfigDeleteSection    ConfigDeleteSection;
+extern ptr_ConfigListParameters   ConfigListParameters;
+extern ptr_ConfigSaveFile         ConfigSaveFile;
+extern ptr_ConfigSaveSection      ConfigSaveSection;
+extern ptr_ConfigSetParameter     ConfigSetParameter;
+extern ptr_ConfigGetParameter     ConfigGetParameter;
+extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp;
+extern ptr_ConfigSetDefaultInt    ConfigSetDefaultInt;
+extern ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat;
+extern ptr_ConfigSetDefaultBool   ConfigSetDefaultBool;
+extern ptr_ConfigSetDefaultString ConfigSetDefaultString;
+extern ptr_ConfigGetParamInt      ConfigGetParamInt;
+extern ptr_ConfigGetParamFloat    ConfigGetParamFloat;
+extern ptr_ConfigGetParamBool     ConfigGetParamBool;
+extern ptr_ConfigGetParamString   ConfigGetParamString;
+
+extern ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath;
+extern ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath;
+extern ptr_ConfigGetUserDataPath       ConfigGetUserDataPath;
+extern ptr_ConfigGetUserCachePath      ConfigGetUserCachePath;
+
+#endif // __PLUGIN_H__
+
diff --git a/source/mupen64plus-input-sdl/src/version.h b/source/mupen64plus-input-sdl/src/version.h
new file mode 100644 (file)
index 0000000..1bd0b08
--- /dev/null
@@ -0,0 +1,37 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-input-sdl - version.h                                     *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009-2012 Richard Goedeken                              *
+ *                                                                         *
+ *   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.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* This header file is for versioning information
+ *
+ */
+
+#if !defined(VERSION_H)
+#define VERSION_H
+
+#define PLUGIN_NAME    "Mupen64Plus SDL Input Plugin"
+#define PLUGIN_VERSION           0x020000
+#define INPUT_PLUGIN_API_VERSION 0x020000
+#define CONFIG_API_VERSION       0x020100
+
+#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
+
+#endif /* #define VERSION_H */
+