mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 01:24:01 +02:00
3rdParty: add mupen64plus-input-raphnetraw
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.o
|
||||
*.swp
|
||||
/projects/unix/_obj*/
|
||||
@@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = git@github.com:/raphnet/mupen64plus-input-raphnetraw.git
|
||||
branch = master
|
||||
commit = 86112413e98a8648edb11d199673cc24d5799af8
|
||||
parent = 06164d41b10707838444095da63841248d6f28f6
|
||||
method = merge
|
||||
cmdver = 0.4.6
|
||||
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<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.
|
||||
@@ -0,0 +1,26 @@
|
||||
Mupen64Plus-Input-raphnetraw INSTALL
|
||||
-----------------------------
|
||||
|
||||
This text file was written to explain the installation process of the
|
||||
Mupen64Plus-Input-raphnetraw 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-raphnetraw 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>
|
||||
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
Mupen64Plus-input-raphnetraw LICENSE
|
||||
-----------------------------
|
||||
|
||||
Mupen64Plus-input-raphnetraw is licensed under the GNU General Public License version 2.
|
||||
|
||||
The author of Mupen64Plus-input-raphnetraw is:
|
||||
* Raphaël Assénat (raphnet)
|
||||
|
||||
Mupen64Plus-input-raphnetraw is based on Mupen64Plus-input-sdl, its authors being:
|
||||
* 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)
|
||||
* Bobby Smiles (bsmiles32)
|
||||
* conchurnavid
|
||||
* Fayvel
|
||||
* HyperHacker
|
||||
* Nebuleon
|
||||
* s-verma
|
||||
* 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.
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
# Input plugin with direct N64 controller access for raphnet adapters
|
||||
|
||||
This mupen64plus plugin uses the direct controller access feature offered by my N64 to USB
|
||||
adapters (versions 3 and up) to let the emulated game communicate with the controllers directly.
|
||||
|
||||
* Perfect accuracy: The controller works exactly as it would on a N64 system, without any calibration or tweaking.
|
||||
* Rumble Pak and Controller Pak (mempak) support (and potentially other accesories too [not confirmed])
|
||||
* Support for other peripherals that connect to controller ports (eg: N64 mouse) [not confirmed]
|
||||
* Low latency
|
||||
|
||||
## Project homepage
|
||||
|
||||
* English: [Direct N64 controller access plugin mupen64plus](http://raphnet.net/programmation/mupen64plus-input-raphnetraw/index_en.php)
|
||||
* French: [Plugin d'accès direct aux manettes N64 pour mupen64plus](http://raphnet.net/programmation/mupen64plus-input-raphnetraw/index.php)
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the terms of the GNU General Public License, version 2.
|
||||
Source code is available on the project homepage and on GitHub.
|
||||
|
||||
## How to use the plugin
|
||||
|
||||
Regardless of your operating system, you will need to install the plugin file(s)
|
||||
in a directory mupen64plus will search for plugins (eg: Along the other plugin files).
|
||||
Then, you must tell mupen64plus to use it. eg:
|
||||
|
||||
```
|
||||
mupen64plus --input mupen64plus-input-raphnetraw
|
||||
```
|
||||
|
||||
Where to obtain the plugin files is described below.
|
||||
|
||||
### Linux
|
||||
|
||||
Please compile it from sources (howto below). This will generate mupen64plus-input-raphnetraw.so
|
||||
for your architecture.
|
||||
|
||||
### Windows (32 and 64 bit)
|
||||
|
||||
You may use the releases distributed by raphnet in a zip file. The file contents will look
|
||||
like this:
|
||||
|
||||
```
|
||||
mupen64plus-input-raphnetraw-windows-0.9/
|
||||
mupen64plus-input-raphnetraw-windows-0.9/README.md
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win64/
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win64/libhidapi-0.dll
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win64/mupen64plus-input-raphnetraw.dll
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win32/
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win32/libhidapi-0.dll
|
||||
mupen64plus-input-raphnetraw-windows-0.9/dist_win32/mupen64plus-input-raphnetraw.dll
|
||||
```
|
||||
|
||||
If you use a 64-bit version of mupen64plus, copy the files from the `dist_win64` directory. For
|
||||
the 32-bit version, copy the files from the `dist_win32` directory.
|
||||
|
||||
## Compiling the Linux / Unix version
|
||||
|
||||
### Prerequesites
|
||||
|
||||
A Linux system such as Debian with the following packages installed: (non-exhaustive list)
|
||||
|
||||
* gcc
|
||||
* make
|
||||
* libhidapi-hidraw0
|
||||
* libhidapi-dev
|
||||
|
||||
### Environment
|
||||
|
||||
#### Directory layout
|
||||
|
||||
The input-raphnetraw plugin requires a checkout of mupen64plus-core (for the plugin api headers).
|
||||
|
||||
* ...somedir/mupen64plus-input-raphnetraw
|
||||
* ...somedir/mupen64plus-core
|
||||
|
||||
#### Compilation
|
||||
|
||||
```sh
|
||||
$ cd .../somedir/
|
||||
$ cd mupen64plus-input-raphnetraw/projects/unix
|
||||
$ make all
|
||||
|
||||
# then, assuming all went well:
|
||||
$ cp mupen64plus-input-raphnetraw.so /your/mupen64plus-plugin-directory
|
||||
|
||||
# or, if you passed an appropriate PREFIX to make, you can just:
|
||||
$ make install
|
||||
```
|
||||
|
||||
## Win32/64 cross-compilation under Linux
|
||||
|
||||
### System requirements
|
||||
|
||||
A Linux system such as Debian with the following packages installed: (non-exhaustive list)
|
||||
|
||||
* mingw-w64
|
||||
* autotools-dev
|
||||
* autoconf
|
||||
* automake
|
||||
* libtool
|
||||
* git
|
||||
* make
|
||||
|
||||
### Environment
|
||||
|
||||
#### Directory layout
|
||||
|
||||
The input-raphnetraw plugin requires a checkout of mupen64plus-core (for the plugin api headers) in the
|
||||
parent directory. Also, each version (32 or 64 bit) requires a matching hidapi build.
|
||||
|
||||
* ...somedir/mupen64plus-input-raphnetraw
|
||||
* ...somedir/mupen64plus-core
|
||||
* ...somedir/hidapi
|
||||
* ...somedir/hidapi64
|
||||
|
||||
#### preparing the hidapi build
|
||||
|
||||
The buildwin32.sh and buildwin64.sh scripts assume the following:
|
||||
|
||||
* For the 32-bit build an hidapi configured and compiled with --host i686-w64-mingw32 is required here: ../../../hidapi
|
||||
* For the 64-bit build an hidapi configured and compiled with --host x86_64-w64-mingw32 is required here: ../../../hidapi64
|
||||
|
||||
hidapi can be obtained like this:
|
||||
|
||||
```sh
|
||||
$ cd ...somedir
|
||||
$ git clone https://github.com/signal11/hidapi.git
|
||||
$ git clone hidapi hidapi64
|
||||
```
|
||||
|
||||
And then to compile the win32 version:
|
||||
```sh
|
||||
cd ...somedir/hidapi
|
||||
./bootstrap
|
||||
./configure --host i686-w64-mingw32
|
||||
make
|
||||
```
|
||||
|
||||
And the win64 version:
|
||||
```sh
|
||||
cd ...somedir/hidapi64
|
||||
./bootstrap
|
||||
./configure --host x86_64-w64-mingw32
|
||||
make
|
||||
```
|
||||
|
||||
#### Compilation
|
||||
|
||||
This would cross-compile the 32 and 64-bit windows versions.
|
||||
|
||||
```bash
|
||||
$ cd .../somedir/
|
||||
$ cd mupen64plus-input-raphnetraw/projects/unix
|
||||
|
||||
# 32-bit version
|
||||
$./buildwin32.sh
|
||||
$ ./buildwin64.sh
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# Raphnet raw Input plugin for Mupen64Plus
|
||||
--------------------------------
|
||||
|
||||
## v1.1.0 - July 16, 2019
|
||||
|
||||
* Update to input plugin API 2.1.0
|
||||
|
||||
## v1.0.2 - November 6, 2018
|
||||
|
||||
* Add support for the 3.6.x adapter firmware
|
||||
|
||||
## v1.0.1 - November 22, 2017
|
||||
|
||||
* Add support for the upcoming 3.5.x adapter firmware
|
||||
(2-player adapters won't work properly otherwise)
|
||||
|
||||
## v1.0.0 - January 15, 2017
|
||||
|
||||
* Support for multiple adapters
|
||||
|
||||
## v0.9.4 - December 3, 2016
|
||||
|
||||
* Improved structure and separation for easier maintenance of the code shared between the Project 64 and mupen64plus versions of this plugin.
|
||||
* Support for the upcoming 3.4.x adapter firmware (will provide even lower latency/overhead)
|
||||
|
||||
## v0.9.3 - November 26, 2016
|
||||
|
||||
* Only handle channels supported by the adapter. This increases performance (reduces lag) by
|
||||
preventing meaningless attempts to communicate with controllers connected to non-existing
|
||||
ports on the adapter. It also fixes issues where games would see more than one controller was present.
|
||||
|
||||
## v0.9.2 - November 24, 2016
|
||||
|
||||
* Protect against invalid commands received from emulator. This fixes some games that failed to start.
|
||||
|
||||
## v0.9.1 - November 23, 2016
|
||||
|
||||
* Polling is now disabled only while a ROM is open.
|
||||
|
||||
## v0.9.0 - November 20, 2016
|
||||
|
||||
* Initial release
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
# * Mupen64plus-input-raphnetraw - Makefile *
|
||||
# * Copyright (C) 2016 Raphael Assenat *
|
||||
# * *
|
||||
# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||
# * *
|
||||
# * 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 raphnetraw 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
|
||||
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, only if it matters for build flags
|
||||
HOST_CPU ?= $(shell uname -m)
|
||||
CPU := OTHER
|
||||
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
|
||||
ifeq ("$(CPU)","OTHER")
|
||||
PIC ?= 1
|
||||
endif
|
||||
|
||||
# base CFLAGS, LDLIBS, and LDFLAGS
|
||||
OPTFLAGS ?= -O3 -flto
|
||||
WARNFLAGS ?= -Wall
|
||||
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -D_GNU_SOURCE=1
|
||||
LDFLAGS += $(SHARED)
|
||||
LDLIBS += -lm
|
||||
|
||||
# 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
|
||||
|
||||
# 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)
|
||||
#xcode-select has been around since XCode 3.0, i.e. OS X 10.5
|
||||
OSX_SDK_ROOT = $(shell xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs
|
||||
OSX_SDK_PATH = $(OSX_SDK_ROOT)/$(shell ls $(OSX_SDK_ROOT) | tail -1)
|
||||
|
||||
ifeq ($(CPU), X86)
|
||||
ifeq ($(ARCH_DETECTED), 64BITS)
|
||||
CFLAGS += -arch x86_64 -mmacosx-version-min=10.5 -isysroot $(OSX_SDK_PATH)
|
||||
LDLIBS += -ldl
|
||||
else
|
||||
CFLAGS += -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=10.5 -isysroot $(OSX_SDK_PATH)
|
||||
LDLIBS += -ldl -read_only_relocs suppress
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS), LINUX)
|
||||
HIDAPI_NAME=hidapi-hidraw
|
||||
else
|
||||
HIDAPI_NAME=hidapi
|
||||
endif
|
||||
|
||||
# test for presence of HIDLIB
|
||||
ifeq ($(origin HID_CFLAGS) $(origin HID_LDLIBS), undefined undefined)
|
||||
HIDAPI_CONFIG = $(CROSS_COMPILE)pkg-config $(HIDAPI_NAME)
|
||||
ifeq ($(shell which $(HIDAPI_CONFIG) 2>/dev/null),)
|
||||
HIDAPI_CONFIG = $(CROSS_COMPILE)pkg-config $(HIDAPI_NAME)
|
||||
ifeq ($(shell which $(HIDAPI_CONFIG) 2>/dev/null),)
|
||||
$(error No HIDAPI development libraries found!)
|
||||
else
|
||||
$(warning Using HIDAPI libraries)
|
||||
endif
|
||||
endif
|
||||
HID_CFLAGS += $(shell $(HIDAPI_CONFIG) --cflags)
|
||||
HID_LDLIBS += $(shell $(HIDAPI_CONFIG) --libs)
|
||||
endif
|
||||
CFLAGS += $(HID_CFLAGS)
|
||||
LDLIBS += $(HID_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
|
||||
ifeq ($(PORTS_1_AND_4), 1)
|
||||
CFLAGS += -DPORTS_1_AND_4
|
||||
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_front.c \
|
||||
$(SRCDIR)/plugin_back.c \
|
||||
$(SRCDIR)/gcn64lib.c \
|
||||
$(SRCDIR)/gcn64.c \
|
||||
$(SRCDIR)/hexdump.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-raphnetraw$(POSTFIX).$(SO_EXTENSION)
|
||||
|
||||
targets:
|
||||
@echo "Mupen64Plus-input-raphnetraw makefile. "
|
||||
@echo " Targets:"
|
||||
@echo " all == Build Mupen64Plus raphnetraw input plugin"
|
||||
@echo " clean == remove object files"
|
||||
@echo " rebuild == clean and re-build all"
|
||||
@echo " install == Install Mupen64Plus raphnetraw input plugin"
|
||||
@echo " uninstall == Uninstall Mupen64Plus raphnetraw 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"
|
||||
@echo " Build Options, tweaks:"
|
||||
@echo " PORTS_1_AND_4 == N64 port 4 -> Adapter port 2"
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
install: $(TARGET)
|
||||
$(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)"
|
||||
$(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)"
|
||||
$(INSTALL) -d "$(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 -MP
|
||||
-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
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
HIDHOME=../../../hidapi
|
||||
UNAME=MINGW32
|
||||
DESTDIR=./dist_win32
|
||||
|
||||
HID_CFLAGS="-I $HIDHOME/hidapi"
|
||||
HID_LDLIBS="-L $HIDHOME/windows/.libs/ -lhidapi"
|
||||
TARGETS=all
|
||||
MAKEFILE=Makefile
|
||||
|
||||
make -f $MAKEFILE clean
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -f $MAKEFILE CROSS_COMPILE=i686-w64-mingw32- UNAME=$UNAME HID_CFLAGS="$HID_CFLAGS" HID_LDLIBS="$HID_LDLIBS" $TARGETS V=1
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $DESTDIR
|
||||
cp mupen64plus-input-raphnetraw.dll $DESTDIR -v
|
||||
cp $HIDHOME/windows/.libs/*.dll $DESTDIR -v
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
HIDHOME=../../../hidapi64
|
||||
UNAME=MINGW64
|
||||
DESTDIR=./dist_win64
|
||||
|
||||
HID_CFLAGS="-I $HIDHOME/hidapi"
|
||||
HID_LDLIBS="-L $HIDHOME/windows/.libs/ -lhidapi"
|
||||
TARGETS=all
|
||||
MAKEFILE=Makefile
|
||||
|
||||
make -f $MAKEFILE clean
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -f $MAKEFILE CROSS_COMPILE=x86_64-w64-mingw32- UNAME=$UNAME HID_CFLAGS="$HID_CFLAGS" HID_LDLIBS="$HID_LDLIBS" $TARGETS V=1
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $DESTDIR
|
||||
cp mupen64plus-input-raphnetraw.dll $DESTDIR -v
|
||||
cp $HIDHOME/windows/.libs/*.dll $DESTDIR -v
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
PREFIX=mupen64plus-input-raphnetraw
|
||||
HEXFILE=$PREFIX.hex
|
||||
|
||||
echo "Release script for $PREFIX"
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Syntax: ./release.sh version releasedir"
|
||||
echo
|
||||
echo "ex: './release 1.0' will produce $PREFIX-1.0.tar.gz in releasedir out of git HEAD,"
|
||||
echo "and place it in the release directory."
|
||||
echo
|
||||
echo "It will also create a tag named v1.0"
|
||||
exit
|
||||
fi
|
||||
|
||||
VERSION=$1
|
||||
RELEASEDIR=$2
|
||||
DIRNAME=$PREFIX-$VERSION
|
||||
FILENAME=$PREFIX-$VERSION.tar.gz
|
||||
TAG=v$VERSION
|
||||
|
||||
echo "Version: $VERSION"
|
||||
echo "Filename: $FILENAME"
|
||||
echo "Release directory: $RELEASEDIR"
|
||||
echo "--------"
|
||||
echo "Ready? Press ENTER to go ahead (or CTRL+C to cancel)"
|
||||
|
||||
read
|
||||
|
||||
if [ -f $RELEASEDIR/$FILENAME ]; then
|
||||
echo "Release file already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git tag $TAG -f
|
||||
git archive --format=tar --prefix=$DIRNAME/ HEAD | gzip > $RELEASEDIR/$FILENAME
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
PROJECT=mupen64plus-input-raphnetraw-windows
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Syntax: ./release.sh version releasedir"
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
|
||||
VERSION=$1
|
||||
RELEASEDIR=$2
|
||||
DIRNAME=$PROJECT-$VERSION
|
||||
FILENAME=$PROJECT-$VERSION.zip
|
||||
|
||||
if [ -d $RELEASEDIR/$DIRNAME ]; then
|
||||
echo "$RELEASEDIR/$DIRNAME already exists";
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $RELEASEDIR/$DIRNAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not mkdir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd projects/unix
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not chdir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./buildwin32.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Win32 build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./buildwin64.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Win64 build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd .. # exit unix
|
||||
cd .. # exit projects
|
||||
|
||||
cp projects/unix/dist_win32 -rv $RELEASEDIR/$DIRNAME
|
||||
cp projects/unix/dist_win64 -rv $RELEASEDIR/$DIRNAME
|
||||
cp README.md -rv $RELEASEDIR/$DIRNAME
|
||||
cp README.md -rv $RELEASEDIR/$DIRNAME/readme.txt
|
||||
cp RELEASE -rv $RELEASEDIR/$DIRNAME/releases.txt
|
||||
|
||||
cd $RELEASEDIR
|
||||
|
||||
zip -r $FILENAME $DIRNAME
|
||||
echo
|
||||
echo
|
||||
echo
|
||||
echo -------------------------------------
|
||||
ls -lh $FILENAME
|
||||
echo Done
|
||||
@@ -0,0 +1,371 @@
|
||||
/* gc_n64_usb : Gamecube or N64 controller to USB adapter firmware
|
||||
Copyright (C) 2007-2017 Raphael Assenat <raph@raphnet.net>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "gcn64.h"
|
||||
#include "gcn64_priv.h"
|
||||
#include "gcn64lib.h"
|
||||
#include "requests.h"
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
static int dusbr_verbose = 0;
|
||||
|
||||
#define IS_VERBOSE() (dusbr_verbose)
|
||||
|
||||
struct supported_adapter {
|
||||
uint16_t vid, pid;
|
||||
int if_number;
|
||||
struct gcn64_adapter_caps caps;
|
||||
};
|
||||
|
||||
static struct supported_adapter supported_adapters[] = {
|
||||
/* vid, pid, if_no, { n_raw, bio_support } */
|
||||
|
||||
{ OUR_VENDOR_ID, 0x0017, 1, { 1, 0 } }, // GC/N64 USB v3.0, 3.1.0, 3.1.1
|
||||
{ OUR_VENDOR_ID, 0x001D, 1, { 1, 0 } }, // GC/N64 USB v3.2.0 ... v3.3.x
|
||||
{ OUR_VENDOR_ID, 0x0020, 1, { 1, 0 } }, // GCN64->USB v3.2.1 (N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0021, 1, { 1, 0 } }, // GCN64->USB v3.2.1 (GC mode)
|
||||
{ OUR_VENDOR_ID, 0x0022, 1, { 2, 0 } }, // GCN64->USB v3.3.x (2x GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0030, 1, { 2, 0 } }, // GCN64->USB v3.3.0 (2x N64-only mode)
|
||||
{ OUR_VENDOR_ID, 0x0031, 1, { 2, 0 } }, // GCN64->USB v3.3.0 (2x GC-only mode)
|
||||
|
||||
{ OUR_VENDOR_ID, 0x0032, 1, { 1, 1 } }, // GC/N64 USB v3.4.x (GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0033, 1, { 1, 1 } }, // GC/N64 USB v3.4.x (N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0034, 1, { 1, 1 } }, // GC/N64 USB v3.4.x (GC mode)
|
||||
{ OUR_VENDOR_ID, 0x0035, 1, { 2, 1 } }, // GC/N64 USB v3.4.x (2x GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0036, 1, { 2, 1 } }, // GC/N64 USB v3.4.x (2x N64-only mode)
|
||||
{ OUR_VENDOR_ID, 0x0037, 1, { 2, 1 } }, // GC/N64 USB v3.4.x (2x GC-only mode)
|
||||
|
||||
// GC/N64 USB v3.5.x flavours
|
||||
{ OUR_VENDOR_ID, 0x0038, 1, { 1, 1 } }, // (GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0039, 1, { 1, 1 } }, // (N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x003A, 1, { 1, 1 } }, // (GC mode)
|
||||
{ OUR_VENDOR_ID, 0x003B, 2, { 2, 1 } }, // (2x GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x003C, 2, { 2, 1 } }, // (2x N64-only mode)
|
||||
{ OUR_VENDOR_ID, 0x003D, 2, { 2, 1 } }, // (2x GC-only mode)
|
||||
|
||||
// GC/N64 USB v3.6.x flavours
|
||||
{ OUR_VENDOR_ID, 0x0060, 1, { 1, 1 } }, // (GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0061, 1, { 1, 1 } }, // (N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0063, 2, { 2, 1 } }, // (2x GC/N64 mode)
|
||||
{ OUR_VENDOR_ID, 0x0064, 2, { 2, 1 } }, // (2x N64-only mode)
|
||||
{ OUR_VENDOR_ID, 0x0067, 1, { 1, 1 } }, // (GC/N64 in GC keyboard mode)
|
||||
|
||||
{ }, // terminator
|
||||
};
|
||||
|
||||
int gcn64_init(int verbose)
|
||||
{
|
||||
dusbr_verbose = verbose;
|
||||
hid_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gcn64_shutdown(void)
|
||||
{
|
||||
hid_exit();
|
||||
}
|
||||
|
||||
static char isProductIdHandled(unsigned short pid, int interface_number, struct gcn64_adapter_caps *caps)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; supported_adapters[i].vid; i++) {
|
||||
if (pid == supported_adapters[i].pid) {
|
||||
if (interface_number == supported_adapters[i].if_number) {
|
||||
if (caps) {
|
||||
memcpy(caps, &supported_adapters[i].caps, sizeof (struct gcn64_adapter_caps));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gcn64_list_ctx *gcn64_allocListCtx(void)
|
||||
{
|
||||
struct gcn64_list_ctx *ctx;
|
||||
ctx = calloc(1, sizeof(struct gcn64_list_ctx));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void gcn64_freeListCtx(struct gcn64_list_ctx *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
if (ctx->devs) {
|
||||
hid_free_enumeration(ctx->devs);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int gcn64_countDevices(void)
|
||||
{
|
||||
struct gcn64_list_ctx *ctx;
|
||||
struct gcn64_info inf;
|
||||
int count = 0;
|
||||
|
||||
ctx = gcn64_allocListCtx();
|
||||
while (gcn64_listDevices(&inf, ctx)) {
|
||||
count++;
|
||||
}
|
||||
gcn64_freeListCtx(ctx);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief List instances of our rgbleds device on the USB busses.
|
||||
* \param info Pointer to gcn64_info structure to store data
|
||||
* \param dst Destination buffer for device serial number/id.
|
||||
* \param dstbuf_size Destination buffer size.
|
||||
*/
|
||||
struct gcn64_info *gcn64_listDevices(struct gcn64_info *info, struct gcn64_list_ctx *ctx)
|
||||
{
|
||||
struct gcn64_adapter_caps caps;
|
||||
|
||||
memset(info, 0, sizeof(struct gcn64_info));
|
||||
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "gcn64_listDevices: Passed null context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->devs)
|
||||
goto jumpin;
|
||||
|
||||
if (IS_VERBOSE()) {
|
||||
printf("Start listing\n");
|
||||
}
|
||||
|
||||
ctx->devs = hid_enumerate(OUR_VENDOR_ID, 0x0000);
|
||||
if (!ctx->devs) {
|
||||
printf("Hid enumerate returned NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ctx->cur_dev = ctx->devs; ctx->cur_dev; ctx->cur_dev = ctx->cur_dev->next)
|
||||
{
|
||||
if (IS_VERBOSE()) {
|
||||
printf("Considering 0x%04x:0x%04x\n", ctx->cur_dev->vendor_id, ctx->cur_dev->product_id);
|
||||
}
|
||||
if (isProductIdHandled(ctx->cur_dev->product_id, ctx->cur_dev->interface_number, &caps))
|
||||
{
|
||||
info->usb_vid = ctx->cur_dev->vendor_id;
|
||||
info->usb_pid = ctx->cur_dev->product_id;
|
||||
wcsncpy(info->str_prodname, ctx->cur_dev->product_string, PRODNAME_MAXCHARS-1);
|
||||
wcsncpy(info->str_serial, ctx->cur_dev->serial_number, SERIAL_MAXCHARS-1);
|
||||
strncpy(info->str_path, ctx->cur_dev->path, PATH_MAXCHARS-1);
|
||||
memcpy(&info->caps, &caps, sizeof(info->caps));
|
||||
return info;
|
||||
}
|
||||
|
||||
jumpin:
|
||||
// prevent 'error: label at end of compound statement'
|
||||
continue;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gcn64_hdl_t gcn64_openDevice(struct gcn64_info *dev)
|
||||
{
|
||||
hid_device *hdev;
|
||||
gcn64_hdl_t hdl;
|
||||
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
if (IS_VERBOSE()) {
|
||||
printf("Opening device path: '%s'\n", dev->str_path);
|
||||
}
|
||||
|
||||
hdev = hid_open_path(dev->str_path);
|
||||
if (!hdev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdl = malloc(sizeof(struct _gcn64_hdl_t));
|
||||
if (!hdl) {
|
||||
perror("malloc");
|
||||
hid_close(hdev);
|
||||
return NULL;
|
||||
}
|
||||
hdl->hdev = hdev;
|
||||
hdl->report_size = 63;
|
||||
memcpy(&hdl->caps, &dev->caps, sizeof(hdl->caps));
|
||||
|
||||
if (!dev->caps.bio_support) {
|
||||
printf("Pre-3.4 version detected. Setting report size to 40 bytes\n");
|
||||
hdl->report_size = 40;
|
||||
}
|
||||
|
||||
return hdl;
|
||||
}
|
||||
|
||||
gcn64_hdl_t gcn64_openBy(struct gcn64_info *dev, unsigned char flags)
|
||||
{
|
||||
struct gcn64_list_ctx *ctx;
|
||||
struct gcn64_info inf;
|
||||
gcn64_hdl_t h;
|
||||
|
||||
if (IS_VERBOSE())
|
||||
printf("gcn64_openBy, flags=0x%02x\n", flags);
|
||||
|
||||
ctx = gcn64_allocListCtx();
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
while (gcn64_listDevices(&inf, ctx)) {
|
||||
if (IS_VERBOSE())
|
||||
printf("Considering '%s'\n", inf.str_path);
|
||||
|
||||
if (flags & GCN64_FLG_OPEN_BY_SERIAL) {
|
||||
if (wcscmp(inf.str_serial, dev->str_serial))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & GCN64_FLG_OPEN_BY_PATH) {
|
||||
if (strcmp(inf.str_path, dev->str_path))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & GCN64_FLG_OPEN_BY_VID) {
|
||||
if (inf.usb_vid != dev->usb_vid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & GCN64_FLG_OPEN_BY_PID) {
|
||||
if (inf.usb_pid != dev->usb_pid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IS_VERBOSE())
|
||||
printf("Found device. opening...\n");
|
||||
|
||||
h = gcn64_openDevice(&inf);
|
||||
gcn64_freeListCtx(ctx);
|
||||
return h;
|
||||
}
|
||||
|
||||
gcn64_freeListCtx(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gcn64_closeDevice(gcn64_hdl_t hdl)
|
||||
{
|
||||
hid_device *hdev = hdl->hdev;
|
||||
|
||||
if (hdev) {
|
||||
hid_close(hdev);
|
||||
}
|
||||
|
||||
free(hdl);
|
||||
}
|
||||
|
||||
int gcn64_send_cmd(gcn64_hdl_t hdl, const unsigned char *cmd, int cmdlen)
|
||||
{
|
||||
hid_device *hdev = hdl->hdev;
|
||||
unsigned char buffer[hdl->report_size+1];
|
||||
int n;
|
||||
|
||||
if (cmdlen > (sizeof(buffer)-1)) {
|
||||
fprintf(stderr, "Error: Command too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
buffer[0] = 0x00; // report ID set to 0 (device has only one)
|
||||
memcpy(buffer + 1, cmd, cmdlen);
|
||||
|
||||
n = hid_send_feature_report(hdev, buffer, sizeof(buffer));
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Could not send feature report (%ls)\n", hid_error(hdev));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64_poll_result(gcn64_hdl_t hdl, unsigned char *cmd, int cmd_maxlen)
|
||||
{
|
||||
hid_device *hdev = hdl->hdev;
|
||||
unsigned char buffer[hdl->report_size+1];
|
||||
int res_len;
|
||||
int n;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
buffer[0] = 0x00; // report ID set to 0 (device has only one)
|
||||
|
||||
n = hid_get_feature_report(hdev, buffer, sizeof(buffer));
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Could not send feature report (%ls)\n", hid_error(hdev));
|
||||
return -1;
|
||||
}
|
||||
if (n==0) {
|
||||
return 0;
|
||||
}
|
||||
res_len = n-1;
|
||||
|
||||
if (res_len>0) {
|
||||
int copy_len;
|
||||
|
||||
copy_len = res_len;
|
||||
if (copy_len > cmd_maxlen) {
|
||||
copy_len = cmd_maxlen;
|
||||
}
|
||||
if (cmd) {
|
||||
memcpy(cmd, buffer+1, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
return res_len;
|
||||
}
|
||||
|
||||
int gcn64_exchange(gcn64_hdl_t hdl, unsigned char *outcmd, int outlen, unsigned char *result, int result_max)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = gcn64_send_cmd(hdl, outcmd, outlen);
|
||||
if (n<0) {
|
||||
fprintf(stderr, "Error sending command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer to the command comes later. For now, this is polled, but in
|
||||
* the future an interrupt-in transfer could be used. */
|
||||
do {
|
||||
n = gcn64_poll_result(hdl, result, result_max);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "Error\r\n");
|
||||
break;
|
||||
}
|
||||
if (n==0) {
|
||||
// printf("."); fflush(stdout);
|
||||
}
|
||||
|
||||
} while (n==0);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _gcn64_h__
|
||||
#define _gcn64_h__
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#define OUR_VENDOR_ID 0x289b
|
||||
#define PRODNAME_MAXCHARS 256
|
||||
#define SERIAL_MAXCHARS 256
|
||||
#define PATH_MAXCHARS 256
|
||||
|
||||
struct gcn64_adapter_caps {
|
||||
int n_raw_channels;
|
||||
int bio_support;
|
||||
};
|
||||
|
||||
struct gcn64_info {
|
||||
wchar_t str_prodname[PRODNAME_MAXCHARS];
|
||||
wchar_t str_serial[SERIAL_MAXCHARS];
|
||||
char str_path[PATH_MAXCHARS];
|
||||
int usb_vid, usb_pid;
|
||||
int access; // True unless direct access to read serial/prodname failed due to permissions.
|
||||
struct gcn64_adapter_caps caps;
|
||||
};
|
||||
|
||||
struct gcn64_list_ctx;
|
||||
|
||||
typedef struct _gcn64_hdl_t *gcn64_hdl_t; // Cast from hid_device
|
||||
|
||||
int gcn64_init(int verbose);
|
||||
void gcn64_shutdown(void);
|
||||
|
||||
struct gcn64_list_ctx *gcn64_allocListCtx(void);
|
||||
void gcn64_freeListCtx(struct gcn64_list_ctx *ctx);
|
||||
struct gcn64_info *gcn64_listDevices(struct gcn64_info *info, struct gcn64_list_ctx *ctx);
|
||||
int gcn64_countDevices(void);
|
||||
|
||||
gcn64_hdl_t gcn64_openDevice(struct gcn64_info *dev);
|
||||
|
||||
#define GCN64_FLG_OPEN_BY_SERIAL 1 /** Serial must match */
|
||||
#define GCN64_FLG_OPEN_BY_PATH 2 /** Path must match */
|
||||
#define GCN64_FLG_OPEN_BY_VID 4 /** USB VID must match */
|
||||
#define GCN64_FLG_OPEN_BY_PID 8 /** USB PID MUST match */
|
||||
/**
|
||||
* \brief Open a device matching a serial number
|
||||
* \param dev The device structure
|
||||
* \param flags Flags
|
||||
* \return A handle to the opened device, or NULL if not found
|
||||
**/
|
||||
gcn64_hdl_t gcn64_openBy(struct gcn64_info *dev, unsigned char flags);
|
||||
|
||||
void gcn64_closeDevice(gcn64_hdl_t hdl);
|
||||
|
||||
int gcn64_send_cmd(gcn64_hdl_t hdl, const unsigned char *cmd, int len);
|
||||
int gcn64_poll_result(gcn64_hdl_t hdl, unsigned char *cmd, int cmdlen);
|
||||
|
||||
int gcn64_exchange(gcn64_hdl_t hdl, unsigned char *outcmd, int outlen, unsigned char *result, int result_max);
|
||||
|
||||
#endif // _gcn64_h__
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef _gcn64_priv_h__
|
||||
#define _gcn64_priv_h__
|
||||
|
||||
#include "hidapi.h"
|
||||
#include "gcn64.h"
|
||||
|
||||
struct gcn64_list_ctx {
|
||||
struct hid_device_info *devs, *cur_dev;
|
||||
};
|
||||
|
||||
typedef struct _gcn64_hdl_t {
|
||||
hid_device *hdev;
|
||||
int report_size;
|
||||
struct gcn64_adapter_caps caps;
|
||||
} *gcn64_hdl_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
#ifndef _gcn64_protocol_h__
|
||||
#define _gcn64_protocol_h__
|
||||
|
||||
#define CONTROLLER_IS_ABSENT 0
|
||||
#define CONTROLLER_IS_N64 1
|
||||
#define CONTROLLER_IS_GC 2
|
||||
#define CONTROLLER_IS_GC_KEYBOARD 3
|
||||
#define CONTROLLER_IS_UNKNOWN 4
|
||||
|
||||
|
||||
/* Return many unknown bits, but two are about the expansion port. */
|
||||
#define N64_GET_CAPABILITIES 0x00
|
||||
#define N64_RESET 0xFF
|
||||
#define N64_CAPS_REPLY_LENGTH 3
|
||||
|
||||
#define OFFSET_EXT_REMOVED 22
|
||||
#define OFFSET_EXT_PRESENT 23
|
||||
|
||||
/* Returns button states and axis values */
|
||||
#define N64_GET_STATUS 0x01
|
||||
#define N64_GET_STATUS_REPLY_LENGTH 4
|
||||
|
||||
/* Read from the expansion bus. */
|
||||
#define N64_EXPANSION_READ 0x02
|
||||
|
||||
/* Write to the expansion bus. */
|
||||
#define N64_EXPANSION_WRITE 0x03
|
||||
|
||||
/* Return information about controller. */
|
||||
#define GC_GETID 0x00
|
||||
#define GC_GETID_REPLY_LENGTH 3
|
||||
|
||||
/* 3-byte get status command. Returns axis and buttons. Also
|
||||
* controls motor. */
|
||||
#define GC_GETSTATUS1 0x40
|
||||
#define GC_GETSTATUS2 0x03
|
||||
#define GC_GETSTATUS3(rumbling) ((rumbling) ? 0x01 : 0x00)
|
||||
#define GC_GETSTATUS_REPLY_LENGTH 8
|
||||
|
||||
/* 3-byte poll keyboard command.
|
||||
* Source: http://hitmen.c02.at/files/yagcd/yagcd/chap9.html#sec9.3.3
|
||||
* */
|
||||
#define GC_POLL_KB1 0x54
|
||||
#define GC_POLL_KB2 0x00
|
||||
#define GC_POLL_KB3 0x00
|
||||
|
||||
/* Gamecube keycodes are from table 9.3.2:
|
||||
* http://hitmen.c02.at/files/yagcd/yagcd/chap9.html#sec9.3.2
|
||||
*
|
||||
* But the table appears to have been built using a PC keyboard
|
||||
* converted (Tototek).
|
||||
*
|
||||
* I was working with an ASCII keyboard so I made a few adjustments
|
||||
* to reflect the /real/ key functions. For instance:
|
||||
*
|
||||
* LWIN, RWIN and MENU are in fact the Henkan, muhenkan and katakana/hiragana keys.
|
||||
* They are equivalemnt to the HID keys International 4, International 5 and International 2.
|
||||
* The - key (code 0x3F) is also HID international 1.
|
||||
* The PrntScrn key (code 0x36) is in fact the Yen key (International 3).
|
||||
* The bracket/brace [{ and }] keys are at different places on this Japanese keyboard,
|
||||
* but following standard PC practice, some keycodes are named after the US usage. Hence,
|
||||
* the aforementioned keys are the 2 keys right of P, even if they are not labeled.
|
||||
*/
|
||||
#define GC_KEY_RESERVED 0x00 // No key
|
||||
|
||||
#define GC_KEY_HOME 0x06
|
||||
#define GC_KEY_END 0x07
|
||||
#define GC_KEY_PGUP 0x08
|
||||
#define GC_KEY_PGDN 0x09
|
||||
#define GC_KEY_SCROLL_LOCK 0x0A
|
||||
|
||||
#define GC_KEY_A 0x10
|
||||
#define GC_KEY_B 0x11
|
||||
#define GC_KEY_C 0x12
|
||||
#define GC_KEY_D 0x13
|
||||
#define GC_KEY_E 0x14
|
||||
#define GC_KEY_F 0x15
|
||||
#define GC_KEY_G 0x16
|
||||
#define GC_KEY_H 0x17
|
||||
#define GC_KEY_I 0x18
|
||||
#define GC_KEY_J 0x19
|
||||
#define GC_KEY_K 0x1A
|
||||
#define GC_KEY_L 0x1B
|
||||
#define GC_KEY_M 0x1C
|
||||
#define GC_KEY_N 0x1D
|
||||
#define GC_KEY_O 0x1E
|
||||
#define GC_KEY_P 0x1F
|
||||
#define GC_KEY_Q 0x20
|
||||
#define GC_KEY_R 0x21
|
||||
#define GC_KEY_S 0x22
|
||||
#define GC_KEY_T 0x23
|
||||
#define GC_KEY_U 0x24
|
||||
#define GC_KEY_V 0x25
|
||||
#define GC_KEY_W 0x26
|
||||
#define GC_KEY_X 0x27
|
||||
#define GC_KEY_Y 0x28
|
||||
#define GC_KEY_Z 0x29
|
||||
#define GC_KEY_1 0x2A
|
||||
#define GC_KEY_2 0x2B
|
||||
#define GC_KEY_3 0x2C
|
||||
#define GC_KEY_4 0x2D
|
||||
#define GC_KEY_5 0x2E
|
||||
#define GC_KEY_6 0x2F
|
||||
#define GC_KEY_7 0x30
|
||||
#define GC_KEY_8 0x31
|
||||
#define GC_KEY_9 0x32
|
||||
#define GC_KEY_0 0x33
|
||||
#define GC_KEY_DASH_UNDERSCORE 0x34 // Key next to 0
|
||||
#define GC_KEY_PLUS_EQUAL 0x35
|
||||
#define GC_KEY_YEN 0x36 // Yen on ascii keyboard. HID International 3.
|
||||
#define GC_KEY_OPEN_BRKT_BRACE 0x37 // 1st key right of P
|
||||
#define GC_KEY_CLOSE_BRKT_BRACE 0x38 // 2nd key right of P
|
||||
#define GC_KEY_SEMI_COLON_COLON 0x39 // ;:
|
||||
#define GC_KEY_QUOTES 0x3A // '"
|
||||
|
||||
// The 3rd key after 'L'. HID Keyboard non-us # and ~
|
||||
#define GC_KEY_BRACKET_MU 0x3B
|
||||
#define GC_KEY_COMMA_ST 0x3C // ,<
|
||||
#define GC_KEY_PERIOD_GT 0x3D // .>
|
||||
#define GC_KEY_SLASH_QUESTION 0x3E // /?
|
||||
|
||||
// (The extra key before right-shift on japanese keyboards.
|
||||
// HID code International 1 [HID usage tables Footnote 15-20]).
|
||||
#define GC_KEY_INTERNATIONAL1 0x3F
|
||||
#define GC_KEY_F1 0x40
|
||||
#define GC_KEY_F2 0x41
|
||||
#define GC_KEY_F3 0x42
|
||||
#define GC_KEY_F4 0x43
|
||||
#define GC_KEY_F5 0x44
|
||||
#define GC_KEY_F6 0x45
|
||||
#define GC_KEY_F7 0x46
|
||||
#define GC_KEY_F8 0x47
|
||||
#define GC_KEY_F9 0x48
|
||||
#define GC_KEY_F10 0x49
|
||||
#define GC_KEY_F11 0x4A
|
||||
#define GC_KEY_F12 0x4B
|
||||
#define GC_KEY_ESC 0x4C
|
||||
#define GC_KEY_INSERT 0x4D
|
||||
#define GC_KEY_DELETE 0x4E
|
||||
|
||||
// (Hankaku/zenkaku/kanji button). Also known as `~
|
||||
#define GC_KEY_HANKAKU 0x4F
|
||||
#define GC_KEY_BACKSPACE 0x50
|
||||
#define GC_KEY_TAB 0x51
|
||||
|
||||
#define GC_KEY_CAPS_LOCK 0x53
|
||||
#define GC_KEY_LEFT_SHIFT 0x54
|
||||
#define GC_KEY_RIGHT_SHIFT 0x55
|
||||
#define GC_KEY_LEFT_CTRL 0x56
|
||||
#define GC_KEY_LEFT_ALT 0x57
|
||||
#define GC_KEY_MUHENKAN 0x58 // HID international 5
|
||||
#define GC_KEY_SPACE 0x59
|
||||
#define GC_KEY_HENKAN 0x5A // HID international 4
|
||||
#define GC_KEY_KANA 0x5B // HID international 2
|
||||
#define GC_KEY_LEFT 0x5C
|
||||
#define GC_KEY_DOWN 0x5D
|
||||
#define GC_KEY_UP 0x5E
|
||||
#define GC_KEY_RIGHT 0x5F
|
||||
|
||||
#define GC_KEY_ENTER 0x61
|
||||
|
||||
void gcn64protocol_hwinit(void);
|
||||
int gcn64_detectController(void);
|
||||
unsigned char gcn64_transaction(const unsigned char *tx, int tx_len, unsigned char *rx, unsigned char rx_max);
|
||||
|
||||
#endif // _gcn64_protocol_h__
|
||||
@@ -0,0 +1,444 @@
|
||||
/* gc_n64_usb : Gamecube or N64 controller to USB adapter firmware
|
||||
Copyright (C) 2007-2015 Raphael Assenat <raph@raphnet.net>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "gcn64lib.h"
|
||||
#include "gcn64_priv.h"
|
||||
#include "requests.h"
|
||||
#include "gcn64_protocol.h"
|
||||
#include "hexdump.h"
|
||||
|
||||
int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max)
|
||||
{
|
||||
unsigned char cmd[2];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_GET_CONFIG_PARAM;
|
||||
cmd[1] = param;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2, rx, rx_max);
|
||||
if (n<2)
|
||||
return n;
|
||||
|
||||
n -= 2;
|
||||
|
||||
// Drop the leading CMD and PARAM
|
||||
if (n) {
|
||||
memmove(rx, rx+2, n);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len)
|
||||
{
|
||||
unsigned char cmd[2 + len];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_SET_CONFIG_PARAM;
|
||||
cmd[1] = param;
|
||||
memcpy(cmd + 2, data, len);
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2 + len, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend)
|
||||
{
|
||||
unsigned char cmd[2];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_SUSPEND_POLLING;
|
||||
cmd[1] = suspend;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_getVersion(gcn64_hdl_t hdl, char *dst, int dstmax)
|
||||
{
|
||||
unsigned char cmd[32];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dstmax <= 0)
|
||||
return -1;
|
||||
|
||||
cmd[0] = RQ_GCN64_GET_VERSION;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 1, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
dst[0] = 0;
|
||||
if (n > 1) {
|
||||
strncpy(dst, (char*)cmd+1, n);
|
||||
}
|
||||
dst[dstmax-1] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_getControllerType(gcn64_hdl_t hdl, int chn)
|
||||
{
|
||||
unsigned char cmd[32];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_GET_CONTROLLER_TYPE;
|
||||
cmd[1] = chn;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
if (n<3)
|
||||
return -1;
|
||||
|
||||
return cmd[2];
|
||||
}
|
||||
|
||||
const char *gcn64lib_controllerName(int type)
|
||||
{
|
||||
switch(type) {
|
||||
case CTL_TYPE_NONE: return "No controller";
|
||||
case CTL_TYPE_N64: return "N64 Controller";
|
||||
case CTL_TYPE_GC: return "GC Controller";
|
||||
case CTL_TYPE_GCKB: return "GC Keyboard";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int gcn64lib_getSignature(gcn64_hdl_t hdl, char *dst, int dstmax)
|
||||
{
|
||||
unsigned char cmd[40];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dstmax <= 0)
|
||||
return -1;
|
||||
|
||||
cmd[0] = RQ_GCN64_GET_SIGNATURE;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 1, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
dst[0] = 0;
|
||||
if (n > 1) {
|
||||
strncpy(dst, (char*)cmd+1, n);
|
||||
}
|
||||
dst[dstmax-1] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_forceVibration(gcn64_hdl_t hdl, unsigned char channel, unsigned char vibrate)
|
||||
{
|
||||
unsigned char cmd[3];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_SET_VIBRATION;
|
||||
cmd[1] = channel;
|
||||
cmd[2] = vibrate;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 3, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx)
|
||||
{
|
||||
unsigned char cmd[3 + tx_len];
|
||||
unsigned char rep[3 + 64];
|
||||
int cmdlen, rx_len, n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = channel;
|
||||
cmd[2] = tx_len;
|
||||
memcpy(cmd+3, tx, tx_len);
|
||||
cmdlen = 3 + tx_len;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, cmdlen, rep, sizeof(rep));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
rx_len = rep[2];
|
||||
if (rx) {
|
||||
memcpy(rx, rep + 3, rx_len);
|
||||
}
|
||||
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
int gcn64lib_16bit_scan(gcn64_hdl_t hdl, unsigned short min, unsigned short max)
|
||||
{
|
||||
int id, n;
|
||||
unsigned char buf[64];
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (id = min; id<=max; id++) {
|
||||
buf[0] = id >> 8;
|
||||
buf[1] = id & 0xff;
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, buf, 2, buf, sizeof(buf));
|
||||
if (n > 0) {
|
||||
printf("CMD 0x%04x answer: ", id);
|
||||
printHexBuf(buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_8bit_scan(gcn64_hdl_t hdl, unsigned char min, unsigned char max)
|
||||
{
|
||||
int id, n;
|
||||
unsigned char buf[64];
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (id = min; id<=max; id++) {
|
||||
buf[0] = id;
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, buf, 1, buf, sizeof(buf));
|
||||
if (n > 0) {
|
||||
printf("CMD 0x%02x answer: ", id);
|
||||
printHexBuf(buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_bootloader(gcn64_hdl_t hdl)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
int cmdlen;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = RQ_GCN64_JUMP_TO_BOOTLOADER;
|
||||
cmdlen = 1;
|
||||
|
||||
gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_n64_expansionWrite(gcn64_hdl_t hdl, unsigned short addr, unsigned char *data, int len)
|
||||
{
|
||||
unsigned char cmd[3 + len];
|
||||
int cmdlen;
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = N64_EXPANSION_WRITE;
|
||||
cmd[1] = addr>>8; // Address high byte
|
||||
cmd[2] = addr&0xff; // Address low byte
|
||||
memcpy(cmd + 3, data, len);
|
||||
cmdlen = 3 + len;
|
||||
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, cmdlen, cmd, sizeof(cmd));
|
||||
if (n != 1) {
|
||||
printf("expansion write returned != 1 (%d)\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cmd[0];
|
||||
}
|
||||
|
||||
int gcn64lib_n64_expansionRead(gcn64_hdl_t hdl, unsigned short addr, unsigned char *dst, int max_len)
|
||||
{
|
||||
unsigned char cmd[3];
|
||||
int n;
|
||||
|
||||
if (!hdl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = N64_EXPANSION_READ;
|
||||
cmd[1] = addr>>8; // Address high byte
|
||||
cmd[2] = addr&0xff; // Address low byte
|
||||
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, dst, max_len);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int gcn64lib_blockIO_compat(gcn64_hdl_t hdl, struct blockio_op *iops, int n_iops)
|
||||
{
|
||||
int i;
|
||||
int res;
|
||||
|
||||
for (i=0; i<n_iops; i++) {
|
||||
res = gcn64lib_rawSiCommand(hdl, iops[i].chn, iops[i].tx_data, iops[i].tx_len, iops[i].rx_data, iops[i].rx_len);
|
||||
if (res <= 0) {
|
||||
// Timeout
|
||||
iops[i].rx_len &= BIO_RXTX_MASK;
|
||||
iops[i].rx_len |= BIO_RX_LEN_TIMEDOUT;
|
||||
} else if (res != iops[i].rx_len) {
|
||||
// Less bytes than expected
|
||||
iops[i].rx_len &= BIO_RXTX_MASK;
|
||||
iops[i].rx_len |= BIO_RX_LEN_TIMEDOUT;
|
||||
} else {
|
||||
// Read n bytes as expected.
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_blockIO(gcn64_hdl_t hdl, struct blockio_op *iops, int n_iops)
|
||||
{
|
||||
unsigned char iobuf[63];
|
||||
int p, i, n;
|
||||
if (!hdl)
|
||||
return -1;
|
||||
|
||||
if (!hdl->caps.bio_support) {
|
||||
return gcn64lib_blockIO_compat(hdl, iops, n_iops);
|
||||
}
|
||||
else {
|
||||
// Request format:
|
||||
//
|
||||
// RQ_GCN64_BLOCK_IO
|
||||
// chn, n_tx, n_rx, tx[]
|
||||
// ...
|
||||
//
|
||||
// The adapter stops processing the buffer when the
|
||||
// buffer ends or when a channel set to 0xff is encountered.
|
||||
//
|
||||
memset(iobuf, 0xff, sizeof(iobuf));
|
||||
iobuf[0] = RQ_GCN64_BLOCK_IO;
|
||||
for (p=1, i=0; i<n_iops; i++) {
|
||||
if (p + 3 + iops[i].tx_len > sizeof(iobuf)) {
|
||||
fprintf(stderr, "io blocks do not fit in buffer\n");
|
||||
return -1;
|
||||
}
|
||||
iobuf[p] = iops[i].chn;
|
||||
p++;
|
||||
iobuf[p] = iops[i].tx_len & BIO_RXTX_MASK;
|
||||
p++;
|
||||
iobuf[p] = iops[i].rx_len & BIO_RXTX_MASK;
|
||||
p++;
|
||||
|
||||
memcpy(iobuf + p, iops[i].tx_data, iops[i].tx_len);
|
||||
p += iops[i].tx_len;
|
||||
}
|
||||
#ifdef DEBUG_BLOCKIO
|
||||
fputs("blockIO request: ", stdout);
|
||||
printHexBuf(iobuf, sizeof(iobuf));
|
||||
#endif
|
||||
|
||||
n = gcn64_exchange(hdl, iobuf, sizeof(iobuf), iobuf, sizeof(iobuf));
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
if (n != sizeof(iobuf)) {
|
||||
fprintf(stderr, "Unexpected iobuf reply size\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG_BLOCKIO
|
||||
fputs("blockIO answer.: ", stdout);
|
||||
printHexBuf(iobuf, sizeof(iobuf));
|
||||
printf("\n");
|
||||
#endif
|
||||
// Answer format:
|
||||
//
|
||||
// RQ_GCN64_BLOCK_IO
|
||||
// n_rx, rx[n_rx]
|
||||
// ...
|
||||
//
|
||||
// n_rx will have bits set according to the result. See BIO_RX*. rx will always
|
||||
// occupy the number of bytes set in the request, regardless of the result.
|
||||
//
|
||||
if (iobuf[0] != RQ_GCN64_BLOCK_IO) {
|
||||
fprintf(stderr, "Invalid iobuf reply\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (p=1,i=0; i<n_iops; i++) {
|
||||
if (p >= sizeof(iobuf)) {
|
||||
fprintf(stderr, "blockIO: adapter reports too much received data\n");
|
||||
break;
|
||||
}
|
||||
|
||||
iops[i].rx_len = iobuf[p];
|
||||
p++;
|
||||
if (p + (iops[i].rx_len & BIO_RXTX_MASK) >= sizeof(iobuf)) {
|
||||
fprintf(stderr, "blockIO: adapter reports too much received data\n");
|
||||
break;
|
||||
}
|
||||
memcpy(iops[i].rx_data, iobuf + p, iops[i].rx_len & BIO_RXTX_MASK);
|
||||
p += iops[i].rx_len & BIO_RXTX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef _gcn64_lib_h__
|
||||
#define _gcn64_lib_h__
|
||||
|
||||
#include "gcn64.h"
|
||||
|
||||
#define CTL_TYPE_NONE 0
|
||||
#define CTL_TYPE_N64 1
|
||||
#define CTL_TYPE_GC 2
|
||||
#define CTL_TYPE_GCKB 3
|
||||
|
||||
int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend);
|
||||
int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len);
|
||||
int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max);
|
||||
int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx);
|
||||
int gcn64lib_getVersion(gcn64_hdl_t hdl, char *dst, int dstmax);
|
||||
int gcn64lib_getSignature(gcn64_hdl_t hdl, char *dst, int dstmax);
|
||||
int gcn64lib_forceVibration(gcn64_hdl_t hdl, unsigned char channel, unsigned char vibrate);
|
||||
int gcn64lib_getControllerType(gcn64_hdl_t hdl, int chn);
|
||||
const char *gcn64lib_controllerName(int type);
|
||||
int gcn64lib_bootloader(gcn64_hdl_t hdl);
|
||||
|
||||
int gcn64lib_n64_expansionWrite(gcn64_hdl_t hdl, unsigned short addr, unsigned char *data, int len);
|
||||
int gcn64lib_n64_expansionRead(gcn64_hdl_t hdl, unsigned short addr, unsigned char *dst, int max_len);
|
||||
|
||||
int gcn64lib_8bit_scan(gcn64_hdl_t hdl, unsigned char min, unsigned char max);
|
||||
int gcn64lib_16bit_scan(gcn64_hdl_t hdl, unsigned short min, unsigned short max);
|
||||
|
||||
#define BIO_RXTX_MASK 0x3F
|
||||
#define BIO_RX_LEN_TIMEDOUT 0x80
|
||||
#define BIO_RX_LEN_PARTIAL 0x40
|
||||
|
||||
struct blockio_op {
|
||||
unsigned char chn;
|
||||
unsigned char tx_len;
|
||||
unsigned char *tx_data;
|
||||
unsigned char rx_len; // expected/max bytes
|
||||
unsigned char *rx_data;
|
||||
};
|
||||
|
||||
int gcn64lib_blockIO(gcn64_hdl_t hdl, struct blockio_op *iops, int n_iops);
|
||||
|
||||
#endif // _gcn64_lib_h__
|
||||
@@ -0,0 +1,29 @@
|
||||
/* gc_n64_usb : Gamecube or N64 controller to USB adapter firmware
|
||||
Copyright (C) 2007-2015 Raphael Assenat <raph@raphnet.net>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
void printHexBuf(unsigned char *buf, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
void printHexBuf(unsigned char *buf, int n);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.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;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* 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
|
||||
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
|
||||
// macros
|
||||
#define osal_inline __inline
|
||||
|
||||
#else /* Not WIN32 */
|
||||
|
||||
// macros
|
||||
#define osal_inline inline
|
||||
|
||||
#endif
|
||||
|
||||
#endif // OSAL_PREPROC_H
|
||||
@@ -0,0 +1,475 @@
|
||||
/* mupen64plus-input-raphnetraw
|
||||
*
|
||||
* Copyright (C) 2016-2017 Raphael Assenat
|
||||
*
|
||||
* An input plugin that lets the game under emulation communicate with
|
||||
* the controllers directly using the direct controller communication
|
||||
* feature of raphnet V3 adapters[1].
|
||||
*
|
||||
* [1] http://www.raphnet.net/electronique/gcn64_usb_adapter_gen3/index_en.php
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* plugin_back.c : Plugin back code (in contrast to the "front" emulator interface
|
||||
*
|
||||
* Revision history:
|
||||
* 28 Nov 2016 : Initial version
|
||||
* 1 Dec 2016 : Switch to block IO api
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "plugin_back.h"
|
||||
#include "gcn64.h"
|
||||
#include "gcn64lib.h"
|
||||
#include "version.h"
|
||||
#include "hexdump.h"
|
||||
|
||||
#undef ENABLE_TIMING
|
||||
|
||||
#ifdef ENABLE_TIMING
|
||||
#include <sys/time.h>
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
#error Timing not supported under Windows
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef TIME_RAW_IO
|
||||
#undef TIME_COMMAND_TO_READ
|
||||
|
||||
#undef TRACE_BLOCK_IO
|
||||
// Filter
|
||||
#define EXTENSION_RW_ONLY 0
|
||||
|
||||
#define MAX_ADAPTERS 4
|
||||
#define MAX_CHANNELS 4
|
||||
|
||||
static void nodebug(int l, const char *m, ...) { }
|
||||
|
||||
static pb_debugFunc DebugMessage = nodebug;
|
||||
|
||||
|
||||
|
||||
#define MAX_OPS 64
|
||||
|
||||
struct adapter {
|
||||
gcn64_hdl_t handle;
|
||||
struct gcn64_info inf;
|
||||
struct blockio_op biops[MAX_OPS];
|
||||
int n_ops;
|
||||
};
|
||||
|
||||
static int g_n_adapters = 0;
|
||||
struct adapter g_adapters[MAX_ADAPTERS] = { };
|
||||
|
||||
struct rawChannel {
|
||||
struct adapter *adapter;
|
||||
int chn;
|
||||
};
|
||||
|
||||
/* Multiple adapters are supported, some are single player, others
|
||||
* two-player. As they are discovered during scan, their
|
||||
* channels (corresponding to physical controller ports) are added
|
||||
* to this table. Then, when plugin_front() calls functions in this
|
||||
* files with a specified channel, the channel is the index in this
|
||||
* table.
|
||||
*/
|
||||
static struct rawChannel g_channels[MAX_CHANNELS] = { };
|
||||
static int g_n_channels = 0;
|
||||
|
||||
int pb_init(pb_debugFunc debugFn)
|
||||
{
|
||||
DebugMessage = debugFn;
|
||||
gcn64_init(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pb_freeAllAdapters(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<g_n_adapters; i++) {
|
||||
if (g_adapters[i].handle) {
|
||||
/* RomClosed() should have done this, but just
|
||||
in case it is not always called, do this again here. */
|
||||
gcn64lib_suspendPolling(g_adapters[i].handle, 0);
|
||||
gcn64_closeDevice(g_adapters[i].handle);
|
||||
}
|
||||
}
|
||||
|
||||
g_n_channels = 0;
|
||||
g_n_adapters = 0;
|
||||
memset(g_adapters, 0, sizeof(g_adapters));
|
||||
memset(g_channels, 0, sizeof(g_channels));
|
||||
}
|
||||
|
||||
int pb_shutdown(void)
|
||||
{
|
||||
pb_freeAllAdapters();
|
||||
gcn64_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The number of channels available.
|
||||
*/
|
||||
int pb_scanControllers(void)
|
||||
{
|
||||
struct gcn64_list_ctx * lctx;
|
||||
int i, j;
|
||||
struct adapter *adap;
|
||||
|
||||
lctx = gcn64_allocListCtx();
|
||||
if (!lctx) {
|
||||
DebugMessage(PB_MSG_ERROR, "Could not allocate gcn64 list context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This may be called many times in the plugin's lifetime. For instance, each
|
||||
* time a new game is selected from the PJ64 menu. Freeing previously found
|
||||
* adapters here and creating a new list makes it possible to disconnect/replace
|
||||
* USB adapters without having to restart PJ64. */
|
||||
pb_freeAllAdapters();
|
||||
|
||||
/* Pass 1: Fill g_adapters[] with the adapters present on the system. */
|
||||
g_n_adapters = 0;
|
||||
adap = &g_adapters[g_n_adapters];
|
||||
while (gcn64_listDevices(&adap->inf, lctx)) {
|
||||
|
||||
adap->handle = gcn64_openDevice(&adap->inf);
|
||||
if (!adap->handle) {
|
||||
DebugMessage(PB_MSG_ERROR, "Could not open gcn64 device serial '%ls'. Skipping it.", adap->inf.str_serial);
|
||||
continue;
|
||||
}
|
||||
|
||||
DebugMessage(PB_MSG_INFO, "Found USB device 0x%04x:0x%04x serial '%ls' name '%ls'",
|
||||
adap->inf.usb_vid, adap->inf.usb_pid, adap->inf.str_serial, adap->inf.str_prodname);
|
||||
DebugMessage(PB_MSG_INFO, "Adapter supports %d raw channel(s)", adap->inf.caps.n_raw_channels);
|
||||
|
||||
g_n_adapters++;
|
||||
if (g_n_adapters >= MAX_ADAPTERS)
|
||||
break;
|
||||
|
||||
adap = &g_adapters[g_n_adapters];
|
||||
}
|
||||
gcn64_freeListCtx(lctx);
|
||||
|
||||
/* Pass 2: Fill the g_channel[] array with the available raw channels.
|
||||
* For instance, if there are adapters A, B and C (where A and C are single-player
|
||||
* and B is dual-player), we get this:
|
||||
*
|
||||
* [0] = Adapter A, raw channel 0
|
||||
* [1] = Adapter B, raw channel 0
|
||||
* [2] = Adapter B, raw channel 1
|
||||
* [3] = Adapter C, raw channel 0
|
||||
*
|
||||
* */
|
||||
for (i=0; i<g_n_adapters; i++) {
|
||||
struct adapter *adap = &g_adapters[i];
|
||||
|
||||
if (adap->inf.caps.n_raw_channels <= 0)
|
||||
continue;
|
||||
|
||||
for (j=0; j<adap->inf.caps.n_raw_channels; j++) {
|
||||
if (g_n_channels >= MAX_CHANNELS) {
|
||||
return g_n_channels;
|
||||
}
|
||||
g_channels[g_n_channels].adapter = adap;
|
||||
g_channels[g_n_channels].chn = j;
|
||||
DebugMessage(PB_MSG_INFO, "Channel %d: Adapter '%ls' raw channel %d", g_n_channels, adap->inf.str_serial, j);
|
||||
g_n_channels++;
|
||||
}
|
||||
}
|
||||
|
||||
return g_n_channels;
|
||||
}
|
||||
|
||||
int pb_romOpen(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_ADAPTERS; i++) {
|
||||
if (g_adapters[i].handle) {
|
||||
gcn64lib_suspendPolling(g_adapters[i].handle, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pb_romClosed(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_ADAPTERS; i++) {
|
||||
if (g_adapters[i].handle) {
|
||||
gcn64lib_suspendPolling(g_adapters[i].handle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void timing(int start, const char *label)
|
||||
{
|
||||
#ifdef ENABLE_TIMING
|
||||
static struct timeval tv_start;
|
||||
static int started = 0;
|
||||
struct timeval tv_now;
|
||||
|
||||
if (start) {
|
||||
gettimeofday(&tv_start, NULL);
|
||||
started = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (started) {
|
||||
gettimeofday(&tv_now, NULL);
|
||||
printf("%s: %ld us\n", label, (tv_now.tv_sec - tv_start.tv_sec) * 1000000 + (tv_now.tv_usec - tv_start.tv_usec) );
|
||||
started = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
static void debug_raw_commands_in(unsigned char *command, int channel_id)
|
||||
{
|
||||
int tx_len = command[0];
|
||||
int rx_len = command[1] & 0x3F;
|
||||
int i;
|
||||
|
||||
printf("chn %d: tx[%d] = {", channel_id, tx_len);
|
||||
for (i=0; i<tx_len; i++) {
|
||||
printf("0x%02x ", command[2+i]);
|
||||
}
|
||||
printf("}, expecting %d byte%c\n", rx_len, rx_len > 1 ? 's':' ');
|
||||
|
||||
}
|
||||
|
||||
static void debug_raw_commands_out(unsigned char *command, int channel_id)
|
||||
{
|
||||
int result = command[1];
|
||||
int i;
|
||||
|
||||
printf("chn %d: result: 0x%02x : ", channel_id, result);
|
||||
if (0 == (command[1] & 0xC0)) {
|
||||
for (i=0; i<result; i++) {
|
||||
printf("0x%02x ", command[2+i]);
|
||||
}
|
||||
} else {
|
||||
printf("error\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int pb_controllerCommand(int Control, unsigned char *Command)
|
||||
{
|
||||
// I thought of sending requests to the adapter from here, reading
|
||||
// the results later in readController.
|
||||
//
|
||||
// But unlike what I expected, controllerCommand is NOT always called
|
||||
// before readController... Will investigate later.
|
||||
#ifdef TIME_COMMAND_TO_READ
|
||||
timing(1, NULL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_performIo(void)
|
||||
{
|
||||
struct adapter *adap;
|
||||
struct blockio_op *biops;
|
||||
int j, i, res;
|
||||
int op_was_extio[MAX_OPS] = { };
|
||||
|
||||
for (j=0; j<g_n_channels; j++)
|
||||
{
|
||||
adap = &g_adapters[j];
|
||||
biops = adap->biops;
|
||||
|
||||
/* Skip adapters that do not have IO operations queued. */
|
||||
if (adap->n_ops <= 0)
|
||||
continue;
|
||||
|
||||
#ifdef TRACE_BLOCK_IO
|
||||
for (i=0; i<adap->n_ops; i++) {
|
||||
if (EXTENSION_RW_ONLY && (biops[i].tx_data[0] < 0x02))
|
||||
continue;
|
||||
op_was_extio[i] = 1;
|
||||
printf("Before blockIO: op %d, chn: %d, : tx: 0x%02x, rx: 0x%02x, data: ", i, biops[i].chn,
|
||||
biops[i].tx_len, biops[i].rx_len);
|
||||
printHexBuf(biops[i].tx_data, biops[i].tx_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TIME_RAW_IO
|
||||
timing(1, NULL);
|
||||
#endif
|
||||
res = gcn64lib_blockIO(adap->handle, biops, adap->n_ops);
|
||||
#ifdef TIME_RAW_IO
|
||||
timing(0, "blockIO");
|
||||
#endif
|
||||
|
||||
if (res == 0) {
|
||||
// biops rx_data pointed into PIFram so data is there. But we need
|
||||
// to patch the RX length parameters (the two most significant bits
|
||||
// are error bits such as timeout..)
|
||||
for (i=0; i<adap->n_ops; i++) {
|
||||
// in PIFram, the read length is one byte before the tx data. A rare
|
||||
// occasion to use a negative array index ;)
|
||||
biops[i].tx_data[-1] = biops[i].rx_len;
|
||||
|
||||
#ifdef TRACE_BLOCK_IO
|
||||
if (EXTENSION_RW_ONLY && (!op_was_extio[i])) // Read
|
||||
continue;
|
||||
|
||||
printf("After blockIO: op %d, chn: %d, : tx: 0x%02x, rx: 0x%02x, data: ", i, biops[i].chn,
|
||||
biops[i].tx_len, biops[i].rx_len);
|
||||
if (biops[i].rx_len & BIO_RX_LEN_TIMEDOUT) {
|
||||
printf("Timeout\n");
|
||||
} else if (biops[i].rx_len & BIO_RX_LEN_PARTIAL) {
|
||||
printf("Incomplete\n");
|
||||
} else {
|
||||
printHexBuf(biops[i].rx_data, biops[i].rx_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// For debugging
|
||||
//exit(1);
|
||||
}
|
||||
|
||||
adap->n_ops = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int pb_commandIsValid(int Control, unsigned char *Command)
|
||||
{
|
||||
if (Control < 0 || Control >= g_n_channels) {
|
||||
DebugMessage(PB_MSG_WARNING, "pb_readController called with Control=%d", Control);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Command) {
|
||||
DebugMessage(PB_MSG_WARNING, "pb_readController called with NULL Command pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When a CIC challenge took place in update_pif_write(), the pif ram
|
||||
// contains a bunch 0xFF followed by 0x00 at offsets 46 and 47. Offset
|
||||
// 48 onwards contains the challenge answer.
|
||||
//
|
||||
// Then when update_pif_read() is called, the 0xFF bytes are be skipped
|
||||
// up to the two 0x00 bytes that increase the channel to 2. Then the
|
||||
// challenge answer is (incorrectly) processed as if it were commands
|
||||
// for the third controller.
|
||||
//
|
||||
// This cause issues with the raphnetraw plugin since it modifies pif ram
|
||||
// to store the result or command error flags. This corrupts the reponse
|
||||
// and leads to challenge failure.
|
||||
//
|
||||
// As I know of no controller commands above 0x03, the filter below guards
|
||||
// against this condition...
|
||||
//
|
||||
if (Control == 2 && Command[2] > 0x03) {
|
||||
DebugMessage(PB_MSG_WARNING, "Invalid controller command");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When Mario Kart 64 uses a controller pak, such PIF ram content
|
||||
// occurs:
|
||||
//
|
||||
// ff 03 21 02 01 f7 ff ff
|
||||
// ff ff ff ff ff ff ff ff
|
||||
// ff ff ff ff ff ff ff ff
|
||||
// ff ff ff ff ff ff ff ff
|
||||
// ff ff ff ff ff ff ff 21
|
||||
// fe 00 00 00 00 00 00 00
|
||||
// 00 00 00 00 00 00 00 00
|
||||
// 00 00 00 00 00 00 00 00
|
||||
//
|
||||
// It results in this:
|
||||
// - Transmission of 3 bytes with a 33 bytes return on channel 0,
|
||||
// - Transmission of 33 bytes with 254 bytes in return on channel 1!?
|
||||
//
|
||||
// Obviously the second transaction is an error. The 0xFE (254) that follows
|
||||
// is where processing should actually stop. This happens to be an invalid length detectable
|
||||
// by looking at the two most significant bits..
|
||||
//
|
||||
if (Command[0] == 0xFE && Command[1] == 0x00) {
|
||||
DebugMessage(PB_MSG_WARNING, "Ignoring invalid io operation (T: 0x%02x, R: 0x%02x)",
|
||||
Command[0], Command[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pb_readController(int Control, unsigned char *Command)
|
||||
{
|
||||
struct rawChannel *channel;
|
||||
struct adapter *adap;
|
||||
struct blockio_op *biops;
|
||||
|
||||
// Called with -1 at the end of PIF ram.
|
||||
if (Control == -1) {
|
||||
return pb_performIo();
|
||||
}
|
||||
|
||||
/* Check for out of bounds Control parameter, for
|
||||
* NULL Command and filter various invalid conditions. */
|
||||
if (!pb_commandIsValid(Control, Command)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add the IO operation to the block io list of
|
||||
* the adapter serving this channel. */
|
||||
|
||||
channel = &g_channels[Control];
|
||||
adap = channel->adapter;
|
||||
|
||||
if (adap->n_ops >= MAX_OPS) {
|
||||
DebugMessage(PB_MSG_ERROR, "Too many io ops");
|
||||
} else {
|
||||
biops = adap->biops;
|
||||
|
||||
biops[adap->n_ops].chn = channel->chn; // Control;
|
||||
biops[adap->n_ops].tx_len = Command[0] & BIO_RXTX_MASK;
|
||||
biops[adap->n_ops].rx_len = Command[1] & BIO_RXTX_MASK;
|
||||
biops[adap->n_ops].tx_data = Command + 2;
|
||||
biops[adap->n_ops].rx_data = Command + 2 + biops[adap->n_ops].tx_len;
|
||||
|
||||
if (biops[adap->n_ops].tx_len == 0 || biops[adap->n_ops].rx_len == 0) {
|
||||
DebugMessage(PB_MSG_WARNING, "TX or RX was zero");
|
||||
return 0;
|
||||
}
|
||||
|
||||
adap->n_ops++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef _plugin_back_h__
|
||||
#define _plugin_back_h__
|
||||
|
||||
/* Those match mupen64plus levels */
|
||||
#define PB_MSG_ERROR 1
|
||||
#define PB_MSG_WARNING 2
|
||||
#define PB_MSG_INFO 3
|
||||
#define PB_MSG_STATUS 4
|
||||
#define PB_MSG_VERBOSE 5
|
||||
|
||||
typedef void (*pb_debugFunc)(int level, const char *message, ...);
|
||||
|
||||
int pb_init(pb_debugFunc debugFn);
|
||||
int pb_shutdown(void);
|
||||
int pb_scanControllers(void);
|
||||
int pb_readController(int Control, unsigned char *Command);
|
||||
int pb_controllerCommand(int Control, unsigned char *Command);
|
||||
int pb_romOpen(void);
|
||||
int pb_romClosed(void);
|
||||
|
||||
#endif // _plugin_back_h__
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
/* mupen64plus-input-raphnetraw
|
||||
*
|
||||
* Copyright (C) 2016 Raphael Assenat
|
||||
*
|
||||
* An input plugin that lets the game under emulation communicate with
|
||||
* the controllers directly using the direct controller communication
|
||||
* feature of raphnet V3 adapters[1].
|
||||
*
|
||||
* [1] http://www.raphnet.net/electronique/gcn64_usb_adapter_gen3/index_en.php
|
||||
*
|
||||
* Based on the Mupen64plus-input-sdl plugin (original banner below)
|
||||
*/
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* 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 <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define M64P_PLUGIN_PROTOTYPES 1
|
||||
#include "config.h"
|
||||
#include "m64p_common.h"
|
||||
#include "m64p_config.h"
|
||||
#include "m64p_plugin.h"
|
||||
#include "m64p_types.h"
|
||||
#include "osal_dynamiclib.h"
|
||||
#include "plugin_front.h"
|
||||
#include "plugin_back.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define MAX_CONTROLLERS 4
|
||||
|
||||
#ifdef PORTS_1_AND_4
|
||||
static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 2, 3, 1 };
|
||||
#undef PLUGIN_NAME
|
||||
#define PLUGIN_NAME "raphnetraw ports 1 and 4"
|
||||
#else
|
||||
static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 1, 2, 3 };
|
||||
#endif
|
||||
|
||||
#define EMU_2_ADAP_PORT(a) ((a) == -1 ? -1 : emu2adap_portmap[a])
|
||||
|
||||
#if 0
|
||||
/* 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;
|
||||
#endif
|
||||
|
||||
/* static data definitions */
|
||||
static void (*l_DebugCallback)(void *, int, const char *) = NULL;
|
||||
static void *l_DebugCallContext = NULL;
|
||||
static int l_PluginInit = 0;
|
||||
|
||||
/* Global functions */
|
||||
static void DebugMessage(int level, const char *message, ...)
|
||||
{
|
||||
char msgbuf[1024];
|
||||
va_list args;
|
||||
|
||||
if (!l_DebugCallback) {
|
||||
printf("No debug callback!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, message);
|
||||
vsnprintf(msgbuf, sizeof(msgbuf), message, args);
|
||||
|
||||
(*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
/* Mupen64Plus plugin functions */
|
||||
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
|
||||
void (*DebugCallback)(void *, int, const char *))
|
||||
{
|
||||
ptr_CoreGetAPIVersions CoreAPIVersionFunc;
|
||||
|
||||
int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
|
||||
|
||||
if (l_PluginInit) {
|
||||
return M64ERR_ALREADY_INIT;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#if 0
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
pb_init(DebugMessage);
|
||||
|
||||
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;
|
||||
|
||||
pb_shutdown();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
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, n_controllers, adap_port;
|
||||
|
||||
n_controllers = pb_scanControllers();
|
||||
|
||||
if (n_controllers <= 0) {
|
||||
DebugMessage(PB_MSG_ERROR, "No adapters detected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_CONTROLLERS; i++) {
|
||||
adap_port = EMU_2_ADAP_PORT(i);
|
||||
|
||||
if (adap_port < n_controllers) {
|
||||
ControlInfo.Controls[i].RawData = 1;
|
||||
|
||||
/* Setting this is currently required or we
|
||||
* won't be called at all.
|
||||
*
|
||||
* Look at pif.c update_pif_write() to see why.
|
||||
*/
|
||||
ControlInfo.Controls[i].Present = 1;
|
||||
}
|
||||
}
|
||||
|
||||
DebugMessage(PB_MSG_INFO, "%s version %i.%i.%i %s(compiled "__DATE__" "__TIME__") initialized.", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION),
|
||||
#ifdef _DEBUG
|
||||
"DEBUG "
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
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)
|
||||
{
|
||||
pb_readController(EMU_2_ADAP_PORT(Control), Command);
|
||||
}
|
||||
|
||||
EXPORT void CALL ControllerCommand(int Control, unsigned char *Command)
|
||||
{
|
||||
pb_controllerCommand(EMU_2_ADAP_PORT(Control), Command);
|
||||
}
|
||||
|
||||
EXPORT void CALL GetKeys( int Control, BUTTONS *Keys )
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL RomClosed(void)
|
||||
{
|
||||
pb_romClosed();
|
||||
}
|
||||
|
||||
EXPORT int CALL RomOpen(void)
|
||||
{
|
||||
pb_romOpen();
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
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)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* 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 <string.h>
|
||||
|
||||
#define M64P_PLUGIN_PROTOTYPES 1
|
||||
#include "m64p_config.h"
|
||||
#include "m64p_plugin.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
|
||||
|
||||
/* 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__
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef _gcn64_requests_h__
|
||||
#define _gcn64_requests_h__
|
||||
|
||||
/* Commands */
|
||||
#define RQ_GCN64_SET_CONFIG_PARAM 0x01
|
||||
#define RQ_GCN64_GET_CONFIG_PARAM 0x02
|
||||
#define RQ_GCN64_SUSPEND_POLLING 0x03
|
||||
#define RQ_GCN64_GET_VERSION 0x04
|
||||
#define RQ_GCN64_GET_SIGNATURE 0x05
|
||||
#define RQ_GCN64_GET_CONTROLLER_TYPE 0x06
|
||||
#define RQ_GCN64_SET_VIBRATION 0x07
|
||||
#define RQ_GCN64_RAW_SI_COMMAND 0x80
|
||||
#define RQ_GCN64_BLOCK_IO 0x81
|
||||
#define RQ_GCN64_JUMP_TO_BOOTLOADER 0xFF
|
||||
|
||||
/* Configuration parameters and constants */
|
||||
#define CFG_PARAM_MODE 0x00
|
||||
|
||||
/* Values for mode */
|
||||
#define CFG_MODE_STANDARD 0x00
|
||||
#define CFG_MODE_N64_ONLY 0x01
|
||||
#define CFG_MODE_GC_ONLY 0x02
|
||||
|
||||
#define CFG_PARAM_SERIAL 0x01
|
||||
|
||||
#define CFG_PARAM_POLL_INTERVAL0 0x10
|
||||
#define CFG_PARAM_POLL_INTERVAL1 0x11
|
||||
#define CFG_PARAM_POLL_INTERVAL2 0x12
|
||||
#define CFG_PARAM_POLL_INTERVAL3 0x13
|
||||
|
||||
#define CFG_PARAM_N64_SQUARE 0x20 // Not implemented
|
||||
#define CFG_PARAM_GC_MAIN_SQUARE 0x21 // Not implemented
|
||||
#define CFG_PARAM_GC_CSTICK_SQUARE 0x22 // Not implemented
|
||||
#define CFG_PARAM_FULL_SLIDERS 0x23
|
||||
#define CFG_PARAM_INVERT_TRIG 0x24
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* 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 raphnetraw Input Plugin"
|
||||
#define PLUGIN_VERSION 0x010100
|
||||
//#define INPUT_PLUGIN_API_VERSION 0x020000
|
||||
#define INPUT_PLUGIN_API_VERSION 0x020100
|
||||
#define CONFIG_API_VERSION 0x020100
|
||||
|
||||
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
|
||||
|
||||
#endif /* #define VERSION_H */
|
||||
|
||||
Reference in New Issue
Block a user