Compare commits

...

60 Commits

Author SHA1 Message Date
RyzenDew abcf468126
Merge pull request #334 from frizzle101101/dev
Dev
2023-04-12 16:41:57 -03:00
frizzle101101 da7b648ac1 fix build issue with directory not existing to extract hid-api for raphnetadapter 2022-11-20 20:49:33 -05:00
frizzle101101 8c39534f36 fix previous commit attempt to fix the camera drift by removing the sintable 2022-11-20 18:55:49 -05:00
frizzle101101 f3d9427692 Revert "removing the sintable ..."
This reverts commit b9056ca5f1.
2022-11-20 18:29:02 -05:00
frizzle101101 5f5413c74d adding git ignore for the hid-api lib as its downloaded via pre build command 2022-11-20 18:26:15 -05:00
frizzle101101 0b63cefd17 fix build issues adding hid-api download as a prebuild event for the raphnet adapter project to 2022-11-19 16:14:45 -05:00
frizzle101101 61874050ef adding raphnet rumble support 2022-11-19 13:27:51 -05:00
frizzle101101 04919e884a fix the faries effect in koriki forest 2022-11-10 00:27:34 -05:00
frizzle101101 3af4c65da3 fixing counterf to update the scaler everytime its used, maybe a beter fix than this?
adding a VecCounterf for replacing vec3f required for highframe rate upgrades, this is the same as VecPosF was intended to be
2022-11-10 00:27:05 -05:00
frizzle101101 e8fd7b1d76 fix a timer function name problem in previous commit 2022-11-05 22:28:25 -04:00
frizzle101101 1ca70f0779 adding sdl support for common amazon mayflash dual n64 to usb(even though its quite bad it only replaces an snes controller) 2022-11-05 21:19:42 -04:00
frizzle101101 89b8364e13 -adding free cam to the sword spin and hanging off a wall
-fixing the classic camera walking towards the camera
-fix yaw rate the right way which waas cause of the yaw titch issue
-other various camera fixes and code optimizations, using actual classic camera code for the no input control scenario
2022-11-05 21:17:41 -04:00
frizzle101101 b9056ca5f1 removing the sintable and using cpp sin and cos instead for better accuracy, removes drift on calculations going between geo and spherical cords 2022-11-05 18:03:40 -04:00
frizzle101101 852a68fbd2 improvments to the controller and mouse accuracy with a better resolution range on the right stick, is dependent on the following commit to solve drift issues 2022-11-05 16:35:13 -04:00
frizzle101101 8eeacf8c28 high fps fix the red flag flapping in desert 2022-11-01 19:08:58 -04:00
frizzle101101 d9aa86f1b1 high fps fix horse decel and sound speed 2022-11-01 19:08:08 -04:00
frizzle101101 20375fa4e4 making gfxprint usable, was used earlier in dev for audio debug and identifying instruments and sound fonts but this implement in audio_sequence is currently not uptodate 2022-10-23 17:23:13 -04:00
frizzle101101 780f7c2890 some comments and renaming 2022-10-23 17:21:17 -04:00
frizzle101101 51ac9860f6 fix audio issues #222 2022-10-23 17:18:43 -04:00
frizzle101101 61709af219 Merge branch 'dev' of https://github.com/frizzle101101/ooot into frizzledev 2022-10-05 00:39:55 -05:00
frizzle101101 72f8a4b509 missed file from last commit
fixes lightning strike rate in high fps
2022-10-05 00:36:35 -05:00
frizzle101101 d0f9e36878 some more identify and fix last commit 2022-10-05 00:35:00 -05:00
frizzle101101 a579fa71b0 fix the sandstorm texture in highfps
some more identify
2022-10-05 00:31:37 -05:00
frizzle101101 e1d82ff070 updating include folder in the solution 2022-10-05 00:27:04 -05:00
frizzle101101 9980297ed3 high fps fixs:
fix the ripple effect over spawn rate
fix the sinking in sand
some more identify and renaming
2022-10-05 00:25:56 -05:00
frizzle101101 0e81119b13 fixing mistake change made in 5805369 that broke effects animation 2022-09-26 11:08:12 -04:00
frizzle101101 3bcb329f24 some identify for ztarget
adding a 3s timer for telling if the z button is being held while ztargeting to provide another cancelation method for ztarget that doesnt require pulling back on the stick
some 60fps improvments to ztarget anamation(not sure these helped still testng)
2022-09-15 11:20:26 +02:00
frizzle101101 23177347bb improving the mouse caputre further so not effect the camera if the mouse is not cptured
Making the first click to capture the mosue not preform an action
2022-09-15 11:02:01 +02:00
frizzle101101 3082d50aa6 fixing camera centering feature, ztarget resets to the vinilla camera 2022-09-11 00:23:11 +02:00
frizzle101101 23bbecc2f3 changeing 30fps to not skip gfx frame mask and be more like 40fps, if there are issues with 30fps then suspect this commit 2022-09-05 21:46:01 -04:00
frizzle101101 7d531b8b82 fixing camera timers and trying to make the yaw rate more like 20 fps for high fps(there is a float truncation to int issue here in the high fps modes i believe with the yaw rate) 2022-09-05 21:44:18 -04:00
frizzle101101 d20c20df21 fixing the door transition camera 2022-09-05 15:39:37 -04:00
frizzle101101 07b103a874 fixing camera for opening a chest in high fps 2022-09-05 15:08:36 -04:00
frizzle101101 c77573553e fixing the softlock on tunnel exit in 60fps caused by the temporary scent camera that is spawned for the transition of the camera out of the tunnel
-this prevents the need for force fps in the tunnel enterance
2022-09-05 14:13:43 -04:00
frizzle101101 452f2b7785 fixing the earllier commit that broke the build missing these changes 2022-08-29 23:43:02 -04:00
frizzle101101 c5c4632de4 some tanslations and a var rename 2022-08-29 23:41:38 -04:00
frizzle101101 58053692db fixing splash and ripple effects(still being generated too much but timing of the animation is corrected) 2022-08-29 23:35:46 -04:00
frizzle101101 f6d68b885a fixing jabujabu walls, button, the flobby toung and bubbles(which still have colision issue) 2022-08-28 23:51:02 -04:00
frizzle101101 9a1ecc2d2f fixing dodgo dependency on asset for floor original tex(this is helpful for playing dongodongo multiple times in a rn and having the floor reset texture properly) 2022-08-28 23:47:49 -04:00
frizzle101101 de9179f355 removing clear from last commit 2022-08-28 13:17:31 -04:00
frizzle101101 9bd41b12d2 fix github build failing on extract assets? 2022-08-28 12:49:17 -04:00
frizzle101101 0141f68679 improving the mouse capture feature with click 2022-08-23 23:00:55 -04:00
frizzle101101 8006a360fd Fix the force20fps causing the fps to be reset to 20 fps on the reset action 2022-08-23 21:26:53 -04:00
frizzle101101 36447ca6c6 adding mouse capture for windowed use 2022-08-23 20:06:44 -04:00
frizzle101101 a5951ddb7e fix wrong link in solution for z_player.h 2022-08-23 20:03:46 -04:00
frizzle101101 dc38f59c7a fixing the mouse stick range 2022-08-23 02:24:30 -04:00
frizzle101101 a518141066 fixing the mouse camera and horizontal centring 2022-08-23 02:11:12 -04:00
frizzle101101 8d65be772d allowing window to pause when focus is lost 2022-08-23 02:09:33 -04:00
frizzle101101 daf51473e4 fix crash on exit (there is still an issue if buffer overflow was happening on exit, will cause a hang, aiz audio needs fixing of the overflow handling in the sound driver, added in offline copy a counter that allows only so many sleeps before breaking the while loop) 2022-08-22 21:01:01 -04:00
frizzle101101 883ad5d026 fix skybox rotation in higher fps modes 2022-08-22 20:55:28 -04:00
frizzle101101 7e847ab8dc
Merge branch 'blawar:dev' into dev 2022-08-22 18:36:35 -04:00
frizzle101101 7e18501d3a add 40fps and some identify, fps scaler tweak(testing) 2022-07-17 21:12:38 -04:00
frizzle101101 82c0c892f6 more timer updates and identify for 60fps, still wip 2022-07-17 17:47:59 -04:00
frizzle101101 9c0b4d14f5
Merge branch 'blawar:dev' into dev 2022-07-10 18:23:40 -04:00
frizzle101101 67b65eed1c
Merge branch 'blawar:dev' into dev 2022-05-08 18:41:51 -04:00
frizzle101101 39eba045cc
Merge branch 'blawar:dev' into dev 2022-04-23 02:14:09 -04:00
frizzle101101 033f57bfdb
Merge branch 'blawar:dev' into dev 2022-04-21 00:00:34 -04:00
frizzle101101 c50f20df0e
Merge branch 'blawar:dev' into dev 2022-04-19 22:42:24 -04:00
frizzle101101 11cbc29b25 Merge branch 'dev' of https://github.com/blawar/ooot into origindev 2022-04-16 13:17:44 -04:00
frizzle101101 42eb8c6638 60fps timer fixes: dongodonge(still not finished, the fire ball trail and how long it lasts needs finding, rotation after entering lava at end needs finding, limb jiggle needs to be figured out, more research and identification needed)
-bomable wall is good
2022-04-16 13:15:48 -04:00
126 changed files with 7427 additions and 973 deletions

View File

@ -31,7 +31,7 @@ jobs:
run: Remove-Item roms -Recurse -Force -ErrorAction SilentlyContinue ; cp -r ../roms .
- name: Extract Assets
run: python setup.py -b EUR_MQD
run: python3 setup.py -b EUR_MQD
- name: Build
working-directory: ${{env.GITHUB_WORKSPACE}}

7
RaphnetAdapter/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.dll
*.so
*.o
*.swp
/projects/unix/_obj*/
/hidapi-win
/hidapi-win.zip

340
RaphnetAdapter/COPYING Normal file
View File

@ -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.

26
RaphnetAdapter/INSTALL Normal file
View File

@ -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>

377
RaphnetAdapter/LICENSES Normal file
View File

@ -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.

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>USE_PRINTF;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers>
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
<WholeProgramOptimization>false</WholeProgramOptimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<SmallerTypeCheck Condition="$(PlatformToolsetVersion)&lt;140">true</SmallerTypeCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Midl>
<PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
</Project>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Debug"
InheritedPropertySheets=".\Default.vsprops"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="_DEBUG;DEBUG"
Optimization="0"
InlineFunctionExpansion="0"
EnableIntrinsicFunctions="false"
FavorSizeOrSpeed="0"
OmitFramePointers="false"
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
BasicRuntimeChecks="3"
SmallerTypeCheck="true"
RuntimeLibrary="1"
/>
<Tool
Name="VCLinkerTool"
ProfileGuidedDatabase=""
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG;DEBUG"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG;DEBUG"
/>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Default"
OutputDirectory="$(Root)bin/$(ConfigurationName)"
IntermediateDirectory="$(Root)build/$(ConfigurationName)/$(ProjectName)"
InheritedPropertySheets=".\Root.vsprops"
DeleteExtensionsOnClean="*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;$(TargetPath)"
BuildLogFile="$(IntDir)\BuildLog.htm"
UseOfMFC="2"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)\$(ProjectName).bsc"
/>
<Tool
Name="VCCLCompilerTool"
UseUnicodeResponseFiles="true"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
IgnoreStandardIncludePath="false"
GeneratePreprocessedFile="0"
KeepComments="false"
StringPooling="true"
MinimalRebuild="true"
ExceptionHandling="2"
BasicRuntimeChecks="0"
SmallerTypeCheck="false"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="true"
EnableEnhancedInstructionSet="0"
FloatingPointModel="0"
FloatingPointExceptions="false"
DisableLanguageExtensions="false"
DefaultCharIsUnsigned="false"
TreatWChar_tAsBuiltInType="true"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="false"
OpenMP="false"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="StdAfx.h"
PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"
ExpandAttributedSource="false"
AssemblerOutput="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
GenerateXMLDocumentationFiles="false"
XMLDocumentationFileName="$(IntDir)\"
BrowseInformation="0"
BrowseInformationFile="$(IntDir)\"
WarningLevel="4"
WarnAsError="false"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CallingConvention="0"
CompileAs="0"
ShowIncludes="false"
UndefineAllPreprocessorDefinitions="false"
EnablePREfast="false"
UseFullPaths="false"
OmitDefaultLibName="false"
ErrorReporting="1"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\lib\$(ProjectName).lib"
UseUnicodeResponseFiles="true"
LinkLibraryDependencies="true"
AdditionalLibraryDirectories=""
SuppressStartupBanner="true"
IgnoreAllDefaultLibraries="false"
/>
<Tool
Name="VCLinkerTool"
RegisterOutput="false"
PerUserRedirection="false"
IgnoreImportLibrary="false"
LinkLibraryDependencies="true"
UseLibraryDependencyInputs="false"
UseUnicodeResponseFiles="true"
AdditionalOptions="/IGNORE:4199 /OPT:ICF=3"
ShowProgress="0"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories=""
ManifestFile="$(IntDir)\$(TargetFileName).intermediate.manifest"
IgnoreAllDefaultLibraries="false"
ModuleDefinitionFile=""
DelayLoadDLLs="advapi32.dll;userenv.dll;shell32.dll;shlwapi.dll;ws2_32.dll;version.dll;wtsapi32.dll"
IgnoreEmbeddedIDL="false"
TypeLibraryResourceID="1"
GenerateDebugInformation="true"
AssemblyDebug="0"
ProgramDatabaseFile="$(TargetDir)pdb/$(TargetName).pdb"
GenerateMapFile="true"
MapFileName="$(TargetDir)map/$(TargetName).map"
MapExports="false"
HeapReserveSize="0"
HeapCommitSize="0"
StackReserveSize="0"
StackCommitSize="0"
LargeAddressAware="0"
TerminalServerAware="0"
SwapRunFromCD="false"
SwapRunFromNet="false"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ProfileGuidedDatabase=""
ResourceOnlyDLL="false"
SetChecksum="false"
RandomizedBaseAddress="1"
FixedBaseAddress="1"
DataExecutionPrevention="0"
TurnOffAssemblyGeneration="false"
SupportUnloadOfDelayLoadedDLL="false"
ImportLibrary="$(TargetDir)lib/$(TargetName).lib"
DelaySign="false"
Profile="false"
CLRThreadAttribute="0"
CLRImageType="0"
ErrorReporting="1"
CLRUnmanagedCodeCheck="false"
/>
<Tool
Name="VCMIDLTool"
AdditionalIncludeDirectories=".;$(SRC);$(SRC)\3rd Party"
IgnoreStandardIncludePath="false"
MkTypLibCompatible="false"
WarningLevel="3"
WarnAsError="false"
SuppressStartupBanner="true"
DefaultCharType="0"
GenerateStublessProxies="true"
GenerateTypeLibrary="true"
TypeLibraryName="$(IntDir)\$(InputName).tlb"
HeaderFileName="$(InputName)_h.h"
DLLDataFileName=""
InterfaceIdentifierFileName="$(InputName)_i.c"
ProxyFileName="$(InputName)_p.c"
EnableErrorChecks="2"
ErrorCheckAllocations="false"
ErrorCheckBounds="false"
ErrorCheckEnumRange="false"
ErrorCheckRefPointers="false"
ErrorCheckStubData="false"
ValidateParameters="true"
StructMemberAlignment="0"
/>
<Tool
Name="VCResourceCompilerTool"
Culture="0"
AdditionalIncludeDirectories=""
IgnoreStandardIncludePath="false"
ShowProgress="false"
ResourceOutputFileName="$(IntDir)\$(InputName).res"
/>
<Tool
Name="VCManifestTool"
UseUnicodeResponseFiles="true"
OutputManifestFile="$(IntDir)\$(TargetFileName).embed.manifest"
ManifestResourceFile="$(IntDir)\$(TargetFileName).embed.manifest.res"
EmbedManifest="true"
DependencyInformationFile="$(IntDir)\mt.dep"
UseFAT32Workaround="false"
SuppressStartupBanner="true"
VerboseOutput="false"
GenerateCatalogFiles="false"
UpdateFileHashes="false"
/>
<Tool
Name="VCXDCMakeTool"
UseUnicodeResponseFiles="true"
DocumentLibraryDependencies="true"
SuppressStartupBanner="true"
ValidateIntelliSense="false"
OutputDocumentFile="$(TargetDir)$(TargetName).xml"
/>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,185 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Configuration">
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<ExtensionsToDeleteOnClean>*.obj;*.ilk;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;$(TargetPath);$(ExtensionsToDeleteOnClean)</ExtensionsToDeleteOnClean>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
<LinkDelaySign>false</LinkDelaySign>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<ItemDefinitionGroup>
<BuildLog>
<Path>$(IntDir)BuildLog.htm</Path>
</BuildLog>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)$(ProjectName).bsc</OutputFile>
</Bscmake>
<ClCompile>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<PreprocessToFile>false</PreprocessToFile>
<PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers>
<PreprocessKeepComments>false</PreprocessKeepComments>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>Async</ExceptionHandling>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<StructMemberAlignment>Default</StructMemberAlignment>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>Not Set</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<FloatingPointExceptions>false</FloatingPointExceptions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<AdditionalOptions />
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdAfx.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<ExpandAttributedSource>false</ExpandAttributedSource>
<AssemblerOutput />
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)vc$(VisualStudioVersion).pdb</ProgramDataBaseFileName>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
<BrowseInformation />
<BrowseInformationFile>$(IntDir)</BrowseInformationFile>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>false</TreatWarningAsError>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<CompileAs>Default</CompileAs>
<ShowIncludes>false</ShowIncludes>
<UndefineAllPreprocessorDefinitions>false</UndefineAllPreprocessorDefinitions>
<EnablePREfast>false</EnablePREfast>
<UseFullPaths>false</UseFullPaths>
<OmitDefaultLibName>false</OmitDefaultLibName>
<ErrorReporting>Prompt</ErrorReporting>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
<UseUnicodeResponseFiles>true</UseUnicodeResponseFiles>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Lib>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<Link>
<SubSystem>Windows</SubSystem>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
<RegisterOutput>false</RegisterOutput>
<PerUserRedirection>false</PerUserRedirection>
<AdditionalOptions>/IGNORE:4199 /OPT:ICF=3 %(AdditionalOptions)</AdditionalOptions>
<ShowProgress>NotSet</ShowProgress>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile />
<DelayLoadDLLs>advapi32.dll;userenv.dll;shell32.dll;shlwapi.dll;ws2_32.dll;version.dll;wtsapi32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<IgnoreEmbeddedIDL>false</IgnoreEmbeddedIDL>
<TypeLibraryResourceID>1</TypeLibraryResourceID>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug />
<ProgramDatabaseFile>$(TargetDir)pdb\$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(TargetDir)map\$(TargetName).map</MapFileName>
<MapExports>false</MapExports>
<HeapReserveSize>0</HeapReserveSize>
<HeapCommitSize>0</HeapCommitSize>
<StackReserveSize>0</StackReserveSize>
<StackCommitSize>0</StackCommitSize>
<LargeAddressAware />
<TerminalServerAware />
<SwapRunFromCD>false</SwapRunFromCD>
<SwapRunFromNET>false</SwapRunFromNET>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProfileGuidedDatabase />
<NoEntryPoint>false</NoEntryPoint>
<SetChecksum>false</SetChecksum>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<FixedBaseAddress>false</FixedBaseAddress>
<DataExecutionPrevention />
<TurnOffAssemblyGeneration>false</TurnOffAssemblyGeneration>
<SupportUnloadOfDelayLoadedDLL>false</SupportUnloadOfDelayLoadedDLL>
<ImportLibrary>$(TargetDir)lib\$(TargetName).lib</ImportLibrary>
<Profile>false</Profile>
<CLRThreadAttribute>DefaultThreadingAttribute</CLRThreadAttribute>
<CLRImageType>Default</CLRImageType>
<LinkErrorReporting>PromptImmediately</LinkErrorReporting>
<CLRUnmanagedCodeCheck>false</CLRUnmanagedCodeCheck>
<ProfileGuidedDatabase />
</Link>
<Midl>
<AdditionalIncludeDirectories>.;$(SolutionDir)\3rd Party;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<MkTypLibCompatible>false</MkTypLibCompatible>
<WarningLevel>3</WarningLevel>
<WarnAsError>false</WarnAsError>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DefaultCharType>Unsigned</DefaultCharType>
<GenerateStublessProxies>true</GenerateStublessProxies>
<GenerateTypeLibrary>true</GenerateTypeLibrary>
<TypeLibraryName>$(IntDir)%(Filename).tlb</TypeLibraryName>
<HeaderFileName>%(Filename)_h.h</HeaderFileName>
<DllDataFileName />
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
<EnableErrorChecks>All</EnableErrorChecks>
<ErrorCheckAllocations>false</ErrorCheckAllocations>
<ErrorCheckBounds>false</ErrorCheckBounds>
<ErrorCheckEnumRange>false</ErrorCheckEnumRange>
<ErrorCheckRefPointers>false</ErrorCheckRefPointers>
<ErrorCheckStubData>false</ErrorCheckStubData>
<ValidateAllParameters>true</ValidateAllParameters>
<StructMemberAlignment>NotSet</StructMemberAlignment>
</Midl>
<ResourceCompile>
<Culture>0x0000</Culture>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<ShowProgress>false</ShowProgress>
<ResourceOutputFileName>$(IntDir)%(Filename).res</ResourceOutputFileName>
</ResourceCompile>
<Manifest>
<OutputManifestFile>$(IntDir)$(TargetFileName).embed.manifest</OutputManifestFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<VerboseOutput>false</VerboseOutput>
<GenerateCatalogFiles>false</GenerateCatalogFiles>
<UpdateFileHashes>false</UpdateFileHashes>
</Manifest>
<ManifestResourceCompile>
<ResourceOutputFileName>$(IntDir)$(TargetFileName).embed.manifest.res</ResourceOutputFileName>
</ManifestResourceCompile>
<Xdcmake>
<DocumentLibraryDependencies>true</DocumentLibraryDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(TargetDir)$(TargetName).xml</OutputFile>
</Xdcmake>
</ItemDefinitionGroup>
<!--Dummy Microsoft Common targets-->
<Target Name="_ConvertPdbFiles" />
<Target Name="_CollectPdbFiles" />
<Target Name="_CollectMdbFiles" />
<Target Name="_CopyMdbFiles" />
</Project>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers>
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
<WholeProgramOptimization>true</WholeProgramOptimization>
<SmallerTypeCheck>false</SmallerTypeCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Release"
InheritedPropertySheets=".\Default.vsprops"
>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
InlineFunctionExpansion="0"
EnableIntrinsicFunctions="false"
FavorSizeOrSpeed="2"
OmitFramePointers="false"
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
PreprocessorDefinitions="NDEBUG"
SmallerTypeCheck="false"
RuntimeLibrary="0"
/>
<Tool
Name="VCLinkerTool"
ProfileGuidedDatabase=""
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
/>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Win32.Debug"
InheritedPropertySheets=".\Win32.vsprops;.\Debug.vsprops;"
>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Win32.Release"
InheritedPropertySheets=".\Win32.vsprops;.\Release.vsprops"
>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets">
<Import Project="PlatformBase.props"/>
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)build\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(ConfigurationType)'=='StaticLibrary'">
<OutDir>$(SolutionDir)bin\$(Configuration)\lib\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<EnableEnhancedInstructionSet></EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
</Project>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;_WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN"
/>
<Tool
Name="VCLinkerTool"
TargetMachine="1"
/>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="Root"
>
<UserMacro
Name="ROOT"
Value="$(SolutionDir)"
/>
<UserMacro
Name="SRC"
Value="$(ROOT)Source\"
/>
</VisualStudioPropertySheet>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets">
<Import Project="PlatformBase.props" />
</ImportGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)64\</OutDir>
<IntDir>$(SolutionDir)build\$(Configuration)64\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(ConfigurationType)'=='StaticLibrary'">
<OutDir>$(SolutionDir)bin\$(Configuration)64\lib\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
</Project>

159
RaphnetAdapter/README.md Normal file
View File

@ -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
```

43
RaphnetAdapter/RELEASE Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

371
RaphnetAdapter/src/gcn64.c Normal file
View File

@ -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;
}

View File

@ -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 = (gcn64_list_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_s(info->str_prodname, ctx->cur_dev->product_string, PRODNAME_MAXCHARS-1);
wcsncpy_s(info->str_serial, ctx->cur_dev->serial_number, SERIAL_MAXCHARS-1);
strncpy_s(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 = (_gcn64_hdl_t*)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 = new unsigned char[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 = new unsigned char[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;
}

View File

@ -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__

View File

@ -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

View File

@ -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__

View File

@ -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;
}

View File

@ -0,0 +1,446 @@
/* 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>
#include <string.h>
#include "gcn64lib.h"
#include "gcn64_priv.h"
#include "requests.h"
#include "gcn64_protocol.h"
#include "hexdump.h"
#define _CRT_SECURE_NO_WARNINGS
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 = new unsigned char[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 = new unsigned char[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 = new unsigned char[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;
}

View File

@ -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__

View File

@ -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");
}

View File

@ -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");
}

View File

@ -0,0 +1,3 @@
void printHexBuf(unsigned char *buf, int n);

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -0,0 +1,482 @@
/* 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 <cstdarg>
#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, ...)
{
va_list args;
va_start(args, m);
vprintf(m, args);
va_end(args);
}
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;
}

View File

@ -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__

View File

@ -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)
{
}

View File

@ -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__

View File

@ -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

View File

@ -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 */

View File

@ -1,4 +1,6 @@
#pragma once
#include "ultra64/thread.h"
struct AudioMgr;
struct SchedContext;
struct IrqMgr;
@ -8,4 +10,5 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr);
void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedContext* sched, IrqMgr* irqMgr);
void AudioMgr_ThreadEntry(void* arg0);
void AudioMgr_Unlock(AudioMgr* audioMgr);
void AudioMgr_Shutdown();
void AudioMgr_Shutdown();
void AudioMgr_Pause(bool pauseOn);

View File

@ -10,3 +10,9 @@ void GfxPrint_SetBasePosPx(GfxPrint* pthis, s32 x, s32 y, u8 multiplier = 4);
void GfxPrint_SetColor(GfxPrint* pthis, u8 r, u8 g, u8 b, u8 a);
void GfxPrint_SetPos(GfxPrint* pthis, s32 x, s32 y);
void GfxPrint_SetPosPx(GfxPrint* pthis, s32 x, s32 y);
#ifdef DEBUG_PRINT
void Debug_Clear();
void Debug_Print(const char* String);
void Debug_Draw(GraphicsContext* gfxCtx);
#endif

View File

@ -12,6 +12,7 @@ void Color_RGBA8_Copy(Color_RGBA8* dst, Color_RGBA8* src);
void Lib_MemSet(u8* dest, size_t size, u8 val);
void Math_ApproachF(f32* pValue, f32 target, f32 fraction, const Step& step);
void Math_ApproachF(CounterF* pValue, f32 target, f32 fraction, const Step& step);
void Math_ApproachF(Rotation* pValue, f32 target, f32 fraction, const Step& step);
void Math_ApproachS(s16* pValue, s16 target, s16 scale, const Step& step);
void Math_ApproachS(Rotation* pValue, s16 target, s16 scale, const FStep& step);
void Math_ApproachZeroF(f32* pValue, f32 fraction, const Step& step);
@ -19,10 +20,12 @@ f32 Math_ApproachZeroF(f32 pValue, f32 fraction, const Step& step);
void Math_ApproachZeroF(CounterF* pValue, f32 fraction, const Step& step);
s32 Math_AsymStepToF(f32* pValue, f32 target, const Step& incrStep, const Step& decrStep);
s32 Math_AsymStepToF(CounterF* pValue, f32 target, const Step& incrStep, const Step& decrStep);
f32 Math_CosS(s16 angle);
s32 Math_ScaledStepToS(s16* pValue, s16 target, const FStep& step);
s32 Math_ScaledStepToS(Rotation* pValue, s16 target, const FStep& step);
f32 Math_CosS(s16 angle);
f32 Math_SinS(s16 angle);
f32 Math_AccurateCosS(s16 angle);
f32 Math_AccurateSinS(s16 angle);
f32 Math_SmoothStepToDegF(f32* pValue, f32 target, f32 fraction, const Step& step, const Step& minStep);
f32 Math_SmoothStepToF(f32* pValue, f32 target, f32 fraction, const Step& step, const Step& minStep);
f32 Math_SmoothStepToF(Rotation* pValue, f32 target, f32 fraction, const FStep& step, const FStep& minStep);
@ -46,6 +49,7 @@ s32 Math_StepUntilF(CounterF* pValue, f32 limit, const Step& step);
s32 Math_StepUntilS(s16* pValue, s16 limit, const Step& step);
s32 Math_StepUntilS(Rotation* pValue, s16 limit, const FStep& step);
void Math_Vec3f_Copy(Vec3f* dest, Vec3f* src);
void Math_VecPos_Copy(VecPos* dest, Vec3f* src);
void Math_Vec3f_Diff(Vec3f* a, Vec3f* b, Vec3f* dest);
f32 Math_Vec3f_DistXYZ(Vec3f* a, Vec3f* b);
f32 Math_Vec3f_DistXYZAndStoreDiff(Vec3f* a, Vec3f* b, Vec3f* dest);

View File

@ -56,8 +56,8 @@ void Player_UpdateBottleHeld(GlobalContext* globalCtx, Player* player, s32 item,
s32 Player_IsTargetingAnActor(Player* player);
void func_8008EC70(Player* player);
void Player_ClearZTarget(Player* player);
void func_8008EE08(Player* player);
void func_8008EEAC(GlobalContext* globalCtx, Actor* actor);
void SetFlagsForClearZTarget(Player* player);
void StartInvolintaryZtarget(GlobalContext* globalCtx, Actor* actor);
s32 func_8008EF44(GlobalContext* globalCtx, s32 ammo);
s32 Player_HoldingHookshot(Player* player);
s32 func_8008F2BC(Player* player, s32 actionParam);

View File

@ -562,12 +562,14 @@ class CounterF
CounterF& operator+=(float f)
{
m_counterScaler = FRAMERATE_SCALER_INV;
m_counter += f / m_counterScaler;
return *this;
}
CounterF& operator-=(float f)
{
m_counterScaler = FRAMERATE_SCALER_INV;
m_counter -= f / m_counterScaler;
return *this;
}

View File

@ -433,11 +433,10 @@ struct TargetContext
/* 0x3C */ Actor* targetedActor;
/* 0x40 */ f32 unk_40;
/* 0x44 */ f32 unk_44;
/* 0x48 */ s16 unk_48;
/* 0x48 */ TimerS16 unk_48;
/* 0x4A */ u8 activeCategory;
/* 0x4B */ Counter unk_4B;
/* 0x4C */ s8 unk_4C;
/* 0x4D */ char unk_4D[0x03];
/* 0x4B */ TimerU8 unk_4B;
/* 0x4C */ TimerS8 unk_4C;
/* 0x50 */ TargetContextEntry arr_50[3];
/* 0x8C */ Actor* unk_8C;
/* 0x90 */ Actor* bgmEnemy; // The nearest enemy to player with the right flags that will trigger NA_BGM_ENEMY

View File

@ -848,9 +848,9 @@ typedef struct
#ifdef LITTLE_ENDIAN
struct
{
u8 arg2;
u8 arg1;
u8 arg0;
u8 scriptIndex;
u8 seqPlayerChannelIndex;
u8 seqPlayerIndex;
u8 op;
};
#else

View File

@ -216,8 +216,8 @@ struct Normal1Anim
/* 0x20 */ f32 unk_20;
/* 0x24 */ s16 slopePitchAdj;
/* 0x26 */ s16 swingYawTarget;
/* 0x28 */ s16 distTimer;
/* 0x2A */ s16 startSwingTimer;
/* 0x28 */ TimerS16 distTimer;
/* 0x2A */ TimerS16 startSwingTimer;
}; // size = 0x2C
struct Normal1
@ -340,7 +340,7 @@ struct Jump2Anim
/* 0x6 */ s16 initYawDiff; // unused, set but not read.
/* 0x8 */ s16 yawAdj;
/* 0xA */ s16 onFloor; // unused, set but not read
/* 0xC */ s16 animTimer;
/* 0xC */ TimerS16 animTimer;
}; // size = 0x10
struct Jump2
@ -413,7 +413,7 @@ struct Battle1
struct Battle4Anim
{
/* 0x0000 */ s16 animTimer;
/* 0x0000 */ TimerS16 animTimer;
}; // size = 0x2
struct Battle4
@ -434,11 +434,11 @@ struct Keep1Anim
/* 0x00 */ f32 unk_00;
/* 0x04 */ f32 unk_04;
/* 0x08 */ f32 unk_08;
/* 0x0C */ struct Actor* unk_0C;
/* 0x0C */ struct Actor* currentTarget;
/* 0x10 */ s16 unk_10;
/* 0x12 */ s16 unk_12;
/* 0x14 */ s16 unk_14;
/* 0x16 */ s16 unk_16;
/* 0x16 */ TimerS16 unk_16;
}; // size = 0x18
struct KeepOn1
@ -591,7 +591,7 @@ struct Subj3Anim
/* 0x0 */ f32 r;
/* 0x4 */ s16 yaw;
/* 0x6 */ s16 pitch;
/* 0x8 */ s16 animTimer;
/* 0x8 */ TimerS16 animTimer;
}; // size = 0xC
struct Subj3
@ -645,9 +645,9 @@ struct Data4
struct Unique1Anim
{
/* 0x0 */ f32 unk_00; // unused
/* 0x4 */ s16 yawTarget;
/* 0x4 */ Rotation yawTarget;
/* 0x6 */ s16 yawTargetAdj;
/* 0x8 */ s16 timer;
/* 0x8 */ TimerS16 timer;
}; // size = 0xC
struct Unique1
@ -695,9 +695,9 @@ struct DoorParams
{
/* 0x0 */ struct Actor* doorActor;
/* 0x4 */ s16 camDataIdx;
/* 0x6 */ s16 timer1;
/* 0x8 */ s16 timer2;
/* 0xA */ s16 timer3;
/* 0x6 */ TimerS16 timer1;
/* 0x8 */ TimerS16 timer2;
/* 0xA */ TimerS16 timer3;
}; // size = 0xC
struct Unique3
@ -818,8 +818,8 @@ struct Demo1
struct Demo3Anim
{
/* 0x00 */ Vec3f initialAt;
/* 0x0C */ f32 unk_0C;
/* 0x10 */ s16 animFrame;
/* 0x0C */ TimerF32 stepScale;
/* 0x10 */ TimerS16 animFrame;
/* 0x12 */ s16 yawDir;
}; // size = 0x14
@ -850,7 +850,7 @@ struct Demo9Anim
/* 0x4 */ s16 keyframe;
/* 0x6 */ s16 doLERPAt;
/* 0x8 */ s16 finishAction;
/* 0xA */ s16 animTimer;
/* 0xA */ TimerS16 animTimer;
}; // size = 0xC
struct Demo9
@ -1011,7 +1011,7 @@ struct Camera
/* 0x166 */ s16 prevCamDataIdx;
/* 0x168 */ s16 csId;
/* 0x16A */ s16 unk_16A;
/* 0x16C */ s16 startControlTimer;
/* 0x16C */ TimerS16 startControlTimer;
}; // size = 0x16C
/**

View File

@ -23,10 +23,10 @@ struct EffectStatus
struct EffectSparkElement
{
/* 0x00 */ Vec3f velocity;
/* 0x0C */ Vec3f position;
/* 0x18 */ Vec3s unkVelocity;
/* 0x1E */ Vec3s unkPosition;
/* 0x00 */ VecPosF velocity;
/* 0x0C */ VecPosF position;
/* 0x18 */ VecPos unkVelocity;
/* 0x1E */ VecPos unkPosition;
}; // size = 0x24
struct EffectSparkInit
@ -40,7 +40,7 @@ struct EffectSparkInit
/* 0x498 */ u32 vDiv; // "v_div"
/* 0x49C */ Color_RGBA8 colorStart[4];
/* 0x4AC */ Color_RGBA8 colorEnd[4];
/* 0x4BC */ s32 timer;
/* 0x4BC */ TimerS32 timer;
/* 0x4C0 */ s32 duration;
}; // size = 0x4C4
@ -55,14 +55,14 @@ struct EffectSpark
/* 0x498 */ u32 vDiv; // "v_div"
/* 0x49C */ Color_RGBA8 colorStart[4];
/* 0x4AC */ Color_RGBA8 colorEnd[4];
/* 0x4BC */ s32 timer;
/* 0x4BC */ TimerS32 timer;
/* 0x4C0 */ s32 duration;
}; // size = 0x4C4
struct EffectBlureElement
{
/* 0x00 */ s32 state;
/* 0x04 */ s32 timer;
/* 0x04 */ TimerS32 timer;
/* 0x08 */ Vec3s p1;
/* 0x0E */ Vec3s p2;
/* 0x14 */ u16 flags;
@ -162,7 +162,7 @@ struct EffectShieldParticle
/* 0x1A8 */ f32 maxInitialSpeed;
/* 0x1AC */ f32 lengthCutoff;
/* 0x1B0 */ u8 duration;
/* 0x1B1 */ u8 timer;
/* 0x1B1 */ TimerU8 timer;
/* 0x1B2 */ LightInfo lightInfo;
/* 0x1C0 */ LightNode* lightNode;
/* 0x1C4 */ s32 lightDecay; // halves light radius every frame when set to 1
@ -242,7 +242,7 @@ struct EffectSs
/* 0x3C */ struct Actor* actor; // interfacing actor, usually the actor that spawned the effect
/* 0x40 */ s32 regs[13]; // specific per effect
/* 0x74 */ u16 flags;
/* 0x76 */ s16 life; // -1 means this entry is free
/* 0x76 */ s16 life;//TimerS16 but causing some to last longer then normal // -1 means this entry is free
/* 0x78 */ u8 priority; // Lower value means higher priority
/* 0x79 */ u8 type;
}; // size = 0x7A

View File

@ -45,7 +45,7 @@ struct LightningStrike
/* 0x02 */ u8 flashGreen;
/* 0x03 */ u8 flashBlue;
/* 0x04 */ u8 flashAlphaTarget;
/* 0x08 */ f32 delayTimer;
/* 0x08 */ TimerF32 delayTimer;
}; // size = 0xC
// describes what skybox files and blending modes to use depending on time of day
@ -122,9 +122,9 @@ struct EnvironmentContext
/* 0xD8 */ f32 unk_D8; // indoor light blend weight?
/* 0xDC */ u8 unk_DC;
/* 0xDD */ u8 gloomySkyMode;
/* 0xDE */ u8 unk_DE; // gloomy sky state
/* 0xDE */ u8 skyState; // gloomy sky state
/* 0xDF */ u8 lightningMode;
/* 0xE0 */ u8 unk_E0; // env sounds state
/* 0xE0 */ u8 dayState; // env sounds state
/* 0xE1 */ u8 fillScreen;
/* 0xE2 */ u8 screenFillColor[4];
/* 0xE6 */ u8 sandstormState;

View File

@ -22,7 +22,7 @@ struct Vec2f
struct Vec3f
{
f32 x, y, z;
f32 x, y, z;
}; // size = 0x0C
struct Vec3us
@ -64,6 +64,22 @@ struct VecPosF
CounterF x, y, z;
};
*/
struct VecCounterF
{
VecCounterF();
VecCounterF(const CounterF& x, const CounterF& y, const CounterF& z);
VecCounterF(const Vec3s& vec);
VecCounterF(const Vec3f& vec);
VecCounterF(Vec3f* vec);
VecCounterF(const Vec3f* vec);
//Vec3f* operator&();
//VecPosF(const Vec3f* vec);
operator Vec3s() const;
operator Vec3f() const;
operator Vec3f*();
operator Vec3f*() const;
CounterF x, y, z;
};
typedef VecRot VecPos;
typedef Vec3f VecRotF;

View File

@ -46,7 +46,7 @@ struct SkyboxContext
/* 0x138 */ Gfx* unk_138;
/* 0x13C */ Vtx* roomVtx;
/* 0x140 */ s16 unk_140;
/* 0x144 */ Vec3f rot;
/* 0x144 */ VecRot rot;
/* 0x150 */ char unk_150[0x10];
}; // size = 0x160

View File

@ -754,7 +754,7 @@ struct RoomContext
/* 0x34 */ void* unk_34;
/* 0x38 */ DmaRequest dmaRequest;
/* 0x70 */ OSMesg loadMsg;
/* 0x74 */ s16 unk_74[2]; // context-specific data used by the current scene draw config
/* 0x74 */ TimerS16 unk_74[2]; // context-specific data used by the current scene draw config
}; // size = 0x78
typedef struct

View File

@ -2699,7 +2699,7 @@ void Audio_UpdateAll(void)
Audio_ProcessSeqCmds();
Audio_UpdateActiveSounds();
func_800FA3DC();
AudioDebug_SetInput();
//AudioDebug_SetInput();
AudioDebug_ProcessInput();
Audio_ScheduleProcessCmds();
sAudioUpdateTaskEnd = gAudioContext.totalTaskCnt;
@ -2707,6 +2707,7 @@ void Audio_UpdateAll(void)
}
}
//unused
void func_800F314C(s8 arg0)
{
Audio_QueueCmdS32(CHAN_LOAD_UKN_82 << 24 | SEQ_PLAYER_BGM_MAIN << 16 | (((u8)arg0 & 0xFF) << 8), 1);
@ -2936,6 +2937,7 @@ f32 Audio_ComputeSoundFreqScale(u8 bankId, u8 entryIdx)
return freq;
}
//filter related?
u8 func_800F37B8(f32 behindScreenZ, SoundBankEntry* arg1, s8 arg2)
{
s8 phi_v0;

View File

@ -96,6 +96,7 @@ void audio_int()
static AudioTask* g_currentAudioTask = nullptr;
static bool g_aziInit = false;
static bool g_aziPause = false;
void audio_thread()
{
@ -107,7 +108,7 @@ void audio_thread()
auto targetTime = std::chrono::high_resolution_clock::now() + interval;
while(g_aziInit)
{
if(std::chrono::high_resolution_clock::now() > targetTime)
if(std::chrono::high_resolution_clock::now() > targetTime && !g_aziPause)
{
auto task = getAudioTask();
@ -190,3 +191,8 @@ void AudioMgr_Shutdown()
if(t1.joinable())
t1.join();
}
void AudioMgr_Pause(bool pauseOn)
{
g_aziPause = pauseOn;
}

View File

@ -217,25 +217,25 @@ void Audio_ProcessLoadCmd(AudioCmd* cmd)
switch(cmd->op)
{
case CHAN_LOAD_UKN_81:
AudioLoad_SyncLoadSeqParts(cmd->arg1, cmd->arg2);
AudioLoad_SyncLoadSeqParts(cmd->seqPlayerChannelIndex, cmd->scriptIndex);
return;
case CHAN_LOAD_UKN_82:
AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2);
Audio_LoadSetFadeInTimer(cmd->arg0, (s32)cmd->data);
AudioLoad_SyncInitSeqPlayer(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->scriptIndex);
Audio_LoadSetFadeInTimer(cmd->seqPlayerIndex, (s32)cmd->data);
return;
case CHAN_LOAD_UKN_85:
AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->arg0, cmd->arg1, (s32)cmd->data);
AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, (s32)cmd->data);
return;
case CHAN_LOAD_DISABLE_SEQUENCE:
if(gAudioContext.seqPlayers[cmd->arg0].enabled)
if(gAudioContext.seqPlayers[cmd->seqPlayerIndex].enabled)
{
if(cmd->asInt == 0)
{
AudioSeq_SequencePlayerDisableAsFinished(&gAudioContext.seqPlayers[cmd->arg0]);
AudioSeq_SequencePlayerDisableAsFinished(&gAudioContext.seqPlayers[cmd->seqPlayerIndex]);
}
else
{
Audio_LoadSetFadeOutTimer(cmd->arg0, cmd->asInt);
Audio_LoadSetFadeOutTimer(cmd->seqPlayerIndex, cmd->asInt);
}
}
return;
@ -276,22 +276,22 @@ void Audio_ProcessLoadCmd(AudioCmd* cmd)
return;
case CHAN_LOAD_INSTRUMENT_ASYNC:
AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2);
AudioLoad_SyncLoadInstrument(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->scriptIndex);
return;
case CHAN_LOAD_BANK_ASYNC:
AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, nullptr);
AudioLoad_AsyncLoadSampleBank(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->scriptIndex, nullptr);
return;
case CHAN_LOAD_FONT_ASYNC:
AudioLoad_AsyncLoadFont(cmd->arg0, cmd->arg1, cmd->arg2, nullptr);
AudioLoad_AsyncLoadFont(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->scriptIndex, nullptr);
return;
case CHAN_LOAD_UKN_FC:
AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, nullptr);
AudioLoad_AsyncLoadSeq(cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->scriptIndex, nullptr);
return;
case CHAN_LOAD_DISCARD_SEQ_FONTS:
AudioLoad_DiscardSeqFonts(cmd->arg1);
AudioLoad_DiscardSeqFonts(cmd->seqPlayerChannelIndex);
return;
case CHAN_LOAD_UKN_90:
gAudioContext.unk_5BDC[cmd->arg0] = cmd->asUShort;
gAudioContext.unk_5BDC[cmd->seqPlayerIndex] = cmd->asUShort;
return;
case CHAN_LOAD_RESET_LOAD_SPECID:
gAudioContext.resetStatus = 5;
@ -303,7 +303,7 @@ void Audio_ProcessLoadCmd(AudioCmd* cmd)
case CHAN_LOAD_SET_FONT_INSTRUMENT0:
case CHAN_LOAD_SET_FONT_INSTRUMENT1:
case CHAN_LOAD_SET_FONT_INSTRUMENT:
Audio_SetFontInstrument(cmd->op - 0xE0, cmd->arg0, cmd->arg1, cmd->data);
Audio_SetFontInstrument(cmd->op - 0xE0, cmd->seqPlayerIndex, cmd->seqPlayerChannelIndex, cmd->data);
return;
case CHAN_LOAD_UKN_FE:
temp_t7 = cmd->asUInt;
@ -444,9 +444,9 @@ void Audio_ProcessCmd(AudioCmd* cmd)
return;
}
if(cmd->arg0 < gAudioContext.audioBufferParameters.numSequencePlayers)
if(cmd->seqPlayerIndex < gAudioContext.audioBufferParameters.numSequencePlayers)
{
seqPlayer = &gAudioContext.seqPlayers[cmd->arg0];
seqPlayer = &gAudioContext.seqPlayers[cmd->seqPlayerIndex];
if(cmd->op & 0x80)
{
Audio_ProcessLoadCmd(cmd);
@ -458,14 +458,14 @@ void Audio_ProcessCmd(AudioCmd* cmd)
return;
}
if(cmd->arg1 < 0x10)
if(cmd->seqPlayerChannelIndex < 0x10)
{
Audio_ProcessChannelCmd(seqPlayer->channels[cmd->arg1], cmd);
Audio_ProcessChannelCmd(seqPlayer->channels[cmd->seqPlayerChannelIndex], cmd);
return;
}
if(cmd->arg1 == 0xFF)
if(cmd->seqPlayerChannelIndex == 0xFF)
{
phi_v0 = gAudioContext.unk_5BDC[cmd->arg0];
phi_v0 = gAudioContext.unk_5BDC[cmd->seqPlayerIndex];
for(i = 0; i < 0x10; i++)
{
if(phi_v0 & 1)
@ -654,13 +654,13 @@ void Audio_ProcessSequenceCmd(SequencePlayer* seqPlayer, AudioCmd* cmd)
seqPlayer->transposition = cmd->asSbyte;
return;
case SEQ_CMD_UKN_46:
seqPlayer->soundScriptIO[cmd->arg2] = cmd->asSbyte;
seqPlayer->soundScriptIO[cmd->scriptIndex] = cmd->asSbyte;
return;
case SEQ_CMD_UKN_4A:
fadeVolume = (s32)cmd->arg1 / 127.0f;
fadeVolume = (s32)cmd->seqPlayerChannelIndex / 127.0f;
goto block_11;
case SEQ_CMD_UKN_4B:
fadeVolume = ((s32)cmd->arg1 / 100.0f) * seqPlayer->fadeVolume;
fadeVolume = ((s32)cmd->seqPlayerChannelIndex / 100.0f) * seqPlayer->fadeVolume;
block_11:
if(seqPlayer->state != 2)
{
@ -753,9 +753,13 @@ void Audio_ProcessChannelCmd(SequenceChannel* channel, AudioCmd* cmd)
}
return;
case CHAN_UPD_SCRIPT_IO:
if(cmd->arg2 < 8)
if(cmd->seqPlayerChannelIndex==0x0b)
{
channel->soundScriptIO[cmd->arg2] = cmd->asSbyte;
cmd->seqPlayerChannelIndex = 0x0b;
}
if(cmd->scriptIndex < 8)
{
channel->soundScriptIO[cmd->scriptIndex] = cmd->asSbyte;
}
return;
case CHAN_UPD_STOP_SOMETHING2:

View File

@ -873,11 +873,11 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd)
freqScale2 = temp_f14;
break;
default:
freqScale = temp_f2;
freqScale2 = temp_f2;
break;
}
freqScale = temp_f2;
portamento->extent = (freqScale2 / freqScale) - 1.0f;
if(PORTAMENTO_IS_SPECIAL(*portamento))
@ -1332,7 +1332,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel)
break;
case 0xDB:
signedParam = (s8)parameters[0];
channel->transposition = signedParam;
channel->transposition = signedParam;
break;
case 0xDA:
offset = (u16)parameters[0];

View File

@ -22,7 +22,7 @@ u8 SKIP_GFX_FRAME_MASK = 0;
#endif
static bool g_force20FPS = false;
static float g_force20FPSLast = 20.0f;
static float g_force20FPSLastMaxFps = 20.0f;
static FramerateProfile g_profile = PROFILE_BOOT;
@ -102,14 +102,12 @@ namespace oot
void setMaxFramerate(float targetFramerate)
{
const float framerate = g_force20FPS ? 20.0f : targetFramerate;
if(framerate == SET_FRAMERATE)
if(targetFramerate == SET_FRAMERATE)
{
return;
}
#ifndef STATIC_FRAMERATE
switch((s32)framerate)
switch((s32)targetFramerate)
{
case 240:
SET_FRAMERATE = 240.0f;
@ -160,6 +158,26 @@ namespace oot
INTERPOLATE_ANIM = true;
SKIP_GFX_FRAME_MASK = 0;
g_profileRates[0] = FRAMERATE_30FPS; // PROFILE_BOOT
g_profileRates[1] = FRAMERATE_60FPS; // PROFILE_PAUSE
g_profileRates[2] = FRAMERATE_60FPS; // PROFILE_GAMEPLAY
g_profileRates[3] = FRAMERATE_60FPS; // PROFILE_UNKNOWN1
g_profileRates[4] = FRAMERATE_60FPS; // PROFILE_UNKNOWN2
g_profileRates[5] = FRAMERATE_60FPS; // PROFILE_SAMPLE
g_profileRates[6] = FRAMERATE_60FPS; // PROFILE_OPENING
g_profileRates[7] = FRAMERATE_60FPS; // PROFILE_SELECT
g_profileRates[8] = FRAMERATE_60FPS; // PROFILE_TITLE
g_profileRates[9] = FRAMERATE_60FPS; // PROFILE_FILE_CHOOSE
break;
case 40:
SET_FRAMERATE = 40.0f;
TICK_RATE = 60.0f;
UPDATE_SCALER = 40.0f / 60.0f;
GAME_SPEED_RATIO = 60.0f / 40.0f;
DEKU_NUT_SPAWN_SCALER = 1.2f;
INTERPOLATE_ANIM = true;
SKIP_GFX_FRAME_MASK = 0;
g_profileRates[0] = FRAMERATE_30FPS; // PROFILE_BOOT
g_profileRates[1] = FRAMERATE_60FPS; // PROFILE_PAUSE
g_profileRates[2] = FRAMERATE_60FPS; // PROFILE_GAMEPLAY
@ -174,11 +192,11 @@ namespace oot
case 30:
SET_FRAMERATE = 30.0f;
TICK_RATE = 60.0f;
UPDATE_SCALER = 1.0f;
GAME_SPEED_RATIO = 1.0f;
UPDATE_SCALER = 30.0f / 60.0f;
GAME_SPEED_RATIO = 60.0f / 30.0f;
DEKU_NUT_SPAWN_SCALER = 1.2f;
INTERPOLATE_ANIM = true;
SKIP_GFX_FRAME_MASK = 1;
SKIP_GFX_FRAME_MASK = 0;
g_profileRates[0] = FRAMERATE_30FPS; // PROFILE_BOOT
g_profileRates[1] = FRAMERATE_60FPS; // PROFILE_PAUSE
@ -237,6 +255,7 @@ namespace oot
FRAMERATE_SCALER = (20.0f * GAME_SPEED_RATIO / TICK_RATE);
FRAMERATE_SCALER_INV = TICK_RATE / (20.0f * GAME_SPEED_RATIO);
R_UPDATE_RATE = framerate_divider();
osSyncPrintf("Framerate: %d\n", (s32)targetFramerate);
config().save();
#endif
@ -264,12 +283,25 @@ float Round(float value)
return roundf(value * 100) / 100.0f;
}
/// <summary>
/// This is a lazy function, for anywhere you dont want the high fps to effect game mechanics. This should only be used as a temporary measure
/// </summary>
/// <param name="force"></param>
void force20FPS(bool force)
{
if(force)
{
g_force20FPSLast = oot::getMaxFramerate();
g_force20FPS = true;
//enable force 20fps remember last fps
g_force20FPSLastMaxFps = oot::getMaxFramerate();
oot::setMaxFramerate(20.0f);
}
else
{
if(!g_force20FPS)
g_force20FPSLastMaxFps = oot::getMaxFramerate();
g_force20FPS = false;
//disable force 20fps and set last fps
oot::setMaxFramerate(g_force20FPSLastMaxFps);
}
g_force20FPS = force;
oot::setMaxFramerate(g_force20FPSLast);
}

View File

@ -23,6 +23,7 @@
#include "def/gamealloc.h"
#include "def/gettime.h"
#include "def/graph.h"
#include "def/gfxprint.h"
#include "def/idle.h"
#include "def/logutils.h"
#include "def/recvmesg.h"
@ -406,6 +407,10 @@ void GameState_Update(GameState* gameState)
func_800C49F4(gfxCtx);
}
#ifdef DEBUG_PRINT
Debug_Draw(gfxCtx);
#endif
gameState->frames++;
}
#include <string.h>

View File

@ -2,6 +2,8 @@
#include "global.h"
#include "gfx.h"
#include "gfxprint.h"
#include "def/z_rcp.h"
#include "def/graph.h"
#include "def/gfxprint.h"
#include "def/printutils.h"
#include "def/xprintf.h"
@ -363,13 +365,6 @@ s32 GfxPrint_Printf(GfxPrint* pthis, const char* fmt, ...)
// Debug printf
#ifdef DEBUG_PRINT
Gfx* func_8009411C(Gfx* gfx);
void Graph_OpenDisps(Gfx** dispRefs, GraphicsContext* gfxCtx, const char* file, s32 line);
void Graph_CloseDisps(Gfx** dispRefs, GraphicsContext* gfxCtx, const char* file, s32 line);
#include <stdio.h>
#include <stdlib.h>
char gDebugLines[20][512];
int gDebugCurrentLine = 0;
@ -405,7 +400,7 @@ void Debug_Draw(GraphicsContext* gfxCtx)
for(int i = 0; i < gDebugCurrentLine; i++)
{
GfxPrint_SetColor(printer, 255, 255, 255, 255);
GfxPrint_SetPos(printer, -5, i);
GfxPrint_SetPos(printer, 0, i);
GfxPrint_Printf(printer, gDebugLines[i]);
}

View File

@ -424,6 +424,9 @@ void Graph_ThreadEntry(void* arg0)
gfx_wait_ready();
if(!isRunning())
break;
if(gNextGameState)
{
gCurrentGameState = std::move(gNextGameState);

View File

@ -104,7 +104,7 @@ VecPosF::VecPosF() : x(0), y(0), z(0)
{
}
VecPosF::VecPosF(const Rotation& x, const Rotation& y, const Rotation& z) : x(x), y(y), z(z)
VecPosF::VecPosF(const CounterF& x, const CounterF& y, const CounterF& z) : x(x), y(y), z(z)
{
}
@ -137,4 +137,64 @@ VecPosF::operator Vec3f() const
vec.z = z;
return vec;
}
*/
*/
VecCounterF::VecCounterF() : x(0), y(0), z(0)
{
}
VecCounterF::VecCounterF(const CounterF& x, const CounterF& y, const CounterF& z) : x(x), y(y), z(z)
{
}
VecCounterF::VecCounterF(const Vec3s& vec) : x(vec.x), y(vec.y), z(vec.z)
{
}
VecCounterF::VecCounterF(const Vec3f& vec) : x(vec.x), y(vec.y), z(vec.z)
{
}
VecCounterF::VecCounterF(Vec3f* vec) : x(vec->x), y(vec->y), z(vec->z)
{
}
VecCounterF::VecCounterF(const Vec3f* vec)
{
}
VecCounterF::operator Vec3s() const
{
Vec3s vec;
vec.x = x;
vec.y = y;
vec.z = z;
return vec;
}
VecCounterF::operator Vec3f() const
{
Vec3f vec;
vec.x = x;
vec.y = y;
vec.z = z;
return vec;
}
VecCounterF::operator Vec3f*()
{
Vec3f vec;
vec.x = x;
vec.y = y;
vec.z = z;
return &vec;
}
VecCounterF::operator Vec3f*() const
{
Vec3f vec;
vec.x = x;
vec.y = y;
vec.z = z;
return &vec;
}

View File

@ -384,7 +384,7 @@ void func_8002C124(TargetContext* targetCtx, GlobalContext* globalCtx)
{
TargetContextEntry* entry;
Player* player;
s16 spCE;
TimerS16 spCE;
f32 temp1;
Vec3f spBC;
s32 spB8;
@ -601,6 +601,7 @@ void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, Gl
targetCtx->unk_48 = 0;
}
//switching between targets sound
lockOnSfxId = CHECK_FLAG_ALL(actorArg->flags, ACTOR_FLAG_VISIBLE | ACTOR_FLAG_2) ? NA_SE_SY_LOCK_ON : NA_SE_SY_LOCK_ON_HUMAN;
Common_PlaySfx(lockOnSfxId);
}
@ -1270,6 +1271,7 @@ void func_8002DF90(DynaPolyActor* dynaActor)
dynaActor->unk_150 = 0.0f;
}
//related to moving a block
void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2)
{
dynaActor->unk_150 += arg1;

View File

@ -1489,7 +1489,7 @@ s16 Camera_CalcDefaultPitch(Camera* camera, s16 arg1, s16 arg2, s16 arg3)
pad = Camera_InterpolateCurve(0.8f, 1.0f - t);
phi_a2 = (1.0f / camera->pitchUpdateRateInv) * pad;
}
return Camera_LERPCeilS(sp1C, arg1, phi_a2, 0xA);
return Camera_LERPCeilS(sp1C, arg1, phi_a2 / FRAMERATE_SCALER_INV, 0xA);
}
s16 Camera_CalcDefaultYaw(Camera* camera, s16 cur, s16 target, f32 arg3, f32 accel)
@ -1500,6 +1500,7 @@ s16 Camera_CalcDefaultYaw(Camera* camera, s16 cur, s16 target, f32 arg3, f32 acc
f32 speedT;
f32 velFactor;
f32 yawUpdRate;
f32 result;
if(camera->xzSpeed > 0.001f)
{
@ -1508,7 +1509,7 @@ s16 Camera_CalcDefaultYaw(Camera* camera, s16 cur, s16 target, f32 arg3, f32 acc
}
else
{
angDelta = target - BINANG_ROT180(cur);
angDelta = target - (BINANG_ROT180(cur));
speedT = PCT(OREG(48));
}
@ -1521,63 +1522,54 @@ s16 Camera_CalcDefaultYaw(Camera* camera, s16 cur, s16 target, f32 arg3, f32 acc
velocity = 0.0f;
}
velFactor = Camera_InterpolateCurve(0.5f, camera->speedRatio);
yawUpdRate = 1.0f / camera->yawUpdateRateInv;
velFactor = Camera_InterpolateCurve(0.5f, camera->speedRatio * FRAMERATE_SCALER_INV);
yawUpdRate = FRAMERATE_SCALER / camera->yawUpdateRateInv;
return cur + (s16)(angDelta * velocity * velFactor * yawUpdRate);
}
#include "../port/controller/controller.h"
#include "../port/player/players.h"
s16 Camera_CalcControllerPitch(Camera* camera, s16 cur, s16 target, s16 arg3)
s16 Camera_CalcControllerPitchDiff(Camera* camera)
{
f32 pitchUpdRate;
f32 pitchUpdRate = 1.0f / 24.0f;//camera->pitchUpdateRateInv;
const oot::hid::Controller& controller = oot::player(0).controller();
s16 rStickY = (s16)controller.state().r_stick_y * (s16)-150;
s32 rStickY = -controller.state().r_stick_y;
if(rStickY != 0)
{
camera->startControlTimer = 250; // 10s
camera->startControlTimer = 250; //250 = 10s
}
pitchUpdRate = 1.0f / camera->pitchUpdateRateInv;
return cur + (s16)(rStickY * pitchUpdRate * oot::config().camera().scalerY() * FRAMERATE_SCALER);
return CLAMP((s16)(rStickY * pitchUpdRate * oot::config().camera().scalerY() * FRAMERATE_SCALER), -0x7FFF, 0x7FFF);
}
s16 Camera_CalcControllerYaw(Camera* camera, s16 cur, s16 target, f32 arg3, f32 accel)
s16 Camera_CalcControllerYawDiff(Camera* camera)
{
if(oot::state.center_camera)
{
return BINANG_ROT180(target);
}
f32 yawUpdRate = 1.0f / 24.0f;//camera->yawUpdateRateInv;
f32 yawUpdRate;
const oot::hid::Controller& controller = oot::player(0).controller();
s16 rStickX = (s16)controller.state().r_stick_x * (s16)-375;
s32 rStickX = -controller.state().r_stick_x;
if(rStickX != 0)
{
camera->startControlTimer = 250; // 10s
camera->startControlTimer = 250; //250 = 10s
}
yawUpdRate = 1.0f / camera->yawUpdateRateInv;
return cur + (s16)(rStickX * yawUpdRate * oot::config().camera().scalerX() * FRAMERATE_SCALER);
return CLAMP((s16)(rStickX * yawUpdRate * oot::config().camera().scalerX() * FRAMERATE_SCALER), -0x7FFF, 0x7FFF);
}
void StepControlTimer(Camera* camera)
{
const oot::hid::Controller& controller = oot::player(0).controller();
if(camera->xzSpeed > 0.001f && (controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0))
{
camera->startControlTimer = 250; // 10s
}
if(camera->startControlTimer > 0)
{
camera->startControlTimer--;
}
}
void func_80046E20(Camera* camera, VecSph* eyeAdjustment, f32 minDist, f32 arg3, f32* arg4, SwingAnimation* anim)
void FollowPlayerWithCollision(Camera* camera, VecSph* eyeAdjustment, f32 minDist, f32 arg3, f32* arg4, SwingAnimation* anim)
{
static CamColChk atEyeColChk;
static CamColChk eyeAtColChk;
@ -1757,13 +1749,16 @@ s32 Camera_Normal1(Camera* camera)
anim->swing.swingUpdateRateTimer = 0;
anim->swingYawTarget = atEyeGeo.yaw;
sUpdateCameraDirection = 0;
anim->startSwingTimer = OREG(50) + OREG(51);
if(!oot::config().camera().useClassicCamera())
if(camera->animState != 0)
{
camera->startControlTimer = OREG(50) + OREG(51);
}
anim->startSwingTimer = OREG(50) + OREG(51);
if(!oot::config().camera().useClassicCamera())
{
camera->startControlTimer = OREG(50) + OREG(51);
}
}
break;
default:
break;
@ -1794,10 +1789,14 @@ s32 Camera_Normal1(Camera* camera)
}
else
{
if(anim->startSwingTimer > 0)
if(camera->xzSpeed > 0.001f)
{
anim->startSwingTimer = OREG(50) + OREG(51);
}
else if(anim->startSwingTimer > 0)
{
if(anim->startSwingTimer > OREG(50))
{
{
anim->swingYawTarget = atEyeGeo.yaw + (BINANG_SUB(BINANG_ROT180(camera->playerPosRot.rot.y), atEyeGeo.yaw) / anim->startSwingTimer);
}
anim->startSwingTimer--;
@ -1871,7 +1870,23 @@ s32 Camera_Normal1(Camera* camera)
camera->dist = eyeAdjustment.r = Camera_ClampDist(camera, eyeAdjustment.r, norm1->distMin, norm1->distMax, anim->distTimer);
if(oot::config().camera().useClassicCamera())
if(!oot::config().camera().useClassicCamera())
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(oot::state.center_camera)
{
eyeAdjustment.pitch = atEyeNextGeo.pitch;
eyeAdjustment.yaw = Camera_LERPCeilS(BINANG_ROT180(camera->playerPosRot.rot.y), atEyeNextGeo.yaw, 3.0f / camera->yawUpdateRateInv, 0xA);
}
else if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeAdjustment.yaw = atEyeNextGeo.yaw + Camera_CalcControllerYawDiff(camera);
eyeAdjustment.pitch = atEyeNextGeo.pitch + Camera_CalcControllerPitchDiff(camera);
}
}
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
if(anim->startSwingTimer <= 0)
{
@ -1890,26 +1905,6 @@ s32 Camera_Normal1(Camera* camera)
eyeAdjustment.pitch = Camera_CalcDefaultPitch(camera, atEyeNextGeo.pitch, norm1->pitchTarget, anim->slopePitchAdj);
}
}
else
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeAdjustment.yaw = Camera_CalcControllerYaw(camera, atEyeNextGeo.yaw, camera->playerPosRot.rot.y, norm1->unk_14, sp94);
eyeAdjustment.pitch = Camera_CalcControllerPitch(camera, atEyeNextGeo.pitch, norm1->pitchTarget, anim->slopePitchAdj);
}
else if(anim->swing.unk_18 != 0)
{
eyeAdjustment.yaw = Camera_LERPCeilS(anim->swing.unk_16, atEyeNextGeo.yaw, 1.0f / camera->yawUpdateRateInv, 0xA);
eyeAdjustment.pitch = Camera_LERPCeilS(anim->swing.unk_14, atEyeNextGeo.pitch, 1.0f / camera->yawUpdateRateInv, 0xA);
}
else if(anim->startSwingTimer <= 0 && camera->startControlTimer <= 0)
{
eyeAdjustment.yaw = Camera_CalcDefaultYaw(camera, atEyeNextGeo.yaw, camera->playerPosRot.rot.y, norm1->unk_14, sp94);
eyeAdjustment.pitch = Camera_CalcDefaultPitch(camera, atEyeNextGeo.pitch, norm1->pitchTarget, anim->slopePitchAdj);
}
}
// set eyeAdjustment pitch from 79.65 degrees to -85 degrees
if(eyeAdjustment.pitch > 0x38A4)
@ -1925,35 +1920,36 @@ s32 Camera_Normal1(Camera* camera)
if((camera->status == CAM_STAT_ACTIVE) && (!(norm1->interfaceFlags & 0x10)))
{
anim->swingYawTarget = BINANG_ROT180(camera->playerPosRot.rot.y);
if(anim->startSwingTimer > 0)
if(oot::config().camera().useClassicCamera())
{
if(!oot::config().camera().useClassicCamera())
if(anim->startSwingTimer > 0)
{
anim->swing.swingUpdateRate = camera->yawUpdateRateInv = norm1->unk_0C * 2.0f;
FollowPlayerWithCollision(camera, &eyeAdjustment, norm1->distMin, norm1->unk_0C, &sp98, &anim->swing);
}
func_80046E20(camera, &eyeAdjustment, norm1->distMin, norm1->unk_0C, &sp98, &anim->swing);
}
else
{
sp88 = *eyeNext;
anim->swing.swingUpdateRate = camera->yawUpdateRateInv = norm1->unk_0C * 2.0f;
if(Camera_BGCheck(camera, at, &sp88))
else
{
if(oot::config().camera().useClassicCamera())
sp88 = *eyeNext;
anim->swing.swingUpdateRate = camera->yawUpdateRateInv = norm1->unk_0C * 2.0f;
if(Camera_BGCheck(camera, at, &sp88))
{
anim->swingYawTarget = atEyeNextGeo.yaw;
anim->startSwingTimer = -1;
}
else
{
func_80046E20(camera, &eyeAdjustment, norm1->distMin, norm1->unk_0C, &sp98, &anim->swing);
*eye = *eyeNext;
}
anim->swing.unk_18 = 0;
}
else
}
else
{
if(anim->startSwingTimer <= 0)
{
*eye = *eyeNext;
anim->swing.swingUpdateRate = camera->yawUpdateRateInv = norm1->unk_0C * 2.0f;
}
anim->swing.unk_18 = 0;
FollowPlayerWithCollision(camera, &eyeAdjustment, norm1->distMin, norm1->unk_0C, &sp98, &anim->swing);
}
if(anim->swing.unk_18 != 0)
@ -2333,8 +2329,8 @@ s32 Camera_Normal3(Camera* camera)
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
sp84.yaw = Camera_CalcControllerYaw(camera, sp74.yaw, playerPosRot->rot.y, norm3->yOffset, 0.0f);
sp84.pitch = Camera_CalcControllerPitch(camera, sp74.pitch, norm3->pitchTarget, 0);
sp84.yaw = sp74.yaw + Camera_CalcControllerYawDiff(camera);
sp84.pitch = sp74.pitch + Camera_CalcControllerPitchDiff(camera);
}
else if(camera->startControlTimer <= 0)
{
@ -2352,7 +2348,7 @@ s32 Camera_Normal3(Camera* camera)
if(camera->status == CAM_STAT_ACTIVE)
{
func_80046E20(camera, &sp84, norm3->distMin, norm3->yawUpdateSpeed, &sp8C, &anim->swing);
FollowPlayerWithCollision(camera, &sp84, norm3->distMin, norm3->yawUpdateSpeed, &sp8C, &anim->swing);
}
else
{
@ -2377,7 +2373,7 @@ s32 Camera_Normal0(Camera* camera)
return Camera_Noop(camera);
}
// z toggle camera
// z target camera with no target
s32 Camera_Parallel1(Camera* camera)
{
Vec3f* eye = &camera->eye;
@ -2399,6 +2395,8 @@ s32 Camera_Parallel1(Camera* camera)
f32 playerHeight;
s32 pad3;
camera->startControlTimer = 0;
playerHeight = Player_GetHeight(camera->player);
if(RELOAD_PARAMS)
{
@ -2406,7 +2404,6 @@ s32 Camera_Parallel1(Camera* camera)
f32 yNormal = (1.0f + PCT(R_CAM_YOFFSET_NORM)) - (PCT(R_CAM_YOFFSET_NORM) * (68.0f / playerHeight));
para1->unk_00 = NEXTPCT * playerHeight * yNormal;
;
para1->distTarget = NEXTPCT * playerHeight * yNormal;
para1->pitchTarget = DEGF_TO_BINANG(NEXTSETTING);
para1->yawTarget = DEGF_TO_BINANG(NEXTSETTING);
@ -2526,13 +2523,14 @@ s32 Camera_Parallel1(Camera* camera)
}
else
{
//somting to do with jumping off ledge
func_800458D4(camera, &atToEyeNextDir, para1->unk_18, &anim->yTarget, para1->interfaceFlags & 1);
}
if(anim->animTimer != 0)
{
camera->unk_14C |= 0x20;
tangle = (((anim->animTimer + 1) * anim->animTimer) >> 1);
tangle = ((s16)((anim->animTimer + 1) * anim->animTimer) >> 1);
spA8.yaw = atToEyeDir.yaw + ((BINANG_SUB(anim->yawTarget, atToEyeDir.yaw) / tangle) * anim->animTimer);
spA8.pitch = atToEyeDir.pitch;
spA8.r = atToEyeDir.r;
@ -2729,34 +2727,24 @@ s32 Camera_Jump1(Camera* camera)
eyeDiffSph.r = Camera_LERPCeilF(eyeDiffTarget.r, eyeAtOffset.r, PCT(OREG(29)), 1.0f);
if(oot::config().camera().useClassicCamera())
if(!oot::config().camera().useClassicCamera())
{
eyeDiffSph.pitch = Camera_LERPCeilS(eyeDiffTarget.pitch, eyeAtOffset.pitch, PCT(OREG(29)), 0xA);
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeDiffSph.yaw = eyeNextAtOffset.yaw + Camera_CalcControllerYawDiff(camera);
eyeDiffSph.pitch = eyeNextAtOffset.pitch + Camera_CalcControllerPitchDiff(camera);
}
}
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
if(anim->swing.unk_18)
{
eyeDiffSph.yaw = Camera_LERPCeilS(anim->swing.unk_16, eyeNextAtOffset.yaw, 1.0f / camera->yawUpdateRateInv, 0xA);
eyeDiffSph.pitch = Camera_LERPCeilS(anim->swing.unk_14, eyeNextAtOffset.pitch, 1.0f / camera->yawUpdateRateInv, 0xA);
}
else
{
eyeDiffSph.yaw = Camera_CalcDefaultYaw(camera, eyeNextAtOffset.yaw, camera->playerPosRot.rot.y, jump1->maxYawUpdate, 0.0f);
}
}
else
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeDiffSph.yaw = Camera_CalcControllerYaw(camera, eyeNextAtOffset.yaw, playerPosRot->rot.y, 0, 0.0f);
eyeDiffSph.pitch = Camera_CalcControllerPitch(camera, eyeNextAtOffset.pitch, 0, 0);
}
else if(anim->swing.unk_18)
{
eyeDiffSph.yaw = Camera_LERPCeilS(anim->swing.unk_16, eyeNextAtOffset.yaw, 1.0f / camera->yawUpdateRateInv, 0xA);
eyeDiffSph.pitch = Camera_LERPCeilS(anim->swing.unk_14, eyeNextAtOffset.pitch, 1.0f / camera->yawUpdateRateInv, 0xA);
}
else if(camera->startControlTimer <= 0)
{
eyeDiffSph.yaw = Camera_CalcDefaultYaw(camera, eyeNextAtOffset.yaw, camera->playerPosRot.rot.y, jump1->maxYawUpdate, 0.0f);
eyeDiffSph.pitch = Camera_LERPCeilS(eyeDiffTarget.pitch, eyeAtOffset.pitch, PCT(OREG(29)), 0xA);
@ -2789,7 +2777,7 @@ s32 Camera_Jump1(Camera* camera)
eyeNext->y += (newEye.y - eyeNext->y) * PCT(OREG(31));
if((camera->status == CAM_STAT_ACTIVE) && !(jump1->interfaceFlags & 0x10))
{
func_80046E20(camera, &eyeDiffSph, jump1->distMin, jump1->yawUpateRateTarget, &spA4, &anim->swing);
FollowPlayerWithCollision(camera, &eyeDiffSph, jump1->distMin, jump1->yawUpateRateTarget, &spA4, &anim->swing);
if(jump1->interfaceFlags & 4)
{
camera->inputDir.x = -eyeAtOffset.pitch;
@ -2947,7 +2935,22 @@ s32 Camera_Jump2(Camera* camera)
bgChkPos.y = playerPosRot->pos.y + (playerHeight * 2.2f);
bgChkPos.z = playerPosRot->pos.z + (Math_CosS(playerPosRot->rot.y) * 25.0f);
if(oot::config().camera().useClassicCamera())
if(!oot::config().camera().useClassicCamera())
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
adjAtToEyeDir.yaw = atToEyeNextDir.yaw + Camera_CalcControllerYawDiff(camera);
adjAtToEyeDir.pitch = atToEyeNextDir.pitch + Camera_CalcControllerPitchDiff(camera);
}
else if(camera->startControlTimer <= 0)
{
adjAtToEyeDir.yaw = Camera_CalcDefaultYaw(camera, atToEyeNextDir.yaw, playerPosRot->rot.y, 0, 0.0f);
adjAtToEyeDir.pitch = Camera_CalcDefaultPitch(camera, atToEyeNextDir.pitch, 0, 0);
}
}
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
sp90 = Camera_GetFloorYNorm(camera, &floorNorm, &bgChkPos, &bgId);
if((sp90 != BGCHECK_Y_MIN) && (playerPosRot->pos.y < sp90))
@ -2975,7 +2978,7 @@ s32 Camera_Jump2(Camera* camera)
{
anim->yawTarget = BINANG_ROT180(playerPosRot->rot.y);
anim->animTimer--;
adjAtToEyeDir.yaw = Camera_LERPCeilS(anim->yawTarget, atToEyeNextDir.yaw, 0.5f, 0xA);
adjAtToEyeDir.yaw = Camera_LERPCeilS(anim->yawTarget, atToEyeNextDir.yaw, 0.1f, 0xA);
}
else if(anim->yawAdj < ABS(yawDiff))
{
@ -2984,22 +2987,7 @@ s32 Camera_Jump2(Camera* camera)
}
else
{
adjAtToEyeDir.yaw = Camera_LERPCeilS(adjAtToEyeDir.yaw, atToEyeNextDir.yaw, 0.25f, 0xA);
}
}
else
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
adjAtToEyeDir.yaw = Camera_CalcControllerYaw(camera, atToEyeNextDir.yaw, playerPosRot->rot.y, 0, 0.0f);
adjAtToEyeDir.pitch = Camera_CalcControllerPitch(camera, atToEyeNextDir.pitch, 0, 0);
}
else if(camera->startControlTimer <= 0)
{
adjAtToEyeDir.yaw = Camera_CalcDefaultYaw(camera, atToEyeNextDir.yaw, playerPosRot->rot.y, 0, 0.0f);
adjAtToEyeDir.pitch = Camera_CalcDefaultPitch(camera, atToEyeNextDir.pitch, 0, 0);
adjAtToEyeDir.yaw = Camera_LERPCeilS(adjAtToEyeDir.yaw, atToEyeNextDir.yaw, 0.05f, 0xA);
}
}
@ -3210,7 +3198,17 @@ s32 Camera_Jump3(Camera* camera)
}
}
if(oot::config().camera().useClassicCamera())
if(!oot::config().camera().useClassicCamera())
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeDiffSph.yaw = eyeNextAtOffset.yaw + Camera_CalcControllerYawDiff(camera);
eyeDiffSph.pitch = eyeNextAtOffset.pitch + Camera_CalcControllerPitchDiff(camera);
}
}
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
if(anim->swing.unk_18 != 0)
{
@ -3223,26 +3221,6 @@ s32 Camera_Jump3(Camera* camera)
eyeDiffSph.pitch = Camera_CalcDefaultPitch(camera, eyeNextAtOffset.pitch, jump3->pitchTarget, 0);
}
}
else
{
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeDiffSph.yaw = Camera_CalcControllerYaw(camera, eyeNextAtOffset.yaw, playerPosRot->rot.y, jump3->unk_14, 0.0f);
eyeDiffSph.pitch = Camera_CalcControllerPitch(camera, eyeNextAtOffset.pitch, jump3->pitchTarget, 0);
}
else if(anim->swing.unk_18 != 0)
{
eyeDiffSph.yaw = Camera_LERPCeilS(anim->swing.unk_16, eyeNextAtOffset.yaw, 1.0f / camera->yawUpdateRateInv, 0xA);
eyeDiffSph.pitch = Camera_LERPCeilS(anim->swing.unk_14, eyeNextAtOffset.pitch, 1.0f / camera->yawUpdateRateInv, 0xA);
}
else if(camera->startControlTimer <= 0)
{
eyeDiffSph.yaw = Camera_CalcDefaultYaw(camera, eyeNextAtOffset.yaw, playerPosRot->rot.y, jump3->unk_14, 0.0f);
eyeDiffSph.pitch = Camera_CalcDefaultPitch(camera, eyeNextAtOffset.pitch, jump3->pitchTarget, 0);
}
}
if(eyeDiffSph.pitch > R_CAM_MAX_PHI)
{
@ -3257,7 +3235,7 @@ s32 Camera_Jump3(Camera* camera)
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeDiffSph);
if((camera->status == CAM_STAT_ACTIVE) && !(jump3->interfaceFlags & 0x10))
{
func_80046E20(camera, &eyeDiffSph, jump3->distMin, jump3->swingUpdateRate, &spBC, &anim->swing);
FollowPlayerWithCollision(camera, &eyeDiffSph, jump3->distMin, jump3->swingUpdateRate, &spBC, &anim->swing);
if(jump3->interfaceFlags & 4)
{
camera->inputDir.x = -eyeAtOffset.pitch;
@ -3290,11 +3268,13 @@ s32 Camera_Jump3(Camera* camera)
return true;
}
//noop
s32 Camera_Jump4(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Jump0(Camera* camera)
{
return Camera_Noop(camera);
@ -3584,11 +3564,13 @@ s32 Camera_Battle1(Camera* camera)
return 0;
}
//noop
s32 Camera_Battle2(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Battle3(Camera* camera)
{
return Camera_Noop(camera);
@ -3611,6 +3593,7 @@ s32 Camera_BattleChargeSpinAttack(Camera* camera)
Battle4Anim* anim = &batt4->anim;
s32 pad;
f32 playerHeight;
PosRot* playerPosRot = &camera->playerPosRot;
playerHeight = Player_GetHeight(camera->player);
if(RELOAD_PARAMS)
@ -3653,18 +3636,34 @@ s32 Camera_BattleChargeSpinAttack(Camera* camera)
camera->yOffsetUpdateRate = Camera_LERPCeilF(PCT(OREG(3)), camera->yOffsetUpdateRate, PCT(OREG(26)) * camera->speedRatio, 0.1f);
camera->fovUpdateRate = 0.0001f;
Camera_CalcAtDefault(camera, &eyeNextAtOffset, batt4->yOffset, 1);
if(anim->animTimer != 0)
if(!oot::config().camera().useClassicCamera())
{
eyeNextOffset.yaw = eyeAtOffset.yaw;
eyeNextOffset.pitch = eyeAtOffset.pitch;
eyeNextOffset.r = eyeAtOffset.r;
anim->animTimer--;
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeNextOffset.yaw = eyeAtOffset.yaw + Camera_CalcControllerYawDiff(camera);
eyeNextOffset.pitch = eyeAtOffset.pitch + Camera_CalcControllerPitchDiff(camera);
eyeNextOffset.r = eyeAtOffset.r;
}
}
else
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
eyeNextOffset.yaw = eyeAtOffset.yaw;
eyeNextOffset.pitch = Camera_LERPCeilS(batt4->pitchTarget, eyeAtOffset.pitch, batt4->lerpUpdateRate, 2);
eyeNextOffset.r = Camera_LERPCeilF(batt4->rTarget, eyeAtOffset.r, batt4->lerpUpdateRate, 0.001f);
if(anim->animTimer != 0)
{
eyeNextOffset.yaw = eyeAtOffset.yaw;
eyeNextOffset.pitch = eyeAtOffset.pitch;
eyeNextOffset.r = eyeAtOffset.r;
anim->animTimer--;
}
else
{
eyeNextOffset.yaw = eyeAtOffset.yaw;
eyeNextOffset.pitch = Camera_LERPCeilS(batt4->pitchTarget, eyeAtOffset.pitch, batt4->lerpUpdateRate, 2);
eyeNextOffset.r = Camera_LERPCeilF(batt4->rTarget, eyeAtOffset.r, batt4->lerpUpdateRate, 0.001f);
}
}
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeNextOffset);
*eye = *eyeNext;
@ -3675,12 +3674,13 @@ s32 Camera_BattleChargeSpinAttack(Camera* camera)
return true;
}
//noop
s32 Camera_Battle0(Camera* camera)
{
return Camera_Noop(camera);
}
// Targeting non-enemy
//z targeting non-enemy
s32 Camera_KeepOn1(Camera* camera)
{
Vec3f* eye = &camera->eye;
@ -3762,7 +3762,7 @@ s32 Camera_KeepOn1(Camera* camera)
camera->animState++;
anim->unk_10 = 0;
anim->unk_04 = 0.0f;
anim->unk_0C = camera->target;
anim->currentTarget = camera->target;
anim->unk_16 = R_DEFA_CAM_ANIM_TIME + OREG(24);
anim->unk_12 = spC0.yaw;
anim->unk_14 = spC0.pitch;
@ -3797,9 +3797,9 @@ s32 Camera_KeepOn1(Camera* camera)
Actor_GetFocus(&camera->targetPosRot, camera->target);
}
Actor_GetFocus(&camera->targetPosRot, camera->target);
if(anim->unk_0C != camera->target)
if(anim->currentTarget != camera->target)
{
anim->unk_0C = camera->target;
anim->currentTarget = camera->target;
camera->atLERPStepScale = 0.0f;
}
camera->xzOffsetUpdateRate = Camera_LERPCeilF(1.0f, camera->xzOffsetUpdateRate, PCT(OREG(25)) * camera->speedRatio, 0.1f);
@ -3807,7 +3807,7 @@ s32 Camera_KeepOn1(Camera* camera)
camera->fovUpdateRate = Camera_LERPCeilF(PCT(OREG(4)), camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.1f);
goto cont;
case 0x10:
anim->unk_0C = NULL;
anim->currentTarget = NULL;
cont:
if(camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || camera->player->stateFlags1 & PLAYER_STATE1_21)
{
@ -3828,7 +3828,7 @@ s32 Camera_KeepOn1(Camera* camera)
default:
*at = playerPosRot->pos;
at->y += playerHeight;
anim->unk_0C = NULL;
anim->currentTarget = NULL;
break;
}
OLib_Vec3fDiffToVecSphGeo(&spD8, at, eyeNext);
@ -4913,16 +4913,19 @@ s32 Camera_Fixed4(Camera* camera)
return true;
}
//noop
s32 Camera_Fixed0(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Subj1(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Subj2(Camera* camera)
{
return Camera_Noop(camera);
@ -5208,27 +5211,32 @@ s32 Camera_Subj4(Camera* camera)
return 1;
}
//noop
s32 Camera_Subj0(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Data0(Camera* camera)
{
return Camera_Noop(camera);
}
//normal1 data?
s32 Camera_Data1(Camera* camera)
{
osSyncPrintf("chau!chau!\n");
return Camera_Normal1(camera);
}
//noop
s32 Camera_Data2(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Data3(Camera* camera)
{
return Camera_Noop(camera);
@ -5311,7 +5319,7 @@ s32 Camera_Data4(Camera* camera)
}
/**
* Hanging off of a ledge
* Hanging off of a ledge/climbing ledge
*/
s32 Camera_Unique1(Camera* camera)
{
@ -5319,11 +5327,10 @@ s32 Camera_Unique1(Camera* camera)
Vec3f* at = &camera->at;
Vec3f* eyeNext = &camera->eyeNext;
Vec3f playerBodyPart0;
s16 phiTarget;
VecSph sp8C;
VecSph unk908PlayerPosOffset;
VecSph eyeNextOffset;
VecSph PlayerPosOffset;
VecSph eyeAtOffset;
VecSph eyeNextAtOffset;
VecSph eyeAtNextOffset;
PosRot* playerPosRot = &camera->playerPosRot;
PosRot playerhead;
Unique1* uniq1 = (Unique1*)camera->paramData;
@ -5354,19 +5361,19 @@ s32 Camera_Unique1(Camera* camera)
sUpdateCameraDirection = 1;
OLib_Vec3fDiffToVecSphGeo(&eyeAtOffset, at, eye);
OLib_Vec3fDiffToVecSphGeo(&eyeNextAtOffset, at, eyeNext);
OLib_Vec3fDiffToVecSphGeo(&eyeAtNextOffset, at, eyeNext);
sCameraInterfaceFlags = uniq1->interfaceFlags;
if(camera->animState == 0)
{
camera->posOffset.y = camera->posOffset.y - camera->playerPosDelta.y;
anim->yawTarget = eyeNextAtOffset.yaw;
anim->yawTarget = eyeAtNextOffset.yaw;
anim->unk_00 = 0.0f;
playerBodyPart0 = camera->player->bodyPartsPos[0];
OLib_Vec3fDiffToVecSphGeo(&unk908PlayerPosOffset, &playerPosRot->pos, &playerBodyPart0);
OLib_Vec3fDiffToVecSphGeo(&PlayerPosOffset, &playerPosRot->pos, &playerBodyPart0);
anim->timer = R_DEFA_CAM_ANIM_TIME;
anim->yawTargetAdj = ABS(BINANG_SUB(unk908PlayerPosOffset.yaw, eyeAtOffset.yaw)) < 0x3A98 ? 0 : ((BINANG_SUB(unk908PlayerPosOffset.yaw, eyeAtOffset.yaw) / anim->timer) / 4) * 3;
anim->yawTargetAdj = ABS(BINANG_SUB(PlayerPosOffset.yaw, eyeAtOffset.yaw)) < 0x3A98 ? 0 : ((BINANG_SUB(PlayerPosOffset.yaw, eyeAtOffset.yaw) / anim->timer) / 4) * 3;
camera->animState++;
}
@ -5378,31 +5385,52 @@ s32 Camera_Unique1(Camera* camera)
camera->yOffsetUpdateRate = Camera_LERPCeilF(0.01f, camera->yOffsetUpdateRate, OREG(26) * 0.01f, 0.01f);
camera->fovUpdateRate = Camera_LERPCeilF(OREG(4) * 0.01f, camera->fovUpdateRate, 0.05f, 0.1f);
Camera_CalcAtDefault(camera, &eyeNextAtOffset, uniq1->yOffset, 1);
OLib_Vec3fDiffToVecSphGeo(&sp8C, at, eyeNext);
camera->dist = Camera_LERPClampDist(camera, sp8C.r, uniq1->distMin, uniq1->distMax);
phiTarget = uniq1->pitchTarget;
sp8C.pitch = Camera_LERPCeilS(phiTarget, eyeNextAtOffset.pitch, 1.0f / camera->pitchUpdateRateInv, 0xA);
if(sp8C.pitch > R_CAM_MAX_PHI)
Camera_CalcAtDefault(camera, &eyeAtNextOffset, uniq1->yOffset, 1);
OLib_Vec3fDiffToVecSphGeo(&eyeNextOffset, at, eye);
if(!oot::config().camera().useClassicCamera())
{
sp8C.pitch = R_CAM_MAX_PHI;
}
if(sp8C.pitch < -R_CAM_MAX_PHI)
{
sp8C.pitch = -R_CAM_MAX_PHI;
}
eyeNextOffset.r = Camera_LERPCeilF(184.0f, eyeAtNextOffset.r, camera->xzOffsetUpdateRate, 0xA);
if(anim->timer != 0)
{
anim->yawTarget += anim->yawTargetAdj;
anim->timer--;
const oot::hid::Controller& controller = oot::player(0).controller();
StepControlTimer(camera);
if(camera->startControlTimer > 0 || controller.state().r_stick_x != 0 || controller.state().r_stick_y != 0)
{
eyeNextOffset.yaw = eyeAtNextOffset.yaw + Camera_CalcControllerYawDiff(camera);
eyeNextOffset.pitch = eyeAtNextOffset.pitch + Camera_CalcControllerPitchDiff(camera);
}
if(eyeNextOffset.pitch > 0x2AF8)
{
eyeNextOffset.pitch = 0x2AF8;
}
if(eyeNextOffset.pitch < -0x2AF8)
{
eyeNextOffset.pitch = -0x2AF8;
}
}
if(oot::config().camera().useClassicCamera() || camera->startControlTimer <= 0)
{
camera->dist = Camera_LERPClampDist(camera, eyeNextOffset.r, uniq1->distMin, uniq1->distMax);
eyeNextOffset.pitch = Camera_LERPCeilS(uniq1->pitchTarget, eyeAtNextOffset.pitch, 1.0f / camera->pitchUpdateRateInv, 0xA);
sp8C.yaw = Camera_LERPFloorS(anim->yawTarget, eyeNextAtOffset.yaw, 0.5f, 0x2710);
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &sp8C);
if(eyeNextOffset.pitch > R_CAM_MAX_PHI)
{
eyeNextOffset.pitch = R_CAM_MAX_PHI;
}
if(eyeNextOffset.pitch < -R_CAM_MAX_PHI)
{
eyeNextOffset.pitch = -R_CAM_MAX_PHI;
}
if(anim->timer != 0)
{
anim->yawTarget += anim->yawTargetAdj;
anim->timer--;
}
eyeNextOffset.yaw = Camera_LERPFloorS(anim->yawTarget, eyeAtNextOffset.yaw, 0.1f, 0xA);
}
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeNextOffset);
*eye = *eyeNext;
Camera_BGCheck(camera, at, eye);
camera->fov = Camera_LERPCeilF(uniq1->fovTarget, camera->fov, camera->fovUpdateRate, 1.0f);
@ -5885,6 +5913,7 @@ s32 Camera_Unique7(Camera* camera)
return true;
}
//noop
s32 Camera_Unique8(Camera* camera)
{
return Camera_Noop(camera);
@ -6589,6 +6618,7 @@ s32 Camera_Demo1(Camera* camera)
return true;
}
//noop
s32 Camera_Demo2(Camera* camera)
{
return Camera_Noop(camera);
@ -6680,7 +6710,9 @@ s32 Camera_Demo3(Camera* camera)
eyeOffset.r = D_8011D658[0].r;
eyeOffset.pitch = D_8011D658[0].pitch;
eyeOffset.yaw = (D_8011D658[0].yaw * anim->yawDir) + camPlayerPosRot->rot.y;
anim->unk_0C = 1.0f;
anim->stepScale = 1.0f;
camera->animState = 0xA;
break;
case 1:
temp_f0 = (anim->animFrame - 2) * (1.0f / 146.0f);
@ -6701,7 +6733,7 @@ s32 Camera_Demo3(Camera* camera)
eyeOffset.pitch = atOffset.pitch;
eyeOffset.yaw = (atOffset.yaw * anim->yawDir) + camPlayerPosRot->rot.y;
anim->unk_0C -= (1.0f / 365.0f);
anim->stepScale -= (1.0f / 365.0f);
break;
case 2:
temp_f0 = (anim->animFrame - 0x94) * 0.1f;
@ -6722,7 +6754,7 @@ s32 Camera_Demo3(Camera* camera)
eyeOffset.r = atOffset.r;
eyeOffset.pitch = atOffset.pitch;
eyeOffset.yaw = (atOffset.yaw * anim->yawDir) + camPlayerPosRot->rot.y;
anim->unk_0C -= 0.04f;
anim->stepScale -= 0.04f;
break;
case 3:
temp_f0 = (anim->animFrame - 0x9F) * (1.0f / 9.0f);
@ -6743,7 +6775,7 @@ s32 Camera_Demo3(Camera* camera)
eyeOffset.r = atOffset.r;
eyeOffset.pitch = atOffset.pitch;
eyeOffset.yaw = (atOffset.yaw * anim->yawDir) + camPlayerPosRot->rot.y;
anim->unk_0C += (4.0f / 45.0f);
anim->stepScale += (4.0f / 45.0f);
break;
case 30:
camera->unk_14C |= 0x400;
@ -6759,7 +6791,7 @@ s32 Camera_Demo3(Camera* camera)
eyeOffset.r = 80.0f;
eyeOffset.pitch = 0;
eyeOffset.yaw = eyeAtOffset.yaw;
anim->unk_0C = 0.1f;
anim->stepScale = 0.1f;
sCameraInterfaceFlags = 0x3400;
if(!((anim->animFrame < 0 || camera->xzSpeed > 0.001f || CHECK_BTN_ALL(globalCtxAlt->input[0].press.button, BTN_A) || CHECK_BTN_ALL(globalCtxAlt->input[0].press.button, BTN_B) ||
@ -6790,11 +6822,7 @@ s32 Camera_Demo3(Camera* camera)
anim->animFrame++;
if(anim->animFrame == 1)
{
camera->animState = 0xA;
}
else if(anim->animFrame == 2)
if(anim->animFrame == 2)
{
camera->animState = 0x1;
}
@ -6821,9 +6849,9 @@ s32 Camera_Demo3(Camera* camera)
if(!skipUpdateEye)
{
eyeOffset.r = Camera_LERPCeilF(eyeOffset.r, eyeAtOffset.r, anim->unk_0C, 2.0f);
eyeOffset.pitch = Camera_LERPCeilS(eyeOffset.pitch, eyeAtOffset.pitch, anim->unk_0C, 0xA);
eyeOffset.yaw = Camera_LERPCeilS(eyeOffset.yaw, eyeAtOffset.yaw, anim->unk_0C, 0xA);
eyeOffset.r = Camera_LERPCeilF(eyeOffset.r, eyeAtOffset.r, anim->stepScale, 2.0f);
eyeOffset.pitch = Camera_LERPCeilS(eyeOffset.pitch, eyeAtOffset.pitch, anim->stepScale, 0xA);
eyeOffset.yaw = Camera_LERPCeilS(eyeOffset.yaw, eyeAtOffset.yaw, anim->stepScale, 0xA);
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeOffset);
*eye = *eyeNext;
}
@ -6836,6 +6864,7 @@ s32 Camera_Demo3(Camera* camera)
return true;
}
//noop
s32 Camera_Demo4(Camera* camera)
{
return Camera_Noop(camera);
@ -7241,6 +7270,7 @@ s32 Camera_Demo7(Camera* camera)
return 0;
}
//noop
s32 Camera_Demo8(Camera* camera)
{
return Camera_Noop(camera);
@ -7412,6 +7442,7 @@ s32 Camera_Demo9(Camera* camera)
return true;
}
//noop
s32 Camera_Demo0(Camera* camera)
{
return Camera_Noop(camera);
@ -7467,16 +7498,19 @@ s32 Camera_Special0(Camera* camera)
return true;
}
//noop
s32 Camera_Special1(Camera* camera)
{
return Camera_Noop(camera);
}
//noop
s32 Camera_Special2(Camera* camera)
{
return Camera_Unique2(camera);
}
//noop
s32 Camera_Special3(Camera* camera)
{
return Camera_Noop(camera);
@ -7798,11 +7832,13 @@ s32 Camera_Special6(Camera* camera)
return true;
}
//noop
s32 Camera_Special8(Camera* camera)
{
return Camera_Noop(camera);
}
//walking through a door camera
s32 Camera_Special9(Camera* camera)
{
s32 pad;
@ -7917,9 +7953,9 @@ s32 Camera_Special9(Camera* camera)
spAC = playerPosRot->pos;
spAC.y += (playerYOffset + params->yOffset);
Camera_LERPCeilVec3f(&spAC, at, 0.5f, 0.5f, 0.1f);
eyeAdjustment.pitch = Camera_LERPCeilS(0xAAA, atEyeOffsetGeo.pitch, 0.3f, 0xA);
eyeAdjustment.yaw = Camera_LERPCeilS(anim->targetYaw, atEyeOffsetGeo.yaw, 0.3f, 0xA);
eyeAdjustment.r = Camera_LERPCeilF(60.0f, atEyeOffsetGeo.r, 0.3f, 1.0f);
eyeAdjustment.pitch = Camera_LERPCeilS(0xAAA, atEyeOffsetGeo.pitch, 0.3f / FRAMERATE_SCALER_INV, 0xA);
eyeAdjustment.yaw = Camera_LERPCeilS(anim->targetYaw, atEyeOffsetGeo.yaw, 0.3f / FRAMERATE_SCALER_INV, 0xA);
eyeAdjustment.r = Camera_LERPCeilF(60.0f, atEyeOffsetGeo.r, 0.3f / FRAMERATE_SCALER_INV, 1.0f);
Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeAdjustment);
*eye = *eyeNext;
spec9->doorParams.timer3--;

View File

@ -179,9 +179,8 @@ void Effect_Add(GlobalContext* globalCtx, s32* pIndex, s32 type, u8 arg3, u8 arg
if(!slotFound)
{
// "EffectAdd(): I cannot secure it. Be careful. Type %d"
osSyncPrintf("EffectAdd():確保できません。注意してください。Type%d\n", type);
osSyncPrintf("エフェクト追加せずに終了します。\n"); // "Exit without adding the effect."
osSyncPrintf("EffectAdd():Cannot be secured. Be careful. Type%d\n", type);
osSyncPrintf("Exit without adding effects.\n");
}
else
{
@ -295,7 +294,7 @@ void Effect_DeleteAll(GlobalContext* globalCtx)
{
s32 i;
osSyncPrintf("エフェクト総て解放\n"); // "All effect release"
osSyncPrintf("Release all effects Begin\n");
for(i = 0; i < SPARK_COUNT; i++)
{
@ -315,5 +314,5 @@ void Effect_DeleteAll(GlobalContext* globalCtx)
sEffectInfoTable[EFFECT_SHIELD_PARTICLE].destroy(&sEffectContext.shieldParticles[i].effect);
}
osSyncPrintf("エフェクト総て解放 終了\n"); // "All effects release End"
osSyncPrintf("Release all effects End\n");
}

View File

@ -211,21 +211,20 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
overlayEntry = &gEffectSsOverlayTable[type];
ASSERT(type < EFFECT_SS_TYPE_MAX, "type < EFFECT_SS2_TYPE_LAST_LABEL", "../z_effect_soft_sprite.c", 556);
if(EffectSs_FindSlot(priority, &index) != 0)
{
// Abort because we couldn't find a suitable slot to add this effect in
return;
}
ASSERT(type < EFFECT_SS_TYPE_MAX, "type < EFFECT_SS2_TYPE_LAST_LABEL", "../z_effect_soft_sprite.c", 556);
sEffectSsInfo.searchStartIndex = index + 1;
overlaySize = POINTER_SUB(overlayEntry->vramEnd, overlayEntry->vramStart);
if(overlayEntry->vramStart == NULL)
{
// "Not an overlay"
osSyncPrintf("EffectSoftSprite2_makeEffect():オーバーレイではありません。\n");
osSyncPrintf("EffectSoftSprite2_makeEffect(): Not an overlay\n");
initInfo = overlayEntry->initInfo;
}
else
@ -237,13 +236,10 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
if(overlayEntry->loadedRamAddr == NULL)
{
osSyncPrintf(VT_FGCOL(RED));
// "The memory of %d byte cannot be secured. Therefore, the program cannot be loaded.
// What a dangerous situation! Naturally, effects will not produced either."
osSyncPrintf(
"EffectSoftSprite2_makeEffect():zelda_malloc_r()により,%"
"dbyteのメモリ確保ができま\nせん。そのため、プログラムのロードも\n出来ません。ただいま危険"
"な状態です!\nもちろん,エフェクトも出ません。\n",
overlaySize);
"EffectSoftSprite2_makeEffect():zelda_malloc_r() The memory of %d byte cannot be secured. Therefore, the program cannot be loaded.\
What a dangerous situation! Naturally, effects will not produced either.\n",
overlaySize);
osSyncPrintf(VT_RST);
return;
}
@ -258,12 +254,10 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
if(initInfo->init == NULL)
{
// "Effects have already been loaded, but the constructor is NULL so the addition will not occur.
// Please fix this. (Waste of memory) %08x %d"
osSyncPrintf(
"EffectSoftSprite2_makeEffect():すでにエフェクトはロード済みで\nすが,"
"コンストラクターがNULLなので追加をやめます。\n直してください。(メモリーの無駄) %08x %d\n",
initInfo, type);
"EffectSoftSprite2_makeEffect():Effects have already been loaded, but the constructor is NULL so the addition will not occur.\n"
"Please fix this. (Waste of memory) %08x %d",
initInfo, type);
return;
}
@ -276,11 +270,9 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
if(initInfo->init(globalCtx, index, &sEffectSsInfo.table[index], initParams) == 0)
{
osSyncPrintf(VT_FGCOL(GREEN));
// "Construction failed for some reason. The constructor returned an error.
// Ceasing effect addition."
osSyncPrintf("EffectSoftSprite2_makeEffect():"
"何らかの理由でコンストラクト失敗。コンストラクターがエラーを返しました。エフェクトの追加を中"
"止します。\n");
osSyncPrintf("EffectSoftSprite2_makeEffect():\
Construction failed for some reason. The constructor returned an error.\
Ceasing effect addition.\n");
osSyncPrintf(VT_RST);
EffectSs_Reset(&sEffectSsInfo.table[index]);
}
@ -289,7 +281,7 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
void EffectSs_Update(GlobalContext* globalCtx, s32 index)
{
EffectSs* effectSs = &sEffectSsInfo.table[index];
if(effectSs->update != NULL)
{
effectSs->velocity.x += effectSs->accel.x;
@ -322,7 +314,7 @@ void EffectSs_UpdateAll(GlobalContext* globalCtx)
if(sEffectSsInfo.table[i].life > -1)
{
EffectSs_Update(globalCtx, i);
EffectSs_Update(globalCtx, i);
}
}
}
@ -342,7 +334,7 @@ void EffectSs_Draw(GlobalContext* globalCtx, s32 index)
void EffectSs_DrawAll(GlobalContext* globalCtx)
{
Lights* lights = LightContext_NewLights(&globalCtx->lightCtx, globalCtx->gfxCtx);
s32 i;
s32 i;
Lights_BindAll(lights, globalCtx->lightCtx.listHead, NULL);
Lights_Draw(lights, globalCtx->gfxCtx);
@ -355,17 +347,13 @@ void EffectSs_DrawAll(GlobalContext* globalCtx)
(sEffectSsInfo.table[i].pos.z < -32000.0f))
{
osSyncPrintf(VT_FGCOL(RED));
// "Since the position is outside the area, delete it.
// Effect label No. %d: Please respond by the program.
// Here is ==> pos (%f, %f, %f) and the label is in z_effect_soft_sprite_dlftbls.decl."
osSyncPrintf(
"EffectSoftSprite2_disp():位置が領域外のため "
"削除します。エフェクトラベルNo.%d:プログラムの方で対応をお願いします。ここです ==> "
"pos(%f, %f, %f)で、ラベルはz_effect_soft_sprite_dlftbls.declにあります。\n",
"EffectSoftSprite2_disp():Since the position is outside the area, delete it.\
Effect label No. %d: Please respond by the program.\
Here is ==> pos (%f, %f, %f) and the label is in z_effect_soft_sprite_dlftbls.decl.\n",
sEffectSsInfo.table[i].type, sEffectSsInfo.table[i].pos.x, sEffectSsInfo.table[i].pos.y, sEffectSsInfo.table[i].pos.z);
osSyncPrintf(VT_FGCOL(GREEN));
// "If you are using pos for something else, consult me."
osSyncPrintf("もし、posを別のことに使っている場合相談に応じます。\n");
osSyncPrintf("If you are using pos for something else, consult me.\n");
osSyncPrintf(VT_RST);
EffectSs_Delete(&sEffectSsInfo.table[i]);

View File

@ -255,7 +255,7 @@ f32 gLensFlareColorIntensity;
s16 gLensFlareScreenFillAlpha;
LightningBolt sLightningBolts[3];
LightningStrike gLightningStrike;
s16 sLightningFlashAlpha;
TimerS16 sLightningFlashAlpha;
s16 gSunScreenPosX;
s16 gSunScreenPosY;
LightNode* sNGameOverLightNode;
@ -263,7 +263,7 @@ LightInfo sNGameOverLightInfo;
LightNode* sSGameOverLightNode;
LightInfo sSGameOverLightInfo;
u8 sGameOverLightsIntensity;
u16 D_8015FDB0;
TimerU16 ScrollingMulitplier;
s32 func_8006F0A0(s32 a0)
{
@ -328,9 +328,9 @@ void Environment_Init(GlobalContext* globalCtx2, EnvironmentContext* envCtx, s32
envCtx->unk_D8 = 1.0f;
envCtx->unk_DC = 0;
envCtx->gloomySkyMode = 0;
envCtx->unk_DE = 0;
envCtx->skyState = 0;
envCtx->lightningMode = LIGHTNING_MODE_OFF;
envCtx->unk_E0 = 0;
envCtx->dayState = 0;
envCtx->fillScreen = false;
envCtx->screenFillColor[0] = 0;
envCtx->screenFillColor[1] = 0;
@ -613,7 +613,7 @@ f32 Environment_LerpWeightAccelDecel(u16 endFrame, u16 startFrame, u16 curFrame,
f32 totalFrames;
f32 temp;
f32 framesElapsed;
f32 ret;
TimerF32 ret;
if(curFrame <= startFrame)
{
@ -681,7 +681,7 @@ void func_8006FB94(EnvironmentContext* envCtx, u8 unused)
{
if(envCtx->gloomySkyMode != 0)
{
switch(envCtx->unk_DE)
switch(envCtx->skyState)
{
case 0:
if((envCtx->gloomySkyMode == 1) && !gSkyboxBlendingEnabled)
@ -695,7 +695,7 @@ void func_8006FB94(EnvironmentContext* envCtx, u8 unused)
envCtx->unk_20 = 2;
D_8011FB34 = 2;
envCtx->unk_22 = envCtx->unk_24 = 100;
envCtx->unk_DE++;
envCtx->skyState++;
}
break;
case 1:
@ -713,7 +713,7 @@ void func_8006FB94(EnvironmentContext* envCtx, u8 unused)
envCtx->unk_22 = envCtx->unk_24 = 100;
envCtx->unk_EE[0] = 0;
envCtx->gloomySkyMode = 0;
envCtx->unk_DE = 0;
envCtx->skyState = 0;
}
break;
}
@ -2137,7 +2137,7 @@ void Environment_DrawLightning(GlobalContext* globalCtx, s32 unused)
void func_800758AC(GlobalContext* globalCtx)
{
globalCtx->envCtx.unk_E0 = 0xFF;
globalCtx->envCtx.dayState = 0xFF;
// both lost woods exits on the bridge from kokiri to hyrule field
if(((void)0, gSaveContext.entranceIndex) == 0x4DE || ((void)0, gSaveContext.entranceIndex) == 0x5E0)
@ -2179,7 +2179,7 @@ void func_800758AC(GlobalContext* globalCtx)
Audio_PlaySequence(globalCtx->sequenceCtx.seqId);
}
globalCtx->envCtx.unk_E0 = 1;
globalCtx->envCtx.dayState = 1;
}
else
{
@ -2190,15 +2190,15 @@ void func_800758AC(GlobalContext* globalCtx)
if(((void)0, gSaveContext.dayTime) > 0xB71C && ((void)0, gSaveContext.dayTime) < 0xCAAC)
{
globalCtx->envCtx.unk_E0 = 3;
globalCtx->envCtx.dayState = 3;
}
else if(((void)0, gSaveContext.dayTime) > 0xCAAC || ((void)0, gSaveContext.dayTime) < 0x4555)
{
globalCtx->envCtx.unk_E0 = 5;
globalCtx->envCtx.dayState = 5;
}
else
{
globalCtx->envCtx.unk_E0 = 7;
globalCtx->envCtx.dayState = 7;
}
}
@ -2206,7 +2206,7 @@ void func_800758AC(GlobalContext* globalCtx)
osSyncPrintf("\n Forced BGM=[%d]", ((void)0, gSaveContext.forcedSeqId)); // "Forced BGM"
osSyncPrintf("\n BGM=[%d]", globalCtx->sequenceCtx.seqId);
osSyncPrintf("\n Ambience=[%d]", globalCtx->sequenceCtx.natureAmbienceId);
osSyncPrintf("\n status=[%d]", globalCtx->envCtx.unk_E0);
osSyncPrintf("\n status=[%d]", globalCtx->envCtx.dayState);
Audio_SetEnvReverb(globalCtx->roomCtx.curRoom.echo);
}
@ -2214,7 +2214,7 @@ void func_800758AC(GlobalContext* globalCtx)
// updates bgm/sfx and other things as the day progresses
void func_80075B44(GlobalContext* globalCtx)
{
switch(globalCtx->envCtx.unk_E0)
switch(globalCtx->envCtx.dayState)
{
case 0:
func_800F6D58(86, 1, 0);
@ -2223,7 +2223,7 @@ void func_80075B44(GlobalContext* globalCtx)
osSyncPrintf("\n\n\nNa_StartMorinigBgm\n\n");
Audio_PlaySequence2(globalCtx->sequenceCtx.seqId);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
break;
case 1:
if(gSaveContext.dayTime > 0xB71C)
@ -2232,14 +2232,14 @@ void func_80075B44(GlobalContext* globalCtx)
{
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xF000FF);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
}
break;
case 2:
if(gSaveContext.dayTime > 0xC000)
{
Common_PlaySfx2(NA_SE_EV_DOG_CRY_EVENING);
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
}
break;
case 3:
@ -2248,12 +2248,12 @@ void func_80075B44(GlobalContext* globalCtx)
func_800F6FB4(globalCtx->sequenceCtx.natureAmbienceId);
func_800F6D58(1, 1, 1);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
break;
case 4:
if(gSaveContext.dayTime > 0xCAAB)
{
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
}
break;
case 5:
@ -2262,7 +2262,7 @@ void func_80075B44(GlobalContext* globalCtx)
{
func_800F6D58(36, 1, 1);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
break;
case 6:
if((gSaveContext.dayTime < 0xCAAC) && (gSaveContext.dayTime > 0x4555))
@ -2275,7 +2275,7 @@ void func_80075B44(GlobalContext* globalCtx)
{
Message_StartTextbox(globalCtx, 0x3066, NULL);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
}
break;
case 7:
@ -2284,12 +2284,12 @@ void func_80075B44(GlobalContext* globalCtx)
{
func_800F6D58(86, 1, 1);
}
globalCtx->envCtx.unk_E0++;
globalCtx->envCtx.dayState++;
break;
case 8:
if(gSaveContext.dayTime > 0x4AAB)
{
globalCtx->envCtx.unk_E0 = 0;
globalCtx->envCtx.dayState = 0;
}
break;
}
@ -2619,10 +2619,11 @@ void Environment_DrawSandstorm(GlobalContext* globalCtx, u8 sandstormState)
envColor.g = ((envColor.g * sp98) + ((6.0f - sp98) * primColor.g)) * (1.0f / 6.0f);
envColor.b = ((envColor.b * sp98) + ((6.0f - sp98) * primColor.b)) * (1.0f / 6.0f);
sp96 = (s32)(D_8015FDB0 * (11.0f / 6.0f));
sp94 = (s32)(D_8015FDB0 * (9.0f / 6.0f));
sp92 = (s32)(D_8015FDB0 * (6.0f / 6.0f));
sp96 = (s32)(ScrollingMulitplier * (11.0f / 6.0f));
sp94 = (s32)(ScrollingMulitplier * (9.0f / 6.0f));
sp92 = (s32)(ScrollingMulitplier * (6.0f / 6.0f));
//onscreen sand storm texture
OPEN_DISPS(globalCtx->gfxCtx, "../z_kankyo.c", 4044);
POLY_XLU_DISP = func_80093F34(POLY_XLU_DISP);
@ -2636,7 +2637,7 @@ void Environment_DrawSandstorm(GlobalContext* globalCtx, u8 sandstormState)
CLOSE_DISPS(globalCtx->gfxCtx, "../z_kankyo.c", 4068);
D_8015FDB0 += (s32)sp98;
ScrollingMulitplier += (s32)sp98;
}
void Environment_AdjustLights(GlobalContext* globalCtx, f32 arg1, f32 arg2, f32 arg3, f32 arg4)

View File

@ -33,6 +33,14 @@ f32 Math_SinS(s16 angle)
return sins(angle) * SHT_MINV;
}
f32 Math_AccurateCosS(s16 angle)
{
return cosf(DEG_TO_RAD((f32)(angle & 0xFFFC) / SHT_MAX) * 180.0f);
}
f32 Math_AccurateSinS(s16 angle)
{
return sinf(DEG_TO_RAD((f32)(angle & 0xFFFC) / SHT_MAX) * 180.0f);
}
/**
* Changes pValue by step (scaled by the update rate) towards target, setting it equal when the target is reached.
* Returns true when target is reached, false otherwise.
@ -434,6 +442,13 @@ void Math_Vec3f_Copy(Vec3f* dest, Vec3f* src)
dest->z = src->z;
}
void Math_VecPos_Copy(VecPos* dest, Vec3f* src)
{
dest->x = src->x;
dest->y = src->y;
dest->z = src->z;
}
void Math_Vec3s_ToVec3f(Vec3f* dest, Vec3s* src)
{
dest->x = src->x;
@ -621,7 +636,9 @@ static inline f32 _Math_SmoothStepToF(T* pValue, f32 target, f32 fraction, const
float minStep = _minStep.value();
if(*pValue != target)
{
f32 stepSize = (target - *pValue) * (fraction);
if(fraction != 1.0f)
fraction = fraction * FRAMERATE_SCALER;
f32 stepSize = (target - *pValue) * fraction;
if((stepSize >= minStep) || (stepSize <= -minStep))
{
@ -713,6 +730,11 @@ void Math_ApproachF(CounterF* pValue, f32 target, f32 fraction, const Step& _ste
_Math_ApproachF(pValue, target, fraction, _step);
}
void Math_ApproachF(Rotation* pValue, f32 target, f32 fraction, const Step& _step)
{
_Math_ApproachF(pValue, target, fraction, _step);
}
/**
* Changes pValue by step towards zero. If step is more than fraction of the remaining distance, step by that instead.
*/

View File

@ -55,7 +55,7 @@ void Map_SetPaletteData(GlobalContext* globalCtx, s16 room)
osSyncPrintf(VT_FGCOL(YELLOW));
// "PALETE Set"
osSyncPrintf("PALETEセット 【 i=%x : room=%x 】Room_Inf[%d][4]=%x ( map_palete_no = %d )\n", paletteIndex, room, mapIndex, gSaveContext.sceneFlags[mapIndex].rooms, interfaceCtx->mapPaletteIndex);
osSyncPrintf("Palette【 i=%x : room=%x 】Room_Inf[%d][4]=%x ( map_palete_no = %d )\n", paletteIndex, room, mapIndex, gSaveContext.sceneFlags[mapIndex].rooms, interfaceCtx->mapPaletteIndex);
osSyncPrintf(VT_RST);
interfaceCtx->mapPalette[paletteIndex * 2] = 2;
@ -199,14 +199,13 @@ void Map_InitData(GlobalContext* globalCtx, s16 room)
case SCENE_JYASINBOSS:
case SCENE_HAKADAN_BS:
osSyncPrintf(VT_FGCOL(YELLOW));
// "Deku Tree Dungeon MAP Texture DMA"
osSyncPrintf("デクの樹ダンジョンMAP テクスチャDMA(%x) scene_id_offset=%d VREG(30)=%d\n", room, mapIndex, VREG(30));
osSyncPrintf("Deku Tree Dungeon MAP Texture DMA(%x) scene_id_offset=%d VREG(30)=%d\n", room, mapIndex, VREG(30));
osSyncPrintf(VT_RST);
globalCtx->interfaceCtx.mapSegment1 = (u8*)map_i_static_lut[gMapData->dgnMinimapTexIndexOffset[mapIndex] + room];
R_COMPASS_OFFSET_X = gMapData->roomCompassOffsetX[mapIndex][room];
R_COMPASS_OFFSET_Y = gMapData->roomCompassOffsetY[mapIndex][room];
Map_SetFloorPalettesData(globalCtx, VREG(30));
osSyncPrintf(" 各階ONチェック\n"); // "MAP Individual Floor ON Check"
osSyncPrintf("MAP Individual Floor ON Check\n");
break;
}
}
@ -241,12 +240,12 @@ void Map_InitRoomData(GlobalContext* globalCtx, s16 room)
case SCENE_JYASINBOSS:
case SCENE_HAKADAN_BS:
gSaveContext.sceneFlags[mapIndex].rooms |= gBitFlags[room];
osSyncPrintf("_%d\n", gSaveContext.sceneFlags[mapIndex].rooms);
osSyncPrintf("Room_inf%d\n", gSaveContext.sceneFlags[mapIndex].rooms);
interfaceCtx->mapRoomNum = room;
interfaceCtx->unk_25A = mapIndex;
Map_SetPaletteData(globalCtx, room);
osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("部屋部屋%d\n", room); // "Room Room = %d"
osSyncPrintf("Room room%d\n", room);
osSyncPrintf(VT_RST);
Map_InitData(globalCtx, room);
break;
@ -592,8 +591,7 @@ void Map_Update(GlobalContext* globalCtx)
if(interfaceCtx->mapRoomNum != sLastRoomNum)
{
// "Current floor = %d Current room = %x Number of rooms = %d"
osSyncPrintf("現在階=%d 現在部屋=%x 部屋数=%d\n", floor, interfaceCtx->mapRoomNum, gMapData->switchEntryCount[mapIndex]);
osSyncPrintf("Current floor%d Current room%x number of rooms%d\n", floor, interfaceCtx->mapRoomNum, gMapData->switchEntryCount[mapIndex]);
sLastRoomNum = interfaceCtx->mapRoomNum;
}
@ -603,8 +601,7 @@ void Map_Update(GlobalContext* globalCtx)
{
interfaceCtx->mapRoomNum = gMapData->switchToRoom[mapIndex][i];
osSyncPrintf(VT_FGCOL(YELLOW));
// "Layer switching = %x"
osSyncPrintf("階層切替=%x\n", interfaceCtx->mapRoomNum);
osSyncPrintf("Layer switching%x\n", interfaceCtx->mapRoomNum);
osSyncPrintf(VT_RST);
Map_InitData(globalCtx, interfaceCtx->mapRoomNum);
gSaveContext.sunsSongState = SUNSSONG_INACTIVE;

View File

@ -88,12 +88,14 @@ Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph)
{
Vec3f v;
f32 sinPitch;
f32 cosPitch = Math_CosS(sph->pitch);
f32 cosPitch;
f32 sinYaw;
f32 cosYaw = Math_CosS(sph->yaw);
f32 cosYaw;
sinPitch = Math_SinS(sph->pitch);
sinYaw = Math_SinS(sph->yaw);
cosPitch = Math_AccurateCosS(sph->pitch);
cosYaw = Math_AccurateCosS(sph->yaw);
sinPitch = Math_AccurateSinS(sph->pitch);
sinYaw = Math_AccurateSinS(sph->yaw);
v.x = sph->r * sinPitch * sinYaw;
v.y = sph->r * cosPitch;

View File

@ -489,7 +489,7 @@ void Player_ClearZTarget(Player* pthis)
pthis->stateFlags2 &= ~PLAYER_STATE2_ZTARGET_CHANGED;
}
void func_8008EE08(Player* pthis)
void SetFlagsForClearZTarget(Player* pthis)
{
if((pthis->actor.bgCheckFlags & BG_STATE_0) || (pthis->stateFlags1 & (PLAYER_STATE1_21 | PLAYER_STATE_HORSE_MOUNTED | PLAYER_STATE_SWIMMING)) ||
(!(pthis->stateFlags1 & (PLAYER_STATE1_18 | PLAYER_STATE1_19)) && ((pthis->actor.world.pos.y - pthis->actor.floorHeight) < 100.0f)))
@ -504,11 +504,11 @@ void func_8008EE08(Player* pthis)
Player_ClearZTarget(pthis);
}
void func_8008EEAC(GlobalContext* globalCtx, Actor* actor)
void StartInvolintaryZtarget(GlobalContext* globalCtx, Actor* actor)
{
Player* pthis = GET_PLAYER(globalCtx);
func_8008EE08(pthis);
SetFlagsForClearZTarget(pthis);
pthis->targetedActor = actor;
pthis->unk_684 = actor;
pthis->stateFlags1 |= PLAYER_STATE1_16;
@ -898,7 +898,7 @@ void func_8008F87C(GlobalContext* globalCtx, Player* pthis, SkelAnime* skelAnime
sp7C = D_80126058[(void)0, gSaveContext.linkAge];
sp78 = D_80126060[(void)0, gSaveContext.linkAge];
sp74 = D_80126068[(void)0, gSaveContext.linkAge] - pthis->unk_6C4;
sp74 = D_80126068[(void)0, gSaveContext.linkAge] - pthis->sinkTimer;
Matrix_Push();
Matrix_TranslateRotateZYX(pos, rot);
@ -988,7 +988,7 @@ s32 func_8008FCC8(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* p
}
}
pos->y -= pthis->unk_6C4;
pos->y -= pthis->sinkTimer;
if(pthis->rotationX != 0)
{

View File

@ -2051,12 +2051,12 @@ void func_8009FC90(GlobalContext* globalCtx)
CLOSE_DISPS(globalCtx->gfxCtx, "../z_scene_table.c", 7653);
}
f32 D_8012A398 = 0.0f;
TimerF32 dynamicWallTimer = 0.0f;
void func_8009FE58(GlobalContext* globalCtx)
void sceneDrawHandlerBDAN(GlobalContext* globalCtx)
{
static s16 D_8012A39C = 538;
static s16 D_8012A3A0 = 4272;
static TimerS16 zoomingFrameTimer = 538;
static TimerS16 stretchingFrameTimer = 4272;
u32 gameplayFrames;
f32 temp;
@ -2081,17 +2081,17 @@ void func_8009FE58(GlobalContext* globalCtx)
if(FrameAdvance_IsEnabled(globalCtx) != true)
{
D_8012A39C += 1820;
D_8012A3A0 += 1820;
zoomingFrameTimer += 1820;
stretchingFrameTimer += 1820;
temp = 0.020000001f;
func_800AA76C(
&globalCtx->view, ((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_CosS(D_8012A39C), ((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_SinS(D_8012A39C),
((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_SinS(D_8012A3A0));
func_800AA78C(&globalCtx->view, 1.f + (0.79999995f * temp * Math_SinS(D_8012A3A0)), 1.f + (0.39999998f * temp * Math_CosS(D_8012A3A0)), 1.f + (1 * temp * Math_CosS(D_8012A39C)));
&globalCtx->view, ((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_CosS(zoomingFrameTimer), ((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_SinS(zoomingFrameTimer),
((360.00018f / 65535.0f) * (M_PI / 180.0f)) * temp * Math_SinS(stretchingFrameTimer));
func_800AA78C(&globalCtx->view, 1.0f + (0.79999995f * temp * Math_SinS(stretchingFrameTimer)), 1.0f + (0.39999998f * temp * Math_CosS(stretchingFrameTimer)), 1.0f + (1 * temp * Math_CosS(zoomingFrameTimer)));
func_800AA7AC(&globalCtx->view, 0.95f);
switch(globalCtx->roomCtx.unk_74[0])
switch(globalCtx->roomCtx.unk_74[0].toS16())
{
case 0:
break;
@ -2118,16 +2118,16 @@ void func_8009FE58(GlobalContext* globalCtx)
break;
}
D_8012A398 += 0.15f + (globalCtx->roomCtx.unk_74[1] * 0.001f);
dynamicWallTimer += 0.15f + (globalCtx->roomCtx.unk_74[1] * 0.001f);
}
if(globalCtx->roomCtx.curRoom.num == 2)
{
Matrix_Scale(1.0f, sinf(D_8012A398) * 0.8f, 1.0f, MTXMODE_NEW);
Matrix_Scale(1.0f, sinf(dynamicWallTimer / FRAMERATE_SCALER_INV) * 0.8f, 1.0f, MTXMODE_NEW);
}
else
{
Matrix_Scale(1.005f, sinf(D_8012A398) * 0.8f, 1.005f, MTXMODE_NEW);
Matrix_Scale(1.005f, sinf(dynamicWallTimer / FRAMERATE_SCALER_INV) * 0.8f, 1.005f, MTXMODE_NEW);
}
gSPSegment(POLY_OPA_DISP++, 0x0D, Matrix_NewMtx(globalCtx->gfxCtx, "../z_scene_table.c", 7809));
@ -2190,7 +2190,7 @@ void func_800A059C(GlobalContext* globalCtx)
void (*sSceneDrawHandlers[])(GlobalContext*) = {
func_80099550, func_8009DA30, func_8009DD5C, func_8009DE78, func_8009E0B8, func_8009E54C, func_8009E730, func_8009E8C0, func_8009EAD8, func_8009EE44, func_8009F074, func_8009F1B4, func_8009F270, func_8009F40C,
func_8009F5D4, func_8009F7D4, func_8009F9D0, func_8009FB74, func_8009FC90, func_800995DC, func_80099878, func_8009FE58, func_8009D758, func_8009B0FC, func_8009AE30, func_8009D974, func_800A0334, func_8009CC00,
func_8009F5D4, func_8009F7D4, func_8009F9D0, func_8009FB74, func_8009FC90, func_800995DC, func_80099878, sceneDrawHandlerBDAN, func_8009D758, func_8009B0FC, func_8009AE30, func_8009D974, func_800A0334, func_8009CC00,
func_80099760, func_8009B86C, func_80099BD8, func_8009A45C, func_8009A798, func_8009A9DC, func_8009B9BC, func_8009BAA4, func_8009BC44, func_8009C3EC, func_8009C0AC, func_8009ACA8, func_8009AFE0, func_8009D0E8,
func_8009C608, func_8009C8B8, func_8009D31C, func_8009D438, func_8009D5B4, func_8009CAC0, func_8009AB98, func_800A059C, func_8009CF84, func_800A057C, func_800A055C,
};

View File

@ -93,7 +93,7 @@ s32 BgBdanObjects_GetContactRu1(BgBdanObjects* pthis, s32 arg1)
case 3:
return pthis->cameraSetting == CAM_SET_DUNGEON1;
default:
osSyncPrintf("Bg_Bdan_Objects_Get_Contact_Ru1\nそんな受信モードは無い%d!!!!!!!!\n");
osSyncPrintf("Bg_Bdan_Objects_Get_Contact_Ru1\nThere is no such reception mode %d!!!!!!!!\n");
return -1;
}
}
@ -112,7 +112,7 @@ void BgBdanObjects_SetContactRu1(BgBdanObjects* pthis, s32 arg1)
gSaveContext.infTable[20] |= 0x40;
break;
default:
osSyncPrintf("Bg_Bdan_Objects_Set_Contact_Ru1\nそんな送信モードは無い%d!!!!!!!!\n");
osSyncPrintf("Bg_Bdan_Objects_Set_Contact_Ru1\nThere is no such transmission mode %d!!!!!!!!\n");
}
}

View File

@ -24,13 +24,13 @@ struct BgBdanSwitch
/* 0x0164 */ BgBdanSwitchActionFunc actionFunc;
/* 0x0168 */ ColliderJntSph collider;
/* 0x0188 */ ColliderJntSphElement colliderItems[1];
/* 0x01C8 */ f32 unk_1C8;
/* 0x01CC */ s16 unk_1CC;
/* 0x01C8 */ TimerF32 unk_1C8;
/* 0x01CC */ TimerS16 unk_1CC;
/* 0x01CE */ char unk_1CE[0x2];
/* 0x01D0 */ f32 unk_1D0;
/* 0x01D4 */ f32 unk_1D4;
/* 0x01D8 */ s16 unk_1D8;
/* 0x01DA */ s16 unk_1DA;
/* 0x01D8 */ TimerS16 unk_1D8;
/* 0x01DA */ TimerS16 unk_1DA;
/* 0x01DC */ u8 unk_1DC;
/* 0x01DD */ char unk_1DD[0x3];
};

View File

@ -242,16 +242,16 @@ void func_8086ED70(BgBombwall* pthis, GlobalContext* globalCtx)
void func_8086EDFC(BgBombwall* pthis, GlobalContext* globalCtx)
{
pthis->dList = gBgBombwallNormalDL;
pthis->unk_2A0 = 1;
pthis->animTimer = 1;
func_8086EB5C(pthis, globalCtx);
pthis->actionFunc = func_8086EE40;
}
void func_8086EE40(BgBombwall* pthis, GlobalContext* globalCtx)
{
if(pthis->unk_2A0 > 0)
if(pthis->animTimer > 0)
{
pthis->unk_2A0--;
pthis->animTimer--;
}
else
{

View File

@ -15,7 +15,6 @@ struct BgBombwall
/* 0x0184 */ ColliderTrisElement colliderItems[3];
/* 0x0298 */ BgBombwallActionFunc actionFunc;
/* 0x029C */ Gfx* dList;
/* 0x02A0 */ s16 unk_2A0;
/* 0x02A0 */ TimerS16 animTimer;
/* 0x02A2 */ u8 unk_2A2;
/* 0x02A3 */ u8 unk_2A3;
};

View File

@ -162,7 +162,7 @@ void func_808BF078(BgYdanMaruta* pthis, GlobalContext* globalCtx)
{
if(pthis->collider.base.acFlags & AC_HIT)
{
pthis->unk_16A = 20;
pthis->timer = 20;
Flags_SetSwitch(globalCtx, pthis->switchFlag);
Common_PlaySfx(NA_SE_SY_CORRECT_CHIME);
pthis->actionFunc = func_808BF108;
@ -178,11 +178,11 @@ void func_808BF108(BgYdanMaruta* pthis, GlobalContext* globalCtx)
{
s16 temp;
if(pthis->unk_16A != 0)
if(pthis->timer != 0)
{
pthis->unk_16A--;
pthis->timer--;
}
if(pthis->unk_16A == 0)
if(pthis->timer == 0)
{
pthis->actionFunc = func_808BF1EC;
}
@ -191,7 +191,7 @@ void func_808BF108(BgYdanMaruta* pthis, GlobalContext* globalCtx)
{
}
temp = (pthis->unk_16A % 4) - 2;
temp = (pthis->timer % 4) - 2;
if(temp == -2)
{
temp = 0;

View File

@ -13,7 +13,7 @@ struct BgYdanMaruta
/* 0x0000 */ DynaPolyActor dyna;
/* 0x0164 */ BgYdanMarutaActionFunc actionFunc;
/* 0x0168 */ u8 switchFlag;
/* 0x016A */ s16 unk_16A;
/* 0x016A */ TimerS16 timer;
/* 0x016C */ ColliderTris collider;
/* 0x018C */ ColliderTrisElement elements[2];
};

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ struct BossDodongoEffect
/* 0x00 */ Vec3f unk_00;
/* 0x0C */ Vec3f unk_0C;
/* 0x18 */ Vec3f unk_18;
/* 0x24 */ u8 unk_24;
/* 0x25 */ u8 unk_25;
/* 0x24 */ bool unk_24;
/* 0x25 */ TimerU8 unk_25;
/* 0x26 */ Color_RGB8 color;
/* 0x2A */ s16 alpha;
/* 0x2C */ f32 unk_2C;
@ -26,68 +26,55 @@ struct BossDodongo
/* 0x014C */ SkelAnime skelAnime;
/* 0x0190 */ BossDodongoActionFunc actionFunc;
/* 0x0194 */ s16 health;
/* 0x0196 */ s16 unk_196;
/* 0x0198 */ s16 unk_198;
/* 0x019A */ s16 unk_19A;
/* 0x0196 */ TimerS16 timer1;//sound related?
/* 0x0198 */ TimerS16 timer2;//sound related?
/* 0x019C */ s16 csState;
/* 0x019E */ s16 unk_19E;
/* 0x01A0 */ s16 unk_1A0;
/* 0x019E */ TimerS16 lavaFloorTimer;//lava floor speed?
/* 0x01A0 */ s16 unk_1A0;//corner related index?
/* 0x01A2 */ s16 unk_1A2;
/* 0x01A4 */ s16 unk_1A4;
/* 0x01A6 */ s16 unk_1A6;
/* 0x01A8 */ s16 numWallCollisions;
/* 0x01AA */ s16 unk_1AA;
/* 0x01AC */ s16 unk_1AC;
/* 0x01AE */ s16 unk_1AE;
/* 0x01B0 */ s16 unk_1B0;
/* 0x01B2 */ char unk_1B2[0x2];
/* 0x01AA */ bool unk_1AA;//used as boolean
/* 0x01AC */ TimerS16 eatExplosiveTimer;//timer for eating the bomb
/* 0x01AE */ TimerS16 fireBallFadeTimer;//maintains the trail effect for fire ball
/* 0x01B4 */ s16 cutsceneCamera;
/* 0x01B6 */ s16 unk_1B6;
/* 0x01B6 */ TimerS16 cutsceneCameraBounceTimer;
/* 0x01B8 */ s16 playerYawInRange;
/* 0x01BA */ s16 playerPosInRange;
/* 0x01BC */ s16 unk_1BC;
/* 0x01BE */ s16 unk_1BE;
/* 0x01C0 */ s16 unk_1C0;
/* 0x01C2 */ s16 unk_1C2;
/* 0x01C4 */ s16 unk_1C4; // Some kind of angle
/* 0x01C6 */ s16 unk_1C6;
/* 0x01C8 */ s16 unk_1C8;
/* 0x01CA */ char unk_1CA[0x2];
/* 0x01BC */ s16 walkingState;
/* 0x01BE */ TimerS16 colorFilterTransitionTimer;
/* 0x01C0 */ TimerS16 whiteFlashFogTimer;
/* 0x01C2 */ s16 unk_1C2;//floor transition index
/* 0x01C4 */ Rotation rollingRot;//rolling timer
/* 0x01C6 */ bool isFloorRock;//used as a boolean
/* 0x01C8 */ TimerS16 unk_1C8;//?unsure?fireball begining transition?
/* 0x01CC */ s16 unk_1CC;
/* 0x01CE */ char unk_1CE[0xC];
/* 0x01DA */ s16 unk_1DA;
/* 0x01DC */ s16 unk_1DC;
/* 0x01DE */ s16 unk_1DE;
/* 0x01E0 */ s16 unk_1E0;
/* 0x01E2 */ u8 unk_1E2;
/* 0x01E3 */ s8 unk_1E3;
/* 0x01E4 */ f32 unk_1E4;
/* 0x01DA */ TimerS16 blowFireTimer;
/* 0x01E2 */ bool unk_1E2;//health related?
/* 0x01E4 */ f32 unk_1E4;//position related
/* 0x01E8 */ f32 unk_1E8;
/* 0x01EC */ f32 unk_1EC;
/* 0x01F0 */ char unk_1F0[0x8];
/* 0x01F8 */ f32 unk_1F8;
/* 0x01FC */ f32 unk_1FC;
/* 0x0200 */ f32 unk_200;
/* 0x01F8 */ f32 unk_1F8;//laydown related?
/* 0x0204 */ f32 unk_204;
/* 0x0208 */ f32 unk_208;
/* 0x0208 */ f32 unk_208;//limb rot scal
/* 0x020C */ f32 unk_20C;
/* 0x0210 */ f32 colorFilterR;
/* 0x0214 */ f32 colorFilterG;
/* 0x0214 */ f32 colorFilterB;
/* 0x021C */ f32 colorFilterMin;
/* 0x0220 */ f32 colorFilterMax;
/* 0x0224 */ f32 unk_224;
/* 0x0224 */ f32 floorTexTransitionMultiplier;
/* 0x0228 */ f32 unk_228;
/* 0x022C */ f32 unk_22C;
/* 0x0230 */ f32 unk_230;
/* 0x0234 */ f32 unk_234;
/* 0x0238 */ f32 unk_238;
/* 0x023C */ f32 unk_23C;
/* 0x0230 */ TimerF32 endSceneCameraPanTimer;
/* 0x0234 */ f32 rollingRotScale; // rotation inc?
/* 0x0238 */ f32 endSceneBodyRotScale;
/* 0x023C */ f32 unk_23C;///groundRotation
/* 0x0240 */ f32 unk_240;
/* 0x0244 */ f32 unk_244;
/* 0x0248 */ char unk_248[0x14];
/* 0x025C */ f32 unk_25C[50];
/* 0x0324 */ f32 unk_324[50];
/* 0x0244 */ f32 unk_244;//fireball travel c?
/* 0x025C */ TimerF32 limbRot[50];
/* 0x0324 */ TimerF32 limbRndRot[50];
/* 0x03EC */ Vec3f vec;
/* 0x03F8 */ Vec3f firePos;
/* 0x0404 */ Vec3f unk_404;

View File

@ -76,7 +76,7 @@ struct BossDoorInfo
struct DoorShutter
{
/* 0x0000 */ DynaPolyActor dyna;
/* 0x0164 */ s16 unk_164;
/* 0x0164 */ TimerS16 unk_164;
/* 0x0166 */ s16 unk_166;
/* 0x0168 */ s16 unk_168;
/* 0x016A */ u8 doorType;
@ -84,7 +84,7 @@ struct DoorShutter
/* 0x016C */ u8 unk_16C;
/* 0x016D */ s32 requiredObjBankIndex;
/* 0x016E */ Timer unk_16E;
/* 0x016F */ s8 unk_16F;
/* 0x016F */ TimerS8 unk_16F;
/* 0x0170 */ f32 unk_170;
/* 0x0174 */ DoorShutterActionFunc actionFunc;
};

View File

@ -143,7 +143,7 @@ void EnBa_Destroy(Actor* thisx, GlobalContext* globalCtx)
void EnBa_SetupIdle(EnBa* pthis)
{
pthis->unk14C = 2;
pthis->state = 2;
pthis->unk31C = 1500;
pthis->actor.speedXZ = 10.0f;
EnBa_SetupAction(pthis, EnBa_Idle);
@ -211,7 +211,7 @@ void EnBa_Idle(EnBa* pthis, GlobalContext* globalCtx)
void EnBa_SetupFallAsBlob(EnBa* pthis)
{
pthis->unk14C = 0;
pthis->state = 0;
pthis->actor.speedXZ = Rand_CenteredFloat(8.0f);
pthis->actor.world.rot.y = Rand_CenteredFloat(65535.0f);
pthis->unk318 = 20;
@ -244,7 +244,7 @@ void EnBa_FallAsBlob(EnBa* pthis, GlobalContext* globalCtx)
void EnBa_SetupSwingAtPlayer(EnBa* pthis)
{
pthis->unk14C = 3;
pthis->state = 3;
pthis->unk318 = 20;
pthis->unk31A = 0;
pthis->unk31C = 1500;
@ -367,7 +367,7 @@ void EnBa_SwingAtPlayer(EnBa* pthis, GlobalContext* globalCtx)
void func_809B7174(EnBa* pthis)
{
pthis->unk14C = 1;
pthis->state = 1;
pthis->unk31C = 1500;
pthis->unk318 = 20;
pthis->actor.colChkInfo.mass = MASS_IMMOVABLE;
@ -437,7 +437,7 @@ void func_809B75A0(EnBa* pthis, GlobalContext* globalCtx2)
pthis->unk31C = 2500;
EffectSsDeadSound_SpawnStationary(globalCtx, &pthis->actor.projectedPos, NA_SE_EN_BALINADE_HAND_DEAD, 1, 1, 40);
pthis->unk14C = 0;
pthis->state = 0;
for(i = 7; i < 14; i++)
{
@ -527,7 +527,7 @@ void EnBa_Update(Actor* thisx, GlobalContext* globalCtx)
{
pthis->actor.focus.pos = pthis->unk158[6];
}
if(pthis->unk14C >= 2)
if(pthis->state >= 2)
{
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &pthis->collider.base);
}

View File

@ -19,10 +19,9 @@ enum EnBaType
struct EnBa
{
/* 0x0000 */ Actor actor;
/* 0x014C */ s32 unk14C;
/* 0x014C */ s32 state;
/* 0x0150 */ EnBaActionFunc actionFunc;
/* 0x0154 */ s16 upperParams;
/* 0x0156 */ s16 unk156;
/* 0x0158 */ Vec3f unk158[14];
/* 0x0200 */ Vec3f unk200[14];
/* 0x02A8 */ Vec3s unk2A8[14];

View File

@ -57,7 +57,7 @@ void EnBdfire_Init(Actor* thisx, GlobalContext* globalCtx)
{
EnBdfire_SetupAction(pthis, func_809BC2A4);
pthis->actor.scale.x = 2.8f;
pthis->unk_154 = 90;
pthis->timer = 90;
Lights_PointNoGlowSetInfo(&pthis->lightInfoNoGlow, pthis->actor.world.pos.x, pthis->actor.world.pos.y, pthis->actor.world.pos.z, 255, 255, 255, 300);
pthis->lightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &pthis->lightInfoNoGlow);
}
@ -66,10 +66,10 @@ void EnBdfire_Init(Actor* thisx, GlobalContext* globalCtx)
EnBdfire_SetupAction(pthis, func_809BC598);
ActorShape_Init(&pthis->actor.shape, 0.0f, ActorShadow_DrawCircle, 0.0f);
pthis->actor.speedXZ = 30.0f;
pthis->unk_154 = (25 - (s32)(pthis->actor.params * 0.8f));
if(pthis->unk_154 < 0)
pthis->timer = (25 - (s32)(pthis->actor.params * 0.8f));
if(pthis->timer < 0)
{
pthis->unk_154 = 0;
pthis->timer = 0;
}
pthis->unk_188 = 4.2000003f - (pthis->actor.params * 0.25f * 0.6f);
@ -82,7 +82,7 @@ void EnBdfire_Init(Actor* thisx, GlobalContext* globalCtx)
{
pthis->unk_18C = 20.0f;
}
pthis->unk_156 = (Rand_ZeroOne() * 8.0f);
pthis->animTimer = (Rand_ZeroOne() * 8.0f);
}
}
@ -115,20 +115,20 @@ void func_809BC2A4(EnBdfire* pthis, GlobalContext* globalCtx)
}
else
{
if(pthis->unk_154 < 70)
if(pthis->timer < 70)
{
Math_SmoothStepToF(&pthis->unk_18C, 128.0f, 0.1f, 1.5f, 0.0f);
Math_SmoothStepToF(&pthis->unk_190, 255.0f, 1.0f, 3.8249998f, 0.0f);
Math_SmoothStepToF(&pthis->unk_194, 100.0f, 1.0f, 1.5f, 0.0f);
}
if(pthis->unk_154 == 0)
if(pthis->timer == 0)
{
temp = 0;
}
else
{
pthis->unk_154--;
temp = pthis->unk_154;
pthis->timer--;
temp = pthis->timer;
}
if(temp == 0)
{
@ -198,14 +198,14 @@ void func_809BC598(EnBdfire* pthis, GlobalContext* globalCtx)
pthis->actor.world.rot.y -= 0x4000;
}
}
if(pthis->unk_154 == 0)
if(pthis->timer == 0)
{
temp = 0;
}
else
{
pthis->unk_154--;
temp = pthis->unk_154;
pthis->timer--;
temp = pthis->timer;
}
if(temp == 0)
{
@ -236,7 +236,7 @@ void EnBdfire_Update(Actor* thisx, GlobalContext* globalCtx)
{
EnBdfire* pthis = (EnBdfire*)thisx;
pthis->unk_156++;
pthis->animTimer++;
pthis->actionFunc(pthis, globalCtx);
Actor_MoveForward(&pthis->actor);
}
@ -247,7 +247,7 @@ void EnBdfire_DrawFire(EnBdfire* pthis, GlobalContext* globalCtx)
s32 pad;
OPEN_DISPS(globalCtx->gfxCtx, "../z_en_bdfire.c", 612);
temp = pthis->unk_156 & 7;
temp = pthis->animTimer & 7;
func_800D1FD4(&globalCtx->billboardMtxF);
func_80094BC4(globalCtx->gfxCtx);
POLY_XLU_DISP = func_80094968(POLY_XLU_DISP);

View File

@ -15,15 +15,13 @@ struct EnBdfire
/* 0x0000 */ Actor actor;
/* 0x014C */ EnBdfireActionFunc actionFunc;
/* 0x0150 */ EnBdfireDrawFunc drawFunc;
/* 0x0154 */ s16 unk_154;
/* 0x0156 */ s16 unk_156;
/* 0x0154 */ TimerS16 timer;//how long the fire ball will last
/* 0x0156 */ TimerS16 animTimer;//timer for animation speed
/* 0x0158 */ s16 unk_158;
/* 0x015A */ char unk_15A[0x2E];
/* 0x0188 */ f32 unk_188;
/* 0x018C */ f32 unk_18C;
/* 0x0190 */ f32 unk_190;
/* 0x0194 */ f32 unk_194;
/* 0x0198 */ char unk_198[0x38];
/* 0x01D0 */ LightNode* lightNode;
/* 0x01D4 */ LightInfo lightInfoNoGlow;
};

View File

@ -3,7 +3,7 @@
/*
* File: z_en_brob.c
* Overlay: ovl_En_Brob
* Description: Flobbery Muscle Block (Jabu-Jabu's Belly)
* Description: Flobbery Muscle Block (The Enimies prodomanently in jabujabu)
*/
#include "z_en_brob.h"
@ -121,7 +121,7 @@ void func_809CADDC(EnBrob* pthis, GlobalContext* globalCtx)
{
func_8003EC50(globalCtx, &globalCtx->colCtx.dyna, pthis->dyna.bgId);
pthis->timer = pthis->actionFunc == func_809CB2B8 ? 200 : 0;
pthis->unk_1AE = 0;
pthis->transitionTimer = 0;
pthis->actionFunc = func_809CB054;
}
@ -129,14 +129,14 @@ void func_809CAE44(EnBrob* pthis, GlobalContext* globalCtx)
{
Animation_PlayOnce(&pthis->skelAnime, &object_brob_Anim_001750);
func_8003EBF8(globalCtx, &globalCtx->colCtx.dyna, pthis->dyna.bgId);
pthis->unk_1AE = 1000;
pthis->transitionTimer = 1000;
pthis->actionFunc = func_809CB114;
}
void func_809CAEA0(EnBrob* pthis)
{
Animation_MorphToLoop(&pthis->skelAnime, &object_brob_Anim_001958, -5.0f);
pthis->unk_1AE = 8000;
pthis->transitionTimer = 8000;
pthis->timer = 1200;
pthis->actionFunc = func_809CB218;
}
@ -144,7 +144,7 @@ void func_809CAEA0(EnBrob* pthis)
void func_809CAEF4(EnBrob* pthis)
{
Animation_MorphToPlayOnce(&pthis->skelAnime, &object_brob_Anim_000290, -5.0f);
pthis->unk_1AE -= 125.0f;
pthis->transitionTimer -= 125.0f;
Actor_SetColorFilter(&pthis->dyna.actor, 0, 0xFF, 0, 0x50);
Audio_PlayActorSound2(&pthis->dyna.actor, NA_SE_EN_GOMA_JR_FREEZE);
pthis->actionFunc = func_809CB2B8;
@ -153,7 +153,7 @@ void func_809CAEF4(EnBrob* pthis)
void func_809CAF88(EnBrob* pthis)
{
Animation_Change(&pthis->skelAnime, &object_brob_Anim_001750, -1.0f, Animation_GetLastFrame(&object_brob_Anim_001750), 0.0f, ANIMMODE_ONCE, -5.0f);
pthis->unk_1AE = 8250;
pthis->transitionTimer = 8250;
pthis->actionFunc = func_809CB354;
}
@ -201,15 +201,15 @@ void func_809CB114(EnBrob* pthis, GlobalContext* globalCtx)
curFrame = pthis->skelAnime.curFrame;
if(curFrame < 8.0f)
{
pthis->unk_1AE += 1000.0f;
pthis->transitionTimer += 1000.0f;
}
else if(curFrame < 12.0f)
{
pthis->unk_1AE += 250.0f;
pthis->transitionTimer += 250.0f;
}
else
{
pthis->unk_1AE -= 250.0f;
pthis->transitionTimer -= 250.0f;
}
}
}
@ -239,7 +239,7 @@ void func_809CB2B8(EnBrob* pthis, GlobalContext* globalCtx)
}
else if(pthis->skelAnime.curFrame < 8.0f)
{
pthis->unk_1AE -= 1250.0f;
pthis->transitionTimer -= 1250.0f;
}
pthis->dyna.actor.colorFilterTimer = 0x50;
}
@ -257,15 +257,15 @@ void func_809CB354(EnBrob* pthis, GlobalContext* globalCtx)
curFrame = pthis->skelAnime.curFrame;
if(curFrame < 8.0f)
{
pthis->unk_1AE -= 1000.0f;
pthis->transitionTimer -= 1000.0f;
}
else if(curFrame < 12.0f)
{
pthis->unk_1AE -= 250.0f;
pthis->transitionTimer -= 250.0f;
}
else
{
pthis->unk_1AE += 250.0f;
pthis->transitionTimer += 250.0f;
}
}
}
@ -391,7 +391,7 @@ void EnBrob_Draw(Actor* thisx, GlobalContext* globalCtx)
EnBrob* pthis = (EnBrob*)thisx;
func_80093D18(globalCtx->gfxCtx);
Matrix_Translate(0.0f, pthis->unk_1AE, 0.0f, MTXMODE_APPLY);
Matrix_Translate(0.0f, pthis->transitionTimer, 0.0f, MTXMODE_APPLY);
SkelAnime_DrawFlexOpa(globalCtx, pthis->skelAnime.skeleton, pthis->skelAnime.jointTable, pthis->skelAnime.dListCount, NULL, EnBrob_PostLimbDraw, pthis);
}

View File

@ -14,7 +14,7 @@ struct EnBrob
/* 0x0164 */ SkelAnime skelAnime;
/* 0x01A8 */ EnBrobActionFunc actionFunc;
/* 0x01AC */ Timer timer;
/* 0x01AE */ s16 unk_1AE;
/* 0x01AE */ TimerS16 transitionTimer;
/* 0x01B0 */ Vec3s jointTable[10];
/* 0x01EC */ Vec3s morphTable[10];
/* 0x0228 */ ColliderCylinder colliders[2];

View File

@ -1,5 +1,10 @@
#define INTERNAL_SRC_OVERLAYS_ACTORS_OVL_EN_BUBBLE_Z_EN_BUBBLE_C
#include "actor_common.h"
/*
* File: z_en_bubble.cpp
* Description: Bubble
*/
#include "z_en_bubble.h"
#include "def/code_8006BA00.h"
#include "def/random.h"
@ -226,10 +231,10 @@ void EnBubble_Fly(EnBubble* pthis, GlobalContext* globalCtx)
CollisionPoly* sp94;
Actor* bumpActor;
Vec3f sp84;
Vec3f sp78;
Vec3f sp6C;
Vec3f sp60;
Vec3f sp54;
VecPos pos1;
VecPos pos2;
Vec3f normal;
Vec3f vel;
f32 bounceSpeed;
s32 bgId;
u8 bounceCount;
@ -246,28 +251,31 @@ void EnBubble_Fly(EnBubble* pthis, GlobalContext* globalCtx)
pthis->sinkSpeed -= 0.1f;
if(pthis->sinkSpeed < pthis->actor.minVelocityY)
{
pthis->sinkSpeed = pthis->actor.minVelocityY;
pthis->sinkSpeed = pthis->actor.minVelocityY / FRAMERATE_SCALER_INV;
}
sp54.x = pthis->velocityFromBounce.x + pthis->velocityFromBump.x;
sp54.y = pthis->velocityFromBounce.y + pthis->velocityFromBump.y + pthis->sinkSpeed;
sp54.z = pthis->velocityFromBounce.z + pthis->velocityFromBump.z;
EnBubble_Vec3fNormalize(&sp54);
vel.x = pthis->velocityFromBounce.x + pthis->velocityFromBump.x;
vel.y = pthis->velocityFromBounce.y + pthis->velocityFromBump.y + pthis->sinkSpeed;
vel.z = pthis->velocityFromBounce.z + pthis->velocityFromBump.z;
EnBubble_Vec3fNormalize(&vel);
sp78.x = pthis->actor.world.pos.x;
sp78.y = pthis->actor.world.pos.y + pthis->actor.shape.yOffset;
sp78.z = pthis->actor.world.pos.z;
sp6C = sp78;
pos1.x = pthis->actor.world.pos.x;
pos1.y = pthis->actor.world.pos.y + pthis->actor.shape.yOffset;
pos1.z = pthis->actor.world.pos.z;
pos2 = pos1;
sp6C.x += (sp54.x * 24.0f);
sp6C.y += (sp54.y * 24.0f);
sp6C.z += (sp54.z * 24.0f);
if(BgCheck_EntityLineTest1(&globalCtx->colCtx, &sp78, &sp6C, &sp84, &sp94, true, true, true, false, &bgId))
pos2.x += (vel.x * 24.0f) / FRAMERATE_SCALER_INV;
pos2.y += (vel.y * 24.0f) / FRAMERATE_SCALER_INV;
pos2.z += (vel.z * 24.0f) / FRAMERATE_SCALER_INV;
Vec3f pos1Chk = pos1;
Vec3f pos2Chk = pos2;
if(BgCheck_EntityLineTest1(&globalCtx->colCtx, &pos1Chk, &pos2Chk, &sp84, &sp94, true, true, true, false, &bgId))
{
sp60.x = COLPOLY_GET_NORMAL(sp94->normal.x);
sp60.y = COLPOLY_GET_NORMAL(sp94->normal.y);
sp60.z = COLPOLY_GET_NORMAL(sp94->normal.z);
EnBubble_Vec3fNormalizedRelfect(&sp54, &sp60, &sp54);
pthis->bounceDirection = sp54;
normal.x = COLPOLY_GET_NORMAL(sp94->normal.x);
normal.y = COLPOLY_GET_NORMAL(sp94->normal.y);
normal.z = COLPOLY_GET_NORMAL(sp94->normal.z);
EnBubble_Vec3fNormalizedRelfect(&vel, &normal, &vel);
pthis->bounceDirection = vel;
bounceCount = pthis->bounceCount;
pthis->bounceCount = ++bounceCount;
if(bounceCount > (s16)(Rand_ZeroOne() * 10.0f))
@ -281,15 +289,15 @@ void EnBubble_Fly(EnBubble* pthis, GlobalContext* globalCtx)
pthis->velocityFromBounce.z = (pthis->bounceDirection.z * bounceSpeed);
pthis->sinkSpeed = 0.0f;
Audio_PlayActorSound2(&pthis->actor, NA_SE_EN_AWA_BOUND);
pthis->graphicRotSpeed = 128.0f;
pthis->graphicRotSpeed = 128.0f / FRAMERATE_SCALER_INV;
pthis->graphicEccentricity = 0.48f;
}
else if(pthis->actor.bgCheckFlags & BG_STATE_5 && sp54.y < 0.0f)
else if(pthis->actor.bgCheckFlags & BG_STATE_5 && vel.y < 0.0f)
{
sp60.x = sp60.z = 0.0f;
sp60.y = 1.0f;
EnBubble_Vec3fNormalizedRelfect(&sp54, &sp60, &sp54);
pthis->bounceDirection = sp54;
normal.x = normal.z = 0.0f;
normal.y = 1.0f;
EnBubble_Vec3fNormalizedRelfect(&vel, &normal, &vel);
pthis->bounceDirection = vel;
bounceCount = pthis->bounceCount;
pthis->bounceCount = ++bounceCount;
if(bounceCount > (s16)(Rand_ZeroOne() * 10.0f))
@ -303,7 +311,7 @@ void EnBubble_Fly(EnBubble* pthis, GlobalContext* globalCtx)
pthis->velocityFromBounce.z = (pthis->bounceDirection.z * bounceSpeed);
pthis->sinkSpeed = 0.0f;
Audio_PlayActorSound2(&pthis->actor, NA_SE_EN_AWA_BOUND);
pthis->graphicRotSpeed = 128.0f;
pthis->graphicRotSpeed = 128.0f / FRAMERATE_SCALER_INV;
pthis->graphicEccentricity = 0.48f;
}
pthis->actor.velocity.x = pthis->velocityFromBounce.x + pthis->velocityFromBump.x;

View File

@ -29,6 +29,6 @@ struct EnBubble
/* 0x022C */ Vec3f bounceDirection;
/* 0x0238 */ Vec3f velocityFromBounce;
/* 0x0244 */ Vec3f normalizedBumpVelocity;
/* 0x0250 */ Vec3f velocityFromBump;
/* 0x025C */ f32 sinkSpeed;
/* 0x0250 */ VecPos velocityFromBump;
/* 0x025C */ TimerF32 sinkSpeed;
};

View File

@ -138,8 +138,8 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx)
}
}
Actor_SpawnAsChild(&globalCtx->actorCtx, &pthis->actor, globalCtx, ACTOR_EN_COW, pthis->actor.world.pos.x, pthis->actor.world.pos.y, pthis->actor.world.pos.z, 0, pthis->actor.shape.rot.y, 0, 1);
pthis->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f;
pthis->unk_27A = 0;
pthis->mooTimer = Rand_ZeroFloat(1000.0f) + 40.0f;
pthis->breathingTimer = 0;
pthis->actor.targetMode = 6;
DREG(53) = 0;
break;
@ -151,7 +151,7 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx)
pthis->actionFunc = func_809DFA84;
func_809DEF94(pthis);
pthis->actor.flags &= ~ACTOR_FLAG_VISIBLE;
pthis->unk_278 = ((u32)(Rand_ZeroFloat(1000.0f)) & 0xFFFF) + 40.0f;
pthis->mooTimer = ((u32)(Rand_ZeroFloat(1000.0f)) & 0xFFFF) + 40.0f;
break;
}
pthis->actor.colChkInfo.mass = MASS_IMMOVABLE;
@ -172,13 +172,13 @@ void EnCow_Destroy(Actor* thisx, GlobalContext* globalCtx)
void func_809DF494(EnCow* pthis, GlobalContext* globalCtx)
{
if(pthis->unk_278 > 0)
if(pthis->mooTimer > 0)
{
pthis->unk_278 -= 1;
pthis->mooTimer -= 1;
}
else
{
pthis->unk_278 = Rand_ZeroFloat(500.0f) + 40.0f;
pthis->mooTimer = Rand_ZeroFloat(500.0f) + 40.0f;
Animation_Change(&pthis->skelAnime, &gCowBodyChewAnim, 1.0f, pthis->skelAnime.curFrame, Animation_GetLastFrame(&gCowBodyChewAnim), ANIMMODE_ONCE, 1.0f);
}
@ -187,29 +187,29 @@ void func_809DF494(EnCow* pthis, GlobalContext* globalCtx)
pthis->unk_276 |= 2;
if(pthis->skelAnime.animation == &gCowBodyChewAnim)
{
pthis->unk_278 = 0;
pthis->mooTimer = 0;
}
}
pthis->unk_27A += 1;
if(pthis->unk_27A >= 0x31)
pthis->breathingTimer += 1;
if(pthis->breathingTimer >= 0x31)
{
pthis->unk_27A = 0;
pthis->breathingTimer = 0;
}
// (1.0f / 100.0f) instead of 0.01f below is necessary so 0.01f doesn't get reused mistakenly
if(pthis->unk_27A < 0x20)
if(pthis->breathingTimer < 0x20)
{
pthis->actor.scale.x = ((Math_SinS(pthis->unk_27A << 0xA) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
pthis->actor.scale.x = ((Math_SinS(pthis->breathingTimer << 0xA) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
}
else
{
pthis->actor.scale.x = 0.01f;
}
if(pthis->unk_27A >= 0x11)
if(pthis->breathingTimer >= 0x11)
{
pthis->actor.scale.y = ((Math_SinS((pthis->unk_27A << 0xA) - 0x4000) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
pthis->actor.scale.y = ((Math_SinS((pthis->breathingTimer << 0xA) - 0x4000) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
}
else
{
@ -329,13 +329,13 @@ void func_809DF96C(EnCow* pthis, GlobalContext* globalCtx)
void func_809DFA84(EnCow* pthis, GlobalContext* globalCtx)
{
if(pthis->unk_278 > 0)
if(pthis->mooTimer > 0)
{
pthis->unk_278--;
pthis->mooTimer--;
}
else
{
pthis->unk_278 = Rand_ZeroFloat(200.0f) + 40.0f;
pthis->mooTimer = Rand_ZeroFloat(200.0f) + 40.0f;
Animation_Change(&pthis->skelAnime, &gCowTailIdleAnim, 1.0f, pthis->skelAnime.curFrame, Animation_GetLastFrame(&gCowTailIdleAnim), ANIMMODE_ONCE, 1.0f);
}
@ -344,7 +344,7 @@ void func_809DFA84(EnCow* pthis, GlobalContext* globalCtx)
pthis->unk_276 |= 2;
if(pthis->skelAnime.animation == &gCowTailIdleAnim)
{
pthis->unk_278 = 0;
pthis->mooTimer = 0;
}
}
}

View File

@ -17,7 +17,7 @@ struct EnCow
/* 0x024C */ Vec3s morphTable[6];
/* 0x0270 */ Vec3s someRot;
/* 0x0276 */ u16 unk_276;
/* 0x0278 */ u16 unk_278;
/* 0x027A */ u16 unk_27A;
/* 0x0278 */ TimerU16 mooTimer;
/* 0x027A */ TimerU16 breathingTimer;
/* 0x027C */ EnCowActionFunc actionFunc;
};

View File

@ -242,7 +242,7 @@ void EnDh_Wait(EnDh* pthis, GlobalContext* globalCtx)
SkelAnime_Update(&pthis->skelAnime);
if(pthis->actor.params != ENDH_START_ATTACK_BOMB)
{
func_8008EEAC(globalCtx, &pthis->actor);
StartInvolintaryZtarget(globalCtx, &pthis->actor);
}
}
}

View File

@ -455,7 +455,7 @@ void EnFish_Dropped_Fall(EnFish* pthis, GlobalContext* globalCtx)
{
osSyncPrintf(VT_COL(YELLOW, BLACK));
// "BG missing? Running Actor_delete"
osSyncPrintf("BG 抜け? Actor_delete します(%s %d)\n", "../z_en_sakana.c", 822);
osSyncPrintf("Missing BG Actor_delete Do(%s %d)\n", "../z_en_sakana.c", 822);
osSyncPrintf(VT_RST);
Actor_Kill(&pthis->actor);
}

View File

@ -71,7 +71,7 @@ void EnHata_Init(Actor* thisx, GlobalContext* globalCtx)
pthis->invScale = 6;
pthis->maxStep = 1000;
pthis->minStep = 1;
pthis->unk_278 = Rand_ZeroOne() * 0xFFFF;
pthis->animTimer = Rand_ZeroOne() * 0xFFFF;
}
void EnHata_Destroy(Actor* thisx, GlobalContext* globalCtx)
@ -110,15 +110,15 @@ void EnHata_Update(Actor* thisx, GlobalContext* globalCtx2)
if(Rand_ZeroOne() > 0.5f)
{
pthis->unk_278 += 6000;
pthis->animTimer += 6000;
}
else
{
pthis->unk_278 += 3000;
pthis->animTimer += 3000;
}
// Mimic varying wind gusts
sin = Math_SinS(pthis->unk_278) * 80.0f;
sin = Math_SinS(pthis->animTimer) * 80.0f;
pitch = -Math_Vec3f_Pitch(&zeroVec, &windVec);
pitch = ((s32)((15000 - pitch) * (1.0f - (globalCtx->envCtx.windSpeed / (255.0f - sin))))) + pitch;
Math_SmoothStepToS(&pthis->limbs[FLAGPOLE_LIMB_FLAG_1_HOIST_END_BASE].y, pitch, pthis->invScale, pthis->maxStep, pthis->minStep);

Some files were not shown because too many files have changed in this diff Show More