Adding clean clones of the Mupen64Plus repos, minus the html documentation for SDL. Also adding svn:ignores for hg related files in these repos.

This commit is contained in:
pjgat09 2013-04-29 01:11:33 +00:00
parent 669edc55b3
commit 8a56a46900
548 changed files with 282188 additions and 0 deletions

View File

@ -0,0 +1,26 @@
Mupen64Plus-Audio-SDL INSTALL
-----------------------------
This text file was written to explain the installation process of the
Mupen64Plus-Audio-SDL module.
If this module is part of a Mupen64Plus source code bundle, the user should run
the "m64p_install.sh" script in the root of the unzipped bundle to install all
of the included modules in the bundle.
If this module is a standalone source code release, you should build the library
from source code and install it via the makefile, like this:
$ cd projects/unix
$ make all
$ sudo make install
If you want to build the Mupen64Plus-Audio-SDL module for installation in a
home folder for a single user, you may build it like this (replacing
<my-folder> with your desired local installation path):
$ cd projects/unix
$ make all
$ make install LIBDIR=<my-folder>

View File

@ -0,0 +1,368 @@
Mupen64Plus-audio-sdl LICENSE
-----------------------------
Mupen64Plus-audio-sdl is licensed under the GNU General Public License version 2.
The authors of Mupen64Plus are:
* Richard Goedeken (Richard42)
* John Chadwick (NMN)
* James Hood (Ebenblues)
* Scott Gorman (okaygo)
* Scott Knauert (Tillin9)
* Jesse Dean (DarkJezter)
* Louai Al-Khanji (slougi)
* Bob Forder (orbitaldecay)
* Jason Espinosa (hasone)
* HyperHacker
* and others.
Mupen64Plus is based on GPL-licensed source code from Mupen64 v0.5, originally written by:
* Hacktarux
* Dave2001
* Zilmar
* Gregor Anich (Blight)
* Juha Luotio (JttL)
* and others.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,103 @@
SDL Audio plugin for Mupen64Plus
---------------------------------
Mupen64Plus-audio-sdl - LATEST REVISION
---------------------------------------
- Bugfix: Don't assume OSS is installed in all linux systems.
- Bugfix: Some combinations of VolumeSetLevel and VolumeMute caused VolumeGetString to return "Mute" when not muted
- Make SDL volume handling the default, since OSS is no longer included in the kernel.
- Minor refactoring of volume handling code.
Mupen64Plus-audio-sdl v1.99.5 - March 10, 2012
--------------------------------------------------
- added version number to SDL-audio plugin config parameters, to support future changes
- updated audio plugin for new Mupen64plus 2.0 API versioning scheme
- makefile fixes and improvements
Mupen64Plus-audio-sdl v1.99.4 - November 22, 2010
--------------------------------------------------
- Bugfix: Plugin should write default config values at startup time
- Bugfix: fixed fast-forward for banjo-kazooie and other games which was broken due to limitation in basic resampling algorithm
- many makefile fixes and improvements
Mupen64Plus-audio-sdl v1.99.3 - February 13, 2010
--------------------------------------------------
- sync with core<-->plugin API change for RomOpen()
- bugfix: logical error in previous audio refactoring causing slowdown/lockup on loading savestate or re-initializing audio
- Makefile improvements:
- 'sdl-config --libs' can give "-Wl,-rpath", so plugin must be linked with CC instead of LD
- issue #257: added to makefile OS type GNU/kFreeBSD
Mupen64Plus-audio-sdl v1.99.2 - January 6, 2010
-------------------------------------------------
- new feature: Completely re-wrote buffering/synchronization code:
- Buffer parameters now work as advertised and all use the same units
- Bugfix: previous defaults and algorithm behavior caused audio choppiness on slower PCs
- Bugfix: maximum speed was previously limited to low value by constraints from primary buffer size
- bugfix: SDL volume control will always be used on systems without OSS support
- new feature: added MSVC8 project file, minor code refactoring to build in Windows
- Makefile improvements:
- throw error if OS/CPU not supported
- use DESTDIR in install/uninstall paths
- Allow user-specified CC/CXX/LD paths
Mupen64Plus-audio-sdl v1.99.1 - December 14, 2009
-------------------------------------------------
- Converted to new Mupen64Plus 2.0 API
- Code cleanup to remove non-standard data types
- Refactored build system to separate source and object files
- bugfix #269: jttl_audio segfaults on exit due to incorrectly ordered shutdown code
Mupen64plus 1.5:
+Additional SDL modulation option for volume control.
+New Gtk GUI for plugin configuration.
+Improved no GUI support.
Mupen64plus 1.4:
+Extended plugin API to allow all for runtime volume changes via OSS.
1.4:
+Use only standard frequency for higher compatibility
+Fast resample algorithm (use only integers)
+Slight improvements in buffer management : pausing audio when buffer underrun occur
1.2:
+Added possibility to swap channels
+Some more optimizations
+Calling RomOpen() is not required anymore. Plugin should now follow Zilmar's specs.
+Added test functions.
+Added support for config file
1.1.1:
+Fixed the bug that was causing terrible noise (thanks Law)
+Much more debugging data appears now if DEBUG is defined
+Few more error checks
1.1:
+Audio device is opened now with native byte ordering of the machine. Just
for compatibility (thanks Flea).
+Fixed possible double freeing bug (thanks Flea)
+Optimizations in AiLenChanged
+Fixed segmentation fault when changing rom.
+Syncronization redone
1.0.1.3:
+Smarter versioning. No more betas.
+More cleaning up done.
+Buffer underrun and overflow messages appear now at stderr (if DEBUG is
defined)
+Many things are now precalculated (this should bring a small performance
boost)
+Buffer underrun bug fixed.
+Segmentation fault when closing rom fixed (at least I think so)
1.0 beta 2:
+Makefile fixed to get rid of annoying warning messages
+Cleaned up some old code
+Default frequency set to 33600Hz (for Master Quest compatibility)
+Better syncronization (needs some work still though)
1.0 beta 1:
+First public release

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{96969748-EA54-43FC-8103-A346E9AD98E7}</ProjectGuid>
<RootNamespace>mupen64plusaudiosdl</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\main.c" />
<ClCompile Include="..\..\src\osal_dynamiclib_win32.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\main.h" />
<ClInclude Include="..\..\src\osal_dynamiclib.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mupen64plus-audio-sdl"
ProjectGUID="{96969748-EA54-43FC-8103-A346E9AD98E7}"
RootNamespace="mupen64plusaudiosdl"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\main.c"
>
</File>
<File
RelativePath="..\..\src\osal_dynamiclib_win32.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\src\main.h"
>
</File>
<File
RelativePath="..\..\src\osal_dynamiclib.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,374 @@
#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# * Mupen64plus-audio-sdl - Makefile *
# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
# * Copyright (C) 2007-2009 Richard Goedeken *
# * Copyright (C) 2007-2008 Tillin9 *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation; either version 2 of the License, or *
# * (at your option) any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * along with this program; if not, write to the *
# * Free Software Foundation, Inc., *
# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# Makefile for SDL Audio plugin in Mupen64plus
# detect operation system
UNAME ?= $(shell uname -s)
OS := NONE
ifeq ("$(UNAME)","Linux")
OS = LINUX
SHARED = -shared
SO_EXTENSION = so
endif
ifeq ("$(UNAME)","linux")
OS = LINUX
SHARED = -shared
SO_EXTENSION = so
endif
ifneq ("$(filter GNU hurd,$(UNAME))","")
OS = LINUX
SHARED = -shared
SO_EXTENSION = so
endif
ifeq ("$(UNAME)","Darwin")
OS = OSX
SHARED = -bundle
SO_EXTENSION = dylib
endif
ifeq ("$(UNAME)","FreeBSD")
OS = FREEBSD
SHARED = -shared
SO_EXTENSION = so
endif
ifeq ("$(UNAME)","OpenBSD")
OS = FREEBSD
SHARED = -shared
SO_EXTENSION = so
$(warning OS type "$(UNAME)" not officially supported.')
endif
ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","")
OS = LINUX
SHARED = -shared
SO_EXTENSION = so
endif
ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW")
OS = MINGW
SHARED = -shared
SO_EXTENSION = dll
PIC = 0
NO_OSS = 1
endif
ifeq ("$(OS)","NONE")
$(error OS type "$(UNAME)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
endif
# detect system architecture
HOST_CPU ?= $(shell uname -m)
NO_ASM ?= 1
CPU := NONE
ifneq ("$(filter x86_64 amd64,$(HOST_CPU))","")
CPU := X86
ifeq ("$(BITS)", "32")
ARCH_DETECTED := 64BITS_32
PIC ?= 0
else
ARCH_DETECTED := 64BITS
PIC ?= 1
endif
endif
ifneq ("$(filter pentium i%86,$(HOST_CPU))","")
CPU := X86
ARCH_DETECTED := 32BITS
PIC ?= 0
endif
ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","")
CPU := PPC
ARCH_DETECTED := 32BITS
BIG_ENDIAN := 1
PIC ?= 1
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","")
CPU := PPC
ARCH_DETECTED := 64BITS
BIG_ENDIAN := 1
PIC ?= 1
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
ifneq ("$(filter arm%,$(HOST_CPU))","")
ifeq ("$(filter arm%b,$(HOST_CPU))","")
CPU := ARM
ARCH_DETECTED := 32BITS
PIC ?= 1
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
endif
ifeq ("$(CPU)","NONE")
$(error CPU type "$(HOST_CPU)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
endif
# base CFLAGS, LDLIBS, and LDFLAGS
OPTFLAGS ?= -O3
WARNFLAGS ?= -Wall
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src
LDFLAGS += $(SHARED)
# default configuration programs
SDL_CONFIG = $(CROSS_COMPILE)sdl-config
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
# 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
LDFLAGS += -fPIC
else
CFLAGS += -fno-PIC
LDFLAGS += -fno-PIC
endif
ifeq ($(BIG_ENDIAN), 1)
CFLAGS += -DM64P_BIG_ENDIAN
endif
# tweak flags for 32-bit build on 64-bit system
ifeq ($(ARCH_DETECTED), 64BITS_32)
ifeq ($(OS), FREEBSD)
$(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386)
endif
CFLAGS += -m32
LDFLAGS += -m32 -Wl,-m,elf_i386
endif
# set special flags per-system
ifeq ($(OS), LINUX)
LDLIBS += -ldl
endif
ifeq ($(OS), OSX)
# Select the proper SDK
# Also, SDKs are stored in a different location since XCode 4.3
OSX_SDK ?= $(shell sw_vers -productVersion | cut -f1 -f2 -d .)
OSX_XCODEMAJ = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f1 -d .)
OSX_XCODEMIN = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f2 -d .)
OSX_XCODEGE43 = $(shell echo "`expr $(OSX_XCODEMAJ) \>= 4``expr $(OSX_XCODEMIN) \>= 3`")
ifeq ($(OSX_XCODEGE43), 11)
OSX_SYSROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
else
OSX_SYSROOT := /Developer/SDKs
endif
ifeq ($(CPU), X86)
ifeq ($(ARCH_DETECTED), 64BITS)
CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
LDFLAGS += -arch x86_64
LDLIBS += -ldl
else
CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
LDFLAGS += -arch i686
LDLIBS += -ldl -read_only_relocs suppress
endif
endif
endif
# test for presence of SDL
ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),)
$(error No SDL development libraries found!)
endif
ifeq ($(OS),FREEBSD)
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
LDLIBS += $(shell $(SDL_CONFIG) --libs)
endif
ifeq ($(OS),OSX)
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
LDLIBS += $(shell $(SDL_CONFIG) --libs)
endif
ifeq ($(OS),LINUX)
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
LDLIBS += $(shell $(SDL_CONFIG) --libs)
endif
ifeq ($(OS),MINGW)
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
LDLIBS += $(shell $(SDL_CONFIG) --libs)
endif
# test for presence of speexdsp
ifneq ($(strip $(shell $(PKG_CONFIG) speexdsp --modversion 2> /dev/null)),)
ifneq ($(NO_SPEEX), 1)
# set speexdsp flags and libraries
CFLAGS += $(shell $(PKG_CONFIG) speexdsp --cflags) -DUSE_SPEEX
LDLIBS += $(shell $(PKG_CONFIG) speexdsp --libs)
endif
else
# warn user
$(warning No libspeexdsp development libraries found. Mupen64plus-sdl-audio will be built without speex-* resampler.)
endif
# test for presence of libsamplerate
ifneq ($(strip $(shell $(PKG_CONFIG) samplerate --modversion 2> /dev/null)),)
ifneq ($(NO_SRC), 1)
# set libsamplerate flags and libraries
CFLAGS += $(shell $(PKG_CONFIG) samplerate --cflags) -DUSE_SRC
LDLIBS += $(shell $(PKG_CONFIG) samplerate --libs)
endif
else
# warn user
$(warning No libsamplerate development libraries found. Mupen64plus-sdl-audio will be built without src-* resampler.)
endif
# test for the presence of OSS
ifneq ($(wildcard /dev/mixer),)
ifneq ($(NO_OSS), 1)
CFLAGS += -DHAS_OSS_SUPPORT
endif
endif
# 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
RM ?= rm -f
INSTALL ?= install
MKDIR ?= mkdir -p
COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
LINK.o = $(Q_LD)$(CC) $(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
# set installation options
ifeq ($(PREFIX),)
PREFIX := /usr/local
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)/main.c \
$(SRCDIR)/volume.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-audio-sdl$(POSTFIX).$(SO_EXTENSION)
targets:
@echo "Mupen64Plus-audio-sdl makefile. "
@echo " Targets:"
@echo " all == Build Mupen64Plus SDL audio plugin"
@echo " clean == remove object files"
@echo " rebuild == clean and re-build all"
@echo " install == Install Mupen64Plus SDL audio plugin"
@echo " uninstall == Uninstall Mupen64Plus SDL audio 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)"
@echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)"
@echo " PIC=(1|0) == Force enable/disable of position independent code"
@echo " NO_SRC=1 == build without libsamplerate; disables src-* high-quality audio resampling"
@echo " NO_SPEEX=1 == build without libspeexdsp; disables speex-* high-quality audio resampling"
@echo " NO_OSS=1 == build without OSS; disables Open Sound System support"
@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 " 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 " LTO=1 == enable experimental build with link-time optimization"
@echo " V=1 == show verbose compiler output"
all: $(TARGET)
install: $(TARGET)
$(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)"
$(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)"
uninstall:
$(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)"
clean:
$(RM) -r $(OBJDIR) $(TARGET)
rebuild: clean all
# build dependency files
CFLAGS += -MD
-include $(OBJECTS:.o=.d)
ifeq ($(LTO), 1)
CFLAGS += -flto
LDFLAGS += -fuse-linker-plugin $(CFLAGS)
endif
# standard build rules
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -o $@ $<
$(TARGET): $(OBJECTS)
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
.PHONY: all clean install uninstall targets

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - main.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008-2012 Tillin9, Richard42 *
* *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* version info */
#define SDL_AUDIO_PLUGIN_VERSION 0x016305
#define AUDIO_PLUGIN_API_VERSION 0x020000
#define CONFIG_API_VERSION 0x020100
#define CONFIG_PARAM_VERSION 1.00
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
/* declarations of pointers to Core config functions */
extern ptr_ConfigListSections ConfigListSections;
extern ptr_ConfigOpenSection ConfigOpenSection;
extern ptr_ConfigDeleteSection ConfigDeleteSection;
extern ptr_ConfigSaveSection ConfigSaveSection;
extern ptr_ConfigListParameters ConfigListParameters;
extern ptr_ConfigSaveFile ConfigSaveFile;
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;

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 <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include "m64p_types.h"
#include "osal_dynamiclib.h"
void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
{
if (pccProcedureName == NULL)
return NULL;
return dlsym(LibHandle, pccProcedureName);
}

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 <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "m64p_types.h"
#include "osal_dynamiclib.h"
m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
{
if (pLibHandle == NULL || pccLibraryPath == NULL)
return M64ERR_INPUT_ASSERT;
*pLibHandle = LoadLibrary(pccLibraryPath);
if (*pLibHandle == NULL)
{
char *pchErrMsg;
DWORD dwErr = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg);
LocalFree(pchErrMsg);
return M64ERR_INPUT_NOT_FOUND;
}
return M64ERR_SUCCESS;
}
void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
{
if (pccProcedureName == NULL)
return NULL;
return GetProcAddress(LibHandle, pccProcedureName);
}
m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
{
int rval = FreeLibrary(LibHandle);
if (rval == 0)
{
char *pchErrMsg;
DWORD dwErr = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg);
LocalFree(pchErrMsg);
return M64ERR_INTERNAL;
}
return M64ERR_SUCCESS;
}

View File

@ -0,0 +1,88 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-sdl-audio - volume.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2007-2008 Richard42 Ebenblues *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#if defined(HAS_OSS_SUPPORT)
/* Sound volume functions. */
#include <sys/soundcard.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h> /* close() */
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include "volume.h"
/* volSet
* Sets volume of left and right PCM channels to given percentage (0-100) value.
*/
void volSet(int percent)
{
int ret, vol;
int mixerfd = open("/dev/mixer", O_RDONLY);
if(mixerfd < 0)
{
perror("/dev/mixer");
return;
}
if(percent > 100)
percent = 100;
else if(percent < 0)
percent = 0;
vol = (percent << 8) + percent; // set both left/right channels to same vol
ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &vol);
if(ret < 0)
perror("Setting PCM volume");
close(mixerfd);
}
/* volGet
* Returns volume of PCM channel as a percentage (0-100).
* Returns 0 on error.
*/
int volGet(void)
{
int vol, ret;
int mixerfd = open("/dev/mixer", O_RDONLY);
if(mixerfd < 0)
{
perror("/dev/mixer");
return 0;
}
ret = ioctl(mixerfd, MIXER_READ(SOUND_MIXER_PCM), &vol);
if(ret < 0)
perror("Reading PCM volume");
close(mixerfd);
return vol & 0xff; // just return the left channel
}
#endif /* defined(HAS_OSS_SUPPORT) */

View File

@ -0,0 +1,33 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - nogui.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2007-2008 Richard42 Ebenblues *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Sound volume functions.
*/
#ifndef __VOLUME_H__
#define __VOLUME_H__
void volSet(int);
int volGet(void);
#endif // __VOLUME_H__

View File

@ -0,0 +1,26 @@
Mupen64Plus-Core INSTALL
------------------------
This text file was written to explain the installation process of the
Mupen64Plus-Core 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-Core 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 SHAREDIR=<my-folder>
$ make install LIBDIR=<my-folder> SHAREDIR=<my-folder>

View File

@ -0,0 +1,48 @@
Mupen64Plus-Core LICENSES
-------------------------
Mupen64Plus-Core is licensed under the GNU General Public License version 2. Please see the
included doc/gpl-license file for the terms and conditions of the GNU General Public License.
The authors of Mupen64Plus are:
* Richard Goedeken (Richard42)
* John Chadwick (NMN)
* James Hood (Ebenblues)
* Scott Gorman (okaygo)
* Scott Knauert (Tillin9)
* Jesse Dean (DarkJezter)
* Louai Al-Khanji (slougi)
* Bob Forder (orbitaldecay)
* Jason Espinosa (hasone)
* HyperHacker
* and others.
The Mupen64Plus API documentation (located in doc/emuwiki-api-doc/*) is Copyright(C) 2009-2011
by Richard Goedeken and is licensed under the GNU General Public License version 2.
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.
The OGLFT library used for the On-Screen Display is based on GPL/LGPL-licensed code Copyright 2002 lignum Computing. Please see the included doc/lgpl-license file for the terms and conditions of the GNU Lesser General Public License. More information about this library is available at the following websites:
- http://oglft.sourceforge.net/index.html
- http://directory.fsf.org/project/OGLFT/
Additionally, mupen includes a number of components licensed under other OSI approved licenses:
The BSD license:
* minizip by Gilles Vollant and others, ftp://ftp.info-zip.org/pub/infozip/license.html
* src/memory/n64_cic_nus_6105.c/.h, by X-Scale
The zlib/libpng license:
* Adler-32 by Mark Adler
* libpng by Glenn Randers-Pehrson, Peter Deutsch, and Guy Eric Schalnat
* MD5 hasing code by Peter Deutsch
The Bitstream license:
* The TrueType font (data/font.ttf) is licensed by the Bitstream license. Please see the included doc/font-license file for the terms and conditions of the Bitstream license.

View File

@ -0,0 +1,146 @@
Mupen64Plus-Core README
-----------------------
The most current version of this README and more documentation can be found on
the Mupen64Plus wiki:
http://code.google.com/p/mupen64plus/wiki/README
Mupen64Plus is based off of mupen64, originally created by Hacktarux. This
package contains the only the Mupen64Plus core library. For a fully functional
emulator, the user must also install graphics, sound, input, and RSP plugins,
as well as a user interface program (called a front-end).
README Sections
1. Requirements for building or running Mupen64Plus
2. Building From Source
3. Installation
4. Key Commands In Emulator
1. Requirements and Pre-requisites
----------------------------------
*Binary Package Requirements*
- SDL 1.2
- libpng
- freetype 2
- zlib
*Source Build Requirements*
In addition to the binary libraries, the following packages are required if you
build Mupen64Plus from source:
- GNU C and C++ compiler, libraries, and headers
- GNU make
- Development packages for all the libraries above
2. Building From Source
-----------------------
If you downloaded the binary distribution of Mupen64Plus, skip to the
Installation section. To build the source distribution, unzip and cd into the
projects/unix directory, then build using make:
$ unzip mupen64plus-core-x-y-z-src.zip
$ cd mupen64plus-core-x-y-z-src/projects/unix
$ make all
Type 'make' by itself to view all available build options:
$ make
Mupen64Plus makefile.
Targets:
all == Build Mupen64Plus and all plugins
clean == remove object files
install == Install Mupen64Plus and all plugins
uninstall == Uninstall Mupen64Plus and all plugins
Options:
BITS=32 == build 32-bit binaries on 64-bit machine
LIRC=1 == enable LIRC support
NO_ASM=1 == build without assembly (no dynamic recompiler or MMX/SSE code)
SHAREDIR=path == extra path to search for shared data files
OPTFLAGS=flag == compiler optimization (default: -O3)
PIC=(1|0) == Force enable/disable of position independent code
Install Options:
PREFIX=path == install/uninstall prefix (default: /usr/local/)
SHAREDIR=path == path to install shared data (default: PREFIX/share/mupen64plus/)
LIBDIR=path == path to install plugin libs (default: PREFIX/lib)
INCDIR=path == path to install core header files (default: PREFIX/include/mupen64plus)
DESTDIR=path == path to prepend to all installation paths (only for packagers)
Debugging Options:
PROFILE=1 == build gprof instrumentation into binaries for profiling
DEBUG=1 == add debugging symbols to binaries
DEBUGGER=1 == build graphical debugger
DBG_CORE=1 == print debugging info in r4300 core
DBG_COUNT=1 == print R4300 instruction count totals (64-bit dynarec only)
DBG_COMPARE=1 == enable core-synchronized r4300 debugging
DBG_PROFILE=1 == dump profiling data for r4300 dynarec to data file
V=1 == show verbose compiler output
3. Installation
---------------
*Binary Distribution*
To install the binary distribution of Mupen64Plus, su to root and run the
provided install.sh script:
$ su
# ./install.sh
# exit
$
The install script will copy the executable to /usr/local/bin and a directory
called /usr/local/share/mupen64plus will be created to hold plugins and other
files used by mupen64plus.
NOTE: By default, install.sh uses /usr/local for the install prefix. Although
the user can specify an alternate prefix to install.sh at the commandline, the
mupen64plus binary was compiled to look for the install directory in /usr/local,
so specifying an alternate prefix to install.sh will cause problems (mupen64plus
will not find the install directory). If you want to use a prefix other than
/usr/local, you will have to download the source package and build with the
PREFIX option (see below).
*Source Distribution*
After building mupen64plus and all plugins, su to root and type 'make install'
to install Mupen64Plus. The install process will copy the executable to
$PREFIX/bin and a directory called $PREFIX/share/mupen64plus will be created
to hold plugins and other files used by mupen64plus. By default, PREFIX is set
to /usr/local. This can be changed by passing the PREFIX option to make. NOTE:
you must pass the prefix, when building AND installing. For example, to install
mupen64plus to /usr, do this:
$ make all
$ sudo make PREFIX=/usr install
$
4. Key Commands In Emulator
---------------------------
The keys or joystick/mouse inputs which will be mapped to the N64 controller
for playing the games are determined by the input plugin. The emulator core
also supports several key commands during emulation, which may be configured by
editing the ~/.config/mupen64plus/mupen64plus.cfg file. They are:
Escape == Quit the emulator
0-9 == Select virtual 'slot' for save/load state (F5 and F7) commands
F5 == Save emulator state
F7 == Load emulator state
F9 == Reset emulator
F10 == slow down emulator by 5%
F11 == speed up emulator by 5%
F12 == take screenshot
Alt-Enter == Toggle between windowed and fullscreen (may not be supported by all video plugins)
p or P == Pause on/off
m or M == Mute/unmute sound
g or G == Press "Game Shark" button (only if cheats are enabled)
/ or ? == single frame advance while paused
F == Fast Forward (playback at 250% normal speed while F key is pressed)
[ == Decrease volume
] == Increase volume

View File

@ -0,0 +1,572 @@
Mupen64Plus-Core Emulator Library RELEASE
-----------------------------------------
Mupen64Plus v1.99.5 - March 10, 2012
------------------------------------
- New feature: support for N64 internal real-time clock
- use X-Scale's PIF-CIC algorithm instead of the hard-coded challenge-response pairs
- New config parameter for path to save SRAM/EEPROM/MPK files, so they can be separated from emulator snapshots
- updated core for new Mupen64plus 2.0 API versioning scheme
- split core configuration data into 2 sections: Core and CoreEvents. Added version numbers and upgrade handling to both
- Accurately emulate the RSP DMA operation (from Bobby Smiles)
- bugfix: #290 - OnScreenDisplay text is sometimes captured in screenshots
- bugfix: when the front-end specifies an override for the configuration directory, always use this path, so that we don't load the config from there and then save it back to the default user path
- bugfix: #468 - On-screen-display problem under OSX
- bugfix: Use option SaveStatePath from config file
- bugfix: don't call SDL_Quit() until the core library is being unloaded. fixes some front-end use cases
- bugfix: #410 - segfault in dma_pi_write()-->strlen() if /home/username/.local/share/mupen64plus/ owned by root
- bugfix: for Interpreter cores, use proper math functions for ceil/floor/round/trunc instead of x87 rounding modes
- many makefile fixes and improvements
Mupen64Plus v1.99.4 - February 22, 2010
---------------------------------------
- Added some type checking to ConfigGetParameter() function, and a new error type
- Bugfix: avoid segfault in the video extension code if SDL initialization fails (because video plugin fails)
- Added new CoreGetRomSettings() function for front-ends
- Allow to run dynarec in hardware DEP protected windows
- Allow core .cfg parser to accept strings without quotes around them
- API change: use new ReadScreen2() video plugin function
- New re-entrant R4300 disassembler, from tty68k/zzt32, a man who loves MIPS processors
- makefile fixes and improvements, code cleanups
Mupen64Plus v1.99.3 - February 13, 2010
---------------------------------------
- New feature: configuration function ConfigGetParameterType()
- New feature: up to 1000 screenshots per ROM are allowed
- New feature: support for Gameshark 3.3 patch codes
- Bugfix: Use Dynarec by default when core supports it. If dynarec is selected but unavailable, fall back to cached interpreter
- Bugfix: screenshot directory handling code used unix-specific path separators; now is platform-independent
- Bugfix: #313 - 64-bit inline assembly code in r4300/x86_64/rjump.c needs to have underscores before the symbols names in OSX
- Bugfix: old bug in the core - hang if a ROM *without* a 16kb EEPROM type is loaded after a ROM *with* a 16kb EEPROM type
- Bugfix: rumble feature caused memory corruption
- Bugfix: Problem with zilmar API: the plugin RomOpen() functions had no way of returning errors to the core, causing crashes
- Replaced api documentation .tar.gz file with the mediawiki text
- Build script improvements:
- new feature: m64p_update.sh script can take an input argument to update to a tag or revision
- new feature: added bash script for building source packages of individual modules
- Makefile improvements:
- dont run ldconfig on make install unless user is root
- added OS type GNU/kFreeBSD
Mupen64Plus v1.99.2 - January 6, 2010
---------------------------------------
- doc: added tarball of emuwiki api documentation from 2010-01-06 for backup purposes
- clean-up: removed almost all of the ifdef WIN32 statements
- bugfix: stop spamming console with "Core: couldn't open memory pack file '...' for reading" messages
- bugfix: stop spamming console with "Core: couldn't open eeprom file '...' for reading" messages
- new feature: MSVC8 project file for mupen64plus-core, refactored code for VC8 compatibility
- Makefile improvements:
- throw error if OS/CPU not supported
- use DESTDIR in install/uninstall paths
- Allow user-specified CC/CXX/LD paths
- makefile needs to install Core header files so that plugins can be built later
Mupen64Plus v1.99.1 - December 14, 2009
---------------------------------------
New 2.0 architecture advantages:
- Simplified emulator Core, making it much more portable
- Removed all GUI code from plugins, making them simpler and more portable
- User interface development is not tied to Core emulator releases
- All messages from core/plugins can be filtered and shown in GUI instead of only on console
- Video Extension allows Front-end to override some video functions, ie to support embedded render window
- Startup in Fullscreen mode, instead of always starting in windowed mode and switching to FS after few seconds
- video resolution can be given via command-line parameter
- all configuration options for core and plugins are in a single config file, can be configured with a single GUI
- dummy plugins are automatically used if plugin loading fails for any reason
- core and plugins all use the same conventions for where to put data/config files
Mupen64Plus core:
- New feature: cheat code support
- New feature: Keyboard shortcuts for Core commands are now user-configurable
- New feature: can load/save PJ64 state files
- Major code cleanup, refactored build system to separate source and object files
- Removed many dependencies to simplify porting to other platforms
- Moved all of the SDL event-related stuff into a new source file eventloop.c
- Use XDG directory convention for file locations on Unix
- bugfix: frame advance feature should advance every frame, instead of every vertical interrupt (every field)
- bugfix: allow diagonal hat movements for core joystick commands
- bugfix: modified SDL event loop joystick code so that gameshark button press is captured, and joystick commands that are level-triggered instead of edge-triggered (such as fast foward) can be accommodated
- bugfix: fixed the outstanding SDL event issues by re-writing the code which handles the joystick-event-driven core commands. Now the axis-based commands use hysteresis and there is a single global event function for determining if the gameshark button is pressed
- bugfix: OSD crash after pause-stop-start-pause of emulator
- bugfix: Set video width and status, aiDacrate during savestate load
- bugfix: in pure interpreter, Dont allow to override r0 register
- bugfix #52: PJ64 load state patch from olejl77
- bugfix #268: use aligned malloc and mprotect to set executable status for dynarec emitted code
- bugfix #51: Floating Point Register data was not correctly converted when switching between 32-bit (MIPS-I) mode and 64-bit (MIPS III).
New code more closely emulates behavior of r4300 hardware. Fixes collision problems in Banjo-Tooie
- bugfix #272: rounding mode for x86 FPU not being set correctly in interpreter and pure interpreter cores
- bugfix: many games need different ScreenUpdateSetting to work properly with Rice Video
Mupen64Plus v1.5 - January 4, 2009
----------------------------------
Major New Features:
- support for Macintosh OSX platform with Intel CPUs
- Qt4 GUI by slougi, Tillin9, and others
- Rom Cache System (r636, others), by Tillin9, Okaygo, and Hasone.
Minor New Features:
- r1235: Debugger: memory breakpoint speedup
- r1170-1178,1181: QT GUI: translations for English, Norwegian, German, and Dutch
- r1155: Use configurable key commands for special emulator functions
- r1134: got our own custom test ROM, courtesy of Marshallh
- r1046: debugger: new r4300 disassembler from ZZT32
- r829: jttl_audio: added GTK GUI configuration dialog
- r793: soft reset (hit F9)
- r782: jttl_audio: both SDL-based and OSS-based volume control methods are now supported
- r765: added savestate conversion tool to be able to load pre-v1.5 savestate files
- r711: 7-zip support
- r692: Multi-file Zip support
- r667: GTK GUI: user-configurable columns in ROM browser
- r659: LZMA archive support
- r638: BZip2 archive support
- r629,634: LIRC - added support for speedup, slowdown, pause, and frame advance
Updates:
- r1007,1032: GTK GUI improvements
- r970, 1019: use SDL threading support instead of pthreads
- r935,938,940: Gtk GUI updates for core and Jttl
- r642,655-657,663,664,747,759,761-763,768-770,774,775,780,781,783,786,787,825,828,931: mupen64plus.ini updates: Good Names, stars, EEPROM types, players, rumble support
Bugfixes:
- r1247: rsp_hle: memory overwrite bug with Zelda:OOT
- r1234: out of bound array bug in memory access function handlers
- r1222,1223,1228,1229: Debugger fixes
- r1183: Blight Input: sometimes the axis direction would flip
- r1133: Added stop rumble to load savestate, fixes issue 165
- r1077: GTK GUI bugfixes
- r1063: rice video: crash in MMX/SSE checking functions
- r800: logical error in strcpy loop in util.c
- r798: small bugfixes in blight_input: 1. only save config file after running config dialog, not every time DLL is closed. 2. If rumble is not available on a controller, don't allow user to switch between rumble and mempack. 3. If rumble is selected in config file but not available on a controller, select mempack instead.
- r789: 3 glN64 bugfixes (segfaults on a 64-bit system in Perfect Dark): prevent clamp values from being negative, handle TMEM wrap-arounds from wacky height/line values in texture cache load and texture CRC functions
- r788: rice video: add checks for uint32 height/width parameters which can be negative, causing segfault on 64-bit systems
- r784: 64-bit problem causing GUI crashes - gotta save/restore all the callee-saved registers around the dynarec
- r758: fixed some savestate problems
- r748: Fixed 64-bit dynarec crash in genj_idle() and genjal_idle()
- r715: Bugfixes thanks to Valgrind. Two using strcpy with source and destination overlay, i.e. strcpy(p,p+1)
- r700: set ScreenUpdateSetting=1 in rice video ini file for Conkers BFD
- r694: require bash shell scripting for install.sh
- r686: fixed OSD crash bug after running a game, disabling OSD, then running another game
- r684: OGLFT measuring functions were taking a huge chunk of CPU time. Refactored code to measure only once and store the line size and the message sizes instead of re-measuring all the time. This eliminated nearly all of the OSD overhead on my PC
- r681: Refactored OGLFT to do color setting outside of glyph compiling, so the OSD fading doesnt force bitmaps to be continually recreated with calls to renderGlyph. Seems to have cut the excessive cpu usage of the OSD about by half
- r680: removed many unused classes from OGLFT font library code
- r676: bugfix in my BYTESWAP macros
- r674: Removed glide64/Tmem_nasm.asm source file and the project dependency on nasm/yasm assemblers
- r673: removed inline assembly sections in rdp_loadblock and rdp_loadtile, including their dependency on functions in Tmem_nasm.asm. Replaced with new C code. This fixes a segfault on some 64-bit source builds
- r669: string function causing crash on 64-bit linux
- r667: issue #88 - added basic view menu in GTK GUI
- r628,633: Small patch to get glide64.so to compile with O3 optimizations
- r622: Fixed segfault in Glide64 as per issue 133
- r619: fix LIRC build to integrate w/ new screenshot mechanism
- r608: another couple of memory leak fixes from Tub, in main/config.c
- r605: fix from Tub for free() bug in main/util.c/list_delete()
- r587: issue #111: close screenshot file after saving
Mupen64Plus v1.4 - June 14, 2008
-----------------------------------
- New feature: Graphical debugger for R4300 core
- New feature: On Screen Display
- New feature: KDE4 GUI (experimental)
- New feature: cheat system with Gameshark codes
- New feature: search/filter box in GTK GUI
- New feature: Single frame advance
- New feature: adjust emulator playback speed up or down in 5% increments
- New feature: Rumble Pak support with force feedback
- New feature: Map emulator functions (fullscreen, stop emulation, etc) to joystick buttons or axis movements.
- New feature: Volume up/down
- Blight Input: Individually configure each direction of X and Y axis, which allows inverting the axis
- JTTL_Audio: libsamplerate support for high quality audio resampling
- GTK GUI: Removed second status bar which was not used
- GTK GUI: Implemented accelerator keys
- GTK GUI: Replaced custom directory browser with GTK file chooser
- GTK GUI: numerous small changes and fixes
- Added Mupen64Plus 'man' (manual) page
- Removed mupen64_audio plugin, as it was unnecessary and mostly broken
- Added NoMemoryExpansion parameter to emulate 4MB console; fixes some games
- Overhaul of rom handling functions; numerous small fixes
- Bugfix: Removed NoAudioDelay core option to resolve issue #48
- Bugfix: check for stopped state in dynarec jump function, to fix unresponsive emulator when game gets stuck in loop
- Bugfix: GTK GUI: #6 - if a ROM is selected in the ROM browser and 'play' is pressed, emulation will start
- Bugfix: GTK GUI: #62 - ROM browser column sorting works
- Bugfix: Rice Video: Support hi-res textures with different scale factors for X and Y
- Bugfix: Blight Input: don't use 100% CPU in configuration dialog
Mupen64Plus v1.3 - March 29th, 2008
-----------------------------------
- New feature: Glide64 video plugin for 32-bit and 64-bit, renamed project Mupen64Plus
- New feature: Combine mupen64 and mupen64_nogui into a single binary
- New feature: ability to change icon size
- New feature: support different directories for install (plugins, icons, etc) and config (save games, config files)
- New feature: support for creating/using ~/.mupen64plus dir for storing user data
- New feature: support for installation via "make install" or "./install.sh"
- New feature: support for plugins given via command line option in GUI mode
- New feature: config dialog checkbox to toggle "noask" setting
- New feature: pause/continue functionality with LIRC
- Removed messagebox utility and replaced it with cleaner alert_message/confirm_message calls
- GTK GUI: Set parent window for all popups so WM will center popup windows over the main gui window
- Added README file with information about usage of Mupen64Plus and plugins
- Removed mupen64_soft_gfx, as it didn't work
- Removed Win32 code from RSP HLE plugin,
- Change fullscreen hotkey to Alt+Enter
- Only plugin filenames (not paths) are stored in the mupen64plus.conf file
- Modified pre.mk and glide64 makefile to auto-select yasm or nasm
- Bugfix: Rice Video: Make configuration during gameplay possible again
- Bugfix: many compiler warnings and errors in Glide64
- Bugfix: segfault in Goldeneye and Perfect Dark for 64-bit dynarec
- Bugfix: 64-bit dynarec bug in genld()
- Bugfix: buffer overflow allocating temp strings for basename/dirname
- Bugfix: GTK GUI: Exiting via File -> Exit wasn't writing out config file to disk
- Bugfix: GTK GUI: "About" menu does not pop up while emulation is running
- Bugfix: Glide64: Refactored a bunch of inline asm code with potential bugs
- Bugfix: Added plugin error checking before emulator is started
- Bugfix: Logo not loading in "about" window
- Bugfix: Segfault in plugin_scan_directory()
- Bugfix: ROM pause/continue while playing
- Bugfix: Too many dialog windows when loading a bad dump or hacked rom
- Bugfix: Closing emulation window now stops emulator
- Bugfix: Rice Video: config dialog bug, now it displays proper resolution
- Bugfix: GTK GUI: "Toolbar Style" now works
- Bugfix: Glide64: changed inline asm label syntax, for compatibility with gcc 4.3.0
- Bugfix: Many other minor bug fixes, GTK warnings fixes, translation corrections, etc
Mupen64-amd64 v1.2 - February 10th, 2008
----------------------------------------
- New feature: Dynamic Recompiler for 64-bit
- New feature: New ROM Browser for Mupen64 GUI build
- New feature: LIRC remote control integration for NOGUI build
- Added R4300 instruction counting capability to 64-bit Dynarec
- Added R4300 profile data output for 32-bit and 64-bit dynamic recompilers
- TLB Optimization / bugfix
- Revised makefiles to support PPC builds
- Bugfix: memory leaks in mupenIniApi.c
- Bugfix: corrupted filenames being saved to disk for mupen64.ini
- Bugfix: crash in jttl_audio
- Bugfix: crash when running game from gui after first time
- Bugfix: spurious noise blip when running game from gui after first time
RiceVideoLinux v1.2 - February 10th, 2008
-----------------------------------------
- Revised makefiles to support PPC builds
- Added more logging to hi-res texture loading
- Bugfix: Texture dumping now works
Mupen64-amd64 v1.1 - December 9th, 2007
----------------------------------------
- New icons for GTK GUI
- Removed GTK 1.2 GUI build; GTK 2.0 is required now
- Added file pointer checking for frwite() calls and error logging
- Added scrolling to the the rom list widget
- Added main/version.h file to store Mupen64-amd64 package version
- Print joystick numbers along with names in blight input to tell multiple devices apart
- Merged okaygo's TLB hack for Goldeneye from Mupen64++
- Rework GTK GUI config dialog; fixed bugs in ROM directory list
- Bugfix: segfault from playing same game twice in a row from GUI
- Bugfix: segfault from fwrite() failure in dma_pi_read in memory/dma.c
- Bugfix: exit properly instead of segfault after dyna_stop is called
- Bugfix: blight input: SDL_PumpEvents must be called from thread which initialized SDL video mode
- Bugfix: blight_input: joystick handling caused glitch in config dialog
- Bugfix: makefile: 32-bit CFLAGS must be used when doing 32-bit build on 64-bit machine
- Bugfix: Added makefile to root folder for building releases
RiceVideoLinux v1.1 - December 9th, 2007
-----------------------------------------
- Removed configure script and config.h; added SDL and GTK library checking and handling in main makefile
- Added capability to load 24-bit PNG files into 32-bit texture buffer
- Added more error logging to hi-res texture code
- Added combiner type logging to DeviceBuilder class
- Bugfix: added quotes around BUILD_NUMBER to prevent segfault on About box
- Bugfix: SSE vertex lighting inline ASM code was incorrect
- Bugfix: makefile: 32-bit CFLAGS must be used when doing 32-bit build on 64-bit machine
- Bugfix: segfault with hi-res textures (incorrect scale factor used when creating memory buffer)
- Bugfix: modified DrawSprite function in RenderExt.cpp to eliminate gaps between textures in Puyo Puyo 4
- Bugfix: opengl error in ApplyTextureFilter due to wrong enum type
- Bugfix: Simplified fragment program and removed ATTRIB parameters to fix problems on Intel X3100 hardware
Mupen64-amd64 v1.0 - November 12th, 2007
----------------------------------------
- Forked from Mupen64 v0.5
- Ported to 64-bit architecture by NMN/SirRichard42
- Fixed texture cache problem in glN64
- Print more information during plugin loading process
- Added blight input config file for logitech dual-action style controllers
- Added SDL_GL_SWAP_CONTROL attribute in glN64 to prevent tearing
- Changed glVoids to voids due to strange compilation bug that occurs on certain systems
- Totally refactored makefiles; now plugins are built as sub-modules
- Better logging for R4300 core selection, disallow Dynamic Recompilation for 64-bit builds at compile time
- Set execstack attribute for all mupen64 binaries, to prevent segfault when Dynamic Recompilation is used
- Lots of code cleanup
- Removed 'multi-user' mode of operation
- Removed 'configure' script and config.h file
- Refactored plugin loading code in _nogui build, much more user-friendly now
- Added comments and SDL shutdown code to main.c
- Bugfix: fixed memory leaks in plugin.c
- Bugfix: strcpy in main/gui_gtk/config.c should not copy overlapping strings
- Bugfix: blight audio: only close down audio and timer sub-systems when exiting
RiceVideoLinux v1.0 - November 12th, 2007
-----------------------------------------
- Forked from RiceVideo 6.1.1 beta 10
- Ported to Linux by Hacktarux
- Ported to 64-bit architecture by SirRichard42
- Added rudimentary debug support for Linux
- Merged all Non-Win32 changes from Mudlord's RiceVideo SVN 6.1.3.2 (mostly hi-res texture load/save)
- Added more logging information
- Tweaked Z-Buffer and Z-Bias (Decal Z-mode) handling to be like that of D3D renderer
- Added screenshot capability for Linux build
- Cleaned up Makefile, added 32-bit and debug build modes, help info
- Removed all Win32 code, massive cleanup
- Fixed uninitialized data members in several places
- Bugfix: crash in Banjo Kazooie - dont delete cached texture if its currently loaded in the g_textures array
- Bugfix: crash in Carmaggedon caused by illegal values in texture loading function
- Bugfix: screen flashes in Mario Kart and Kirby64, tweaked .ini ScreenUpdateSetting
what's new in 0.5:
- Core
+ detection of invalid code cache for ambiguous region now use
adler32 (faster than previous algorithm)
+ fixed a bug in ini file compression
+ added support for framebuffer effects functions : these functions
are there to help the plugins that support framebuffer extension
to zilmar's spec. These functions are based on rice's idea. I've
worked closely with Gonetz to implement these and the only plugin
that support this feature is Glide64 0.8 (when option is enabled).
Many hard to emulate framebuffer effects are supported by this
feature. Mariokart's monitor in first race running fullspeed and
puzzle effect in banjo's intro are two examples that i can think
about but there are many more.
+ detection of VI interupt rate works on weird country codes
+ better detection of self modifying code in dma
+ warnings fixed on new gcc versions
+ rsp's dmem and imem are now contiguous in PC's memory (some windows
plugins were requiring this)
+ slightly improved audio timing
+ better detection of self modifying code when accessing memory
through TLB
+ fixed a bug in RSP memory write
+ reading from ai_current_delay register should work even when
Count register is looping
+ in interpreter code : fixed a bug in jump opcodes (detection
of exceptions in delay slot in some rare conditions)
+ the event scheduler has better support for Count register loops
+ better AI interrupt handling (for musyx games for example)
+ jump opcodes changed in pure interpreter core so that they are
timed exactly like on the other cores (easier to debug this way)
+ fixed a bug when accessing memory through invalid TLB in LDL, LDR,
LWL, LWR, SWL, SDL, SDR, SWR opcodes
+ added LL, SC opcodes
+ two consecutive jump opcodes doesn't crash in the dynarec (result
is undefined according to the r4300 manual but some games are doing
it).
+ basic implementation of fpu opcodes in dynarec
+ division by 0 in FPU opcodes is returning NaN
+ all jump opcodes implemented in the dynarec
+ faster inside function loop with dynarec (register cache)
+ various bug fixes in dynarec opcodes
+ memory access improvements in dynarec
- Linux version
+ GUI and all plugins have been switched to GKT2 (all old plugins
should be recompiled for GTK2)
+ detection of GTK 1.2 or GTK 2 in the configure script : if both
are detected, the user can choose which one to use
+ configure script rewritten so that it's compatible with standard
unix shells instead of bash
+ much improved multi-user install support : if multi-user is choosen
in configure script, mupen64 should be compiled ("make") and installed
("make install"). Then, when a user launch mupen64, it will create
automatically a .mupen64 folder in his home and put all required files
there.
+ language saved and restored correctly when quitting mupen64
+ the console version (mupen64_nogui) has command line support and can
read settings from the gui version config file thanks to jogibear's patch
+ autoincrement save slot option when quick saving (thanks to jdratlif's
patch)
+ speed limiter in the core
+ support for plugin configuration changes when a rom is running
- Windows version
+ autoincrement save slot option when quick saving (thanks to jdratlif's
patch)
+ stabilty improvements on the GUI (when closing a rom for example)
+ added support for readScreen function to support avi recording feature
on plugins that don't use opengl or directx (ie: glide64...)
- Sound plugin
+ thread synchronisation improvements
what's new in 0.4:
- A totally new core based on a dynamic recompiler with register caching,
it doesn't compile the fpu yet but it's already much faster compared
to older versions of mupen64 :)
- Self mod code detection has been improved and emulation is faster now
- A lot of little fixes that should improve compaibitlity quite a bit
- A new video recording feature (record in own mupen64 movie format that
can be converted later into a standard avi file)
- The windows GUI has been redesigned by linker
- A lot of other things i forgot... sorry :P
what's new in 0.3:
- All versions
+ General speed up, 10-20 in most games
Save states long loading time fixed, now it should load in less than
a second
+ sound sync is far more accurate now (thanks to Azimer)
it makes some additionnal games booting
+ 64dd detection to fix F-zero
+ a little idle loops bug has been fixed
- Windows port
+ Configuration and initialisation of plugins now can be done prior
running a rom. It fixes numerous configuration issues with plugins as
well
+ Recent roms menu with option to clear and freeze
+ Command line arguments support with option to run in GUIless mode,
compatible with 1964 options, read more about it in pdf
+ Choosing and saving of plugins used per game, access it from Rom
Properties
+ Reset rom menu added
+ Speed Modifier to allow game to run at any speed between 1-200% of
original
Use + and - to increase, decrease it, while in the game. And . to
return to 100%.
+ Start game in fullscreen option
+ Pause emulation when idle fixes
+ Global plugin settings (should be unchecked if you want to use plugins
per game option from rom properties)
+ Switch on/off ToolBar (ALT+T) and Status Bar (ALT+S), useful when
plugin sets wrong resolution in windowed mode, and for those who hate
toolbars :)
+ Selection of columns to show in rom browser
+ English language template updated
+ Support for debugview by linker
Put dll in the main folder, if you want to see log output
+ Tonnes of little fixes...
- RSP hle plugin
+ mario kart sound fixed
what's new in 0.2:
- Core
+ better sound plugin integration
+ optimizations in interrupt handling
+ a totally new interpreter core (half of a compiler => far much faster)
it caches the opcodes when they're decoded
+ self modifying code detection code for the new interpreter and the
compiler when it'll be implemented
+ RSP plugin integration
+ pif2 implemented for banjo tooie
- RSP hle plugin
+ the first version of this plugin based on uhle sound code
+ 3 main audio ucode implemented (based on uhle)
+ mp3 ucode implemented (direct asm to c translation)
+ jpeg ucode (direct asm to c translation)
+ boot code for btooie and dk
+ on windows: ability to use the hle part of a sound plugin while using another
to output the sound (example: using hle from Azimer's plugin and
ouputing with Jabo's plugin)
This option doesn't work with azimer's audio plugin 0.3 version
Please see more info about RSP and this feature in
readme.pdf in chapter "3.3.2 Configuration"
- Sound Plugin for linux
+ a new lle sound plugin that's using the OSS api
- Windows port
+ Major cleanup of gui code and bug fixes
+ Gui improvements in rombrowser
+ Gui changes in configuration sheets and about dialog
+ Updates in language support and template
Dialog with proper credits to translators ,send us your translations now :)
+ Support for screenshots from menu (depends on video plugin) (F3 key)
+ Added some shortcuts for gui functions to accelerators
+ Option to choose directories of plugins,screenshots and save states in sheets
+ Auto limit VI/s according to game region (60 or 50)
+ Ini updated with latest N64 releases
+ ...
what's new in 0.1:
- Core
+ sram bug zelda oot fixed
+ flashram is working
+ a new interupt system that'll enabled
more accurate timing in the future but can cause
some compatibility issues right now
+ bug in DMULT/DMULTU opcode fixed
+ some optimizations in jump instructions
+ sound plugins support implemented but not well supported
use sound at your own risk :D
+ a clean tlb implementation
+ tlb exception handled correctly
+ compressed save states with slots
+ the whole memory map has been almost completes
+ newly emulated games include goldeneye, conker's bad fur day
and perfect dark :)
- Windows port
+ Zipped Cache to Rom Browser
+ Multy slot save states
+ Md5 based Ini
+ Rom properties dialog
+ Sound support
+ Config plugins dialog
Allows you to chose and configure plugins
+ Multy directories in rom browser
with recursion as an option
+ Audit roms dialog
+ Many bugs fixed and minor features added
+ ...
- Linux port
+ A new gui made by Blight very similar to the windows one
Everything in the gui is new so one line many new things ;)
what's new in 0.0.90:
- this is a huge update many games are playable now :) but only pure
interpreter work on this release it will be fixed in the future
but currently i am only working on compatibility
- i have totally rewritten the pure interpreter core
- nearly all missing opcodes have been added
- interrupt code has been totally rewritten and should never crash now
- tlb code rewritten, it's faster even if it's not perfect yet
- some fpu opcodes have been debugged
- fpu precision emulation improvements (only for x86 processors)
- many bugs to allow port to big endian processors
- fixed endianness when cpu write directly to pif ram
- rewritten dma code for pure interpreter (with this core it always
work now )
- update dp status register when a display list has been processed
it fixed a lot of roms
- implemented 8Mb RDRAM
- implemented memory pack, eeprom, sram (thanks to Jabo and Zilmar
for the pj64 source code on this part)
- flashram is partially implemented (it's enough to get zelda2 starting)
- a new debugger for linux was made by DavFR (it's for linux and
it uses gtk library)
- zip file support
- a new gui for windows port has been made by ShadowPri, it features
a rom browser with *classic* UHLE look,multy directories support ,
a toolbar (thx Schibo for help on it :), multy languages support,
saving of configuration, ....
- and much more ;)
what's new in 0.0.4:
- a new pure interpreter core (better compatibility but really slow,
will help to debug in the future)
- input plugins (a basic keyboard plugin is included and the obsidian
joystick plugin )
- coprocessor unusable exception implemented
- gui for windows
- again many little bugs i can't remember fixed
- automatic comparison between two cores via a pipe (for debugging)
- ....
what's new in 0.0.3:
- unaligned dma exception fix
- a little gui in gtk
- new opcodes implemented
- memory map fixes
- better initial registers (this was find in the pj64 source code
thanks Zilmar and Jabo)
- implemented Zilmar spec Gfx plugins
- included : a linux port of the tr64 plugin v0.5c
what's new in 0.0.2:
- MARIO64 works!!!
- sound temporarly disabled (Just to not hurt your ears because
hle audio doesn't work :)
- various speed improvements
- various stupid bugs removed
what's new in 0.0.1:
- everything it's the first public release :)

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,191 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Core Parameters =
These are standard parameters which are used by the Mupen64Plus Core library. They are stored in a configuration section called "Core" and may be altered by the front-end in order to adjust the behaviour of the emulator. These may be adjusted at any time and the effect of the change should occur immediately.
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Version
|M64TYPE_FLOAT
|Mupen64Plus Core config parameter set version number. Please don't change.
|-
|OnScreenDisplay
|M64TYPE_BOOL
|Draw on-screen display if True, otherwise don't draw OSD
|-
|R4300Emulator
|M64TYPE_INT
|Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more
|-
|NoCompiledJump
|M64TYPE_BOOL
|Disable compiled jump commands in dynamic recompiler (should be set to False)
|-
|DisableExtraMem
|M64TYPE_BOOL
|Disable 4MB expansion RAM pack. May be necessary for some games.
|-
|AutoStateSlotIncrement
|M64TYPE_BOOL
|Increment the save state slot after each save operation.
|-
|EnableDebugger
|M64TYPE_BOOL
|Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support.
|-
|CurrentStateSlot
|M64TYPE_INT
|Save state slot (0-9) to use when saving/loading the emulator state
|-
|ScreenshotPath
|M64TYPE_STRING
|Path to directory where screenshots are saved. If this is blank, the default value of "<tt>GetConfigUserDataPath()</tt>"/screenshot will be used.
|-
|SaveStatePath
|M64TYPE_STRING
|Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of "<tt>GetConfigUserDataPath()</tt>"/save will be used.
|-
|SaveSRAMPath
|M64TYPE_STRING
|Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of "<tt>GetConfigUserDataPath()</tt>"/save will be used.
|-
|SharedDataPath
|M64TYPE_STRING
|Path to a directory to search when looking for shared data files in the <tt>ConfigGetSharedDataFilepath()</tt> function.
|-
|}
These configuration parameters are used in the Core's event loop to detect keyboard and joystick commands. They are stored in a configuration section called "CoreEvents" and may be altered by the front-end in order to adjust the behaviour of the emulator. These may be adjusted at any time and the effect of the change should occur immediately. The Keysym value stored is actually <tt>(SDLMod << 16) || SDLKey</tt>, so that keypresses with modifiers like shift, control, or alt may be used.
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Kbd Mapping Stop
|M64TYPE_INT
|SDL keysym for stopping the emulator
|-
|Kbd Mapping Fullscreen
|M64TYPE_INT
|SDL keysym for switching between fullscreen/windowed modes
|-
|Kbd Mapping Save State
|M64TYPE_INT
|SDL keysym for saving the emulator state
|-
|Kbd Mapping Load State
|M64TYPE_INT
|SDL keysym for loading the emulator state
|-
|Kbd Mapping Increment Slot
|M64TYPE_INT
|SDL keysym for advancing the save state slot
|-
|Kbd Mapping Reset
|M64TYPE_INT
|SDL keysym for resetting the emulator
|-
|Kbd Mapping Speed Down
|M64TYPE_INT
|SDL keysym for slowing down the emulator
|-
|Kbd Mapping Speed Up
|M64TYPE_INT
|SDL keysym for speeding up the emulator
|-
|Kbd Mapping Screenshot
|M64TYPE_INT
|SDL keysym for taking a screenshot
|-
|Kbd Mapping Pause
|M64TYPE_INT
|SDL keysym for pausing the emulator
|-
|Kbd Mapping Mute
|M64TYPE_INT
|SDL keysym for muting/unmuting the sound
|-
|Kbd Mapping Increase Volume
|M64TYPE_INT
|SDL keysym for increasing the volume
|-
|Kbd Mapping Decrease Volume
|M64TYPE_INT
|SDL keysym for decreasing the volume
|-
|Kbd Mapping Fast Forward
|M64TYPE_INT
|SDL keysym for temporarily going really fast
|-
|Kbd Mapping Frame Advance
|M64TYPE_INT
|SDL keysym for advancing by one frame when paused
|-
|Kbd Mapping Gameshark
|M64TYPE_INT
|SDL keysym for pressing the game shark button
|-
|}
These configuration parameters are used in the Core's event loop to detect joystick commands.
The command strings use a simple format described here. For commands activated by pressing a joystick axis, the format is "J'''x'''A'''y'''+" or "J'''x'''A'''y'''-", where '''x''' is the SDL joystick number (must be between 0 and 9) and '''y''' is the axis number. For the last character, '''+''' represents movement in the positive direction, while '''-''' represents movement in the negative direction. For commands activated by pressing a button, the format is "J'''x'''B'''y'''", where '''x''' is the SDL joystick number (must be between 0 and 9) and '''y''' is the button number. For commands activated by pressing a ''hat'' (a directional switch) on the joystick, the format is "J'''x'''H'''y'''V'''z'''", where '''x''' is the SDL joystick number (must be between 0 and 9), '''y''' is the hat number, and '''z''' is the hat value. The hat value corresponds with the SDL_HAT_ enumerated types: Up is 1, Right is 2, Down is 4, and Left is 8. For diagonal directions, these values may be ''or''d together.
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Version
|M64TYPE_FLOAT
|Mupen64Plus CoreEvents config parameter set version number. Please don't change.
|-
|Joy Mapping Stop
|M64TYPE_STRING
|Joystick event string for stopping the emulator
|-
|Joy Mapping Fullscreen
|M64TYPE_STRING
|Joystick event string for switching between fullscreen/windowed modes
|-
|Joy Mapping Save State
|M64TYPE_STRING
|Joystick event string for saving the emulator state
|-
|Joy Mapping Load State
|M64TYPE_STRING
|Joystick event string for loading the emulator state
|-
|Joy Mapping Increment Slot
|M64TYPE_STRING
|Joystick event string for advancing the save state slot
|-
|Joy Mapping Screenshot
|M64TYPE_STRING
|Joystick event string for taking a screenshot
|-
|Joy Mapping Pause
|M64TYPE_STRING
|Joystick event string for pausing or resuming the emulator
|-
|Joy Mapping Mute
|M64TYPE_STRING
|Joystick event string for muting/unmuting the sound
|-
|Joy Mapping Increase Volume
|M64TYPE_STRING
|Joystick event string for increasing the volume
|-
|Joy Mapping Decrease Volume
|M64TYPE_STRING
|Joystick event string for decreasing the volume
|-
|Joy Mapping Fast Forward
|M64TYPE_STRING
|Joystick event string for temporarily going really fast
|-
|Joy Mapping Gameshark
|M64TYPE_STRING
|Joystick event string for pressing the game shark button
|-
|}

View File

@ -0,0 +1,395 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Plugin Parameters =
These are standard parameters which are used by the Mupen64Plus plugins. The behavior of the plugin library when these parameters are changed while the emulator is running is not defined here. Some plugins will load the parameters when starting and store internal copies of the parameters for use during emulation. Other plugins may read the value of the parameters while running.
=== Audio-SDL ===
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Version
|M64TYPE_FLOAT
|Mupen64Plus Audio SDL config parameter set version number. Please don't change.
|-
|DEFAULT_FREQUENCY
|M64TYPE_INT
|Frequency which is used if rom doesn't want to change it
|-
|SWAP_CHANNELS
|M64TYPE_BOOL
|Swaps left and right channels
|-
|PRIMARY_BUFFER_SIZE
|M64TYPE_INT
|Size of primary buffer in output samples. This is where audio is loaded after it's extracted from n64's memory.
|-
|PRIMARY_BUFFER_TARGET
|M64TYPE_INT
|Fullness level target for Primary audio buffer, in equivalent output samples.
|-
|SECONDARY_BUFFER_SIZE
|M64TYPE_INT
|Size of secondary buffer in samples. This is SDL's hardware buffer.
|-
|RESAMPLE
|M64TYPE_STRING
|Audio resampling algorithm. "trivial" for fastest, lowest-quality algorithm. If compiled with SPEEX support, this can be "speex-fixed-0" to "speex-fixed-10". If compiled with libsrc support, this can be "src-sinc-best-quality", "src-sinc-medium-quality", "src-sinc-fastest", "src-zero-order-hold", or "src-linear".
|-
|VOLUME_CONTROL_TYPE
|M64TYPE_INT
|Volume control type: 1 = SDL (only affects Mupen64Plus output) 2 = OSS mixer (adjusts master PC volume)
|-
|VOLUME_ADJUST
|M64TYPE_INT
|Percentage change each time the volume is increased or decreased
|-
|VOLUME_DEFAULT
|M64TYPE_INT
|Default volume when a game is started. Only used if VOLUME_CONTROL_TYPE is 1
|-
|}
=== Video-General ===
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Fullscreen
|M64TYPE_BOOL
|Use fullscreen mode if True, or windowed mode if False
|-
|ScreenWidth
|M64TYPE_INT
|Width of output window or fullscreen width
|-
|ScreenHeight
|M64TYPE_INT
|Height of output window or fullscreen height
|-
|}
=== Video-Rice ===
{| border="1"
!Parameter Name!!Type!!Usage
|-
|FrameBufferSetting
|M64TYPE_INT
|Frame Buffer Emulation (0=ROM default, 1=disable)
|-
|FrameBufferWriteBackControl
|M64TYPE_INT
|Frequency to write back the frame buffer (0=every frame, 1=every other frame, etc)
|-
|RenderToTexture
|M64TYPE_INT
|Render-to-texture emulation (0=none, 1=ignore, 2=normal, 3=write back, 4=write back and reload)
|-
|ScreenUpdateSetting
|M64TYPE_INT
|Control when the screen will be updated (0=ROM default, 1=VI origin update, 2=VI origin change, 3=CI change, 4=first CI change, 5=first primitive draw, 6=before screen clear, 7=after screen drawn)
|-
|NormalAlphaBlender
|M64TYPE_BOOL
|Force to use normal alpha blender
|-
|FastTextureLoading
|M64TYPE_BOOL
|Use a faster algorithm to speed up texture loading and CRC computation (may break hi-res texture loading)
|-
|AccurateTextureMapping
|M64TYPE_BOOL
|Use different texture coordinate clamping code
|-
|InN64Resolution
|M64TYPE_BOOL
|Force emulated frame buffers to be in N64 native resolution
|-
|SaveVRAM
|M64TYPE_BOOL
|Try to reduce Video RAM usage (should never be used)
|-
|DoubleSizeForSmallTxtrBuf
|M64TYPE_BOOL
|Enable this option to have better render-to-texture quality
|-
|DefaultCombinerDisable
|M64TYPE_BOOL
|Force to use normal color combiner
|-
|EnableHacks
|M64TYPE_BOOL
|Enable game-specific settings from INI file
|-
|EnableFog
|M64TYPE_BOOL
|Enable or disable fog generation
|-
|WinFrameMode
|M64TYPE_BOOL
|If enabled, graphics will be drawn in WinFrame mode instead of solid and texture mode
|-
|FullTMEMEmulation
|M64TYPE_BOOL
|N64 Texture Memory Full Emulation (may fix some games, may break others)
|-
|OpenGLVertexClipper
|M64TYPE_BOOL
|Enable vertex clipper for fog operations
|-
|EnableSSE
|M64TYPE_BOOL
|Enable SSE optimizations for capable CPUs
|-
|EnableVertexShader
|M64TYPE_BOOL
|Use GPU vertex shader
|-
|SkipFrame
|M64TYPE_BOOL
|If this option is enabled, the plugin will skip every other frame
|-
|TexRectOnly
|M64TYPE_BOOL
|If enabled, texture enhancement will be done only for TxtRect ucode
|-
|SmallTextureOnly
|M64TYPE_BOOL
|If enabled, texture enhancement will be done only for textures width+height<=128
|-
|LoadHiResTextures
|M64TYPE_BOOL
|Enable hi-resolution texture file loading
|-
|LoadHiResCRCOnly
|M64TYPE_BOOL
|Filter hi-resolution texture filenames based only on the CRC and ignore format+size tags (Glide64 compatibility)
|-
|DumpTexturesToFiles
|M64TYPE_BOOL
|Enable texture dumping
|-
|ShowFPS
|M64TYPE_BOOL
|Display On-screen FPS
|-
|FogMethod
|M64TYPE_INT
|Enable, Disable or Force fog generation (0=Disable, 1=Enable n64 choose, 2=Force Fog)
|-
|Mipmapping
|M64TYPE_INT
|Use Mipmapping? 0=no, 1=nearest, 2=bilinear, 3=trilinear
|-
|MultiSampling
|M64TYPE_INT
|Enable/Disable MultiSampling (0=off, 2,4,8,16=quality)
|-
|TextureEnhancement
|M64TYPE_INT
|Primary texture filter (0=None, 1=2X, 2=2XSAI, 3=HQ2X, 4=LQ2X, 5=HQ4X, 6=Sharpen, 7=Sharpen More, 8=External, 9=Mirrored)
|-
|TextureEnhancementControl
|M64TYPE_INT
|Secondary texture filter (0 = none, 1-4 = filtered)
|-
|ForceTextureFilter
|M64TYPE_INT
|Force to use texture filtering or not (0=auto: n64 choose, 1=force no filtering, 2=force filtering)
|-
|TextureQuality
|M64TYPE_INT
|Color bit depth to use for textures (0=default, 1=32 bits, 2=16 bits
|-
|OpenGLDepthBufferSetting
|M64TYPE_INT
|Z-buffer depth (only 16 or 32)
|-
|ColorQuality
|M64TYPE_INT
|Color bit depth for rendering window (0=32 bits, 1=16 bits)
|-
|OpenGLRenderSetting
|M64TYPE_INT
|OpenGL rendering level to support (0=auto, 1=OGL_1.1, 2=OGL_1.2, 3=OGL_1.3, 4=OGL_1.4, 5=OGL_1.4_V2, 6=OGL_TNT2, 7=NVIDIA_OGL, 8=OGL_FRAGMENT_PROGRAM)
|-
|AnisotropicFiltering
|M64TYPE_INT
|Enable/Disable Anisotropic Filtering for Mipmapping (0=no filtering, 2-16=quality). This is uneffective if EnableMipmapping is false. If the given value is to high to be supported by your graphic card, the value will be the highest value your graphic card can support. Better result with Trilinear filtering
|}
=== Input-SDL ===
The Mupen64Plus-Input-SDL plugin uses a separate config section for each simulated N64 controller. The sections are named: <tt>Input-SDL-Control1</tt>, <tt>Input-SDL-Control2</tt>, <tt>Input-SDL-Control3</tt>, and <tt>Input-SDL-Control4</tt>. The 4 sections all contain the same parameters.
<b>General-purpose Controller Configuration Parameters</b>
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Version
|M64TYPE_FLOAT
|Mupen64Plus Input-SDL config parameter set version number. Please don't change.
|-
|plugged
|M64TYPE_BOOL
|Specifies whether this controller is 'plugged in' to the simulated N64
|-
|plugin
|M64TYPE_INT
|Specifies which type of expansion pak is in the controller: 1=None, 2=Mem pak, 5=Rumble pak
|-
|mouse
|M64TYPE_BOOL
|If True, then mouse buttons may be used with this controller, and mouse movement will map to X/Y analog stick
|-
|device
|M64TYPE_INT
|Specifies which joystick is bound to this controller: -2=Keyboard/mouse, -1=Auto config, 0 or more= SDL Joystick number
|-
|MouseSensitivity
|M64TYPE_STRING
|The sensitivity coefficients for the mouse to move the N64 controller axis value from 0. For X, Y axes. Values must be positive.
|-
|AnalogDeadzone
|M64TYPE_STRING
|The minimum absolute value of the SDL analog joystick axis to move the N64 controller axis value from 0. For X, Y axes.
|-
|AnalogPeak
|M64TYPE_STRING
|An absolute value of the SDL joystick axis >= AnalogPeak will saturate the N64 controller axis value (at 80). For X, Y axes. For each axis, this must be greater than the corresponding AnalogDeadzone value
|-
|}
<b>Digital Controller Configuration</b>
These parameters are used to bind input events with N64 Controller button presses. There are 14 simulated buttons and 2 special buttons for switching between the Mem Pak and Rumble Pak expansion units. Each configuration parameter is a string which specifies input events which will map to the given N64 button. The configuration strings consist of zero or more input event words. A list of available input event words is given here:
{| border="1"
!Input Event Word!!Usage
|-
|<tt>key(&lt;keysym&gt;)</tt>
|&lt;keysym&gt; = SDLK_* key symbol enumerated type
|-
|<tt>button(&lt;num&gt;)</tt>
|&lt;num&gt; = SDL Joystick Button Number (0 or greater)
|-
|<tt>axis(&lt;num&gt;&lt;dir&gt;)</tt>
|&lt;num&gt; = SDL Joystick Axis Number, &lt;dir&gt; = axis direction (+ = positive, - = negative)
|-
|<tt>axis(&lt;num&gt;&lt;dir&gt;,&lt;deadzone&gt;)</tt>
|&lt;num&gt; = SDL Joystick Axis Number, &lt;dir&gt; = axis direction (+ = positive, - = negative), &lt;deadzone&gt; = minimum axis value (max 32767) to activate button; default 6000
|-
|<tt>hat(&lt;num&gt; &lt;dir&gt;)</tt>
|&lt;num&gt; = SDL Joystick Hat Number, &lt;dir&gt; = hat direction (Up, Down, Left, or Right)
|-
|<tt>mouse(&lt;num&gt;)</tt>
|&lt;num&gt; = mouse button number (1 = left button, 2 = middle, 3 = right, etc)
|-
|}
<br>
{| border="1"
!Parameter Name!!Type!!Usage
|-
|DPad R
|M64TYPE_STRING
|Input event string for mapping the Right button on the D-pad
|-
|DPad L
|M64TYPE_STRING
|Input event string for mapping the Left button on the D-pad
|-
|DPad D
|M64TYPE_STRING
|Input event string for mapping the Down button on the D-pad
|-
|DPad U
|M64TYPE_STRING
|Input event string for mapping the Up button on the D-pad
|-
|Start
|M64TYPE_STRING
|Input event string for mapping the Start button
|-
|Z Trig
|M64TYPE_STRING
|Input event string for mapping the Z trigger
|-
|B Button
|M64TYPE_STRING
|Input event string for mapping the "B" button
|-
|A Button
|M64TYPE_STRING
|Input event string for mapping the "A" button
|-
|C Button R
|M64TYPE_STRING
|Input event string for mapping the Right "C" button
|-
|C Button L
|M64TYPE_STRING
|Input event string for mapping the Left "C" button
|-
|C Button D
|M64TYPE_STRING
|Input event string for mapping the Down "C" button
|-
|C Button U
|M64TYPE_STRING
|Input event string for mapping the Up "C" button
|-
|R Trig
|M64TYPE_STRING
|Input event string for mapping the Right trigger
|-
|L Trig
|M64TYPE_STRING
|Input event string for mapping the Left trigger
|-
|Mempak switch
|M64TYPE_STRING
|Input event string for toggling the Memory Pak unit
|-
|Rumblepak switch
|M64TYPE_STRING
|Input event string for toggling the Rumble Pak unit
|-
|}
<b>Analog Controller Configuration</b>
These parameters are used to bind input events with N64 Controller analog stick movements. There are only 2 analog stick axes, X and Y. Each configuration parameter is a string which specifies input events which will map to the given N64 controller axis movement. The configuration strings consist of zero or more input event words. A list of available input event words is given here:
{| border="1"
!Input Event Word!!Usage
|-
|<tt>key(&lt;key_a&gt;,&lt;key_b&gt;)</tt>
|&lt;key_a&gt; = SDLK_* key symbol for up/left movement. &lt;key_b&gt; = SDLK_* key symbol for down/right movement. The strength of these movements can be modulated with the Left-Shift and Left-Control keys.
|-
|<tt>button(&lt;num_a&gt;,&lt;num_b&gt;)</tt>
|&lt;num_a&gt; = SDL Joystick Button Number for up/left movement. &lt;num_b&gt; = SDL Joystick Button Number for down/right movement.
|-
|<tt>axis(&lt;num_a&gt;&lt;dir_a&gt;,&lt;num_b&gt;&lt;dir_b&gt;)</tt>
|&lt;num_a&gt; = SDL Joystick Axis Number for up/left movement, &lt;dir_a&gt; = axis direction for up/left movement (+ = positive, - = negative). &lt;num_b&gt; = SDL Joystick Axis Number for down/right movement, &lt;dir_b&gt; = axis direction for down/right movement.
|-
|<tt>hat(&lt;num&gt; &lt;dir_a&gt; &lt;dir_b&gt;)</tt>
|&lt;num&gt; = SDL Joystick Hat Number, &lt;dir_a&gt; = hat direction for up/left movement (Up, Down, Left, or Right), &lt;dir_b&gt; = hat direction for right/down movement
|-
|}
<br>
{| border="1"
!Parameter Name!!Type!!Usage
|-
|Y Axis
|M64TYPE_STRING
|Input event string for mapping the Y axis (up/down) of the analog stick
|-
|X Axis
|M64TYPE_STRING
|Input event string for mapping the X axis (left/right) of the analog stick
|-
|}

View File

@ -0,0 +1,67 @@
[http://mupen64plus.retrouprising.com Project page]
Please note: as of January 2011, this API is a work in progress.<br />
The core Mupen64Plus v2.0 modules are complete, but work on GUI front-end applications is ongoing.
To view the design proposal which preceded this API definition, go to [[Mupen64Plus v2.0 Design Proposal 3|Design Proposal 3]].
== New Architecture ==
Earlier versions of Mupen64Plus (and other plugin-based N64 emulators) used a single monolithic application (containing the emulator core) and four plugins. The plugins were dynamically-loaded libraries, and the application used one plugin of each type: Video, Audio, Input, and RSP. Each plugin and the application contained its own GUI code for user interface, and each plugin and the application were individually responsible for finding their own data files and finding, loading, parsing, and storing their own configuration data files.
This was an acceptable architecture for emulators which were only designed to run on a single platform (such as Windows), but causes a lot of developer and user headaches when applied to a cross-platform emulator such as Mupen64Plus. For this reason, we are re-designing the layout of the emulator to solve some of the problems caused by the old architecture.
Under the new architecture, the old monolithic emulator application is split into two parts: a core emulator library and a main application, called the front-end. The front-end is primarily responsible for the user interface. All GUI code will be removed from the core and plugin libraries. The primary function of the core library is to emulate the R4300 CPU and memory system, attaching the plugins to form a full N64 system emulator. The core library also contains some utility functions which may be used by the front-end and plugins, such as a configuration parameter handler.
== High-level Usage ==
The expected sequence of operations which will be taken by the front-end application are as follows:
# Load core library (libmupen64plus.so) and set function pointers
# Call <tt>CoreGetVersion</tt>, check core version and capabilities
# Call <tt>CoreStartup</tt> to initialize the core library
# Load front-end configuration from core config API or through own mechanism
# Find plugins, open dynamic libraries, call <tt>PluginStartup</tt> for each
# Enter message loop for user interaction
# If user selects ROM and presses Play:
#* Load and de-compress the ROM
#* Use <tt>CoreDoCommand</tt> to open the ROM
#* Call <tt>CoreAttachPlugin</tt> to attach selected plugins to core
#* Use <tt>CoreDoCommand</tt> to start emulation
#* When emulation is finished, call <tt>CoreDetachPlugin</tt> on all plugins, then close the ROM
== Core API ==
=== [[Mupen64Plus v2.0 Core Basic|Basic Core Functions]] ===
These two functions (<tt>PluginGetVersion</tt> and <tt>CoreErrorMessage</tt>) are utility functions and may be called at any time (even before core startup). These functions are used by both the front-end and the plugins.
=== [[Mupen64Plus v2.0 Core Front-End|Front-End Functions]] ===
There are several types of functions here, which are exported from the Core library to be used by the front-end. There are 'housekeeping' functions, for startup and shutdown, and attaching and detaching plugins. There is also a Command API which is used for many simple functions such as loading, executing, or stopping a ROM. Finally the Cheat API is here, for adding and removing cheat functions.
=== [[Mupen64Plus v2.0 Core Video Extension|Video Extension API]] ===
These functions are exported from the Core library for use by the video plugin. These functions are used for high-level video setup tasks such as enumerating available screen resolutions, setting the video mode, window caption, OpenGL attributes, and fullscreen mode. The video extension API allows for the abstraction of these functions away from the hard-coded SDL function calls currently in the video plugins, so that a front-end may override these functions and provide its own video API.
=== [[Mupen64Plus v2.0 Core Debugger|Debugger Functions]] ===
These are the debugger functions, which are also called only from the front-end. Most of these functions will return with an error if the core library was not compiled with the debugger enabled. A front-end may examine the <tt>Capabilities</tt> value returned by the <tt>CoreGetVersion</tt> function to determine if the core library was built with the debugger enabled.
=== [[Mupen64Plus v2.0 Core Config|Configuration API]] ===
These configuration functions are exported from the core library and are used by the core and the plugins to store all of their persistent configuration parameters. The front-end application may also use these functions to store its configuration options, or it may use a different mechanism. This section also contains two Operating System Abstraction functions. These functions are used by the core, plugins, and the front-end to find full filepaths to shared data files and user-specific data files.
== Plugin API ==
=== [[Mupen64Plus v2.0 Plugin API|Plugin API]] ===
This section lists all of the functions which are exported by the plugins. The front-end application should only use the <tt>PluginStartup</tt>, <tt>PluginShutdown</tt>, and <tt>PluginGetVersion</tt> functions. All other functions will only be called from the core.
== Configuration Parameters ==
=== [[Mupen64Plus Core Parameters|Core Parameters]] ===
This section lists the names and descriptions of all of the configuration parameters used by the Core library.
=== [[Mupen64Plus Plugin Parameters|Plugin Parameters]] ===
This section lists the names and descriptions of all of the configuration parameters used by the Plugin libraries.

View File

@ -0,0 +1,47 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Basic Core API =
Most libmupen64plus functions return an <tt>m64p_error</tt> return code, which is an enumerated type defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. Front-end code should check the return value of each call to a libmupen64plus function.
{| border="1"
|Prototype
|'''<tt>m64p_error PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)</tt>'''
|-
|Input Parameters
|'''<tt>PluginType</tt>''' Pointer to an enumerated type to store the plugin type. The value <tt>M64PLUGIN_CORE</tt> will always be stored.<br />
'''<tt>PluginVersion</tt>''' Pointer to an integer to store the version number of the Mupen64Plus core. Version number 2.1.3 would be stored as 0x00020103.<br />
'''<tt>APIVersion</tt>''' Pointer to an integer to store the version number of the Core--Front-end API used by the Mupen64plus core library.<br />
'''<tt>PluginNamePtr</tt>''' Pointer to a const character pointer to receive the name of the core library. The const char * which is returned must point to a persistent string (ie, not stored on the stack).<br />
'''<tt>Capabilities</tt>''' Pointer to an integer to store a logically-or'd set of flags which specify the capabilities of the core which were built into the library during compilation. These are defined in the <tt>m64p_core_caps</tt> enumerated type, defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]].
|-
|Usage
|This function retrieves version information from the core library. This function is the same for the core library and the plugins, so that a front-end may examine all shared libraries in a directory and determine their types. Any of the input parameters may be set to NULL and this function will succeed but won't return the corresponding information.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error CoreGetAPIVersions(int *ConfigVersion, int *DebugVersion, int *VidextVersion, int *ExtraVersion)</tt>'''
|-
|Input Parameters
|'''<tt>ConfigVersion</tt>''' Pointer to an integer to store the version number of the Config API exported by the Mupen64plus core library.<br />
'''<tt>DebugVersion</tt>''' Pointer to an integer to store the version number of the Debug API exported by the Mupen64plus core library.<br />
'''<tt>VidextVersion</tt>''' Pointer to an integer to store the version number of the Video Extension API exported by the Mupen64plus core library.<br />
'''<tt>ExtraVersion</tt>''' Pointer to an integer to store an API version number for future use. Currently set to 0.<br />
|-
|Usage
|This function retrieves API version information from the core library. This function may be used by either the front-end application or any plugin modules. Any of the input parameters may be set to NULL and this function will succeed but won't return the corresponding information.
|}
<br />
{| border="1"
|Prototype
|'''<tt>const char * CoreErrorMessage(m64p_error ReturnCode)</tt>'''
|-
|Input Parameters
|'''<tt>ReturnCode</tt>''' Enumerated type containing an error code.
|-
|Usage
|This function returns a pointer to a NULL-terminated string giving a human-readable description of the error.
|}
<br />

View File

@ -0,0 +1,313 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Configuration API =
Most libmupen64plus functions return an <tt>m64p_error</tt> return code, which is an enumerated type defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. Front-end code should check the return value of each call to a libmupen64plus function.
== Selector Functions ==
These functions are used by the front-end to discover the sections in the configuration file, open a section, discover parameters within a section, and find out if a section has been changed.
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigListSections(void *context, void (*SectionListCallback)(void * context, const char * SectionName))</tt>'''
|-
|Input Parameters
|'''<tt>context</tt>''' Void pointer to be passed to the SectionListCallback function<br />
'''<tt>SectionListCallback</tt>''' Pointer to function in front-end for receiving the name of every section in the Mupen64Plus Core configuration data. This function will be called once for each section in the core configuration data structure, and then the ConfigListSections() function will return.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>SectionListCallback</tt>''' pointer cannot be NULL.
|-
|Usage
|This function is called to enumerate the list of Sections in the Mupen64Plus Core configuration file. It is expected that there will be a section named "Core" for core-specific configuration data, "Graphics" for common graphics options, and one section for each plugin library.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigOpenSection(const char *SectionName, m64p_handle *ConfigSectionHandle)</tt>'''
|-
|Input Parameters
|'''<tt>SectionName</tt>''' Name of the Mupen64Plus configuration section to open. This name is case-insensitive. If no section exists with the given name, a new one will be created with no parameters. This name may consist of any ASCII characters between 32 and 127 except brackets "[]".<br />
'''<tt>ConfigSectionHandle</tt>''' This is a handle (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) which is required to be used for subsequent calls to core configuration functions to list, retrieve, or set configuration parameters.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>SectionName</tt>''' and '''<tt>ConfigSectionHandle</tt>''' pointers cannot be NULL.
|-
|Usage
|This function is used to give a configuration section handle to the front-end which may be used to read or write configuration parameter values in a given section of the configuration file.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigListParameters(m64p_handle ConfigSectionHandle, void *context, void (*ParameterListCallback)(void * context, const char *ParamName, m64p_type ParamType))</tt>'''
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>context</tt>''' Void pointer to be passed to the ParameterListCallback function<br />
'''<tt>ParameterListCallback</tt>''' Pointer to function in front-end for receiving the name of every parameter in the given section of the Mupen64Plus Core configuration data. This function will be called once for each parameter in the section, and then the ConfigListParameters() function will return.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''' and '''<tt>ParameterListCallback</tt>''' pointers cannot be NULL.
|-
|Usage
|This function is called to enumerate the list of Parameters in a given Section of the Mupen64Plus Core configuration file.
|}
<br />
{| border="1"
|Prototype
|'''<tt>int ConfigHasUnsavedChanges(const char *SectionName)</tt>'''
|-
|Input Parameters
|'''<tt>SectionName</tt>''' Name of the Mupen64Plus configuration section to check for unsaved changes. This name is case-insensitive. If this pointer is NULL or points to an empty string, then all sections are checked.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.<br />
This function was added in the Config API version 2.2.0.
|-
|Usage
|This function is called to determine if a given Section (or all sections) of the Mupen64Plus Core configuration file has been modified since it was last saved. A return value of 0 means there are no unsaved changes, while a 1 will be returned if there are unsaved changes.
|}
== Modifier Functions ==
These functions are used for deleting parts of the configuration list or saving the configuration data to disk.
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigDeleteSection(const char *SectionName)</tt>'''
|-
|Input Parameters
|'''<tt>SectionName</tt>''' Name of the Mupen64Plus configuration section to delete. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except brackets "[]".<br />
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|This function deletes a section from the Mupen64Plus configuration data.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigSaveFile(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|This function saves the Mupen64Plus configuration file to disk.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigSaveSection(const char *SectionName)</tt>'''
|-
|Input Parameters
|'''<tt>SectionName</tt>''' Name of the Mupen64Plus configuration section to save. This name is case-insensitive.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The named section must exist in the current configuration.<br />
This function was added in the Config API version 2.1.0.
|-
|Usage
|This function saves one section of the current Mupen64Plus configuration to disk, while leaving the other sections unmodified.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigRevertChanges(const char *SectionName)</tt>'''
|-
|Input Parameters
|'''<tt>SectionName</tt>''' Name of the Mupen64Plus configuration section to modify. This name is case-insensitive. This pointer cannot be NULL.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The named section must exist in the current configuration.<br />
This function was added in the Config API version 2.2.0.
|-
|Usage
|This function reverts changes previously made to one section of the current Mupen64Plus configuration file, so that it will match with the configuration at the last time that it was loaded from or saved to disk.
|}
== Generic Get/Set Functions ==
These functions should be used for reading or writing configuration values in most cases.
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigSetParameter(m64p_handle ConfigSectionHandle, const char *ParamName, m64p_type ParamType, const void *ParamValue)</tt>'''
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' NULL-terminated string containing the name of the parameter whose value is being set. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.<br />
'''<tt>ParamType</tt>''' An <tt>m64p_type</tt> value giving the type of the data object that '''ParamValue''' points to. If this is different from the native data representation used by the core, it will be converted into the type used by the core.<br />
'''<tt>ParamValue</tt>''' Pointer to data object containing the value of the parameter to be set.<br />
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''', '''<tt>ParamName</tt>''' and '''<tt>ParamValue</tt>''' pointers cannot be NULL.
|-
|Usage
|This function sets the value of one of the emulator's configuration parameters in the section which is represented by '''<tt>ConfigSectionHandle</tt>'''.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigGetParameter(m64p_handle ConfigSectionHandle, const char *ParamName, m64p_type ParamType, void *ParamValue, int MaxSize)</tt>'''
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' NULL-terminated string containing the name of the parameter whose value is being retrieved. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.<br />
'''<tt>ParamType</tt>''' An <tt>m64p_type</tt> value giving the type of the data object that '''ParamValue''' points to. If this is different from the native data representation used by the core, it will be converted into the type given by '''ParamType'''.<br />
'''<tt>ParamValue</tt>''' Pointer to data object to receive the value of the parameter being retrieved.<br />
'''<tt>MaxSize</tt>''' Size (in bytes) of the data object that '''ParamValue''' points to.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''', '''<tt>ParamName</tt>''' and '''<tt>ParamValue</tt>''' pointers cannot be NULL.
|-
|Usage
|This function retrieves the value of one of the emulator's parameters in the section which is represented by '''<tt>ConfigSectionHandle</tt>'''.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigGetParameterType(m64p_handle ConfigSectionHandle, const char *ParamName, m64p_type *ParamType)</tt>'''
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' Pointer to a NULL-terminated string containing the name of the parameter whose type is being retrieved. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.<br />
'''<tt>ParamType</tt>''' Pointer to an <tt>m64p_type</tt> value to receive the type of the parameter indicated by '''<tt>ParamName</tt>'''.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''', '''<tt>ParamName</tt>''', and '''<tt>ParamType</tt>''' pointers cannot be NULL.
|-
|Usage
|This function retrieves the type of one of the emulator's parameters in the section which is represented by '''<tt>ConfigSectionHandle</tt>'''. If there is no parameter with the given '''<tt>ParamName</tt>''', the error <tt>M64ERR_INPUT_NOT_FOUND</tt> will be returned.
|}
<br />
{| border="1"
|Prototype
|'''<tt>const char * ConfigGetParameterHelp(m64p_handle ConfigSectionHandle, const char *ParamName)</tt>'''
|-
|Return Value
|Pointer to a NULL-terminated string containing usage information for the '''<tt>ParamName</tt>''' parameter. May be NULL.
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' NULL-terminated string containing the name of the parameter for which usage information is being retrieved. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''', and '''<tt>ParamName</tt>''' pointers cannot be NULL.
|-
|Usage
|This function retrieves the help information about one of the emulator's parameters in the section which is represented by '''<tt>ConfigSectionHandle</tt>'''.
|}
== Special Get/Set Functions ==
These parameterized Get/SetDefault functions are provided for simplifying the task of handling default values within a single module. Each code module using the Core's configuration API should set the default values for all configuration parameters used by that module during its Startup() function. This allows the software to set up the default values automatically rather than storing them in a separate "default config file" which has proven problematic in the past. This also solves the problem which occurs when an upgraded module contains a new config parameter not present in the previous release.
The special Get functions return the configuration value directly rather than writing them through a pointer and returning an error code. For this reason, these parameterized Get functions should only be used within a module which 'owns' the configuration section and set up its default values in the Startup() function. Because these functions cannot signal an error to the caller, a front-end should not use these functions to retrieve configuration values for the core or the plugins, unless the names of the parameters have been enumerated with <tt>ConfigListParameters</tt> and are therefore guaranteed to exist.
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error ConfigSetDefaultInt(m64p_handle ConfigSectionHandle, const char *ParamName, int ParamValue, const char *ParamHelp)</tt>'''<br />
'''<tt>m64p_error ConfigSetDefaultFloat(m64p_handle ConfigSectionHandle, const char *ParamName, float ParamValue, const char *ParamHelp)</tt>'''<br />
'''<tt>m64p_error ConfigSetDefaultBool(m64p_handle ConfigSectionHandle, const char *ParamName, int ParamValue, const char *ParamHelp)</tt>'''<br />
'''<tt>m64p_error ConfigSetDefaultString(m64p_handle ConfigSectionHandle, const char *ParamName, const char * ParamValue, const char *ParamHelp)</tt>'''
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' NULL-terminated string containing the name of the parameter whose value is being set. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.<br />
'''<tt>ParamValue</tt>''' Integer or null-terminated string pointer containing the value of the parameter to be set.<br />
'''<tt>ParamHelp</tt>''' NULL-terminated string containing some human-readable information about the usage of this parameter. Can be NULL.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''' and '''<tt>ParamName</tt>''' pointers cannot be NULL.
|-
|Usage
|This function is used to set the value of a configuration parameter if it is not already present in the configuration file. This may happen if a new user runs the emulator, or an upgraded module uses a new parameter, or the user deletes his or her configuration file. If a parameter named '''<tt>ParamName</tt>''' is already present in the given section of the configuration file, then no action will be taken and this function will return successfully. Otherwise, a new parameter will be created its value will be assigned to '''<tt>ParamValue</tt>'''.
|}
<br />
{| border="1"
|Prototype
|
{|
|-
|'''<tt>int</tt>''' || '''<tt>ConfigGetParamInt(m64p_handle ConfigSectionHandle, const char *ParamName)</tt>'''
|-
|'''<tt>float</tt>''' || '''<tt>ConfigGetParamFloat(m64p_handle ConfigSectionHandle, const char *ParamName)</tt>'''
|-
|'''<tt>int</tt>''' || '''<tt>ConfigGetParamBool(m64p_handle ConfigSectionHandle, const char *ParamName)</tt>'''
|-
|'''<tt>const char *</tt>''' || '''<tt>ConfigGetParamString(m64p_handle ConfigSectionHandle, const char *ParamName)</tt>'''
|}
|-
|Input Parameters
|'''<tt>ConfigSectionHandle</tt>''' An <tt>m64p_handle</tt> given by the '''<tt>ConfigOpenSection</tt>''' function.<br />
'''<tt>ParamName</tt>''' NULL-terminated string containing the name of the parameter whose value is being retrieved. This name is case-insensitive. This name may consist of any ASCII characters between 32 and 127 except the equals and hash signs, and may not end in a space.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. The '''<tt>ConfigSectionHandle</tt>''' and '''<tt>ParamName</tt>''' pointers cannot be NULL.
|-
|Usage
|This function retrieves the value of one of the emulator's parameters in the section which is represented by '''<tt>ConfigSectionHandle</tt>''', and returns the value directly to the calling function. If an errors occurs (such as if '''<tt>ConfigSectionHandle</tt>''' is invalid, or there is no configuration parameter named '''<tt>ParamName</tt>'''), then an error will be sent to the front-end via the <tt>DebugCallback()</tt> function, and either a 0 (zero) or an empty string will be returned.
|}
== OS-Abstraction Functions ==
{| border="1"
|Prototype
|'''<tt>const char * ConfigGetSharedDataFilepath(const char *filename)</tt>'''
|-
|Return Value
|Pointer to a NULL-terminated string containing a full directory path and filename to a given shared data file, or NULL if this file was not found.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|It is common for shared data files on Unix systems to be installed in different places on different systems. Therefore, this core function is provided to allow a plugin to retrieve a full pathname to a given shared data file. This type of file is intended to be shared among multiple users on a system, so it is likely to be read-only. Examples of these types of files include: the .ini files for Rice Video and Glide64, the font and Mupen64Plus.ini files for the core, and the cheat code files for the front-end. This function will first search in a directory given via the <tt>DataPath</tt> parameter to the '''<tt>CoreStartup</tt>''' function, then in a directory given by the <tt>SharedDataPath</tt> core configuration parameter, then in a directory which may be supplied at compile time through a Makefile or configure script option, and finally in some common system locations (such as /usr/share/mupen64plus and /usr/local/share/mupen64plus on Unix systems).
|}
<br />
{| border="1"
|Prototype
|'''<tt>const char * ConfigGetUserConfigPath(void)</tt>'''
|-
|Return Value
|Pointer to a NULL-terminated string containing the directory path to user-specific configuration files.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|This function may be used by the plugins or front-end to get a path to the directory for storing user-specific configuration files. This will be the directory where the configuration file "mupen64plus.cfg" is located.
|}
<br />
{| border="1"
|Prototype
|'''<tt>const char * ConfigGetUserDataPath(void)</tt>'''
|-
|Return Value
|Pointer to a NULL-terminated string containing the directory path to user-specific data files.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|This function may be used by the plugins or front-end to get a path to the directory for storing user-specific data files. This may be used to store files such as screenshots, saved game states, or hi-res textures.
|}
<br />
{| border="1"
|Prototype
|'''<tt>const char * ConfigGetUserCachePath(void)</tt>'''
|-
|Return Value
|Pointer to a NULL-terminated string containing the directory path to user-specific caching data files.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function.
|-
|Usage
|This function may be used by the plugins or front-end to get a path to the directory for storing user-specific caching data files. Files in this directory may be deleted by the user to save space, so critical information should not be stored here. This directory may be used to store files such as the ROM browser cache.
|}

View File

@ -0,0 +1,282 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Core Debugger API =
Most libmupen64plus functions return an <tt>m64p_error</tt> return code, which is an enumerated type defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. Front-end code should check the return value of each call to a libmupen64plus function.
== General Debugger Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error DebugSetCallbacks(void (*dbg_frontend_init)(void), void (*dbg_frontend_update)(unsigned int pc), void (*dbg_frontend_vi)(void))</tt>'''
|-
|Input Parameters
|'''<tt>dbg_frontend_init</tt>''' Pointer to function which is called when debugger is initialized.<br />
'''<tt>dbg_frontend_update</tt>''' Pointer to function which is called after debugger hits a breakpoint or executes one instruction in stepping mode.<br />
'''<tt>dbg_frontend_vi</tt>''' Pointer to function which is called during each vertical interrupt.
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function is called by the front-end to supply debugger callback function pointers. If debugger is enabled and then later disabled within the GUI, this function may be called with NULL pointers in order to disable the callbacks.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error DebugSetCoreCompare(void (*dbg_core_compare)(unsigned int), void (*dbg_core_data_sync)(int, void *))</tt>'''
|-
|Input Parameters
|'''<tt>dbg_core_compare</tt>''' Pointer to function which is called after each R4300 instruction, for comparing the operation of one R4300 emulator core against another.<br />
'''<tt>dbg_core_data_sync</tt>''' Pointer to function which is used to transfer data from the sending emulator core to the receiving core, such as controller button press or movement data.
|-
|Requirements
|The Mupen64Plus library must be initialized before calling this function.
|-
|Usage
|This function is called by the front-end to supply callback function pointers for the Core Comparison feature. This feature is designed to work as follows. The front-end application will set up some channel for communicating data between two separately running instances of mupen64plus. For example, the unix console front-end will use named FIFOs. The front-end will register callback functions for comparing the 2 cores' states via this <tt>DebugSetCoreCompare</tt> API call. When the <tt>dbg_core_compare</tt> callback fires, the front-end will use the <tt>DebugGetCPUDataPtr</tt> function (and <tt>DebugMemGetPointer</tt> function if desired) to transmit emulator core state data from the 'sending' instance to the 'receiving' instance. The receiving instance may then check the core state data against it's own internal state and report any discrepancies. When the <tt>dbg_core_data_sync</tt> callback fires, the front-end should transmit a block of data from the sending instance to the receiving instance. This is for the purposes of synchronizing events such as controller inputs or state loading commands, so that the 2 cores may stay synchronized. This feature does not require the <tt>M64CAPS_DEBUGGER</tt> capability to built into the core, but it does require the <tt>M64CAPS_CORE_COMPARE</tt> capability.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error DebugSetRunState(int runstate)</tt>'''
|-
|Input Parameters
|'''<tt>runstate</tt>''' 0 == pause, 1 == single instruction step, 2 == run
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function sets the run state of the R4300 CPU emulator.
|}
<br />
{| border="1"
|Prototype
|'''<tt>int DebugGetState(m64p_dbg_state statenum)</tt>'''
|-
|Input Parameters
|'''<tt>statenum</tt>''' An <tt>m64p_dbg_state</tt> enumerated type specifying which debugger state variable to read.
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function reads and returns a debugger state variable, which are enumerated in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]].
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error DebugStep(void)</tt>'''
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized, the emulator core must be executing a ROM, and the debugger must be active before calling this function.
|-
|Usage
|This function signals the debugger to advance one instruction when in the stepping mode.
|}
<br />
{| border="1"
|Prototype
|'''<tt>void DebugDecodeOp(unsigned int instruction, char *op, char *args, int pc)</tt>'''
|-
|Input Parameters
|'''<tt>instruction</tt>''' 32-bit R4300 instruction opcode<br />
'''<tt>op</tt>''' Pointer to character array to store decoded instruction mnemonic<br />
'''<tt>args</tt>''' Pointer to character array to store instruction arguments<br />
'''<tt>pc</tt>''' Program Counter address at which '''<tt>instruction</tt>''' is stored
|-
|Requirements
|The Mupen64Plus library must be built with debugger support.
|-
|Usage
|This is a helper function for the debugger front-end. This instruction takes a PC value and an R4300 instruction opcode and writes the disassembled instruction mnemonic and arguments into character buffers. This is intended to be used to display disassembled code.
|}
== Memory Functions ==
{| border="1"
|Prototype
|'''<tt>void * DebugMemGetRecompInfo(m64p_dbg_mem_info recomp_type, unsigned int address, int index)</tt>'''
|-
|Input Parameters
|'''<tt>recomp_type</tt>''' Type of information to retrieve about a recompiled machine instruction. Must be a M64P_DBG_RECOMP_* type.<br />
'''<tt>address</tt>''' Program Counter value (in N64 memory space) of R4300 instruction about which to retrieve the recompiled x86 instructions.<br />
'''<tt>index</tt>''' Index of recompiled instruction about which to receive information.
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function. This function may not be available on all platforms.
|-
|Usage
|This function is used by the front-end to retrieve disassembly information about recompiled code. For example, the dynamic recompiler may take a single R4300 instruction and compile it into 10 x86 instructions. This function may then be used to retrieve the disassembled code of the 10 x86 instructions. For '''<tt>recomp_type</tt>''' of <tt>M64P_DBG_RECOMP_OPCODE</tt> or <tt>M64P_DBG_RECOMP_ARGS</tt>, a character pointer will be returned which gives the disassembled instruction code. For '''<tt>recomp_type</tt>''' of <tt>M64P_DBG_RECOMP_ADDR</tt>, a pointer to the recompiled x86 instruction will be given.
|}
<br />
{| border="1"
|Prototype
|'''<tt>int DebugMemGetMemInfo(m64p_dbg_mem_info mem_info_type, unsigned int address)</tt>'''
|-
|Input Parameters
|'''<tt>mem_info_type</tt>''' Type of information to retrieve about an N64 memory location. Must be a M64P_DBG_MEM_* type.<br />
'''<tt>address</tt>''' Memory location (in N64 memory space) about which to retrieve some information.
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function returns an integer value regarding the memory location '''<tt>address</tt>''', corresponding to the information requested by '''<tt>mem_info_type</tt>''', which is a type enumerated in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. For example, if '''<tt>address</tt>''' contains R4300 program code, the front-end may request the number of x86 instructions emitted by the dynamic recompiler by requesting <tt>M64P_DBG_MEM_NUM_RECOMPILED</tt>.
|}
<br />
{| border="1"
|Prototype
|'''<tt>void * DebugMemGetPointer(m64p_dbg_memptr_type mem_ptr_type)</tt>'''
|-
|Input Parameters
|'''<tt>mem_ptr_type</tt>''' Memory type to which a pointer is requested.
|-
|Requirements
|The Mupen64Plus library must be initialized before calling this function.
|-
|Usage
|This function returns a memory pointer (in x86 memory space) to a block of emulated N64 memory. This may be used to retrieve a pointer to a special N64 block (such as the serial, video, or audio registers) or the RDRAM. The '''<tt>m64p_dbg_memptr_type</tt>''' type is enumerated in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]
|}
<br />
{| border="1"
|Prototype
|
{|
|-
|'''<tt>unsigned long long</tt>''' || '''<tt>DebugMemRead64(unsigned int address)</tt>'''
|-
|'''<tt>unsigned int</tt>''' || '''<tt>DebugMemRead32(unsigned int address)</tt>'''
|-
|'''<tt>unsigned short</tt>''' || '''<tt>DebugMemRead16(unsigned int address)</tt>'''
|-
|'''<tt>unsigned char</tt>''' || '''<tt>DebugMemRead8(unsigned int address)</tt>'''
|}
|-
|Input Parameters
|'''<tt>address</tt>''' Memory location (in N64 memory space) from which to retrieve a value.<br />
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|These functions retrieve a value from the emulated N64 memory. The returned value will be correctly byte-swapped for the host architecture.
|}
<br />
{| border="1"
|Prototype
|'''<tt>void DebugMemWrite64(unsigned int address, unsigned long long value)</tt>'''<br />
'''<tt>void DebugMemWrite32(unsigned int address, unsigned int value)</tt>'''<br />
'''<tt>void DebugMemWrite16(unsigned int address, unsigned short value)</tt>'''<br />
'''<tt>void DebugMemWrite8(unsigned int address, unsigned char value)</tt>'''
|-
|Input Parameters
|'''<tt>address</tt>''' Memory location (in N64 memory space) to which to write a value.<br />
'''<tt>value</tt>''' Value to write into emulated memory.
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|These functions write a value into the emulated N64 memory. The given value will be correctly byte-swapped before storage.
|}
== R4300 CPU Functions ==
{| border="1"
|Prototype
|'''<tt>void *DebugGetCPUDataPtr(m64p_dbg_cpu_data cpu_data_type)</tt>'''
|-
|Input Parameters
|'''<tt>cpu_data_type</tt>''' CPU register type to which a pointer is requested.<br />
|-
|Requirements
|The Mupen64Plus library must be initialized before calling this function.
|-
|Usage
|This function returns a memory pointer (in x86 memory space) to a specific register in the emulated R4300 CPU. The '''<tt>m64p_dbg_cpu_data</tt>''' type is enumerated in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. It is important to note that when the R4300 CPU core is in the Cached Interpreter or Dynamic Recompiler modes, the address of the PC register is not constant; it will change after each instruction is executed. The pointers to all other registers will never change, as the other registers are global variables.
|}
== Breakpoint Functions ==
{| border="1"
|Prototype
|'''<tt>int DebugBreakpointLookup(unsigned int address, unsigned int size, unsigned int flags)</tt>'''
|-
|Input Parameters
|'''<tt>address</tt>''' Starting address (in R4300 memory space) to search<br />
'''<tt>size</tt>''' Size of address space in bytes to search<br />
'''<tt>flags</tt>''' Breakpoint flags
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function searches through all current breakpoints in the debugger to find one that matches the given input parameters. If a matching breakpoint is found, the index number is returned. If no breakpoints are found, -1 is returned.
|}
<br />
{| border="1"
|Prototype
|'''<tt>int DebugBreakpointCommand(m64p_dbg_bkp_command command, unsigned int index, void *ptr)</tt>'''
|-
|Input Parameters
|'''<tt>command</tt>''' Enumerated value specifying the breakpoint command to execute<br />
'''<tt>index</tt>''' Purpose varies by command, see table below<br />
'''<tt>ptr</tt>''' Purpose varies by command, see table below
|-
|Requirements
|The Mupen64Plus library must be built with debugger support and must be initialized before calling this function.
|-
|Usage
|This function is used to process common breakpoint commands, such as adding, removing, or searching the breakpoints. The meanings of the '''<tt>index</tt>''' and '''<tt>ptr</tt>''' input parameters vary by command, and are given in the table below. The '''<tt>m64p_dbg_bkp_command</tt>''' type is enumerated in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]].
|}
<br />
{| border="1"
!Command!!Return Value!!Function!!<tt>index</tt> Parameter!!<tt>ptr</tt> Parameter
|-
|M64P_BKP_CMD_ADD_ADDR
|Index of new breakpoint
|Add an execution breakpoint at a given R4300 address.
|R4300 address
|unused
|-
|M64P_BKP_CMD_ADD_STRUCT
|Index of new breakpoint
|Add a custom breakpoint specified in a <tt>breakpoint</tt> structure.
|unused
|Pointer to <tt>breakpoint</tt> struct of new breakpoint
|-
|M64P_BKP_CMD_REPLACE
|unused
|Replace an existing breakpoint with one specified by a <tt>breakpoint</tt> structure.
|Index of breakpoint to replace
|Pointer to <tt>breakpoint</tt> struct of new breakpoint
|-
|M64P_BKP_CMD_REMOVE_ADDR
|unused
|Remove an existing breakpoint
|R4300 address of breakpoint to remove
|unused
|-
|M64P_BKP_CMD_REMOVE_IDX
|unused
|Remove an existing breakpoint
|Index of breakpoint to remove
|unused
|-
|M64P_BKP_CMD_ENABLE
|unused
|Enable a specified breakpoint
|Index of breakpoint to enable
|unused
|-
|M64P_BKP_CMD_DISABLE
|unused
|Disable a specified breakpoint
|Index of breakpoint to disable
|unused
|-
|M64P_BKP_CMD_CHECK
|Index of breakpoint if found, otherwise -1
|Search for an execution breakpoint at a given address
|R4300 address at which to search
|unused
|}

View File

@ -0,0 +1,332 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Core<-->Front-End API =
Most libmupen64plus functions return an <tt>m64p_error</tt> return code, which is an enumerated type defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. Front-end code should check the return value of each call to a libmupen64plus function.
== Startup/Shutdown Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error CoreStartup(int APIVersion, const char *ConfigPath, const char *DataPath, void *Context, void (*DebugCallback)(void *Context, int level, const char *message), void *Context2, void (*StateCallback)(void *Context2, m64p_core_param ParamChanged, int NewValue))</tt>'''
|-
|Input Parameters
|'''<tt>APIVersion</tt>''' Integer containing the version number of the Core API used by the front-end.<br />
'''<tt>ConfigPath</tt>''' File path to folder containing Mupen64Plus.cfg. Can be NULL.<br />
'''<tt>DataPath</tt>''' Folder to search first when looking for shared data files. Can be NULL.<br />
'''<tt>Context</tt>''' Pointer which will be passed back to the '''<tt>DebugCallback</tt>''' function. Can be NULL.<br />
'''<tt>DebugCallback</tt>''' Pointer to function in front-end for receiving debug information and warnings from the core. This function must be thread-safe. Can be NULL. The value of <tt>level</tt> is 1 for an error, 2 for a warning, 3 for info, and 4 for verbose info.<br />
'''<tt>Context2</tt>''' Pointer which will be passed back to the '''<tt>StateCallback</tt>''' function. Can be NULL.<br />
'''<tt>StateCallback</tt>''' Pointer to function in front-end for receiving core state change notifications. This function must be thread-safe. Can be NULL.
|-
|Requirements
|This function must be called before any other libmupen64plus functions.
|-
|Usage
|This function initializes libmupen64plus for use by allocating memory, creating data structures, and loading the configuration file. If '''<tt>ConfigPath</tt>''' is NULL, libmupen64plus will search for the configuration file in its usual place (On Linux, in <tt>~/.config/mupen64plus/</tt>). This function may return <tt>M64ERR_INCOMPATIBLE</tt> if older front-end is used with newer core.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error CoreShutdown(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Usage
|This function saves the configuration file, then destroys data structures and releases memory allocated by the core library.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error CoreAttachPlugin(m64p_plugin_type PluginType, m64p_dynlib_handle PluginLibHandle)</tt>'''
|-
|Input Parameters
|'''<tt>PluginType</tt>''' Enumerated type specifying the plugin type to attach to the core. If this type of plugin is currently attached to the core, an error will be returned.<br />
'''<tt>PluginLibHandle</tt>''' Dynamic library handle (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) corresponding with the plugin object to attach.
|-
|Requirements
|Both the core library and the plugin library must already be initialized with the <tt>CoreStartup()/PluginStartup()</tt> functions, and a ROM must be open. This function cannot be called while the emulator is running. The plugins must be attached in the following order: Video, Audio, Input, RSP.
|-
|Usage
|This function attaches the given plugin to the emulator core. There can only be one plugin of each type attached to the core at any given time.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error CoreDetachPlugin(m64p_plugin_type PluginType)</tt>'''
|-
|Input Parameters
|'''<tt>PluginType</tt>''' Enumerated type specifying the plugin type to detach from the core. If no plugin of this type is currently attached to the core, this function will exit with a return value of <tt>M64ERR_SUCCESS</tt>.
|-
|Requirements
|Both the core library and the plugin library must already be initialized with the <tt>CoreStartup()/PluginStartup()</tt> functions. This function cannot be called while the emulator is running.
|-
|Usage
|This function detaches the given plugin from the emulator core, and re-attaches the 'dummy' plugin functions.
|}
== Command Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error CoreDoCommand(m64p_command Command, int ParamInt, void *ParamPtr)</tt>'''
|-
|Input Parameters
|'''<tt>Command</tt>''' Enumerated type specifying which command should be executed.<br />
'''<tt>ParamInt</tt>''' An integer value which may be used as an input to the command.<br />
'''<tt>ParamPtr</tt>''' A pointer which may be used as an input to the command.<br />
|-
|Requirements
|The core library must already be initialized with the <tt>CoreStartup()</tt> function. Each command may have its own requirements as well.
|-
|Usage
|This function sends a command to the emulator core. A table of all commands is given below.
|}
<br />
{| border="1"
!Command!!Function!!Input Parameters!!Requirements
|-
|M64CMD_ROM_OPEN
|This will cause the core to read in a binary ROM image provided by the front-end.
|'''<tt>ParamPtr</tt>''' Pointer to the uncompressed ROM image in memory.<br />'''<tt>ParamInt</tt>''' The size in bytes of the ROM image.
|The emulator cannot be currently running. A ROM image must not be currently opened.
|-
|M64CMD_ROM_CLOSE
|This will close any currently open ROM. The current cheat code list will also be deleted.
|N/A
|The emulator cannot be currently running. A ROM image must have been previously opened. There should be no plugins currently attached.
|-
|M64CMD_ROM_GET_HEADER
|This will retrieve the header data of the currently open ROM.
|'''<tt>ParamPtr</tt>''' Pointer to a <tt>rom_header</tt> struct to receive the data.<br />'''<tt>ParamInt</tt>''' The size in bytes of the <tt>rom_header</tt> struct.
|A ROM image must be open.
|-
|M64CMD_ROM_GET_SETTINGS
|This will retrieve the settings data of the currently open ROM.
|'''<tt>ParamPtr</tt>''' Pointer to a <tt>rom_settings</tt> struct to receive the data.<br />'''<tt>ParamInt</tt>''' The size in bytes of the <tt>rom_settings</tt> struct.
|A ROM image must be open.
|-
|M64CMD_EXECUTE
|This command will start the emulator and begin executing the ROM image. This function call will not return until the game has been stopped.
|N/A
|The emulator cannot be currently running. A ROM image must have been previously opened.
|-
|M64CMD_STOP
|This will stop the emulator, if it is currently running.
|N/A
|This command will execute asynchronously.
|-
|M64CMD_PAUSE
|This command will pause the emulator if it is running.
|N/A
|This function will return a non-successful error code if the emulator is in the stopped state. This command may execute asynchronously.
|-
|M64CMD_RESUME
|This command will resume execution of the emulator if it is paused.
|N/A
|This function will return a non-successful error code if the emulator is in the stopped state. This command may execute asynchronously.
|-
|M64CMD_CORE_STATE_QUERY
|This command will query the emulator core for the value of a state parameter
|'''<tt>ParamInt</tt>''' An <tt>m64p_core_param</tt> enumerated type specifying the desired state variable'''<br /><tt>ParamPtr</tt>''' Pointer to an integer to receive the value of the requested state variable.
|None
|-
|M64CMD_CORE_STATE_SET
|This command will set the value of a state parameter in the emulator core
|'''<tt>ParamInt</tt>''' An <tt>m64p_core_param</tt> enumerated type specifying the desired state variable'''<br /><tt>ParamPtr</tt>''' Pointer to an integer to containing the value of the requested state variable.
|The initial requirements vary depending upon the variable being set. Setting some variables requires the emulator to be running.
|-
|M64CMD_STATE_LOAD
|This command will attempt to load a saved state file. If '''<tt>ParamPtr</tt>''' is not NULL, this function will load a state file from a full pathname specified by this pointer. Otherwise ('''<tt>ParamPtr</tt>''' is NULL), it will load from the current slot.
|'''<tt>ParamInt</tt>''' Ignored'''<br /><tt>ParamPtr</tt>''' Pointer to string containing state file path and name, or NULL
|The emulator must be currently running or paused. This command will execute asynchronously.
|-
|M64CMD_STATE_SAVE
|This command will save a state file. If '''<tt>ParamPtr</tt>''' is not NULL, this function will save a state file to a full pathname specified by this pointer. Otherwise ('''<tt>ParamPtr</tt>''' is NULL), it will save to the current slot.
|'''<tt>ParamInt</tt>''' This parameter will only be used if '''<tt>ParamPtr</tt>''' is not NULL. If 1, a Mupen64Plus state file will be saved. If 2, a Project64 compressed state file will be saved. If 3, a Project64 uncompressed state file will be saved. '''<br /><tt>ParamPtr</tt>''' Pointer to string containing state file path and name, or NULL<br />
|The emulator must be currently running or paused. This command will execute asynchronously.
|-
|M64CMD_STATE_SET_SLOT
|This command will set the currently selected save slot index
|'''<tt>ParamInt</tt>''' Value to set for the current slot index. Must be between 0 and 9'''<br /><tt>ParamPtr</tt>''' Ignored<br />
|None
|-
|M64CMD_SEND_SDL_KEYDOWN
|This command will inject an SDL_KEYDOWN event into the emulator's core event loop. Keys not handled by the core will be passed to the input plugin.
|'''<tt>ParamInt</tt>''' Key value of the keypress event to inject, with SDLMod in the upper 16 bits and SDLKey in the lower 16 bits.
|The emulator must be currently running or paused.
|-
|M64CMD_SEND_SDL_KEYUP
|This command will inject an SDL_KEYUP event into the emulator's core event loop.
|'''<tt>ParamInt</tt>''' Key value of the keypress event to inject, with SDLMod in the upper 16 bits and SDLKey in the lower 16 bits.
|The emulator must be currently running or paused.
|-
|M64CMD_SET_FRAME_CALLBACK
|This command either registers or removes (if '''<tt>ParamPtr</tt>''' is NULL) a frame callback function. This function will be called after each video frame is rendered. The front-end callback function may call the video plugin's ReadScreen2() function to retrieve the frame if desired.
|'''<tt>ParamPtr</tt>''' Can be either NULL or a <tt>m64p_frame_callback</tt> object.
|None
|-
|M64CMD_TAKE_NEXT_SCREENSHOT
|This will cause the core to save a screenshot at the next possible opportunity.
|N/A
|The emulator must be currently running or paused. This command will execute asynchronously.
|-
|M64CMD_READ_SCREEN
|This command will copy the current contents of the video display to the buffer pointer by '''<tt>ParamPtr</tt>'''.
|'''<tt>ParamInt</tt>''' 1 to copy the buffer that is currently displayed (front buffer), 0 to copy the buffer that is being drawn (back buffer).'''<br /><tt>ParamPtr</tt>'''A pointer to a buffer of at least width*height*3 bytes. The buffer will be filled with the current display. The format is RGB888 with the origin in the lower left corner.
|The emulator must be currently running or paused.
|-
|M64CMD_RESET
|Reset the emulated machine.
|'''<tt>ParamInt</tt>''' 0 to do a soft reset, 1 to do a hard reset.'''<br /><tt>ParamPtr</tt>''' Ignored
|The emulator must be currently running or paused.
|-
|M64CMD_ADVANCE_FRAME
|Advance one frame (the emulator will run until the next frame, then pause).
|'''<tt>ParamInt</tt>''' Ignored'''<br /><tt>ParamPtr</tt>''' Ignored
|The emulator must be currently running or paused.
|}
<br />
== Core State Parameters ==
These core parameters may be read and/or written using the M64CMD_CORE_STATE_QUERY and M64CMD_CORE_STATE_SET commands. The front-end application will receive a callback (via the <tt>StateCallback</tt> function pointer given to the '''<tt>CoreStartup</tt>''' function) when these parameters change value. This callback will be sent even if the function which caused the state change was called by the front-end application itself. Not all of these parameters are readable or writable. Each parameter's value is held in a single 32-bit integer. The meaning of this integer is given in the Parameter Encoding column. See the table below for details on these core parameters.
<br />
{| border="1"
!Name!!Readable!!Writable!!<tt>int</tt> Parameter Encoding!!Notes
|-
|M64CORE_EMU_STATE
|Yes
|Yes
|<tt>enum m64p_emu_state</tt>
|<tt>1</tt>=Stopped, <tt>2</tt>=Running, <tt>3</tt>=Paused
|-
|M64CORE_VIDEO_MODE
|Yes
|Yes
|<tt>enum m64p_video_mode</tt>
|<tt>1</tt>=None (video not running), <tt>2</tt>=Windowed, <tt>3</tt>=Fullscreen
|-
|M64CORE_SAVESTATE_SLOT
|Yes
|Yes
|
|Valid values are 0 through 9.
|-
|M64CORE_SPEED_FACTOR
|Yes
|Yes
|Emulator playback speed in percent
|Valid values are 1 to 1000.
|-
|M64CORE_SPEED_LIMITER
|Yes
|Yes
|<tt>1</tt> to enable speed limiter, or <tt>0</tt> to disable speed limiter.
|When speed limiter is disabled, emulator will run as fast as possible (useful for benchmarking).
|-
|M64CORE_VIDEO_SIZE
|Yes
|No
|<tt>(ScreenWidth << 16) + ScreenHeight</tt>
|This parameter is read-only.
|-
|M64CORE_AUDIO_VOLUME
|Yes
|Yes
|Volume level in percent, 0 - 100
|
|-
|M64CORE_AUDIO_MUTE
|Yes
|Yes
|<tt>1</tt> if muted, otherwise <tt>0</tt>
|
|-
|M64CORE_INPUT_GAMESHARK
|Yes
|Yes
|<tt>1</tt> when Gameshark button pressed, <tt>0</tt> when button released.
|Callback function will be invoked on both button press and release.
|-
|M64CORE_STATE_LOADCOMPLETE
|No
|No
|<tt>1</tt> if state loading was successful, <tt>0</tt> if state loading failed.
|This parameter cannot be read or written. It is only used for callbacks, because the state load/save operations are asynchronous.
|-
|M64CORE_STATE_SAVECOMPLETE
|No
|No
|<tt>1</tt> if state saving was successful, <tt>0</tt> if state saving failed.
|This parameter cannot be read or written. It is only used for callbacks, because the state load/save operations are asynchronous.
|}
<br />
== ROM Handling Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error CoreGetRomSettings(m64p_rom_settings *RomSettings, int RomSettingsLength, int Crc1, int Crc2)</tt>'''
|-
|Input Parameters
|'''<tt>RomSettings</tt>''' Pointer to <tt>m64p_rom_settings</tt> object to be filled in with data.<br />
'''<tt>RomSettingsLength</tt>''' Size of the object pointed to by '''<tt>RomSettings</tt>''' in bytes.<br />
'''<tt>Crc1</tt>''' A 32-bit integer value containing the first CRC (taken from the ROM header) to identify the ROM.<br />
'''<tt>Crc2</tt>''' A 32-bit integer value containing the second CRC (taken from the ROM header) to identify the ROM.
|-
|Requirements
|The core library must already be initialized with the <tt>CoreStartup()</tt> function. The '''<tt>RomSettings</tt>''' pointer must not be NULL. The '''<tt>RomSettingsLength</tt>''' value must be greater than or equal to the size of the <tt>m64p_rom_settings</tt> structure. This function does not require any ROM image to be currently open.
|-
|Usage
|This function searches through the data in the <tt>Mupen64Plus.ini</tt> file to find an entry which matches the given '''<tt>Crc1</tt>''' and '''<tt>Crc2</tt>''' hashes, and if found, fills in the '''<tt>RomSettings</tt>''' structure with the data from the <tt>Mupen64Plus.ini</tt> file.
|}
<br />
== Video Extension Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error CoreOverrideVidExt(m64p_video_extension_functions *VideoFunctionStruct);</tt>'''
|-
|Input Parameters
|'''<tt>VideoFunctionStruct</tt>''' Pointer to a structure (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) containing pointers to the Front-end's custom Video Extension functions to override the default SDL functions
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. This function cannot be called while the emulator is running.
|-
|Usage
|This function overrides the core's internal SDL-based OpenGL functions which are called from the video plugin to perform various basic tasks like opening the video window, toggling between windowed and fullscreen modes, and swapping frame buffers after a frame has been rendered. This override functionality allows a front-end to define its own video extension functions to be used instead of the SDL functions, such as for the purpose of embedding the emulator display window inside of a Qt GUI window. If any of the function pointers in the structure are NULL, the override function will be disabled and the core's internal SDL functions will be used. The v2.0 core expects the <tt>Functions</tt> struct member to be equal to 9 or more.
|}
<br />
== Cheat Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error CoreAddCheat(const char *CheatName, m64p_cheat_code *CodeList, int NumCodes)</tt>'''
|-
|Input Parameters
|'''<tt>CheatName</tt>''' Pointer to NULL-terminated string containing a unique name for this Cheat Function.<br />
'''<tt>CodeList</tt>''' Pointer to an array of <tt>m64p_cheat_code</tt> objects.<br />
'''<tt>NumCodes</tt>''' Number of <tt>m64p_cheat_code</tt> elements in the cheat code array.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. A ROM image must be currently opened.
|-
|Usage
|This function will add a Cheat Function to a list of currently active cheats which are applied to the open ROM, and set its state to Enabled. This function may be called before a ROM begins execution or while a ROM is currently running. Some cheat codes must be applied before the ROM begins executing, and may not work correctly if added after the ROM begins execution. A Cheat Function consists of a list of one or more <tt>m64p_cheat_code</tt> elements. If a Cheat Function with the given '''<tt>CheatName</tt>''' already exists, it will be removed and the new Cheat Function will be added in its place.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error CoreCheatEnabled(const char *CheatName, int Enabled)</tt>'''
|-
|Input Parameters
|'''<tt>CheatName</tt>''' Pointer to NULL-terminated string containing the name of an existing Cheat Function.<br />
'''<tt>Enabled</tt>''' Boolean value to which to set the enabled state of the specified Cheat Function.
|-
|Requirements
|The Mupen64Plus library must already be initialized before calling this function. A ROM image must be currently opened.
|-
|Usage
|This function enables or disables a specified Cheat Function.
|}

View File

@ -0,0 +1,157 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Video Extension API =
Most libmupen64plus functions return an <tt>m64p_error</tt> return code, which is an enumerated type defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]. Plugin code should check the return value of each call to a libmupen64plus function.
All of these functions should only be called from within the video plugin; they should not be called from the front-end.
== Startup/Shutdown Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_Init(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Requirements
|This function should be called before any other Video Extension functions.
|-
|Usage
|This function should be called from within the RomOpen() video plugin function call. The default SDL implementation of this function simply calls SDL_InitSubSystem(SDL_INIT_VIDEO). It does not open a rendering window or switch video modes.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_Quit(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Usage
|This function closes any open rendering window and shuts down the video system. The default SDL implementation of this function calls SDL_QuitSubSystem(SDL_INIT_VIDEO). This function should be called from within the RomClosed() video plugin function.
|}
<br />
== Screen Handling Functions ==
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_ListFullscreenModes(m64p_2d_size *SizeArray, int *NumSizes)</tt>'''
|-
|Input Parameters
|'''<tt>SizeArray</tt>''' Pointer to an array of <tt>m64p_2d_size</tt> objects, defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]<br />
'''<tt>NumSizes</tt>''' Pointer to an integer which contains the size of '''<tt>SizeArray</tt>''' for input, and the number of size objects stored for output.
|-
|Requirements
|The video extension must be initialized before calling this function.
|-
|Usage
|This function is used to enumerate the available resolutions for fullscreen video modes. An array '''<tt>SizeArray</tt>''' is passed into the function, which is then filled (up to <tt>*'''NumSizes'''</tt> objects) with resolution sizes. The number of sizes actually written is stored in the integer which is pointed to by '''<tt>NumSizes</tt>'''.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_SetVideoMode(int Width, int Height, int BitsPerPixel, m64p_video_mode ScreenMode)</tt>'''
|-
|Input Parameters
|'''<tt>Width</tt>''' Horizontal resolution in pixels of desired video window<br />
'''<tt>Height</tt>''' Vertical resolution in pixels of desired video window<br />
'''<tt>BitsPerPixel</tt>''' Pixel color resolution of desired video window. This value must be 16, 24, or 32<br />
'''<tt>ScreenMode</tt>''' Either <tt>M64VIDEO_WINDOWED</tt> or <tt>M64VIDEO_FULLSCREEN</tt>
|-
|Requirements
|The video extension must be initialized before calling this function.
|-
|Usage
|This function creates a rendering window or switches into a fullscreen video mode. Any desired OpenGL attributes should be set before calling this function.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_SetCaption(const char *Title)</tt>'''
|-
|Input Parameters
|'''<tt>Title</tt>''' Pointer to a NULL-terminated string containing the desired title text of the emulator rendering window
|-
|Requirements
|The video extension must be initialized before calling this function.
|-
|Usage
|This function sets the caption text of the emulator rendering window.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_ToggleFullScreen(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Requirements
|The video extension must be initialized before calling this function. The rendering window should already be created.
|-
|Usage
|This function toggles between fullscreen and windowed rendering modes.
|}
<br />
== OpenGL Functions ==
{| border="1"
|Prototype
|'''<tt>void * VidExt_GL_GetProcAddress(const char* Proc)</tt>'''
|-
|Input Parameters
|'''<tt>Proc</tt>''' Pointer to a NULL-terminated string containing the name of the desired OpenGL extension function.
|-
|Requirements
|The video extension must be initialized before calling this function.
|-
|Usage
|This function is used to get a pointer to an OpenGL extension function. This is only necessary on the Windows platform, because the OpenGL implementation shipped with Windows only supports OpenGL version 1.1.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value)</tt>'''
|-
|Input Parameters
|'''<tt>Attr</tt>''' Enumerated type (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) specifying which OpenGL attribute to set<br />
'''<tt>Value</tt>''' Value to set for the attribute
|-
|Requirements
|The video extension must be initialized before calling this function. The desired attributes should be set before calling '''<tt>VidExt_SetVideoMode</tt>'''
|-
|Usage
|This function is used to set certain OpenGL attributes which must be specified before creating the rendering window with '''<tt>VidExt_SetVideoMode</tt>'''.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue)</tt>'''
|-
|Input Parameters
|'''<tt>Attr</tt>''' Enumerated type (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) specifying OpenGL attribute of which to get value<br />
'''<tt>pValue</tt>''' Pointer to integer Value which will be set to attribute's value
|-
|Requirements
|The video extension must be initialized before calling this function.
|-
|Usage
|This function may be used to check that OpenGL attributes where successfully set to the rendering window after the '''<tt>VidExt_SetVideoMode</tt>''' function call.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error VidExt_GL_SwapBuffers(void)</tt>'''
|-
|Input Parameters
|N/A
|-
|Requirements
|The video extension must be initialized before calling this function. The rendering window should already be created.
|-
|Usage
|This function is used to swap the front/back buffers after rendering an output video frame.
|}
<br />

View File

@ -0,0 +1,103 @@
[http://mupen64plus.retrouprising.com Project page]
== Primary Goal ==
The primary goal of this re-architecture is to split this large project into smaller projects which may proceed to be developed independently of each other. The advantages of the new architecture are:
* The build system can be greatly simplified
* Each module can use its own build system. For example, the Qt GUI might switch to cmake for better Qt integration.
* Porting the emulator core to other platforms (namely Win32) will be greatly simplified by removing the most platform-specific pieces.
* Making releases for each package will be simpler and faster
* Mupen64Plus may be included into the Debian/Ubuntu repositories since glN64 (with its 'unknown' license) will be a separate project
== Topography ==
This re-architecture will force us to lay boundaries with well-defined APIs between different parts of the emulator. Here are some initial suggestions for the new layout of the modules:
# Mupen64plus-core
#* To simplify porting to other platforms, the core needs to be as lean as possible
#* For this reason, the GUI interfaces, the ROM cache, and the zip/lzma/7zip decompressors will be removed
#* The core will contain the code for:
#** Emulating the R4300 main CPU and memory systems
#** Loading and configuring plugins
#** Reading, parsing, and writing all configuration files for the core + plugins
#** Parsing and returning information about ROM images
#** Core user interface for keyboard and LIRC input
#** Savestates and screenshots
#** An on-screen display
#** Cheat and debugger core functions
#** 'Dummy' plugins
# Mupen64plus-console, Mupen64plus-gtk, Mupen64plus-qt
#* Command-line only, GTK, and Qt front-end interfaces
#* Each front-end for the core library will be a separate project
#* The ROM cache code will be forked and included into both GUIs
#* The front-ends will be responsible for finding and loading the core library and the plugins
#* The dynamic library handle of the core will be passed to all the plugins, and the dynamic library handle of the plugins will be passed to the core
#* The front-ends will be responsible for loading and decompressing the ROM image, and passing a pointer to the core
# Plugins (RiceVideo, glN64, glide64, Blight Input, JTTL Audio)
#* The plugins will be spun off into separate projects
#* The plugin API will change, and will be incompatible with the old Zilmar spec
== Project Owners ==
Richard42 will retain ownership of the Mupen64plus-core and Mupen64plus-console modules. I will recommend that Slougi take ownership of the Qt GUI. The plugins and GTK GUI are up for grabs.
== Work To Do ==
Tasks which have been completed will be marked with the <s>strikethrough</s> format.
=== Prior to starting on the code ===
# <s>Write design document for Core API</s>
#* Front-end + debugger + cheat
#* Configuration interface
#* Video plugin
#* Audio plugin
#* Input plugin
#* RSP plugin
# <s>Set up new Mercurial repository for project</s>
=== Coding tasks ===
# <s>First steps</s>
#* <s>Split & fork the source files into new structure</s>
# Core
#* <s>Refactor/simplify makefiles</s>
#* <s>Remove #include statements from header files</s>
#* <s>Write new configuration load/parse/save functionality</s>
#* <s>Separate event loop out of main.c into new source file</s>
#* <s>Fix broken WM_KeyDown/WM_KeyUp commands sent to input plugin</s>
#* <s>Remove main() function</s>
#* <s>Remove main/winlnxdefs.h</s>
#* <s>Add new shared library interface (Must be thread-safe and re-entrant where necessary)</s>
#** <s>api/callbacks.c</s>
#** <s>api/common.c</s>
#** <s>api/config.c</s>
#** <s>api/debugger.c</s>
#** <s>api/frontend.c</s>
#** <s>api/vidext.c</s>
#* <s>Refactor core code for new debug info interface (instead of printf(), send back to front-end)</s>
#* <s>Modify plugin-handling code to use new plugin API</s>
#* <s>Fix 64-bit dynamic recompiler for dynamic lib</s>
#* <s>Update translate.c file handling and translations</s>
#* <s>Update cheat.c cheat code handling</s>
#* <s>Remove compare_core.c, add core comparison feature to console-ui</s>
#* <s>Generate versioned core library</s>
#* <s>Simplify makefile / pre.mk</s>
#* <s>Refactor install.sh</s>
#* Go through google code issue list, apply patches and close issue reports
# Front-ends
#* <s>Refactor/simplify makefiles</s>
## <s>CLI</s>
##* <s>Write from scratch, based on main.c</s>
##* Update man page
## GUI-Qt
##* Adapt from previous mupen64puls Qt GUI code, pulling code from CLI front-end (Slougi)
## GUI-GTK
##* Adapt from previous mupen64puls GTK GUI code, pulling code from CLI front-end (TBD)
# <s>Plug-ins</s>
#* For each plug-in:
#** <s>m64p-rsp-hle</s>
#** <s>m64p-audio-sdl</s>
#** <s>m64p-video-rice</s>
#** <s>m64p-input-sdl</s>
#* Remove existing configuration read/write code
#* Add Deadzone and Scaling parameters to Blight Input plugin
#* Refactor to use new configuration interface through core library
#* Refactor for changes in core plugin API
#* Refactor for new debug info interface (instead of printf(), send back to front-end)

View File

@ -0,0 +1,285 @@
[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]
= Mupen64Plus v2.0 Plugin API =
This section lists all of the functions which are exported by the plugins. The front-end application should only use the PluginStartup, PluginShutdown, and PluginGetVersion functions. All other functions will only be called from the core.
== Common Plugin API ==
These functions are present in all of the plugins.
{| border="1"
|Prototype
|'''<tt>m64p_error PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *Context, int level, const char *Message))</tt>'''
|-
|Input Parameters
|'''<tt>CoreLibHandle</tt>''' Dynamic library handle (defined in [[Mupen64Plus v2.0 headers#m64p_types.h|m64p_types.h]]) corresponding with the core mupen64plus library.<br />
'''<tt>Context</tt>''' Pointer which will be passed back to the '''<tt>DebugCallback</tt>''' function. Can be NULL.<br />
'''<tt>DebugCallback</tt>''' Pointer to function in front-end for receiving debug information and warnings from the plugin. This function must be thread-safe. Can be NULL.
|-
|Requirements
|This function must be called before any other plugin functions. The Core library must already be started before calling this function. This function must be called before attaching the plugin to the core.
|-
|Usage
|This function initializes plugin for use by allocating memory, creating data structures, and loading the configuration data. This function may return <tt>M64ERR_INCOMPATIBLE</tt> if an older core library is used with a newer plugin.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error PluginShutdown(void)</tt>'''
|-
|Requirements
|This plugin should be detached from the core before calling this function.
|-
|Usage
|This function destroys data structures and releases memory allocated by the plugin library.
|}
<br />
{| border="1"
|Prototype
|'''<tt>m64p_error PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)</tt>'''
|-
|Input Parameters
|'''<tt>PluginType</tt>''' Pointer to an enumerated type to store the plugin type of this plugin.<br />
'''<tt>PluginVersion</tt>''' Pointer to an integer to store the version number of this plugin. Version number 2.1.3 would be stored as 0x00020103.<br />
'''<tt>APIVersion</tt>''' Pointer to an integer to store the version number of the Core-Plugin API for this type of plugin used by this plugin.<br />
'''<tt>PluginNamePtr</tt>''' Pointer to a const character pointer to receive the name of this plugin. The const char * which is returned must point to a persistent string (ie, not stored on the stack).<br />
'''<tt>Capabilities</tt>''' Pointer to an integer to store a logically-or'd set of flags which specify the capabilities of the plugin which were built into the library during compilation. These are currently only defined for the core, so this will always return 0 for a plugin.
|-
|Usage
|This function retrieves version information from the plugin. This function is the same for the core library and the plugins, so that a front-end may examine all shared libraries in a directory and determine their types. Any of the input parameters may be set to NULL and this function will succeed but won't return the corresponding information.
|}
== Video Plugin API ==
=== Mupen64Plus v2.0 Video Plugin API ===
{|
|<tt>void ChangeWindow(void);</tt>
|Toggle Fullscreen/Windowed mode
|-
|<tt>BOOL InitiateGFX(GFX_INFO Gfx_Info);</tt>
|Called during <tt>CoreAttachPlugin</tt> to send info about the emulator core to the graphics plugin and start up the graphics sub-system. This should create the rendering window and the OpenGL context.
|-
|<tt>void MoveScreen(int xpos, int ypos);</tt>
|This function is called in response to the emulator receiving a WM_MOVE, passing the xpos and ypos from that message.
|-
|<tt>void ProcessDList(void);</tt>
|Process high-level graphics D-list. (not currently used)
|-
|<tt>void ProcessRDPList(void);</tt>
|Process low-level graphics D-list.
|-
|<tt>void RomClosed(void);</tt>
|Called after the emulator is stopped.
|-
|<tt>int RomOpen(void);</tt>
|Called just before the emulator begins executing a ROM. '''***changed*** - this function now returns an int (boolean)'''
|-
|<tt>void ShowCFB (void);</tt>
|Called from the RSP plugin to signal a condition to the video plugin.
|-
|<tt>void UpdateScreen(void);</tt>
|This function is called in response to a VSync condition if the VI bit in MI_INTR_REG is set
|-
|<tt>void ViStatusChanged(void);</tt>
|This function is called to notify the video plugin that the ViStatus registers value has been changed.
|-
|<tt>void ViWidthChanged(void);</tt>
|This function is called to notify the video plugin that the ViWidth registers value has been changed.
|-
|<tt>void ReadScreen2(void *dest, int *width, int *height, int front);</tt>
|This function reads the pixels of the frame buffer that is either currently displayed (front != 0) or being drawn (front == 0)
|-
|<tt>void SetRenderingCallback(void (*callback)(int bScreenRedrawn));</tt>
|Allows the core to register a callback function that will be called by the graphics plugin just before the the frame buffers are swapped. '''***changed*** - as of video api v2.1.0, the callback function must take a single int (boolean) parameter, which tells the core whether or not the screen has been redrawn since the last time the callback was called. This is used to prevent screenshots from containing OSD text.'''
|-
|<tt>void FBRead(unsigned int addr)</tt>
|Read data from frame buffer into emulated RAM space
|-
|<tt>void FBWrite(unsigned int addr, unsigned int size)</tt>
|Write data from emulated RAM space into frame buffer
|-
|<tt>void FBGetFrameBufferInfo(void *p)</tt>
|Get some information about the frame buffer
|}
=== Remove From Older Video API ===
{|
|-
|<tt>void CaptureScreen (char * Directory);</tt>
|-
|<tt>void CloseDLL(void);</tt>
|-
|<tt>void DllAbout(HWND hParent);</tt>
|-
|<tt>void DllConfig(HWND hParent);</tt>
|-
|<tt>void DllTest(HWND hParent);</tt>
|-
|<tt>void DrawScreen(void);</tt>
|-
|<tt>void GetDllInfo(PLUGIN_INFO *PluginInfo);</tt>
|-
|<tt>void ReadScreen(void **dest, int *width, int *height);</tt>
|-
|<tt>void SetConfigDir(char *configDir);</tt>
|-
|<br />
<tt>typedef struct {...} PLUGIN_INFO</tt>
|}
== Audio Plugin API ==
=== Mupen64Plus v2.0 Audio Plugin API ===
{|
|<tt>void AiDacrateChanged(int SystemType);</tt>
|This function is called to notify the audio plugin that the AiDacrate register's value has been changed.
|-
|<tt>void AiLenChanged(void);</tt>
|This function is called to notify the audio plugin that the AiLen register's value has been changed.
|-
|<tt>BOOL InitiateAudio(AUDIO_INFO Audio_Info);</tt>
|Called during <tt>CoreAttachPlugin</tt> to send info about the emulator core to the audio plugin.
|-
|<tt>void ProcessAList(void);</tt>
|Signal that there is an A-list to be processed. (not currently used)
|-
|<tt>int RomOpen(void);</tt>
|Called just before the emulator begins executing a ROM. '''***changed*** - this function now returns an int (boolean)'''
|-
|<tt>void RomClosed(void);</tt>
|Called after the emulator is stopped.
|-
|<tt>void SetSpeedFactor(int percent);</tt>
|Called when the emulator playback speed changes.
|-
|<tt>void VolumeUp(void);</tt><br />
<tt>void VolumeDown(void);</tt>
|Increase or decrease volume level
|-
|<tt>int VolumeGetLevel(void);</tt>
|Get current volume level in percentage, between 0 and 100. '''***NEW***'''
|-
|<tt>void VolumeSetLevel(int level);</tt>
|Set current volume level. <tt>level</tt> must be between 0 and 100. '''***NEW***'''
|-
|<tt>void VolumeMute(void);</tt>
|Toggle between audio muted and un-muted
|-
|<tt>const char * VolumeGetString(void);</tt>
|Return a string describing the current volume level
|}
=== Remove From Older Audio API ===
{|
|-
|<tt>DWORD AiReadLength(void);</tt>
|-
|<tt>void AiUpdate(BOOL Wait);</tt>
|-
|<tt>void CloseDLL(void);</tt>
|-
|<tt>void DllAbout(HWND hParent);</tt>
|-
|<tt>void DllConfig(HWND hParent);</tt>
|-
|<tt>void DllTest(HWND hParent);</tt>
|-
|<tt>void GetDllInfo(PLUGIN_INFO *PluginInfo);</tt>
|-
|<tt>BOOL PauseAudio(BOOL Pause);</tt>
|-
|<tt>void SetConfigDir(char *configDir);</tt>
|-
|<br />
<tt>typedef struct {...} PLUGIN_INFO</tt>
|}
== Input Plugin API ==
=== Mupen64Plus v2.0 Input Plugin API ===
{|
|<tt>void ControllerCommand(int Control, BYTE * Command);</tt>
|Process the raw data that has just been sent to a specific controller.
|-
|<tt>void GetKeys(int Control, BUTTONS * Keys);</tt>
|Get the current state of the controller's buttons
|-
|<tt>void InitiateControllers(CONTROL_INFO ControlInfo);</tt>
|Setup controller data structures
|-
|<tt>void ReadController(int Control, BYTE *Command);</tt>
|Process the raw data in the pif ram that is about to be read. (not currently used)
|-
|<tt>int RomOpen(void);</tt>
|Called just before the emulator begins executing a ROM. '''***changed*** - this function now returns an int (boolean)'''
|-
|<tt>void RomClosed(void);</tt>
|Called after the emulator is stopped.
|-
|<tt>void SDL_KeyDown(int keymod, int keysym);</tt>
|Pass a SDL_KEYDOWN-style message to the input plugin
|-
|<tt>void SDL_KeyUp(int keymod, int keysym);</tt>
|Pass a SDL_KEYUP-style message to the input plugin
|}
=== Remove From Older Input API ===
{|
|-
|<tt>void CloseDLL(void);</tt>
|-
|<tt>void DllAbout(HWND hParent);</tt>
|-
|<tt>void DllConfig(HWND hParent);</tt>
|-
|<tt>void DllTest(HWND hParent);</tt>
|-
|<tt>void GetDllInfo(PLUGIN_INFO *PluginInfo);</tt>
|-
|<tt>void SetConfigDir(char *configDir);</tt>
|-
|<tt>void WM_KeyDown(WPARAM wParam, LPARAM lParam);</tt>
|-
|<tt>void WM_KeyUp(WPARAM wParam, LPARAM lParam);</tt>
|-
|<br />
<tt>typedef struct {...} PLUGIN_INFO</tt>
|}
== RSP Plugin API ==
=== Mupen64Plus v2.0 RSP Plugin API ===
{|
|<tt>DWORD DoRspCycles(DWORD Cycles);</tt>
|Process pending RSP tasks.
|-
|<tt>void InitiateRSP(RSP_INFO Rsp_Info, DWORD *CycleCount);</tt>
|Called during <tt>CoreAttachPlugin</tt> to send info about the emulator core to the audio plugin.
|-
|<tt>void RomClosed(void);</tt>
|Called after the emulator is stopped.
|}
=== Remove From Older RSP API ===
{|
|-
|<tt>void CloseDLL(void);</tt>
|-
|<tt>void DllAbout(HWND hParent);</tt>
|-
|<tt>void DllConfig(HWND hParent);</tt>
|-
|<tt>void DllTest(HWND hParent);</tt>
|-
|<tt>void GetDllInfo(PLUGIN_INFO *PluginInfo);</tt>
|-
|<tt>void GetRspDebugInfo(RSPDEBUG_INFO * RSPDebugInfo);</tt>
|-
|<tt>void InitiateRSPDebugger(DEBUG_INFO DebugInfo);</tt>
|-
|<br />
<tt>typedef struct {...} PLUGIN_INFO</tt><br />
<tt>typedef struct {...} RSPDEBUG_INFO</tt><br />
<tt>typedef struct {...} DEBUG_INFO</tt>
|}

View File

@ -0,0 +1,322 @@
[http://mupen64plus.retrouprising.com Project page]
== m64p_types.h ==
/* ----------------------------------------- */
/* Platform-specific stuff */
/* ----------------------------------------- */
/* necessary headers */
#if defined(WIN32)
#include <windows.h>
#endif
/* DLL handles and function declaration specifiers */
#if defined(WIN32)
#define IMPORT extern "C" __declspec(dllimport)
#define EXPORT __declspec(dllexport)
#define CALL __cdecl
typedef HMODULE m64p_dynlib_handle;
#else
#define IMPORT extern "C"
#define EXPORT __attribute__((visibility("default")))
#define CALL
typedef void * m64p_dynlib_handle;
#endif
/* ----------------------------------------- */
/* Structures and Types for Core library API */
/* ----------------------------------------- */
typedef void * m64p_handle;
typedef void (*m64p_frame_callback)(unsigned int FrameIndex);
typedef void (*m64p_input_callback)(void);
typedef void (*m64p_audio_callback)(void);
typedef void (*m64p_vi_callback)(void);
typedef enum {
M64TYPE_INT = 1,
M64TYPE_FLOAT,
M64TYPE_BOOL,
M64TYPE_STRING
} m64p_type;
typedef enum {
M64MSG_ERROR = 1,
M64MSG_WARNING,
M64MSG_INFO,
M64MSG_STATUS,
M64MSG_VERBOSE
} m64p_msg_level;
typedef enum {
M64ERR_SUCCESS = 0,
M64ERR_NOT_INIT, /* Function is disallowed before InitMupen64Plus() is called */
M64ERR_ALREADY_INIT, /* InitMupen64Plus() was called twice */
M64ERR_INCOMPATIBLE, /* API versions between components are incompatible */
M64ERR_INPUT_ASSERT, /* Invalid parameters for function call, such as ParamValue=NULL for GetCoreParameter() */
M64ERR_INPUT_INVALID, /* Invalid input data, such as ParamValue="maybe" for SetCoreParameter() to set a BOOL-type value */
M64ERR_INPUT_NOT_FOUND, /* The input parameter(s) specified a particular item which was not found */
M64ERR_NO_MEMORY, /* Memory allocation failed */
M64ERR_FILES, /* Error opening, creating, reading, or writing to a file */
M64ERR_INTERNAL, /* Internal error (bug) */
M64ERR_INVALID_STATE, /* Current program state does not allow operation */
M64ERR_PLUGIN_FAIL, /* A plugin function returned a fatal error */
M64ERR_SYSTEM_FAIL, /* A system function call, such as an SDL or file operation, failed */
M64ERR_UNSUPPORTED, /* Function call is not supported (ie, core not built with debugger) */
M64ERR_WRONG_TYPE /* A given input type parameter cannot be used for desired operation */
} m64p_error;
typedef enum {
M64CAPS_DYNAREC = 1,
M64CAPS_DEBUGGER = 2,
M64CAPS_CORE_COMPARE = 4
} m64p_core_caps;
typedef enum {
M64PLUGIN_NULL = 0,
M64PLUGIN_RSP = 1,
M64PLUGIN_GFX,
M64PLUGIN_AUDIO,
M64PLUGIN_INPUT,
M64PLUGIN_CORE
} m64p_plugin_type;
typedef enum {
M64EMU_STOPPED = 1,
M64EMU_RUNNING,
M64EMU_PAUSED
} m64p_emu_state;
typedef enum {
M64VIDEO_NONE = 1,
M64VIDEO_WINDOWED,
M64VIDEO_FULLSCREEN
} m64p_video_mode;
typedef enum {
M64CORE_EMU_STATE = 1,
M64CORE_VIDEO_MODE,
M64CORE_SAVESTATE_SLOT,
M64CORE_SPEED_FACTOR,
M64CORE_SPEED_LIMITER,
M64CORE_VIDEO_SIZE,
M64CORE_AUDIO_VOLUME,
M64CORE_AUDIO_MUTE,
M64CORE_INPUT_GAMESHARK,
M64CORE_STATE_LOADCOMPLETE,
M64CORE_STATE_SAVECOMPLETE
} m64p_core_param;
typedef enum {
M64CMD_NOP = 0,
M64CMD_ROM_OPEN,
M64CMD_ROM_CLOSE,
M64CMD_ROM_GET_HEADER,
M64CMD_ROM_GET_SETTINGS,
M64CMD_EXECUTE,
M64CMD_STOP,
M64CMD_PAUSE,
M64CMD_RESUME,
M64CMD_CORE_STATE_QUERY,
M64CMD_STATE_LOAD,
M64CMD_STATE_SAVE,
M64CMD_STATE_SET_SLOT,
M64CMD_SEND_SDL_KEYDOWN,
M64CMD_SEND_SDL_KEYUP,
M64CMD_SET_FRAME_CALLBACK,
M64CMD_TAKE_NEXT_SCREENSHOT,
M64CMD_CORE_STATE_SET,
M64CMD_READ_SCREEN,
M64CMD_RESET,
M64CMD_ADVANCE_FRAME
} m64p_command;
typedef struct {
unsigned int address;
int value;
} m64p_cheat_code;
/* ----------------------------------------- */
/* Structures to hold ROM image information */
/* ----------------------------------------- */
typedef enum
{
SYSTEM_NTSC = 0,
SYSTEM_PAL,
SYSTEM_MPAL
} m64p_system_type;
typedef struct
{
unsigned char init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
unsigned char init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
unsigned char init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
unsigned char init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
unsigned int ClockRate; /* 0x04 */
unsigned int PC; /* 0x08 */
unsigned int Release; /* 0x0C */
unsigned int CRC1; /* 0x10 */
unsigned int CRC2; /* 0x14 */
unsigned int Unknown[2]; /* 0x18 */
unsigned char Name[20]; /* 0x20 */
unsigned int unknown; /* 0x34 */
unsigned int Manufacturer_ID; /* 0x38 */
unsigned short Cartridge_ID; /* 0x3C - Game serial number */
unsigned short Country_code; /* 0x3E */
} m64p_rom_header;
typedef struct
{
char goodname[256];
char MD5[33];
unsigned char savetype;
unsigned char status; /* Rom status on a scale from 0-5. */
unsigned char players; /* Local players 0-4, 2/3/4 way Netplay indicated by 5/6/7. */
unsigned char rumble; /* 0 - No, 1 - Yes boolean for rumble support. */
} m64p_rom_settings;
/* ----------------------------------------- */
/* Structures and Types for the Debugger */
/* ----------------------------------------- */
typedef enum {
M64P_DBG_RUN_STATE = 1,
M64P_DBG_PREVIOUS_PC,
M64P_DBG_NUM_BREAKPOINTS,
M64P_DBG_CPU_DYNACORE,
M64P_DBG_CPU_NEXT_INTERRUPT
} m64p_dbg_state;
typedef enum {
M64P_DBG_MEM_TYPE = 1,
M64P_DBG_MEM_FLAGS,
M64P_DBG_MEM_HAS_RECOMPILED,
M64P_DBG_MEM_NUM_RECOMPILED,
M64P_DBG_RECOMP_OPCODE = 16,
M64P_DBG_RECOMP_ARGS,
M64P_DBG_RECOMP_ADDR
} m64p_dbg_mem_info;
typedef enum {
M64P_MEM_NOMEM = 0,
M64P_MEM_NOTHING,
M64P_MEM_RDRAM,
M64P_MEM_RDRAMREG,
M64P_MEM_RSPMEM,
M64P_MEM_RSPREG,
M64P_MEM_RSP,
M64P_MEM_DP,
M64P_MEM_DPS,
M64P_MEM_VI,
M64P_MEM_AI,
M64P_MEM_PI,
M64P_MEM_RI,
M64P_MEM_SI,
M64P_MEM_FLASHRAMSTAT,
M64P_MEM_ROM,
M64P_MEM_PIF,
M64P_MEM_MI,
M64P_MEM_BREAKPOINT
} m64p_dbg_mem_type;
typedef enum {
M64P_MEM_FLAG_READABLE = 0x01,
M64P_MEM_FLAG_WRITABLE = 0x02,
M64P_MEM_FLAG_READABLE_EMUONLY = 0x04, // the EMUONLY flags signify that emulated code can read/write here, but debugger cannot
M64P_MEM_FLAG_WRITABLE_EMUONLY = 0x08
} m64p_dbg_mem_flags;
typedef enum {
M64P_DBG_PTR_RDRAM = 1,
M64P_DBG_PTR_PI_REG,
M64P_DBG_PTR_SI_REG,
M64P_DBG_PTR_VI_REG,
M64P_DBG_PTR_RI_REG,
M64P_DBG_PTR_AI_REG
} m64p_dbg_memptr_type;
typedef enum {
M64P_CPU_PC = 1,
M64P_CPU_REG_REG,
M64P_CPU_REG_HI,
M64P_CPU_REG_LO,
M64P_CPU_REG_COP0,
M64P_CPU_REG_COP1_DOUBLE_PTR,
M64P_CPU_REG_COP1_SIMPLE_PTR,
M64P_CPU_REG_COP1_FGR_64,
M64P_CPU_TLB
} m64p_dbg_cpu_data;
typedef enum {
M64P_BKP_CMD_ADD_ADDR = 1,
M64P_BKP_CMD_ADD_STRUCT,
M64P_BKP_CMD_REPLACE,
M64P_BKP_CMD_REMOVE_ADDR,
M64P_BKP_CMD_REMOVE_IDX,
M64P_BKP_CMD_ENABLE,
M64P_BKP_CMD_DISABLE,
M64P_BKP_CMD_CHECK
} m64p_dbg_bkp_command;
#define M64P_MEM_INVALID 0xFFFFFFFF // invalid memory read will return this
#define BREAKPOINTS_MAX_NUMBER 128
#define BPT_FLAG_ENABLED 0x01
#define BPT_FLAG_CONDITIONAL 0x02
#define BPT_FLAG_COUNTER 0x04
#define BPT_FLAG_READ 0x08
#define BPT_FLAG_WRITE 0x10
#define BPT_FLAG_EXEC 0x20
#define BPT_FLAG_LOG 0x40 //Log to the console when this breakpoint hits.
#define BPT_CHECK_FLAG(a, b) ((a.flags & b) == b)
#define BPT_SET_FLAG(a, b) a.flags = (a.flags | b);
#define BPT_CLEAR_FLAG(a, b) a.flags = (a.flags & (~b));
#define BPT_TOGGLE_FLAG(a, b) a.flags = (a.flags ^ b);
typedef struct _breakpoint {
unsigned int address;
unsigned int endaddr;
unsigned int flags;
//unsigned int condition; //Placeholder for breakpoint condition
} breakpoint;
/* ------------------------------------------------- */
/* Structures and Types for Core Video Extension API */
/* ------------------------------------------------- */
typedef struct {
unsigned int uiWidth;
unsigned int uiHeight;
} m64p_2d_size;
typedef enum {
M64P_GL_DOUBLEBUFFER = 1,
M64P_GL_BUFFER_SIZE,
M64P_GL_DEPTH_SIZE,
M64P_GL_RED_SIZE,
M64P_GL_GREEN_SIZE,
M64P_GL_BLUE_SIZE,
M64P_GL_ALPHA_SIZE,
M64P_GL_SWAP_CONTROL,
M64P_GL_MULTISAMPLEBUFFERS,
M64P_GL_MULTISAMPLESAMPLES
} m64p_GLattr;
typedef struct {
unsigned int Functions;
m64p_error (*VidExtFuncInit)(void);
m64p_error (*VidExtFuncQuit)(void);
m64p_error (*VidExtFuncListModes)(m64p_2d_size *, int *);
m64p_error (*VidExtFuncSetMode)(int, int, int, int);
void * (*VidExtFuncGLGetProc)(const char*);
m64p_error (*VidExtFuncGLSetAttr)(m64p_GLattr, int);
m64p_error (*VidExtFuncGLGetAttr)(m64p_GLattr, int *);
m64p_error (*VidExtFuncGLSwapBuf)(void);
m64p_error (*VidExtFuncSetCaption)(const char *);
m64p_error (*VidExtFuncToggleFS)(void);
} m64p_video_extension_functions;

View File

@ -0,0 +1,40 @@
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
Bitstream Vera Sans
Bitstream Vera Sans - Roman Release 1.10 Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
Bitstream Vera is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts
accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to
reproduce and distribute the Font Software, including without limitation the rights to use, copy,
merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom
the Font Software is furnished to do so, subject to the following conditions:
The above copyright and trademark notices and this permission notice shall be included in all copies
of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or
characters in the Fonts may be modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word
"Vera".
This License becomes null and void to the extent applicable to Fonts or Font Software that has been
modified and is distributed under the "Bitstream Vera" names.
The Font Software may be sold as part of a larger software package but no copy of one or more of the
Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE
GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL,
SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc.,
shall not be used in advertising or otherwise to promote the sale, use or other dealings in this
Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc.,
respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.com

View File

@ -0,0 +1,342 @@
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,505 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,174 @@
Mupen64Plus API versions
---------------------------------------------------------------------------------------------------
Goal:
The Mupen64Plus API versioning scheme was invented to give a more friendly and less confusing
experience for users as the various components evolve over time. There are 6 basic components
to the Mupen64Plus system, which may be independently built and installed:
1. The Front-end UI application
2. The Core emulator library
3. The Video plugin
4. The Audio plugin
5. The Input plugin
6. The RSP plugin
These components interact with each other in several different ways. The design goal of the
versioning scheme is to gracefully handle all situations in which two components support different
versions of their common API (due to one component being newer than the other). In particular,
each pair of components sharing a common API must discover whether or not they are compatible with
each other. They must make this determination early enough in the startup process to inform the
user of an incompatibility and gracefully exit the software if necessary without crashing. There
are 2 different decisions that pertain to the compatibility determination:
1. Major API version. The various API version numbers are 32-bit. The major version number is
stored in the upper 16 bits, and the minor version number is in the lower 16 bits. If two
components have different major API version numbers, then they are definitely incompatible.
2. Minor API version. If two components with a common API have different minor version numbers,
then the newer component may decide whether or not it can interact with the older component
based upon the older component's version number. The newer component may optionally disable
new features and still retain backwards compatibility, or it may refuse to operate with the
older component. This decision is left to the component author when new features are added.
---------------------------------------------------------------------------------------------------
Basic Design:
In mupen64plus-core/src/plugin/plugin.h, the following macros are defined:
#define RSP_API_MAJOR_VERSION 0x20000
#define GFX_API_MAJOR_VERSION 0x20000
#define AUDIO_API_MAJOR_VERSION 0x20000
#define INPUT_API_MAJOR_VERSION 0x20000
In mupen64plus-core/src/main/version.h, the following macros are defined:
#define FRONTEND_API_VERSION 0x020000
#define CONFIG_API_VERSION 0x020000
#define DEBUG_API_VERSION 0x020000
#define VIDEXT_API_VERSION 0x020000
1. When the front-end application calls the CoreStartup(), it passes it's Core<-->Front-end API
version to the core. If the API major version numbers for the core and front-end don't match,
the core return from this function with a failure code of M64ERR_INCOMPATIBLE.
2. The Console-UI front-end also checks for API compatibility, during the AttachCoreLib() function
call. It is not strictly necessary for a front-end application to verify the API compatibility
with the core, since the core will also check during CoreStartup(). However, by doing so, an
updated front-end may detect a core library using a newer (but backwards-compatible) API, and
enable some extra features as a result of the expanded API.
3. At the time each plugin is attached to the core (during CoreAttachPlugin function call), the
core checks the version number of the plugin API by calling the PluginGetVersion function. If
the major version number of the plugin's reported API (APIVersion & 0xffff0000) does not match
the corresponding version number for that plugin type in the core (defined in plugin.h), then
the plugin is incompatible and cannot be attached to the core. Currently the plugins have no
way to request the major version number required for a particular plugin type in the core
library.
4. The emulator core exports several different API groups which may be used by the front-end and
plugin modules. Currently, these groups are: Front-end, Config, Debug, and Video Extension.
A front-end application or any plugin may call the CoreGetAPIVersions() function to retrieve
the API version numbers for these groups. Any plugin or front-end which can use any updated
(not present in the original "2.0" API) functions in one of these groups should call the core's
CoreGetAPIVersions() function (during PluginStartup for a plugin or at core attach time for a
front-end) to check the version # of the API supported by the core, and react accordingly.
5. All front-ends and plugins should verify API version compatibility for the Config API.
---------------------------------------------------------------------------------------------------
Handling Future Changes:
1. New feature added to a plugin library
If the feature is backwards-compatible with older cores, then plugin API minor version will
be bumped. Otherwise, major version number will be bumped. If change is backwards-compatible,
then newest core can test the plugin's API version and only enable the feature if present.
2. New feature added to Core<-->Front-end API
Typically this will happen when a new function or a new feature of an existing function is
added to the core. If the older front-ends will still be compatible with newer cores, then the
minor version number of the front-end API will be bumped. Otherwise the major version number
will be bumped. A newer front-end can check the version of the API supported by the core and
choose whether to retain backwards-compatibility with older cores or refuse to interoperate.
3. New feature added to Core Config API
If older plugins can still use the Core Config API with the new feature, then Config API minor
version will be bumped. Otherwise, major version number will be bumped. Newer plugins should
check the Core's Config API version and maintain backwards compatibility with older cores if
possible.
4. New feature added to Core Debug API
If older front-ends can still use the Core Debug API with the new feature, then Debug API minor
version number will be bumped. Otherwise, major version number will be bumped. Newer
front-end applications should check the Core's Debug API version and maintain backwards
compatibility with older cores if possible.
5. New feature added to Video Extension API
This is the most complicated interface, because it involves 3 components: the video plugin, the
core, and the front-end application. If older video plugins can still use the newer Video
Extension API with the core, *and* newer front-end applications can work with older cores, then
the Video Extension API minor version number will be bumped. Otherwise, the major version
number will be bumped. Newer video plugins can check the Core's Video Extension API version
and maintain backwards compatibility with older cores if possible, otherwise they can refuse
and give a compatibility error. Front-end applications (such as the default console-ui) which
do not hook into the Video Extension do not need to check the Core's Video Extension API
version. However, front-end applications which do hook into the Video Extension must check the
API version. If the Core and Front-end have different API major version numbers, then they are
incompatible. Also if the Core has a *newer* minor version than the front-end, then they are
incompatible. This is a unique restriction, and it must be checked and verified by the
front-end; the Core has no way to check this.
---------------------------------------------------------------------------------------------------
Changelog:
- Version 2.0.0 is the base for all APIs
- FRONTEND_API_VERSION version 2.0.1:
- added "m64p_command" type "M64CMD_CORE_STATE_SET", handled by CoreDoCommand()
- added "m64p_core_param" type "M64CORE_SPEED_LIMITER", handled by "M64CMD_CORE_STATE_QUERY" and "M64CMD_CORE_STATE_SET" commands
- FRONTEND_API_VERSION version 2.0.2:
- added "m64p_command" types:
- M64CMD_GET_SCREEN_WIDTH
- M64CMD_GET_SCREEN_HEIGHT
- M64CMD_READ_SCREEN
- M64CMD_VOLUME_UP
- M64CMD_VOLUME_DOWN
- M64CMD_VOLUME_GET_LEVEL
- M64CMD_VOLUME_SET_LEVEL
- M64CMD_VOLUME_MUTE
- M64CMD_RESET
- M64CMD_ADVANCE_FRAME
- extend command M64CMD_STATE_SAVE to support saving uncompressed PJ64 savestate files as well as zip compressed
- FRONTEND_API_VERSION version 2.1.0:
- removed "m64p_command" types:
- M64CMD_GET_SCREEN_WIDTH
- M64CMD_GET_SCREEN_HEIGHT
- M64CMD_VOLUME_UP
- M64CMD_VOLUME_DOWN
- M64CMD_VOLUME_GET_LEVEL
- M64CMD_VOLUME_SET_LEVEL
- M64CMD_VOLUME_MUTE
- added new "m64p_core_param" types:
- M64CORE_VIDEO_SIZE
- M64CORE_AUDIO_VOLUME
- M64CORE_AUDIO_MUTE
- M64CORE_INPUT_GAMESHARK
- M64CORE_STATE_LOADCOMPLETE
- M64CORE_STATE_SAVECOMPLETE
- CONFIG_API_VERSION version 2.1.0:
- add new function "ConfigSaveSection()" to save only a single config section to disk
- CONFIG_API_VERSION version 2.2.0:
- add new function "ConfigHasUnsavedChanges()" to determine if a given Section (or all sections)
of the Mupen64Plus Core configuration file has been modified since it was last saved or loaded.
- add new function "ConfigRevertChanges()" to revert changes previously made to one section of
the configuration file, so that it will match with the configuration at the last time that it
was loaded from or saved to disk.
- VIDEO_API_VERSION version 2.1.0:
- video render callback function now takes a boolean (int) parameter, which specifies whether the
video frame has been re-drawn since the last time the render callback was called. This allows
us to take screenshots without the On-Screen-Display text

View File

@ -0,0 +1,413 @@
This page describes the dynamic recompiler in [[Mupen64Plus]], and the changes made for the ARM port.
==The original dynamic recompiler by Hacktarux==
The dynamic recompiler used in Mupen64plus v1.5 is based on the original written by Hacktarux in 2002.
It recompiles contiguous blocks of MIPS instructions. First, each instruction is decoded into a dynamically-allocated 132-byte data structure.
<source lang="text">
typedef struct _precomp_instr
{
void (*ops)();
union
{
struct
{
long long int *rs;
long long int *rt;
short immediate;
} i;
struct
{
unsigned int inst_index;
} j;
struct
{
long long int *rs;
long long int *rt;
long long int *rd;
unsigned char sa;
unsigned char nrd;
} r;
struct
{
unsigned char base;
unsigned char ft;
short offset;
} lf;
struct
{
unsigned char ft;
unsigned char fs;
unsigned char fd;
} cf;
} f;
unsigned int addr; /* word-aligned instruction address in r4300 address space */
unsigned int local_addr; /* byte offset to start of corresponding x86_64 instructions, from start of code block */
reg_cache_struct reg_cache_infos;
} precomp_instr;
</source>
The decoded instructions are then compiled, generating x86 instructions for each MIPS instruction. A 32K block is allocated with malloc() to hold the x86 code. If this size proves insufficient, it is incrementally resized with realloc().
MIPS registers are allocated to x86 registers with a least-recently-used replacement policy. All cached registers are written back prior to a branch, or a memory read or write.
To facilitate invalidation and replacement of modified code blocks, each 4K page is compiled separately. If a sequence of instructions crosses a 4K page boundary, the current block is ended, and the next instructions will be compiled as a separate block.
Branch instructions within a 4K page are compiled as branches directly to the target address. Branches which cross a 4K page go through an indirect address lookup.
Compiled code blocks are invalidated on write. On an actual MIPS CPU, the instruction cache is invalidated using the CACHE instruction, however a few N64 games clear the cache using other methods. Trapping writes appears to be the most reliable method of ensuring cache coherency in the emulated system. The cache instruction is ignored.
==Problems with the original design==
The most significant performance problem with this design is its excessive memory usage. The decoded instruction data is retained (132 bytes for each MIPS instruction) and occasionally referenced during execution. Memory accesses frequently miss the L2 cache, resulting in poor performance.
Additionally, the register cache is relatively inefficient, since all registers are flushed before any read or write operation.
==A new approach==
To reduce memory usage, the new design allocates a single large block of memory (generally 32 MiB, but the size is configurable) which is used for recompiled code. This memory is allocated using mmap with the PROT_EXEC bit set, to ensure operation on CPUs with no-execute (NX) page permissions.
Contiguous blocks of MIPS instructions are compiled (that is, it does not attempt to follow branches or 'hot-paths').
The recompiler consists of eight stages, plus a linker, and a memory manager.
Compiled blocks are invalidated on write, as before, however as the compiler will cross a 4K page, writes may invalidate adjacent pages as well.
Currently the dynarec generates x86, x86-64, ARMv5, and ARMv7 (little-endian). Most of the code is shared between the architectures, but a different code generator is included at compile time, using different #include statements depending on the CPU type.
==Pass 1: Disassembly==
When an instruction address is encountered which has not been compiled, the function new_recompile_block is called, with the (virtual) address of the target instruction as its sole parameter. If the address is invalid, the function returns a nonzero value and the caller is responsible for handling the pagefault.
Instructions are decoded until an unconditional jump, usually a return, is encountered. Disassembly is ordinarilly continued past a JAL (subroutine call) instruction, however this strategy is abandoned if invalid instructions are encountered.
Up to 4096 instructions (16K of MIPS code) may be disassembled at once. Surprisingly, some games do actually reach this limit.
==Pass 2: Liveness analysis==
After disassembly, liveness analysis is performed on the registers. This determines when a particular register will no longer be used, and thus can be removed from the register cache.
A separate analysis is done on the upper 32 bits of 64-bit registers. This can determine when only the lower 32 bits of a register are significant, thus allowing use of a 32-bit register. This enables more efficient code generation on 32-bit processors.
==Pass 3: Register allocation==
The 31 MIPS registers must be mapped onto seven available registers on x86, or twelve available registers on ARM.
Instructions with 64-bit results require two registers on 32-bit host processors. 32-bit instructions require only one. A flag is set for registers containing 32-bit values, and these registers will be sign-extended before they are written to the register file.
Registers are made available using a least-soon-needed replacement policy. When the register cache is full, and no registers can be eliminated using the liveness analysis, a ten-instruction lookahead is used to determine which registers will not be needed soon and these registers are evicted from the cache.
==Pass 4: Free unused registers==
After the initial register allocation, the allocations are reviewed to determine if any registers remain allocated longer than necessary. These are then removed from the register cache. This avoids having to write back a large number of registers just before a branch, and makes more registers available for the next pass.
==Pass 5: Pre-allocate registers==
If a register will be used soon and needs to be loaded, try to load it early if the register is available. This improves execution on CPUs with a load-use penalty.
==Pass 6: Optimize clean/dirty state==
If a cached register is 'dirty' and needs to be written out, try to do so as soon as the register will no longer be modified. This avoids having to write the same register on multiple code paths due to conditional branches. Additionally, try to avoid writing out dirty registers inside of loops.
==Pass 7: Identify where registers are assumed to be 32-bit==
When a 64-bit register is mapped to a 32-bit register with the assumption that the value will be sign-extended before being used, it is necessary to ensure that no register contains a 64-bit value when branching to such a location. These instructions are flagged to identify them as requiring 32-bit inputs. This information is used by the linker, and the exception return (ERET) handler.
==Pass 8: Assembly==
This generates and outputs the recompiled code.
Following the main code block, handlers for certain exceptions as well as alternate entry points are added.
If a recompiled instruction relies on a certain MIPS register being cached in a certain native register, then a short 'stub' of code is generated to load the necessary registers. When an instruction outside of this block needs to jump to that location, it will instead jump to the stub. The necessary registers will be loaded, and then it will jump into the main code sequence.
On architectures which require literal pools (ARMv5) these are inserted as necessary.
==Linker==
The linker fills in all unresolved branches. Branches within the block are linked to their target address. Branches which jump outside of the block are linked to their target if that address has been compiled already. These inter-block branches are recorded in the jump_out array. This information will be used to remove the links in the event that the target of the branch is invalidated.
Unresolved branches point to a stub which loads the address of the branch instruction and the virtual address of its target into registers, and calls the dynamic linker. When this code is executed, the dynamic linker will compile the target if necessary, and then patch the branch instruction with the new address.
==Memory manager==
The last step in new_recompile_block is to ensure that there will be sufficient memory available to compile the next block. If there is not, then the oldest blocks are purged.
The dynarec cache can be described as a 32MB circular buffer divided into eight segments. Memory is allocated in order from beginning to end.
When there are less than 2 empty segments, the next segment in sequence is cleared, wrapping around to the beginning of the buffer. This continues as memory is needed, wrapping around from end to beginning.
==Invalidation and restoration==
Normally, code blocks are looked up via a hash table, using the virtual address of the target instruction. However, for purposes of invalidation, blocks are grouped by physical address. This can be described as a virtually-indexed, physically-tagged (VIPT) cache.
References to compiled blocks are stored in one of 4096 linked lists in the jump_in array. Each list covers a 4K block of memory, and 2048 such lists are sufficient to cover the 8MB of RAM in the Nintendo 64. The remaining lists are for code in ROM, and the bootloader in SP memory.
When a write hits a memory page marked as cached, all entries in the corresponding list are invalidated. If any code is found to cross a 4K boundary, the adjacent lists are invalidated also.
Sometimes blocks may be invalidated even when none of the code is actually modified. This can happen if data is written to memory in the same 4K page, or if code is reloaded without actually modifying it. If blocks which were previously invalidated are subsequently found to be unmodified, those blocks are marked in the restore_candidate array. If the block remains unmodified, it will be restored as a valid block, to avoid recompiling blocks which do not need to be recompiled. This is performed by the clean_blocks function which is called periodically.
The jump_in array, which lists unmodified blocks, is physically indexed, however the jump_dirty array, which lists potentially-modified blocks, is virtually indexed. This allows blocks which have changed physical addresses, but are still at the same virtual address, to be recognized as being the same as before, and not in need of recompilation.
==Dynamic linker==
Branches with unresolved addresses jump to the dynamic linker. This will look through the jump_in list corresponding to the physical page containing the virtual target address. If found, the branch instruction will be patched with the address, and then it will jump to this address.
If not found, the jump_dirty list will be searched for blocks which were previously compiled but may have been modified. If a potential match is found, the code will be compared against a cached copy to determine if any changes have been made. If not, then it will jump to the block. Because the memory could be modified again, branch instructions referencing these blocks are not altered, and continue to point to the dynamic linker. These blocks will continue to be verified each time they are called, until restored to the jump_in list by the clean_blocks function described above.
If no compiled block is found, or the existing block was modified, the target is recompiled.
==Address lookup==
When a JR (jump register) instruction is encountered, the address of the recompiled code must be looked up using the address of the MIPS code. The majority of such instructions jump to the link register (r31) to return to the location following a JAL (call) instruction.
When a JAL or JALR is executed, the address of the following instruction is inserted into a small 32-entry hash table, which is checked when a JR r31 instruction is executed. This allows for a quick return from subroutine calls.
If the JR instruction uses a register other than r31, or the small hash table lookup fails to find a match, a larger 131072-entry hash table is checked. This table contains 65536 bins with up to 2 addresses per bin. If this also fails to find a match (which occurs less than 1% of the time) an exhaustive search of all compiled addresses within that 4K memory page is performed.
If no match is found by any of these methods, the target address is compiled, and the new address is inserted into the hash table.
==Cycle counting==
Cycles are counted before each branch by adding the cycles from the preceding instructions to a specific register. The cycle count is in R10 on ARM and ESI on x86. The value in this register is normally a negative number. When this number exceeds zero, a conditional branch is taken which jumps to an interrupt handler.
For example, the following x86 code adds eight cycles:
<source lang="text">
add $8,%esi
jns interrupt_handler
</source>
The conditional branch jumps to a small bit of code located after the main compiled block, which saves the cached registers to the register file, sets the instruction pointer which will be used upon return from the interrupt, and then calls cc_interrupt.
As in the original mupen64plus, the emulated clock runs at 37.5 MHz, and each instruction takes 2 clock cycles.
==Interrupt handler==
When the cycle count register reaches its limit, cc_interrupt is called, which in turn calls gen_interupt [sic]. If interrupts are not enabled, cc_interrupt returns. If interrupts are enabled, and an interrupt is to be taken, the pending_exception flag will be set. In this case, cc_interrupt does not return, and instead pops the stack and causes an unconditional jump to the address in pcaddr (usually 0x80000180).
There is one additional case where the interrupt handler may be called. If interrupts were disabled, and are enabled by writing to coprocessor 0 register 12, any pending interrupts are handled immediately.
==Delay slots==
MIPS has 'delay slots', where the instruction after the branch is executed before the branch is taken. Instructions in delay slots are issued out-of-order in the recompiled code.
[[Image:Recompiler delay slot reordering.png]]
When a branch jumps into the delay slot of another branch, this case must be handled slightly differently:
[[Image:Recompiler delay slot reordering 2.png]]
The branch test and delay slot are executed in-order if a dependency exists, or for 'likely' branches where the delay slot is nullified when the branch condition is false. These cases are infrequent (typically less than 10% of branches).
==Constant propagation==
When an instruction loads a constant into a register, the register is tagged as a constant. The constant tag will be retained if subsequent instructions modify the constant using other constants. During assembly, such a sequence of instructions is combined into a single load. For example:
<source lang="text">
LUI r8,12340000 --> mov $0x12345678,%eax
ORI r8,r8,5678
</source>
This optimization is not performed where a branch target intervenes, eg
<source lang="text">
...
LUI r8,12340000 --> mov $0x12340000,%eax
L1:
ORI r8,r8,5678 --> or $0x5678,%eax
...
BEQ r0,r0,L1
</source>
Registers containing constants are identified by bits in the isconst and wasconst fields of the regstat structure. The wasconst bit is set for a register if the register contained a known constant before the instruction, and the isconst bit is set for a register if the register will contain a known constant after the instruction executes.
==Translation lookaside buffer emulation==
Most Nintendo 64 games do not use virtual memory, but some do. At startup, main memory is directly mapped at addresses from 0x80000000 to 0x803FFFFF, or up to 0x807FFFFF if the memory expansion is used.
Normally, read or write operations are checked against this range, and if outside this range, control is passed to the appropriate I/O handler. This is done as follows:
MIPS instruction: LW r1,8(r2)
ARM code:
<source lang="text">
add r1, r2, #8
cmp r1, #8388608
bvc handler
ldr r1, [r1]
</source>
If there are valid entries in the TLB, this would instead be compiled as follows:
<source lang="text">
add r1, r2, #8
mov r0, #264
add r0, r0, r1, lsr #12
ldr r0, [r11, r0, lsl #2]
tst r0, r0
bmi handler
ldr r1, [r1, r0, lsl #2]
</source>
This looks up the offset in the memory_map table (which, in this example, is located at r11+264*4). The high bit is tested to determine whether a valid mapping exists for this page.
==Page fault emulation==
If a memory address references an invalid page, a conditional branch is taken to a bit of code placed after the main block. This will save any modified cached registers, and call an appropriate handler function for the address. The handler will either perform I/O, or generate an exception (pagefault).
==Mapping executable pages==
If the dynamic recompiler encounters code which is not in contiguous physical memory, it will end the block at the page boundary, so that the block can be removed cleanly if the mapping is changed.
There is a special case of this, where a branch and delay slot span two pages. If a branch instruction is the last instruction in a virtual memory page, it is compiled in a different manner than other branches. The branch condition is evaluated, and the target address is placed in a register (%ebp on x86, and r8 on ARM). A special form of the dynamic linker (dyna_linker_ds) is used to link the branch to its corresponding delay slot in another block. If no page fault occurs, the delay slot executes and then jumps to the address in the register. For conditional branches that are not taken, the target address is the next instruction. This code is generated by the pagespan_assemble function.
== Self-modifying code detection ==
Pages not containing code which has been compiled or where the code may have been modified since compilation are marked in the invalid_code array. Writes are checked against this array, and if a write hits a valid (compiled and unmodified) page, invalidate_block is called:
MIPS instruction: SW r1,8(r2)
ARM code:
<source lang="text">
ldr r3, [r11, #88] // pointer to invalid_code
add r4, r2, #8
cmp r4, #8388608
bvc handler
str r1, [r4]
ldrb r14, [r3, r4 lsr #12]
cmp r14, #1
bne invstub
</source>
In TLB mode, the invalid_code array is not checked directly. Instead, pages are marked non-writable in memory_map.
== Long jumps ==
Branch instructions are limited to a +/-32MB range on ARM. In some cases, the dynamic recompiler needs to generate calls to locations beyond this range. This is accomplished via a jump table located at the end of the code generation area, and the full address is loaded via a pointer. The jump table is generated in arch_init().
As these indirect jumps cause some delay, it is best to avoid this situation if possible, by locating this area close to the other executable code.
== Compile options ==
=== ARMv5_ONLY ===
If this is defined, the UXTH instruction is not used, and the dynamic recompiler will generate literal pools instead of using movw/movt. This provides compatibility with older processors, but generates somewhat less efficient code.
=== RAM_OFFSET ===
When compiling for ARM, this allocates an additional register which is used to add an offset to all pointers to memory addresses between 0x80000000 and 0x807FFFFF. This allows the N64's memory to be mapped at an alternate address. This incurs a small performance penalty, but is required for certain operating systems (eg Google Android, which places shared libraries at 0x80000000).
This option is not used for x86. The x86 instruction set allows for a full 32-bit offset in the instruction encoding, making it unnecessary to allocate an additional register for this purpose.
=== CORTEX_A8_BRANCH_PREDICTION_HACK ===
If this is defined, the dynamic recompiler will avoid generating consecutive branch instructions without another instruction in between. This avoids a possible branch misprediction on the Cortex-A8 due to this processor having dual instruction decoders, but only one branch-prediction unit. See [[Assembly Code Optimization]] for details.
=== USE_MINI_HT ===
If this is defined, attempt to look up return addresses in a small hash table before checking the larger hash table. Usually improves performance.
=== IMM_PREFETCH ===
If this is defined, the x86 PREFETCH instruction is used to prefetch entries from the hash table. The increase in code size often outweighs the benefit of this.
=== REG_PREFETCH ===
Similar to the above, but loads the address into a register first, then uses the ARM PLD instruction. The increase in code size almost always outweighs the benefit of this.
=== R29_HACK ===
Assume that the stack pointer (r29) is always a valid memory address and do not check it. It is similar to the optimization described [http://strmnnrmn.blogspot.com/2007/08/interesting-dynarec-hack.html here]. This can crash the emulator and is not enabled by default.
== Debugging ==
Debugging information can be obtained by defining the assem_debug macro as printf. This will cause the dynamic recompiler to print debugging information to stdout. For each disassembled MIPS instruction, an entry similar to the following will be printed:
<source lang="text">
U: r1 r8 r11 r16 r31 UU: r29 32: r0 r9
pre: eax=-1 ecx=9 edx=-1 ebx=-1 ebp=29 esi=36 edi=-1
needs: ecx ebp esi r: r9
entry: eax=-1 ecx=9 edx=-1 ebx=-1 ebp=29 esi=36 edi=-1
dirty: ecx ebp esi
800001d8: LW r16,r29+14
eax=16 ecx=9 edx=-1 ebx=-1 ebp=29 esi=36 edi=-1 dirty: eax ecx ebp esi
32: r0 r9 r16
</source>
U: A list of MIPS registers which will not be used before they are overwritten (liveness analysis)
UU: A list of MIPS registers for which the upper 32 bits will not be used before they are overwritten
32: Registers that contain 32-bit sign-extended values
pre: The state of the register mapping prior to execution of this instruction. (-1 = no mapping; 36 = cycle count; The complete list of values with special meanings can be found in the source code)
needs: a list of register mappings that were considered necessary and which could not be eliminated to make room for other mappings
r: Registers that are known to contain 32-bit values and where optimizations rely on the assumption that the register does not contain a value outside of the range -2<sup>31</sup> to 2<sup>31</sup>-1
entry: The minimum set of register mappings required to jump to this point
dirty: Cached registers that have been modified and will need to be written back
address: instruction - The decoded opcode, followed by the register mapping in effect after this instruction executes
An asterisk (*) designates locations which are the target of a branch instruction. Constant propagation will not be performed across these points.
After the complete disassembly, the recompiled native code is shown.
Note that the output can be quite voluminous; 20-30 MB is typical.
==Potential improvements==
===Copy propagation/offset propagation===
A common instruction sequence is of the form:
<source lang="text">
LUI r9,12340000
ADD r9,r9,r8
LW r9,5678(r9)
</source>
It would be helpful to recognize this as a load from r8+12345678. The current constant propagation code does not do so.
===Constant propagation and register assignment===
Constant propagation is currently done after register assignment. Registers are assigned even if the register will always contain a known value. In certain cases, such as where the constant is used only to generate a memory address, this could be avoided and no register would need to be allocated.
===Unaligned memory access===
A small improvement could be made by combining adjacent LWL/LWR instructions. The potential gain from doing so is very limited because these instructions typically represent less than 1% of all memory accesses.
===SLT/branch merging===
A frequent occurrence in MIPS code is an SLT or SLTI instruction followed by a branch. This is generated relatively inefficiently on x86 and ARM, first doing a compare and set, then testing this value and doing a conditional branch. Doing only one comparison would save at least one instruction, and could potentially save up to three instructions if the liveness analysis reveals that the result of the SLT instruction is used nowhere else.
While a potentially useful optimization, there are several problems with this approach. First, there are often additional instructions between the slt and the branch. These must be checked to make sure they do not modify the registers as that would prevent reordering the instruction stream as desired. Secondly, if the result of the slt is found to be live, but unmodified, on both paths of the branch, clean_registers will normally write this value before the branch, to avoid duplicating the writeback code on both paths of the branch. This optimization would have to be removed if the slt was combined with the branch.
===x86-64===
Currently the x86-64 backend generates only 32-bit instructions. Proper 64-bit code generation would improve performance.
===PowerPC===
It would be possible to add a PowerPC code generator to the dynamic recompiler. Currently no one is working on this. (The mupen64gc project is using a different codebase.)
The following is a summary of the changes which would be necessary to add a PowerPC backend.
The slt* instructions use conditional moves, which are unavailable on PowerPC. A suitable alternative (such as moves from the condition register) would need to be used.
The assembler can generate as much as 256K of code in a single block, however conditional branches on PowerPC are limited to +/-64K. It will be necessary to either restrict the block size, or insert jump tables in a manner similar to the literal pools on ARM.
PowerPC generally relies on early branch resolution rather than statistical branch prediction. Scheduling branch condition tests earlier may be advantageous. (For example, the address bounds check could be done in address_generation, rather than just before the load or store. Similarly it may be advantageous to test the branch condition and update the cycle count before executing the delay slot.)
===MIPS===
Recompiling MIPS into MIPS would be relatively straightforward, however the current code generator has no facility for filling delay slots. This capability would be required for efficient code generation.
[[Category:Emulators]]
[[Category:Optimization]]
[[Category:Development]]

View File

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{92D3FEB9-2129-41C5-8577-BCD7D961EF41}</ProjectGuid>
<RootNamespace>mupen64pluscore</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;inline=__inline;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>shell32.lib;opengl32.lib;glu32.lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib\zlib.lib;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib\libpng.lib;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\lib\freetype.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)mupen64plus.dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;inline=__inline;M64P_OSD;M64P_PARALLEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>shell32.lib;opengl32.lib;glu32.lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib\zlib.lib;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib\libpng.lib;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\lib\freetype.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)mupen64plus.dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\r4300\x86\assemble.c" />
<ClCompile Include="..\..\src\api\callbacks.c" />
<ClCompile Include="..\..\src\main\cheat.c" />
<ClCompile Include="..\..\src\api\common.c" />
<ClCompile Include="..\..\src\api\config.c" />
<ClCompile Include="..\..\src\debugger\dbg_breakpoints.c" />
<ClCompile Include="..\..\src\debugger\dbg_decoder.c" />
<ClCompile Include="..\..\src\debugger\dbg_memory.c" />
<ClCompile Include="..\..\src\debugger\debugger.c">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.xdc</XMLDocumentationFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
<XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.xdc</XMLDocumentationFileName>
</ClCompile>
<ClCompile Include="..\..\src\api\debugger.c" />
<ClCompile Include="..\..\src\memory\dma.c" />
<ClCompile Include="..\..\src\plugin\dummy_audio.c" />
<ClCompile Include="..\..\src\plugin\dummy_input.c" />
<ClCompile Include="..\..\src\plugin\dummy_rsp.c" />
<ClCompile Include="..\..\src\plugin\dummy_video.c" />
<ClCompile Include="..\..\src\osal\dynamiclib_win32.c" />
<ClCompile Include="..\..\src\main\eventloop.c" />
<ClCompile Include="..\..\src\r4300\exception.c" />
<ClCompile Include="..\..\src\osal\files_win32.c" />
<ClCompile Include="..\..\src\memory\flashram.c" />
<ClCompile Include="..\..\src\api\frontend.c" />
<ClCompile Include="..\..\src\r4300\x86\gbc.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop0.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop1.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop1_d.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop1_l.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop1_s.c" />
<ClCompile Include="..\..\src\r4300\x86\gcop1_w.c" />
<ClCompile Include="..\..\src\r4300\x86\gr4300.c" />
<ClCompile Include="..\..\src\r4300\x86\gregimm.c" />
<ClCompile Include="..\..\src\r4300\x86\gspecial.c" />
<ClCompile Include="..\..\src\r4300\x86\gtlb.c" />
<ClCompile Include="..\..\src\r4300\interupt.c" />
<ClCompile Include="..\..\src\main\zip\ioapi.c" />
<ClCompile Include="..\..\src\main\lirc.c" />
<ClCompile Include="..\..\src\main\main.c" />
<ClCompile Include="..\..\src\main\md5.c" />
<ClCompile Include="..\..\src\memory\memory.c" />
<ClCompile Include="..\..\src\memory\n64_cic_nus_6105.c" />
<ClCompile Include="..\..\src\osd\OGLFT.cpp" />
<ClCompile Include="..\..\src\osd\osd.cpp" />
<ClCompile Include="..\..\src\memory\pif.c" />
<ClCompile Include="..\..\src\plugin\plugin.c" />
<ClCompile Include="..\..\src\r4300\profile.c" />
<ClCompile Include="..\..\src\r4300\pure_interp.c" />
<ClCompile Include="..\..\src\r4300\r4300.c" />
<ClCompile Include="..\..\src\r4300\recomp.c" />
<ClCompile Include="..\..\src\r4300\x86\regcache.c" />
<ClCompile Include="..\..\src\r4300\reset.c" />
<ClCompile Include="..\..\src\r4300\x86\rjump.c" />
<ClCompile Include="..\..\src\main\rom.c" />
<ClCompile Include="..\..\src\main\savestates.c" />
<ClCompile Include="..\..\src\osd\screenshot.cpp" />
<ClCompile Include="..\..\src\memory\tlb.c" />
<ClCompile Include="..\..\src\main\zip\unzip.c" />
<ClCompile Include="..\..\src\main\util.c" />
<ClCompile Include="..\..\src\api\vidext.c" />
<ClCompile Include="..\..\src\main\workqueue.c" />
<ClCompile Include="..\..\src\main\zip\zip.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\r4300\x86\assemble.h" />
<ClInclude Include="..\..\src\api\callbacks.h" />
<ClInclude Include="..\..\src\main\cheat.h" />
<ClInclude Include="..\..\src\api\config.h" />
<ClInclude Include="..\..\src\main\zip\crypt.h" />
<ClInclude Include="..\..\src\debugger\dbg_breakpoints.h" />
<ClInclude Include="..\..\src\debugger\dbg_decoder.h" />
<ClInclude Include="..\..\src\debugger\dbg_memory.h" />
<ClInclude Include="..\..\src\debugger\dbg_opprintf.h" />
<ClInclude Include="..\..\src\debugger\dbg_types.h" />
<ClInclude Include="..\..\src\debugger\debugger.h" />
<ClInclude Include="..\..\src\api\debugger.h" />
<ClInclude Include="..\..\src\memory\dma.h" />
<ClInclude Include="..\..\src\plugin\dummy_audio.h" />
<ClInclude Include="..\..\src\plugin\dummy_input.h" />
<ClInclude Include="..\..\src\plugin\dummy_rsp.h" />
<ClInclude Include="..\..\src\plugin\dummy_video.h" />
<ClInclude Include="..\..\src\osal\dynamiclib.h" />
<ClInclude Include="..\..\src\main\eventloop.h" />
<ClInclude Include="..\..\src\r4300\exception.h" />
<ClInclude Include="..\..\src\osal\files.h" />
<ClInclude Include="..\..\src\memory\flashram.h" />
<ClInclude Include="..\..\src\r4300\x86\interpret.h" />
<ClInclude Include="..\..\src\r4300\interupt.h" />
<ClInclude Include="..\..\src\main\zip\ioapi.h" />
<ClInclude Include="..\..\src\main\lirc.h" />
<ClInclude Include="..\..\src\api\m64p_common.h" />
<ClInclude Include="..\..\src\api\m64p_config.h" />
<ClInclude Include="..\..\src\api\m64p_debugger.h" />
<ClInclude Include="..\..\src\api\m64p_frontend.h" />
<ClInclude Include="..\..\src\api\m64p_plugin.h" />
<ClInclude Include="..\..\src\api\m64p_types.h" />
<ClInclude Include="..\..\src\api\m64p_vidext.h" />
<ClInclude Include="..\..\src\r4300\macros.h" />
<ClInclude Include="..\..\src\main\main.h" />
<ClInclude Include="..\..\src\main\md5.h" />
<ClInclude Include="..\..\src\memory\memory.h" />
<ClInclude Include="..\..\src\memory\n64_cic_nus_6105.h" />
<ClInclude Include="..\..\src\osd\OGLFT.h" />
<ClInclude Include="..\..\src\r4300\ops.h" />
<ClInclude Include="..\..\src\osd\osd.h" />
<ClInclude Include="..\..\src\memory\pif.h" />
<ClInclude Include="..\..\src\plugin\plugin.h" />
<ClInclude Include="..\..\src\osal\preproc.h" />
<ClInclude Include="..\..\src\r4300\r4300.h" />
<ClInclude Include="..\..\src\r4300\recomp.h" />
<ClInclude Include="..\..\src\r4300\recomph.h" />
<ClInclude Include="..\..\src\r4300\x86\regcache.h" />
<ClInclude Include="..\..\src\r4300\reset.h" />
<ClInclude Include="..\..\src\main\rom.h" />
<ClInclude Include="..\..\src\main\savestates.h" />
<ClInclude Include="..\..\src\osd\screenshot.h" />
<ClInclude Include="..\..\src\memory\tlb.h" />
<ClInclude Include="..\..\src\main\zip\unzip.h" />
<ClInclude Include="..\..\src\main\util.h" />
<ClInclude Include="..\..\src\main\version.h" />
<ClInclude Include="..\..\src\api\vidext.h" />
<ClInclude Include="..\..\src\main\workqueue.h" />
<ClInclude Include="..\..\src\main\zip\zip.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,685 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mupen64plus-core"
ProjectGUID="{92D3FEB9-2129-41C5-8577-BCD7D961EF41}"
RootNamespace="mupen64pluscore"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;inline=__inline;M64P_OSD;M64P_PARALLEL"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="shell32.lib opengl32.lib glu32.lib ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib ..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib\zlib.lib ..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib\libpng.lib ..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\lib\freetype.lib"
OutputFile="$(OutDir)\mupen64plus.dll"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;DYNAREC;inline=__inline;M64P_OSD;M64P_PARALLEL"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
CompileAs="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="shell32.lib opengl32.lib glu32.lib ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib ..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib\zlib.lib ..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib\libpng.lib ..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\lib\freetype.lib"
OutputFile="$(OutDir)\mupen64plus.dll"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\r4300\x86\assemble.c"
>
</File>
<File
RelativePath="..\..\src\api\callbacks.c"
>
</File>
<File
RelativePath="..\..\src\main\cheat.c"
>
</File>
<File
RelativePath="..\..\src\api\common.c"
>
</File>
<File
RelativePath="..\..\src\api\config.c"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_breakpoints.c"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_decoder.c"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_memory.c"
>
</File>
<File
RelativePath="..\..\src\debugger\debugger.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\api\debugger.c"
>
</File>
<File
RelativePath="..\..\src\memory\dma.c"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_audio.c"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_input.c"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_rsp.c"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_video.c"
>
</File>
<File
RelativePath="..\..\src\osal\dynamiclib_win32.c"
>
</File>
<File
RelativePath="..\..\src\main\eventloop.c"
>
</File>
<File
RelativePath="..\..\src\r4300\exception.c"
>
</File>
<File
RelativePath="..\..\src\osal\files_win32.c"
>
</File>
<File
RelativePath="..\..\src\memory\flashram.c"
>
</File>
<File
RelativePath="..\..\src\api\frontend.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gbc.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop0.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop1.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop1_d.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop1_l.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop1_s.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gcop1_w.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gr4300.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gregimm.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gspecial.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\gtlb.c"
>
</File>
<File
RelativePath="..\..\src\r4300\interupt.c"
>
</File>
<File
RelativePath="..\..\src\main\zip\ioapi.c"
>
</File>
<File
RelativePath="..\..\src\main\lirc.c"
>
</File>
<File
RelativePath="..\..\src\main\main.c"
>
</File>
<File
RelativePath="..\..\src\main\md5.c"
>
</File>
<File
RelativePath="..\..\src\memory\memory.c"
>
</File>
<File
RelativePath="..\..\src\memory\n64_cic_nus_6105.c"
>
</File>
<File
RelativePath="..\..\src\osd\OGLFT.cpp"
>
</File>
<File
RelativePath="..\..\src\osd\osd.cpp"
>
</File>
<File
RelativePath="..\..\src\memory\pif.c"
>
</File>
<File
RelativePath="..\..\src\plugin\plugin.c"
>
</File>
<File
RelativePath="..\..\src\r4300\profile.c"
>
</File>
<File
RelativePath="..\..\src\r4300\pure_interp.c"
>
</File>
<File
RelativePath="..\..\src\r4300\r4300.c"
>
</File>
<File
RelativePath="..\..\src\r4300\recomp.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\regcache.c"
>
</File>
<File
RelativePath="..\..\src\r4300\reset.c"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\rjump.c"
>
</File>
<File
RelativePath="..\..\src\main\rom.c"
>
</File>
<File
RelativePath="..\..\src\main\savestates.c"
>
</File>
<File
RelativePath="..\..\src\osd\screenshot.cpp"
>
</File>
<File
RelativePath="..\..\src\memory\tlb.c"
>
</File>
<File
RelativePath="..\..\src\main\zip\unzip.c"
>
</File>
<File
RelativePath="..\..\src\main\util.c"
>
</File>
<File
RelativePath="..\..\src\api\vidext.c"
>
</File>
<File
RelativePath="..\..\src\main\workqueue.c"
>
</File>
<File
RelativePath="..\..\src\main\zip\zip.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\src\r4300\x86\assemble.h"
>
</File>
<File
RelativePath="..\..\src\api\callbacks.h"
>
</File>
<File
RelativePath="..\..\src\main\cheat.h"
>
</File>
<File
RelativePath="..\..\src\api\config.h"
>
</File>
<File
RelativePath="..\..\src\main\zip\crypt.h"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_breakpoints.h"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_decoder.h"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_memory.h"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_opprintf.h"
>
</File>
<File
RelativePath="..\..\src\debugger\dbg_types.h"
>
</File>
<File
RelativePath="..\..\src\debugger\debugger.h"
>
</File>
<File
RelativePath="..\..\src\api\debugger.h"
>
</File>
<File
RelativePath="..\..\src\memory\dma.h"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_audio.h"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_input.h"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_rsp.h"
>
</File>
<File
RelativePath="..\..\src\plugin\dummy_video.h"
>
</File>
<File
RelativePath="..\..\src\osal\dynamiclib.h"
>
</File>
<File
RelativePath="..\..\src\main\eventloop.h"
>
</File>
<File
RelativePath="..\..\src\r4300\exception.h"
>
</File>
<File
RelativePath="..\..\src\osal\files.h"
>
</File>
<File
RelativePath="..\..\src\memory\flashram.h"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\interpret.h"
>
</File>
<File
RelativePath="..\..\src\r4300\interupt.h"
>
</File>
<File
RelativePath="..\..\src\main\zip\ioapi.h"
>
</File>
<File
RelativePath="..\..\src\main\lirc.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_common.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_config.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_debugger.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_frontend.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_plugin.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_types.h"
>
</File>
<File
RelativePath="..\..\src\api\m64p_vidext.h"
>
</File>
<File
RelativePath="..\..\src\r4300\macros.h"
>
</File>
<File
RelativePath="..\..\src\main\main.h"
>
</File>
<File
RelativePath="..\..\src\main\md5.h"
>
</File>
<File
RelativePath="..\..\src\memory\memory.h"
>
</File>
<File
RelativePath="..\..\src\memory\n64_cic_nus_6105.h"
>
</File>
<File
RelativePath="..\..\src\osd\OGLFT.h"
>
</File>
<File
RelativePath="..\..\src\r4300\ops.h"
>
</File>
<File
RelativePath="..\..\src\osd\osd.h"
>
</File>
<File
RelativePath="..\..\src\memory\pif.h"
>
</File>
<File
RelativePath="..\..\src\plugin\plugin.h"
>
</File>
<File
RelativePath="..\..\src\osal\preproc.h"
>
</File>
<File
RelativePath="..\..\src\r4300\r4300.h"
>
</File>
<File
RelativePath="..\..\src\r4300\recomp.h"
>
</File>
<File
RelativePath="..\..\src\r4300\recomph.h"
>
</File>
<File
RelativePath="..\..\src\r4300\x86\regcache.h"
>
</File>
<File
RelativePath="..\..\src\r4300\reset.h"
>
</File>
<File
RelativePath="..\..\src\main\rom.h"
>
</File>
<File
RelativePath="..\..\src\main\savestates.h"
>
</File>
<File
RelativePath="..\..\src\osd\screenshot.h"
>
</File>
<File
RelativePath="..\..\src\memory\tlb.h"
>
</File>
<File
RelativePath="..\..\src\main\zip\unzip.h"
>
</File>
<File
RelativePath="..\..\src\main\util.h"
>
</File>
<File
RelativePath="..\..\src\main\version.h"
>
</File>
<File
RelativePath="..\..\src\api\vidext.h"
>
</File>
<File
RelativePath="..\..\src\main\workqueue.h"
>
</File>
<File
RelativePath="..\..\src\main\zip\zip.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,573 @@
#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# * Mupen64plus - Makefile *
# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
# * Copyright (C) 2008-2009 Richard Goedeken *
# * Copyright (C) 2007-2008 DarkJeztr Tillin9 *
# * *
# * 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 Mupen64Plus Core
# detect operating system
UNAME ?= $(shell uname -s)
OS := NONE
ifeq ("$(UNAME)","Linux")
OS = LINUX
endif
ifeq ("$(UNAME)","linux")
OS = LINUX
endif
ifneq ("$(filter GNU hurd,$(UNAME))","")
OS = LINUX
endif
ifeq ("$(UNAME)","Darwin")
OS = OSX
endif
ifeq ("$(UNAME)","FreeBSD")
OS = FREEBSD
endif
ifeq ("$(UNAME)","OpenBSD")
OS = FREEBSD
CFLAGS += -DIOAPI_NO_64
$(warning OS type "$(UNAME)" not officially supported.')
endif
ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","")
OS = LINUX
endif
ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW")
OS = MINGW
PIC = 0
endif
ifeq ("$(OS)","NONE")
$(error OS type "$(UNAME)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
endif
# detect system architecture
HOST_CPU ?= $(shell uname -m)
CPU := NONE
ifneq ("$(filter x86_64 amd64,$(HOST_CPU))","")
CPU := X86
ifeq ("$(BITS)", "32")
ARCH_DETECTED := 64BITS_32
PIC ?= 0
else
ARCH_DETECTED := 64BITS
PIC ?= 1
endif
endif
ifneq ("$(filter pentium i%86,$(HOST_CPU))","")
CPU := X86
ARCH_DETECTED := 32BITS
PIC ?= 0
endif
ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","")
CPU := PPC
ARCH_DETECTED := 32BITS
BIG_ENDIAN := 1
PIC ?= 1
NO_ASM := 1
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","")
CPU := PPC
ARCH_DETECTED := 64BITS
BIG_ENDIAN := 1
PIC ?= 1
NO_ASM := 1
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
ifneq ("$(filter arm%,$(HOST_CPU))","")
ifeq ("$(filter arm%b,$(HOST_CPU))","")
CPU := ARM
ARCH_DETECTED := 32BITS
PIC ?= 1
NEW_DYNAREC := 1
CFLAGS += -mfpu=vfp -mfloat-abi=softfp
$(warning Architecture "$(HOST_CPU)" not officially supported.')
endif
endif
ifeq ("$(CPU)","NONE")
$(error CPU type "$(HOST_CPU)" not supported. Please file bug report at 'http://code.google.com/p/mupen64plus/issues')
endif
# base CFLAGS, LDLIBS, and LDFLAGS
OPTFLAGS ?= -O3
WARNFLAGS ?= -Wall
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -DM64P_PARALLEL
CXXFLAGS += -fvisibility-inlines-hidden
LDLIBS += -lm
# default configuration programs
SDL_CONFIG = $(CROSS_COMPILE)sdl-config
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
# 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
LDFLAGS += -fPIC
else
CFLAGS += -fno-PIC
LDFLAGS += -fno-PIC
endif
ifeq ($(BIG_ENDIAN), 1)
CFLAGS += -DM64P_BIG_ENDIAN
endif
# tweak flags for 32-bit build on 64-bit system
ifeq ($(ARCH_DETECTED), 64BITS_32)
ifeq ($(OS), FREEBSD)
$(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386)
endif
CFLAGS += -m32
LDFLAGS += -m32 -Wl,-m,elf_i386
endif
# set special flags per-system
ifeq ($(OS), FREEBSD)
TARGET = libmupen64plus$(POSTFIX).so.2.0.0
SONAME = libmupen64plus$(POSTFIX).so.2
LDFLAGS += -Wl,-Bsymbolic -shared -Wl,-export-dynamic -Wl,-soname,$(SONAME)
LDLIBS += -L${LOCALBASE}/lib -lc
endif
ifeq ($(OS), LINUX)
TARGET = libmupen64plus$(POSTFIX).so.2.0.0
SONAME = libmupen64plus$(POSTFIX).so.2
LDFLAGS += -Wl,-Bsymbolic -shared -Wl,-export-dynamic -Wl,-soname,$(SONAME)
LDLIBS += -ldl
# only export api symbols
LDFLAGS += -Wl,-version-script,$(SRCDIR)/api/api_export.ver
endif
ifeq ($(OS), OSX)
# Select the proper SDK
# Also, SDKs are stored in a different location since XCode 4.3
OSX_SDK ?= $(shell sw_vers -productVersion | cut -f1 -f2 -d .)
OSX_XCODEMAJ = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f1 -d .)
OSX_XCODEMIN = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f2 -d .)
OSX_XCODEGE43 = $(shell echo "`expr $(OSX_XCODEMAJ) \>= 4``expr $(OSX_XCODEMIN) \>= 3`")
ifeq ($(OSX_XCODEGE43), 11)
OSX_SYSROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
else
OSX_SYSROOT := /Developer/SDKs
endif
TARGET = libmupen64plus$(POSTFIX).dylib
LDFLAGS += -bundle -read_only_relocs suppress
LDLIBS += -ldl
ifeq ($(CPU), X86)
ifeq ($(ARCH_DETECTED), 64BITS)
CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
LDFLAGS += -arch x86_64
else
CFLAGS += -pipe -mmmx -msse -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
LDFLAGS += -arch i686
ifneq ($(PROFILE), 1)
CFLAGS += -fomit-frame-pointer
endif
endif
endif
endif
ifeq ($(OS), MINGW)
TARGET = mupen64plus$(POSTFIX).dll
LDFLAGS += -Wl,-Bsymbolic -shared -Wl,-export-all-symbols
# only export api symbols
LDFLAGS += -Wl,-version-script,$(SRCDIR)/api/api_export.ver
LDLIBS += -lpthread
endif
ifeq ($(CPU_ENDIANNESS), BIG)
CFLAGS += -DM64P_BIG_ENDIAN
endif
# disable verbose output
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
Q_CC = @echo ' CC '$@;
Q_CXX = @echo ' CXX '$@;
Q_LD = @echo ' LD '$@;
endif
endif
# test for essential build dependencies
ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
$(error $(PKG_CONFIG) not found)
endif
ifeq ($(shell $(PKG_CONFIG) --modversion libpng 2>/dev/null),)
$(error No libpng development libraries found!)
endif
ifeq ($(OS), OSX) # use system zlib on OSX
LDLIBS += -lz
else
ifeq ($(shell $(PKG_CONFIG) --modversion zlib 2>/dev/null),)
$(error No zlib development libraries found!)
endif
CFLAGS += $(shell $(PKG_CONFIG) --cflags zlib)
LDLIBS += $(shell $(PKG_CONFIG) --libs zlib)
endif
CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
LDLIBS += $(shell $(PKG_CONFIG) --libs libpng)
# test for presence of SDL
ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),)
$(error No SDL development libraries found!)
endif
CFLAGS += $(shell $(SDL_CONFIG) --cflags)
LDLIBS += $(shell $(SDL_CONFIG) --libs)
OSD ?= 1
ifeq ($(OSD), 1)
CFLAGS += -DM64P_OSD
ifeq ($(shell $(PKG_CONFIG) --modversion freetype2 2>/dev/null),)
$(error No FreeType 2 development libraries found!)
endif
# search for OpenGL libraries
GL_LIBS=
ifeq ($(OS), OSX)
GL_LIBS = -framework OpenGL
endif
ifeq ($(OS), MINGW)
GL_LIBS = -lopengl32 -lglu32
endif
ifeq ("$(GL_LIBS)", "")
ifeq ($(shell $(PKG_CONFIG) --modversion gl 2>/dev/null),)
$(error No OpenGL development libraries found!)
endif
ifeq ($(shell $(PKG_CONFIG) --modversion glu 2>/dev/null),)
$(error No OpenGL utility development libraries found!)
endif
CFLAGS += $(shell $(PKG_CONFIG) --cflags gl glu)
GL_LIBS = $(shell $(PKG_CONFIG) --libs gl glu)
endif
CFLAGS += $(shell $(PKG_CONFIG) --cflags freetype2)
LDLIBS += $(shell $(PKG_CONFIG) --libs freetype2) $(GL_LIBS)
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
COMPILE.cc = $(Q_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
LINK.o = $(Q_LD)$(CXX) $(LDFLAGS) $(TARGET_ARCH)
ifeq ($(OS),OSX)
LDCONFIG ?= true # no 'ldconfig' under OSX
else
ifeq ($(OS),LINUX)
LDCONFIG ?= PATH="$$PATH:/sbin" ldconfig -n
endif
ifeq ($(OS),FREEBSD)
LDCONFIG ?= PATH="$$PATH:/sbin" ldconfig -m
endif
endif
# compiler/linker flags for various compile-time options.
# 1. macro for no assembly language
ifeq ($(NO_ASM), 1)
CFLAGS += -DNO_ASM
endif
# 2. variables for profiling and adding debugging symbols
ifeq ($(PROFILE), 1)
CFLAGS += -pg -g
LDFLAGS += -pg
INSTALL_STRIP_FLAG ?=
else
ifeq ($(DEBUG), 1)
CFLAGS += -g
INSTALL_STRIP_FLAG ?=
else
ifneq ($(OS),OSX)
INSTALL_STRIP_FLAG ?= -s
endif
endif
endif
# 3. other options given to the makefile on the command line
ifeq ($(LIRC), 1)
CFLAGS += -DWITH_LIRC
endif
ifeq ($(DEBUGGER), 1)
CFLAGS += -DDBG
endif
ifeq ($(DBG_COMPARE), 1)
CFLAGS += -DCOMPARE_CORE
endif
ifeq ($(DBG_CORE), 1)
CFLAGS += -DCORE_DBG
endif
ifeq ($(DBG_COUNT), 1)
CFLAGS += -DCOUNT_INSTR
endif
ifeq ($(DBG_TIMING), 1)
CFLAGS += -DPROFILE
LDFLAGS += -lrt
endif
ifeq ($(DBG_PROFILE), 1)
CFLAGS += -DPROFILE_R4300
endif
# 4. compile-time directory paths for building into the library
ifneq ($(SHAREDIR),)
CFLAGS += -DSHAREDIR="$(SHAREDIR)"
endif
# set installation options
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
ifeq ($(SHAREDIR),)
SHAREDIR := $(PREFIX)/share/mupen64plus
endif
ifeq ($(LIBDIR),)
LIBDIR := $(PREFIX)/lib
endif
ifeq ($(INCDIR),)
INCDIR := $(PREFIX)/include/mupen64plus
endif
SRCDIR = ../../src
OBJDIR = _obj$(POSTFIX)
# list of required source files for compilation
SOURCE = \
$(SRCDIR)/api/callbacks.c \
$(SRCDIR)/api/common.c \
$(SRCDIR)/api/config.c \
$(SRCDIR)/api/debugger.c \
$(SRCDIR)/api/frontend.c \
$(SRCDIR)/api/vidext.c \
$(SRCDIR)/main/main.c \
$(SRCDIR)/main/util.c \
$(SRCDIR)/main/cheat.c \
$(SRCDIR)/main/eventloop.c \
$(SRCDIR)/main/md5.c \
$(SRCDIR)/main/rom.c \
$(SRCDIR)/main/savestates.c \
$(SRCDIR)/main/workqueue.c \
$(SRCDIR)/memory/dma.c \
$(SRCDIR)/memory/flashram.c \
$(SRCDIR)/memory/memory.c \
$(SRCDIR)/memory/n64_cic_nus_6105.c \
$(SRCDIR)/memory/pif.c \
$(SRCDIR)/memory/tlb.c \
$(SRCDIR)/plugin/plugin.c \
$(SRCDIR)/plugin/dummy_video.c \
$(SRCDIR)/plugin/dummy_audio.c \
$(SRCDIR)/plugin/dummy_input.c \
$(SRCDIR)/plugin/dummy_rsp.c \
$(SRCDIR)/r4300/r4300.c \
$(SRCDIR)/r4300/exception.c \
$(SRCDIR)/r4300/interupt.c \
$(SRCDIR)/r4300/profile.c \
$(SRCDIR)/r4300/pure_interp.c \
$(SRCDIR)/r4300/recomp.c \
$(SRCDIR)/r4300/reset.c \
$(SRCDIR)/osd/screenshot.cpp
ifeq ("$(OS)","MINGW")
SOURCE += \
$(SRCDIR)/osal/dynamiclib_win32.c \
$(SRCDIR)/osal/files_win32.c
else
SOURCE += \
$(SRCDIR)/osal/dynamiclib_unix.c \
$(SRCDIR)/osal/files_unix.c
endif
ifeq ($(OSD), 1)
SOURCE += \
$(SRCDIR)/osd/OGLFT.cpp \
$(SRCDIR)/osd/osd.cpp
endif
# source files for optional features
ifneq ($(NO_ASM), 1)
ifeq ($(CPU), X86)
ifeq ($(ARCH_DETECTED), 64BITS)
DYNAREC = x86_64
else
DYNAREC = x86
endif
endif
ifeq ($(CPU), ARM)
ifeq ($(ARCH_DETECTED), 32BITS)
DYNAREC = arm
endif
endif
endif
ifneq ($(DYNAREC), )
CFLAGS += -DDYNAREC
ifeq ($(NEW_DYNAREC), 1)
ifeq ($(DYNAREC), x86)
CFLAGS += -DNEW_DYNAREC=1
else
ifeq ($(DYNAREC), arm)
CFLAGS += -DNEW_DYNAREC=3
else
$(error NEW_DYNAREC is only supported on 32 bit x86 and 32 bit armel)
endif
endif
SOURCE += \
$(SRCDIR)/r4300/empty_dynarec.c \
$(SRCDIR)/r4300/new_dynarec/linkage_$(DYNAREC).S \
$(SRCDIR)/r4300/new_dynarec/new_dynarec.c
else
SOURCE += \
$(SRCDIR)/r4300/$(DYNAREC)/assemble.c \
$(SRCDIR)/r4300/$(DYNAREC)/gbc.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop0.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop1.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop1_d.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop1_l.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop1_s.c \
$(SRCDIR)/r4300/$(DYNAREC)/gcop1_w.c \
$(SRCDIR)/r4300/$(DYNAREC)/gr4300.c \
$(SRCDIR)/r4300/$(DYNAREC)/gregimm.c \
$(SRCDIR)/r4300/$(DYNAREC)/gspecial.c \
$(SRCDIR)/r4300/$(DYNAREC)/gtlb.c \
$(SRCDIR)/r4300/$(DYNAREC)/regcache.c \
$(SRCDIR)/r4300/$(DYNAREC)/rjump.c
endif
else
SOURCE += $(SRCDIR)/r4300/empty_dynarec.c
endif
ifeq ($(LIRC), 1)
SOURCE += $(SRCDIR)/main/lirc.c
LDLIBS += -llirc_client
endif
ifeq ($(shell $(PKG_CONFIG) --modversion minizip 2>/dev/null),)
SOURCE += \
$(SRCDIR)/main/zip/ioapi.c \
$(SRCDIR)/main/zip/zip.c \
$(SRCDIR)/main/zip/unzip.c
CFLAGS += -DNOCRYPT -DNOUNCRYPT
else
CFLAGS += $(shell $(PKG_CONFIG) --cflags minizip) -DLIBMINIZIP
LDLIBS += $(shell $(PKG_CONFIG) --libs minizip)
endif
ifeq ($(DEBUGGER), 1)
SOURCE += \
$(SRCDIR)/debugger/debugger.c \
$(SRCDIR)/debugger/dbg_decoder.c \
$(SRCDIR)/debugger/dbg_memory.c \
$(SRCDIR)/debugger/dbg_breakpoints.c
LDLIBS += -lopcodes -lbfd
endif
# generate a list of object files to build, make a temporary directory for them
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(filter %.c, $(SOURCE)))
OBJECTS += $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(filter %.cpp, $(SOURCE)))
OBJECTS += $(patsubst $(SRCDIR)/%.S, $(OBJDIR)/%.o, $(filter %.S, $(SOURCE)))
OBJDIRS = $(dir $(OBJECTS))
$(shell $(MKDIR) $(OBJDIRS))
# build targets
targets:
@echo "Mupen64Plus-core makefile. "
@echo " Targets:"
@echo " all == Build Mupen64Plus core library"
@echo " clean == remove object files"
@echo " install == Install Mupen64Plus core library"
@echo " uninstall == Uninstall Mupen64Plus core library"
@echo " Build Options:"
@echo " BITS=32 == build 32-bit binaries on 64-bit machine"
@echo " LIRC=1 == enable LIRC support"
@echo " NO_ASM=1 == build without assembly (no dynamic recompiler or MMX/SSE code)"
@echo " SHAREDIR=path == extra path to search for shared data files"
@echo " OPTFLAGS=flag == compiler optimization (default: -O3)"
@echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)"
@echo " PIC=(1|0) == Force enable/disable of position independent code"
@echo " OSD=(1|0) == Enable/disable build of OpenGL On-screen display"
@echo " NEW_DYNAREC=1 == Replace dynamic recompiler with Ari64's experimental dynarec"
@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 == path to install core library (default: PREFIX/lib)"
@echo " INCDIR=path == path to install core header files (default: PREFIX/include/mupen64plus)"
@echo " DESTDIR=path == path to prepend to all installation paths (only for packagers)"
@echo " Debugging Options:"
@echo " PROFILE=1 == build gprof instrumentation into binaries for profiling"
@echo " DEBUG=1 == add debugging symbols to binaries"
@echo " DEBUGGER=1 == build debugger API into core for front-ends. runs slower."
@echo " DBG_CORE=1 == print debugging info in r4300 core"
@echo " DBG_COUNT=1 == print R4300 instruction count totals (64-bit dynarec only)"
@echo " DBG_COMPARE=1 == enable core-synchronized r4300 debugging"
@echo " DBG_TIMING=1 == print timing data"
@echo " DBG_PROFILE=1 == dump profiling data for r4300 dynarec to data file"
@echo " LTO=1 == enable experimental build with link-time optimization"
@echo " V=1 == show verbose compiler output"
all: $(TARGET)
install: $(TARGET)
$(INSTALL) -d "$(DESTDIR)$(LIBDIR)"
$(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(LIBDIR)"
$(INSTALL) -d "$(DESTDIR)$(SHAREDIR)"
$(INSTALL) -m 0644 ../../data/* "$(DESTDIR)$(SHAREDIR)"
$(INSTALL) -d "$(DESTDIR)$(INCDIR)"
$(INSTALL) -m 0644 ../../src/api/m64p_*.h "$(DESTDIR)$(INCDIR)"
-$(LDCONFIG) "$(DESTDIR)$(LIBDIR)"
if [ ! -e "$(DESTDIR)$(LIBDIR)/$(SONAME)" ]; then ln -sf "$(TARGET)" "$(DESTDIR)$(LIBDIR)/$(SONAME)"; fi
uninstall:
$(RM) "$(DESTDIR)$(LIBDIR)/$(TARGET)"
if [ "$(SONAME)" != "" ]; then $(RM) "$(DESTDIR)$(LIBDIR)/$(SONAME)"; fi
$(RM) $(DESTDIR)$(INCDIR)/m64p_*.h
$(RM) "$(DESTDIR)$(SHAREDIR)/mupen64plus.cht"
$(RM) "$(DESTDIR)$(SHAREDIR)/mupen64plus.ini"
$(RM) "$(DESTDIR)$(SHAREDIR)/font.ttf"
$(RM) "$(DESTDIR)$(SHAREDIR)/mupencheat.txt"
clean:
$(RM) -r $(TARGET) $(SONAME) $(OBJDIR)
# build dependency files
CFLAGS += -MD
-include $(OBJECTS:.o=.d)
CXXFLAGS += $(CFLAGS)
ifeq ($(LTO), 1)
CFLAGS += -flto
CXXFLAGS += -flto
LDFLAGS += -fuse-linker-plugin $(CXXFLAGS)
endif
# standard build rules
$(OBJDIR)/%.o: $(SRCDIR)/%.S
$(COMPILE.c) -o $@ $<
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -o $@ $<
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(COMPILE.cc) -o $@ $<
$(TARGET): $(OBJECTS)
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
if [ "$(SONAME)" != "" ]; then ln -sf $@ $(SONAME); fi
.PHONY: all clean install uninstall targets

View File

@ -0,0 +1,68 @@
{ global:
ConfigDeleteSection;
ConfigGetParamBool;
ConfigGetParameter;
ConfigGetParameterHelp;
ConfigGetParameterType;
ConfigGetParamFloat;
ConfigGetParamInt;
ConfigGetParamString;
ConfigGetSharedDataFilepath;
ConfigGetUserCachePath;
ConfigGetUserConfigPath;
ConfigGetUserDataPath;
ConfigHasUnsavedChanges;
ConfigListParameters;
ConfigListSections;
ConfigOpenSection;
ConfigRevertChanges;
ConfigSaveFile;
ConfigSaveSection;
ConfigSetDefaultBool;
ConfigSetDefaultFloat;
ConfigSetDefaultInt;
ConfigSetDefaultString;
ConfigSetParameter;
CoreAddCheat;
CoreAttachPlugin;
CoreCheatEnabled;
CoreDetachPlugin;
CoreDoCommand;
CoreErrorMessage;
CoreGetAPIVersions;
CoreGetRomSettings;
CoreOverrideVidExt;
CoreShutdown;
CoreStartup;
DebugBreakpointCommand;
DebugBreakpointLookup;
DebugDecodeOp;
DebugGetCPUDataPtr;
DebugGetState;
DebugMemGetMemInfo;
DebugMemGetPointer;
DebugMemGetRecompInfo;
DebugMemRead16;
DebugMemRead32;
DebugMemRead64;
DebugMemRead8;
DebugMemWrite16;
DebugMemWrite32;
DebugMemWrite64;
DebugMemWrite8;
DebugSetCallbacks;
DebugSetCoreCompare;
DebugSetRunState;
DebugStep;
PluginGetVersion;
VidExt_GL_GetProcAddress;
VidExt_GL_SetAttribute;
VidExt_GL_GetAttribute;
VidExt_GL_SwapBuffers;
VidExt_Init;
VidExt_ListFullscreenModes;
VidExt_Quit;
VidExt_SetCaption;
VidExt_SetVideoMode;
VidExt_ToggleFullScreen;
local: *; };

View File

@ -0,0 +1,78 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/callbacks.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core functions for handling callbacks to the
* front-end application
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "m64p_types.h"
#include "callbacks.h"
/* local variables */
static ptr_DebugCallback pDebugFunc = NULL;
static ptr_StateCallback pStateFunc = NULL;
static void * DebugContext = NULL;
static void * StateContext = NULL;
/* global Functions for use by the Core */
m64p_error SetDebugCallback(ptr_DebugCallback pFunc, void *Context)
{
pDebugFunc = pFunc;
DebugContext = Context;
return M64ERR_SUCCESS;
}
m64p_error SetStateCallback(ptr_StateCallback pFunc, void *Context)
{
pStateFunc = pFunc;
StateContext = Context;
return M64ERR_SUCCESS;
}
void DebugMessage(int level, const char *message, ...)
{
char msgbuf[256];
va_list args;
if (pDebugFunc == NULL)
return;
va_start(args, message);
vsprintf(msgbuf, message, args);
(*pDebugFunc)(DebugContext, level, msgbuf);
va_end(args);
}
void StateChanged(m64p_core_param param_type, int new_value)
{
if (pStateFunc == NULL)
return;
(*pStateFunc)(StateContext, param_type, new_value);
}

View File

@ -0,0 +1,39 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/callbacks.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the definitions for callback functions which will be
* called from the other Core modules
*/
#if !defined(API_CALLBACKS_H)
#define API_CALLBACKS_H
#include "m64p_types.h"
#include "m64p_frontend.h"
/* Functions for use by the Core, to send information back to the front-end app */
extern m64p_error SetDebugCallback(ptr_DebugCallback pFunc, void *Context);
extern m64p_error SetStateCallback(ptr_StateCallback pFunc, void *Context);
extern void DebugMessage(int level, const char *message, ...);
extern void StateChanged(m64p_core_param param_type, int new_value);
#endif /* API_CALLBACKS_H */

View File

@ -0,0 +1,109 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/common.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core common functions which will be exported
* outside of the core library.
*/
#include <stdlib.h>
#define M64P_CORE_PROTOTYPES 1
#include "m64p_types.h"
#include "m64p_common.h"
#include "../main/version.h"
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_CORE;
if (PluginVersion != NULL)
*PluginVersion = MUPEN_CORE_VERSION;
if (APIVersion != NULL)
*APIVersion = FRONTEND_API_VERSION;
if (PluginNamePtr != NULL)
*PluginNamePtr = MUPEN_CORE_NAME;
if (Capabilities != NULL)
{
*Capabilities = 0;
#if defined(DBG)
*Capabilities |= M64CAPS_DEBUGGER;
#endif
#if defined(DYNAREC)
*Capabilities |= M64CAPS_DYNAREC;
#endif
#if defined(COMPARE_CORE)
*Capabilities |= M64CAPS_CORE_COMPARE;
#endif
}
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL CoreGetAPIVersions(int *ConfigVersion, int *DebugVersion, int *VidextVersion, int *ExtraVersion)
{
/* set version info */
if (ConfigVersion != NULL)
*ConfigVersion = CONFIG_API_VERSION;
if (DebugVersion != NULL)
*DebugVersion = DEBUG_API_VERSION;
if (VidextVersion != NULL)
*VidextVersion = VIDEXT_API_VERSION;
if (ExtraVersion != NULL)
*ExtraVersion = 0;
return M64ERR_SUCCESS;
}
static const char *ErrorMessages[] = {
"SUCCESS: No error",
"NOT_INIT: A function was called before it's associated module was initialized",
"ALREADY_INIT: Initialization function called twice",
"INCOMPATIBLE: API versions between components are incompatible",
"INPUT_ASSERT: Invalid function parameters, such as a NULL pointer",
"INPUT_INVALID: An input function parameter is logically invalid",
"INPUT_NOT_FOUND: The input parameter(s) specified a particular item which was not found",
"NO_MEMORY: Memory allocation failed",
"FILES: Error opening, creating, reading, or writing to a file",
"INTERNAL: logical inconsistency in program code. Probably a bug.",
"INVALID_STATE: An operation was requested which is not allowed in the current state",
"PLUGIN_FAIL: A plugin function returned a fatal error",
"SYSTEM_FAIL: A system function call, such as an SDL or file operation, failed",
"UNSUPPORTED: Function call is not supported (ie, core not built with debugger)",
"WRONG_TYPE: A given input type parameter cannot be used for desired operation" };
EXPORT const char * CALL CoreErrorMessage(m64p_error ReturnCode)
{
int i = (int) ReturnCode;
if (i < 0 || i > (sizeof(ErrorMessages) / sizeof(char *)))
return "ERROR: Invalid m64p_error code given to CoreErrorMessage()";
return ErrorMessages[i];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/config.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2009 Richard Goedeken *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core configuration functions
*/
#include "m64p_types.h"
/* these functions are only to be used within the Core library */
m64p_error ConfigInit(const char *ConfigDirOverride, const char *DataDirOverride);
m64p_error ConfigShutdown(void);

View File

@ -0,0 +1,390 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/debugger.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core debugger functions which will be exported
* outside of the core library.
*/
#include <stdlib.h>
#define M64P_CORE_PROTOTYPES 1
#include "m64p_types.h"
#include "m64p_debugger.h"
#include "callbacks.h"
#include "debugger.h"
#include "debugger/dbg_types.h"
#include "debugger/dbg_breakpoints.h"
#include "debugger/dbg_decoder.h"
#include "debugger/dbg_memory.h"
#include "debugger/debugger.h"
#include "memory/memory.h"
#include "r4300/r4300.h"
extern unsigned int op; /* this is in r4300/pure_interp.c */
/* local variables */
static void (*callback_ui_init)(void) = NULL;
static void (*callback_ui_update)(unsigned int) = NULL;
static void (*callback_ui_vi)(void) = NULL;
static void (*callback_core_compare)(unsigned int) = NULL;
static void (*callback_core_data_sync)(int, void *) = NULL;
/* global Functions for use by the Core */
void DebuggerCallback(eDbgCallbackType type, unsigned int param)
{
if (type == DEBUG_UI_INIT)
{
if (callback_ui_init != NULL)
(*callback_ui_init)();
}
else if (type == DEBUG_UI_UPDATE)
{
if (callback_ui_update != NULL)
(*callback_ui_update)(param);
}
else if (type == DEBUG_UI_VI)
{
if (callback_ui_vi != NULL)
(*callback_ui_vi)();
}
}
void CoreCompareCallback(void)
{
if (callback_core_compare != NULL)
(*callback_core_compare)(op);
}
void CoreCompareDataSync(int length, void *ptr)
{
if (callback_core_data_sync != NULL)
(*callback_core_data_sync)(length, ptr);
}
/* exported functions for use by the front-end User Interface */
EXPORT m64p_error CALL DebugSetCoreCompare(void (*dbg_core_compare)(unsigned int), void (*dbg_core_data_sync)(int, void *))
{
callback_core_compare = dbg_core_compare;
callback_core_data_sync = dbg_core_data_sync;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL DebugSetCallbacks(void (*dbg_frontend_init)(void), void (*dbg_frontend_update)(unsigned int pc), void (*dbg_frontend_vi)(void))
{
#ifdef DBG
callback_ui_init = dbg_frontend_init;
callback_ui_update = dbg_frontend_update;
callback_ui_vi = dbg_frontend_vi;
return M64ERR_SUCCESS;
#else
return M64ERR_UNSUPPORTED;
#endif
}
EXPORT m64p_error CALL DebugSetRunState(int runstate)
{
#ifdef DBG
run = runstate; /* in debugger/debugger.c */
return M64ERR_SUCCESS;
#else
return M64ERR_UNSUPPORTED;
#endif
}
EXPORT int CALL DebugGetState(m64p_dbg_state statenum)
{
#ifdef DBG
switch (statenum)
{
case M64P_DBG_RUN_STATE:
return run;
case M64P_DBG_PREVIOUS_PC:
return previousPC;
case M64P_DBG_NUM_BREAKPOINTS:
return g_NumBreakpoints;
case M64P_DBG_CPU_DYNACORE:
return r4300emu;
case M64P_DBG_CPU_NEXT_INTERRUPT:
return next_interupt;
default:
DebugMessage(M64MSG_WARNING, "Bug: invalid m64p_dbg_state input in DebugGetState()");
return 0;
}
return 0;
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugGetState() called, but Debugger not supported in Core library");
return 0;
#endif
}
EXPORT m64p_error CALL DebugStep(void)
{
#ifdef DBG
if (!g_DebuggerActive)
return M64ERR_INVALID_STATE;
debugger_step(); /* in debugger/debugger.c */
return M64ERR_SUCCESS;
#else
return M64ERR_UNSUPPORTED;
#endif
}
EXPORT void CALL DebugDecodeOp(unsigned int instruction, char *op, char *args, int pc)
{
#ifdef DBG
r4300_decode_op(instruction, op, args, pc);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugDecodeOp() called, but Debugger not supported in Core library");
#endif
}
EXPORT void * CALL DebugMemGetRecompInfo(m64p_dbg_mem_info recomp_type, unsigned int address, int index)
{
#ifdef DBG
switch (recomp_type)
{
case M64P_DBG_RECOMP_OPCODE:
return get_recompiled_opcode(address, index);
case M64P_DBG_RECOMP_ARGS:
return get_recompiled_args(address, index);
case M64P_DBG_RECOMP_ADDR:
return get_recompiled_addr(address, index);
default:
DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetRecompInfo() called with invalid m64p_dbg_mem_info");
return NULL;
}
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetRecompInfo() called, but Debugger not supported in Core library");
return NULL;
#endif
}
EXPORT int CALL DebugMemGetMemInfo(m64p_dbg_mem_info mem_info_type, unsigned int address)
{
#ifdef DBG
switch (mem_info_type)
{
case M64P_DBG_MEM_TYPE:
return get_memory_type(address);
case M64P_DBG_MEM_FLAGS:
return get_memory_flags(address);
case M64P_DBG_MEM_HAS_RECOMPILED:
return get_has_recompiled(address);
case M64P_DBG_MEM_NUM_RECOMPILED:
return get_num_recompiled(address);
default:
DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetMemInfo() called with invalid m64p_dbg_mem_info");
return 0;
}
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetMemInfo() called, but Debugger not supported in Core library");
return 0;
#endif
}
EXPORT void * CALL DebugMemGetPointer(m64p_dbg_memptr_type mem_ptr_type)
{
switch (mem_ptr_type)
{
case M64P_DBG_PTR_RDRAM:
return rdram;
case M64P_DBG_PTR_PI_REG:
return &pi_register;
case M64P_DBG_PTR_SI_REG:
return &si_register;
case M64P_DBG_PTR_VI_REG:
return &vi_register;
case M64P_DBG_PTR_RI_REG:
return &ri_register;
case M64P_DBG_PTR_AI_REG:
return &ai_register;
default:
DebugMessage(M64MSG_ERROR, "Bug: DebugMemGetPointer() called with invalid m64p_dbg_memptr_type");
return NULL;
}
}
EXPORT unsigned long long CALL DebugMemRead64(unsigned int address)
{
#ifdef DBG
if ((address & 3) == 0)
return read_memory_64(address);
else
return read_memory_64_unaligned(address);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemRead64() called, but Debugger not supported in Core library");
return 0LL;
#endif
}
EXPORT unsigned int CALL DebugMemRead32(unsigned int address)
{
#ifdef DBG
if ((address & 3) == 0)
return read_memory_32(address);
else
return read_memory_32_unaligned(address);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemRead32() called, but Debugger not supported in Core library");
return 0;
#endif
}
EXPORT unsigned short CALL DebugMemRead16(unsigned int address)
{
#ifdef DBG
return read_memory_16(address);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemRead16() called, but Debugger not supported in Core library");
return 0;
#endif
}
EXPORT unsigned char CALL DebugMemRead8(unsigned int address)
{
#ifdef DBG
return read_memory_8(address);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemRead8() called, but Debugger not supported in Core library");
return 0;
#endif
}
EXPORT void CALL DebugMemWrite64(unsigned int address, unsigned long long value)
{
#ifdef DBG
if ((address & 3) == 0)
write_memory_64(address, value);
else
write_memory_64_unaligned(address, value);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemWrite64() called, but Debugger not supported in Core library");
#endif
}
EXPORT void CALL DebugMemWrite32(unsigned int address, unsigned int value)
{
#ifdef DBG
if ((address & 3) == 0)
write_memory_32(address, value);
else
write_memory_32_unaligned(address, value);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemWrite32() called, but Debugger not supported in Core library");
#endif
}
EXPORT void CALL DebugMemWrite16(unsigned int address, unsigned short value)
{
#ifdef DBG
write_memory_16(address, value);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemWrite16() called, but Debugger not supported in Core library");
#endif
}
EXPORT void CALL DebugMemWrite8(unsigned int address, unsigned char value)
{
#ifdef DBG
write_memory_8(address, value);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugMemWrite8() called, but Debugger not supported in Core library");
#endif
}
EXPORT void * CALL DebugGetCPUDataPtr(m64p_dbg_cpu_data cpu_data_type)
{
switch (cpu_data_type)
{
case M64P_CPU_PC:
return &PC->addr;
case M64P_CPU_REG_REG:
return reg;
case M64P_CPU_REG_HI:
return &hi;
case M64P_CPU_REG_LO:
return &lo;
case M64P_CPU_REG_COP0:
return reg_cop0;
case M64P_CPU_REG_COP1_DOUBLE_PTR:
return reg_cop1_double;
case M64P_CPU_REG_COP1_SIMPLE_PTR:
return reg_cop1_simple;
case M64P_CPU_REG_COP1_FGR_64:
return reg_cop1_fgr_64;
case M64P_CPU_TLB:
return tlb_e;
default:
DebugMessage(M64MSG_ERROR, "Bug: DebugGetCPUDataPtr() called with invalid input m64p_dbg_cpu_data");
return NULL;
}
}
EXPORT int CALL DebugBreakpointLookup(unsigned int address, unsigned int size, unsigned int flags)
{
#ifdef DBG
return lookup_breakpoint(address, size, flags);
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugBreakpointLookup() called, but Debugger not supported in Core library");
return -1;
#endif
}
EXPORT int CALL DebugBreakpointCommand(m64p_dbg_bkp_command command, unsigned int index, void *ptr)
{
#ifdef DBG
switch (command)
{
case M64P_BKP_CMD_ADD_ADDR:
return add_breakpoint(index);
case M64P_BKP_CMD_ADD_STRUCT:
return add_breakpoint_struct((breakpoint *) ptr);
case M64P_BKP_CMD_REPLACE:
replace_breakpoint_num(index, (breakpoint *) ptr);
return 0;
case M64P_BKP_CMD_REMOVE_ADDR:
remove_breakpoint_by_address(index);
return 0;
case M64P_BKP_CMD_REMOVE_IDX:
remove_breakpoint_by_num(index);
return 0;
case M64P_BKP_CMD_ENABLE:
enable_breakpoint(index);
return 0;
case M64P_BKP_CMD_DISABLE:
disable_breakpoint(index);
return 0;
case M64P_BKP_CMD_CHECK:
return check_breakpoints(index);
default:
DebugMessage(M64MSG_ERROR, "Bug: DebugBreakpointCommand() called with invalid input m64p_dbg_bkp_command");
return -1;
}
#else
DebugMessage(M64MSG_ERROR, "Bug: DebugBreakpointCommand() called, but Debugger not supported in Core library");
return -1;
#endif
}

View File

@ -0,0 +1,46 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/debugger.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the definitions for debugger functions which will be
* called from the other Core modules
*/
#if !defined(API_DEBUGGER_H)
#define API_DEBUGGER_H
#include "m64p_types.h"
/* Debugger Definitions */
typedef enum {
DEBUG_UI_INIT = 1,
DEBUG_UI_UPDATE,
DEBUG_UI_VI,
DEBUG_CORE_COMPARE
} eDbgCallbackType;
/* Functions for use by the Core, to send information back to the front-end app */
extern void DebuggerCallback(eDbgCallbackType type, unsigned int param);
extern void CoreCompareCallback(void);
extern void CoreCompareDataSync(int length, void *ptr);
#endif /* API_DEBUGGER_H */

View File

@ -0,0 +1,367 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/frontend.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core front-end functions which will be exported
* outside of the core library.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <SDL.h>
#define M64P_CORE_PROTOTYPES 1
#include "m64p_types.h"
#include "callbacks.h"
#include "m64p_config.h"
#include "m64p_frontend.h"
#include "config.h"
#include "vidext.h"
#include "main/cheat.h"
#include "main/eventloop.h"
#include "main/main.h"
#include "main/rom.h"
#include "main/savestates.h"
#include "main/version.h"
#include "main/util.h"
#include "main/workqueue.h"
#include "osd/screenshot.h"
#include "plugin/plugin.h"
/* some local state variables */
static int l_CoreInit = 0;
static int l_ROMOpen = 0;
/* functions exported outside of libmupen64plus to front-end application */
EXPORT m64p_error CALL CoreStartup(int APIVersion, const char *ConfigPath, const char *DataPath, void *Context,
void (*DebugCallback)(void *, int, const char *), void *Context2,
void (*StateCallback)(void *, m64p_core_param, int))
{
if (l_CoreInit)
return M64ERR_ALREADY_INIT;
/* very first thing is to set the callback functions for debug info and state changing*/
SetDebugCallback(DebugCallback, Context);
SetStateCallback(StateCallback, Context2);
/* check front-end's API version */
if ((APIVersion & 0xffff0000) != (FRONTEND_API_VERSION & 0xffff0000))
{
DebugMessage(M64MSG_ERROR, "CoreStartup(): Front-end (API version %i.%i.%i) is incompatible with this core (API %i.%i.%i)",
VERSION_PRINTF_SPLIT(APIVersion), VERSION_PRINTF_SPLIT(FRONTEND_API_VERSION));
return M64ERR_INCOMPATIBLE;
}
/* set up the default (dummy) plugins */
plugin_connect(M64PLUGIN_GFX, NULL);
plugin_connect(M64PLUGIN_AUDIO, NULL);
plugin_connect(M64PLUGIN_INPUT, NULL);
plugin_connect(M64PLUGIN_CORE, NULL);
savestates_init();
/* next, start up the configuration handling code by loading and parsing the config file */
if (ConfigInit(ConfigPath, DataPath) != M64ERR_SUCCESS)
return M64ERR_INTERNAL;
/* set default configuration parameter values for Core */
if (ConfigOpenSection("Core", &g_CoreConfig) != M64ERR_SUCCESS || g_CoreConfig == NULL)
return M64ERR_INTERNAL;
if (!main_set_core_defaults())
return M64ERR_INTERNAL;
/* The ROM database contains MD5 hashes, goodnames, and some game-specific parameters */
romdatabase_open();
workqueue_init();
l_CoreInit = 1;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL CoreShutdown(void)
{
if (!l_CoreInit)
return M64ERR_NOT_INIT;
/* close down some core sub-systems */
romdatabase_close();
ConfigShutdown();
workqueue_shutdown();
savestates_deinit();
/* tell SDL to shut down */
SDL_Quit();
l_CoreInit = 0;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type PluginType, m64p_dynlib_handle PluginLibHandle)
{
m64p_error rval;
if (!l_CoreInit)
return M64ERR_NOT_INIT;
if (g_EmulatorRunning || !l_ROMOpen)
return M64ERR_INVALID_STATE;
rval = plugin_connect(PluginType, PluginLibHandle);
if (rval != M64ERR_SUCCESS)
return rval;
rval = plugin_start(PluginType);
if (rval != M64ERR_SUCCESS)
return rval;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL CoreDetachPlugin(m64p_plugin_type PluginType)
{
if (!l_CoreInit)
return M64ERR_NOT_INIT;
if (g_EmulatorRunning)
return M64ERR_INVALID_STATE;
return plugin_connect(PluginType, NULL);
}
EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *ParamPtr)
{
m64p_error rval;
int keysym, keymod;
if (!l_CoreInit)
return M64ERR_NOT_INIT;
switch(Command)
{
case M64CMD_NOP:
return M64ERR_SUCCESS;
case M64CMD_ROM_OPEN:
if (g_EmulatorRunning || l_ROMOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL || ParamInt < 4096)
return M64ERR_INPUT_ASSERT;
rval = open_rom((const unsigned char *) ParamPtr, ParamInt);
if (rval == M64ERR_SUCCESS)
{
l_ROMOpen = 1;
ScreenshotRomOpen();
cheat_init();
}
return rval;
case M64CMD_ROM_CLOSE:
if (g_EmulatorRunning || !l_ROMOpen)
return M64ERR_INVALID_STATE;
l_ROMOpen = 0;
cheat_delete_all();
cheat_uninit();
return close_rom();
case M64CMD_ROM_GET_HEADER:
if (!l_ROMOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
if (sizeof(m64p_rom_header) < ParamInt)
ParamInt = sizeof(m64p_rom_header);
memcpy(ParamPtr, &ROM_HEADER, ParamInt);
// Mupen64Plus used to keep a m64p_rom_header with a clean ROM name
// Keep returning a clean ROM name for backwards compatibility
if (ParamInt >= 0x20)
{
int size = (ParamInt >= 0x20 + 20) ? 20 : (ParamInt - 0x20);
memcpy((char *)ParamPtr + 0x20, ROM_PARAMS.headername, size);
}
return M64ERR_SUCCESS;
case M64CMD_ROM_GET_SETTINGS:
if (!l_ROMOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
if (sizeof(m64p_rom_settings) < ParamInt)
ParamInt = sizeof(m64p_rom_settings);
memcpy(ParamPtr, &ROM_SETTINGS, ParamInt);
return M64ERR_SUCCESS;
case M64CMD_EXECUTE:
if (g_EmulatorRunning || !l_ROMOpen)
return M64ERR_INVALID_STATE;
/* print out plugin-related warning messages */
plugin_check();
/* the main_run() function will not return until the player has quit the game */
rval = main_run();
return rval;
case M64CMD_STOP:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
/* this stop function is asynchronous. The emulator may not terminate until later */
return main_core_state_set(M64CORE_EMU_STATE, M64EMU_STOPPED);
case M64CMD_PAUSE:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
return main_core_state_set(M64CORE_EMU_STATE, M64EMU_PAUSED);
case M64CMD_RESUME:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
return main_core_state_set(M64CORE_EMU_STATE, M64EMU_RUNNING);
case M64CMD_CORE_STATE_QUERY:
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
return main_core_state_query((m64p_core_param) ParamInt, (int *) ParamPtr);
case M64CMD_CORE_STATE_SET:
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
return main_core_state_set((m64p_core_param) ParamInt, *((int *)ParamPtr));
case M64CMD_STATE_LOAD:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
main_state_load((char *) ParamPtr);
return M64ERR_SUCCESS;
case M64CMD_STATE_SAVE:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (ParamPtr != NULL && (ParamInt < 1 || ParamInt > 3))
return M64ERR_INPUT_INVALID;
main_state_save(ParamInt, (char *) ParamPtr);
return M64ERR_SUCCESS;
case M64CMD_STATE_SET_SLOT:
if (ParamInt < 0 || ParamInt > 9)
return M64ERR_INPUT_INVALID;
return main_core_state_set(M64CORE_SAVESTATE_SLOT, ParamInt);
case M64CMD_SEND_SDL_KEYDOWN:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
keysym = ParamInt & 0xffff;
keymod = (ParamInt >> 16) & 0xffff;
event_sdl_keydown(keysym, keymod);
return M64ERR_SUCCESS;
case M64CMD_SEND_SDL_KEYUP:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
keysym = ParamInt & 0xffff;
keymod = (ParamInt >> 16) & 0xffff;
event_sdl_keyup(keysym, keymod);
return M64ERR_SUCCESS;
case M64CMD_SET_FRAME_CALLBACK:
g_FrameCallback = (m64p_frame_callback) ParamPtr;
return M64ERR_SUCCESS;
case M64CMD_TAKE_NEXT_SCREENSHOT:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
main_take_next_screenshot();
return M64ERR_SUCCESS;
case M64CMD_READ_SCREEN:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
if (ParamInt < 0 || ParamInt > 1)
return M64ERR_INPUT_INVALID;
return main_read_screen(ParamPtr, ParamInt);
case M64CMD_RESET:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (ParamInt < 0 || ParamInt > 1)
return M64ERR_INPUT_INVALID;
return main_reset(ParamInt);
case M64CMD_ADVANCE_FRAME:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
main_advance_one();
return M64ERR_SUCCESS;
default:
return M64ERR_INPUT_INVALID;
}
return M64ERR_INTERNAL;
}
EXPORT m64p_error CALL CoreOverrideVidExt(m64p_video_extension_functions *VideoFunctionStruct)
{
if (!l_CoreInit)
return M64ERR_NOT_INIT;
return OverrideVideoFunctions(VideoFunctionStruct); /* in vidext.c */
}
EXPORT m64p_error CALL CoreAddCheat(const char *CheatName, m64p_cheat_code *CodeList, int NumCodes)
{
if (!l_CoreInit)
return M64ERR_NOT_INIT;
if (CheatName == NULL || CodeList == NULL)
return M64ERR_INPUT_ASSERT;
if (strlen(CheatName) < 1 || NumCodes < 1)
return M64ERR_INPUT_INVALID;
if (cheat_add_new(CheatName, CodeList, NumCodes))
return M64ERR_SUCCESS;
return M64ERR_INPUT_INVALID;
}
EXPORT m64p_error CALL CoreCheatEnabled(const char *CheatName, int Enabled)
{
if (!l_CoreInit)
return M64ERR_NOT_INIT;
if (CheatName == NULL)
return M64ERR_INPUT_ASSERT;
if (cheat_set_enabled(CheatName, Enabled))
return M64ERR_SUCCESS;
return M64ERR_INPUT_INVALID;
}
EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int RomSettingsLength, int Crc1, int Crc2)
{
romdatabase_entry* entry;
int i;
if (!l_CoreInit)
return M64ERR_NOT_INIT;
if (RomSettings == NULL)
return M64ERR_INPUT_ASSERT;
if (RomSettingsLength < sizeof(m64p_rom_settings))
return M64ERR_INPUT_INVALID;
/* Look up this ROM in the .ini file and fill in goodname, etc */
entry = ini_search_by_crc(Crc1, Crc2);
if (entry == NULL)
return M64ERR_INPUT_NOT_FOUND;
strncpy(RomSettings->goodname, entry->goodname, 255);
RomSettings->goodname[255] = '\0';
for (i = 0; i < 16; i++)
sprintf(RomSettings->MD5 + i*2, "%02X", entry->md5[i]);
RomSettings->MD5[32] = '\0';
RomSettings->savetype = entry->savetype;
RomSettings->status = entry->status;
RomSettings->players = entry->players;
RomSettings->rumble = entry->rumble;
return M64ERR_SUCCESS;
}

View File

@ -0,0 +1,90 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_common.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This header file defines typedefs for function pointers to common Core
* and plugin functions, for use by the front-end and plugin modules to attach
* to the dynamic libraries.
*/
#if !defined(M64P_COMMON_H)
#define M64P_COMMON_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* PluginGetVersion()
*
* This function retrieves version information from a library. This
* function is the same for the core library and the plugins.
*/
typedef m64p_error (*ptr_PluginGetVersion)(m64p_plugin_type *, int *, int *, const char **, int *);
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *, int *, int *, const char **, int *);
#endif
/* CoreGetAPIVersions()
*
* This function retrieves API version information from the core.
*/
typedef m64p_error (*ptr_CoreGetAPIVersions)(int *, int *, int *, int *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreGetAPIVersions(int *, int *, int *, int *);
#endif
/* CoreErrorMessage()
*
* This function returns a pointer to a NULL-terminated string giving a
* human-readable description of the error.
*/
typedef const char * (*ptr_CoreErrorMessage)(m64p_error);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL CoreErrorMessage(m64p_error);
#endif
/* PluginStartup()
*
* This function initializes a plugin for use by allocating memory, creating
* data structures, and loading the configuration data.
*/
typedef m64p_error (*ptr_PluginStartup)(m64p_dynlib_handle, void *, void (*)(void *, int, const char *));
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle, void *, void (*)(void *, int, const char *));
#endif
/* PluginShutdown()
*
* This function destroys data structures and releases memory allocated by
* the plugin library.
*/
typedef m64p_error (*ptr_PluginShutdown)(void);
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL PluginShutdown(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* #define M64P_COMMON_H */

View File

@ -0,0 +1,242 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_config.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2009 Richard Goedeken *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This header file defines typedefs for function pointers to the Core's
* configuration handling functions.
*/
#if !defined(M64P_CONFIG_H)
#define M64P_CONFIG_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ConfigListSections()
*
* This function is called to enumerate the list of Sections in the Mupen64Plus
* configuration file. It is expected that there will be a section named "Core"
* for core-specific configuration data, "Graphics" for common graphics options,
* and one or more sections for each plugin library.
*/
typedef m64p_error (*ptr_ConfigListSections)(void *, void (*)(void *, const char *));
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigListSections(void *, void (*)(void *, const char *));
#endif
/* ConfigOpenSection()
*
* This function is used to give a configuration section handle to the front-end
* which may be used to read or write configuration parameter values in a given
* section of the configuration file.
*/
typedef m64p_error (*ptr_ConfigOpenSection)(const char *, m64p_handle *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigOpenSection(const char *, m64p_handle *);
#endif
/* ConfigListParameters()
*
* This function is called to enumerate the list of Parameters in a given
* Section of the Mupen64Plus configuration file.
*/
typedef m64p_error (*ptr_ConfigListParameters)(m64p_handle, void *, void (*)(void *, const char *, m64p_type));
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigListParameters(m64p_handle, void *, void (*)(void *, const char *, m64p_type));
#endif
/* ConfigSaveFile()
*
* This function saves the entire current Mupen64Plus configuration to disk.
*/
typedef m64p_error (*ptr_ConfigSaveFile)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigSaveFile(void);
#endif
/* ConfigSaveSection()
*
* This function saves one section of the current Mupen64Plus configuration to disk.
*/
typedef m64p_error (*ptr_ConfigSaveSection)(const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigSaveSection(const char *);
#endif
/* ConfigHasUnsavedChanges()
*
* This function determines if a given Section (or all sections) of the Mupen64Plus Core configuration file has been modified since it was last saved or loaded.
*/
typedef int (*ptr_ConfigHasUnsavedChanges)(const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL ConfigHasUnsavedChanges(const char *);
#endif
/* ConfigDeleteSection()
*
* This function deletes a section from the Mupen64Plus configuration data.
*/
typedef m64p_error (*ptr_ConfigDeleteSection)(const char *SectionName);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigDeleteSection(const char *SectionName);
#endif
/* ConfigRevertChanges()
*
* This function reverts changes previously made to one section of the configuration file, so that it will match with the configuration at the last time that it was loaded from or saved to disk.
*/
typedef m64p_error (*ptr_ConfigRevertChanges)(const char *SectionName);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigRevertChanges(const char *SectionName);
#endif
/* ConfigSetParameter()
*
* This function sets the value of one of the emulator's configuration
* parameters.
*/
typedef m64p_error (*ptr_ConfigSetParameter)(m64p_handle, const char *, m64p_type, const void *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigSetParameter(m64p_handle, const char *, m64p_type, const void *);
#endif
/* ConfigGetParameter()
*
* This function retrieves the value of one of the emulator's parameters.
*/
typedef m64p_error (*ptr_ConfigGetParameter)(m64p_handle, const char *, m64p_type, void *, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigGetParameter(m64p_handle, const char *, m64p_type, void *, int);
#endif
/* ConfigGetParameterType()
*
* This function retrieves the type of one of the emulator's parameters.
*/
typedef m64p_error (*ptr_ConfigGetParameterType)(m64p_handle, const char *, m64p_type *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigGetParameterType(m64p_handle, const char *, m64p_type *);
#endif
/* ConfigGetParameterHelp()
*
* This function retrieves the help information about one of the emulator's
* parameters.
*/
typedef const char * (*ptr_ConfigGetParameterHelp)(m64p_handle, const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL ConfigGetParameterHelp(m64p_handle, const char *);
#endif
/* ConfigSetDefault***()
*
* These functions are used to set the value of a configuration parameter if it
* is not already present in the configuration file. This may happen if a new
* user runs the emulator, or an upgraded module uses a new parameter, or the
* user deletes his or her configuration file. If the parameter is already
* present in the given section of the configuration file, then no action will
* be taken and this function will return successfully.
*/
typedef m64p_error (*ptr_ConfigSetDefaultInt)(m64p_handle, const char *, int, const char *);
typedef m64p_error (*ptr_ConfigSetDefaultFloat)(m64p_handle, const char *, float, const char *);
typedef m64p_error (*ptr_ConfigSetDefaultBool)(m64p_handle, const char *, int, const char *);
typedef m64p_error (*ptr_ConfigSetDefaultString)(m64p_handle, const char *, const char *, const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL ConfigSetDefaultInt(m64p_handle, const char *, int, const char *);
EXPORT m64p_error CALL ConfigSetDefaultFloat(m64p_handle, const char *, float, const char *);
EXPORT m64p_error CALL ConfigSetDefaultBool(m64p_handle, const char *, int, const char *);
EXPORT m64p_error CALL ConfigSetDefaultString(m64p_handle, const char *, const char *, const char *);
#endif
/* ConfigGetParam***()
*
* These functions retrieve the value of one of the emulator's parameters in
* the given section, and return the value directly to the calling function. If
* an errors occurs (such as an invalid Section handle, or invalid
* configuration parameter name), then an error will be sent to the front-end
* via the DebugCallback() function, and either a 0 (zero) or an empty string
* will be returned.
*/
typedef int (*ptr_ConfigGetParamInt)(m64p_handle, const char *);
typedef float (*ptr_ConfigGetParamFloat)(m64p_handle, const char *);
typedef int (*ptr_ConfigGetParamBool)(m64p_handle, const char *);
typedef const char * (*ptr_ConfigGetParamString)(m64p_handle, const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL ConfigGetParamInt(m64p_handle, const char *);
EXPORT float CALL ConfigGetParamFloat(m64p_handle, const char *);
EXPORT int CALL ConfigGetParamBool(m64p_handle, const char *);
EXPORT const char * CALL ConfigGetParamString(m64p_handle, const char *);
#endif
/* ConfigGetSharedDataFilepath()
*
* This function is provided to allow a plugin to retrieve a full pathname to a
* given shared data file. This type of file is intended to be shared among
* multiple users on a system, so it is likely to be read-only.
*/
typedef const char * (*ptr_ConfigGetSharedDataFilepath)(const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL ConfigGetSharedDataFilepath(const char *);
#endif
/* ConfigGetUserConfigPath()
*
* This function may be used by the plugins or front-end to get a path to the
* directory for storing user-specific configuration files. This will be the
* directory where "mupen64plus.cfg" is located.
*/
typedef const char * (*ptr_ConfigGetUserConfigPath)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL ConfigGetUserConfigPath(void);
#endif
/* ConfigGetUserDataPath()
*
* This function may be used by the plugins or front-end to get a path to the
* directory for storing user-specific data files. This may be used to store
* files such as screenshots, saved game states, or hi-res textures.
*/
typedef const char * (*ptr_ConfigGetUserDataPath)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL ConfigGetUserDataPath(void);
#endif
/* ConfigGetUserCachePath()
*
* This function may be used by the plugins or front-end to get a path to the
* directory for storing cached user-specific data files. Files in this
* directory may be deleted by the user to save space, so critical information
* should not be stored here. This directory may be used to store files such
* as the ROM browser cache.
*/
typedef const char * (*ptr_ConfigGetUserCachePath)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT const char * CALL ConfigGetUserCachePath(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* #define M64P_CONFIG_H */

View File

@ -0,0 +1,202 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_debugger.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This header file defines typedefs for function pointers to Core Debugger
* functions.
*/
#if !defined(M64P_DEBUGGER_H)
#define M64P_DEBUGGER_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* DebugSetCallbacks()
*
* This function is called by the front-end to supply debugger callback
* function pointers. If debugger is enabled and then later disabled within the
* UI, this function may be called with NULL pointers in order to disable the
* callbacks.
*/
typedef m64p_error (*ptr_DebugSetCallbacks)(void (*)(void), void (*)(unsigned int), void (*)(void));
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(unsigned int), void (*)(void));
#endif
/* DebugSetCoreCompare()
*
* This function is called by the front-end to supply callback function pointers
* for the Core Comparison feature.
*/
typedef m64p_error (*ptr_DebugSetCoreCompare)(void (*)(unsigned int), void (*)(int, void *));
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL DebugSetCoreCompare(void (*)(unsigned int), void (*)(int, void *));
#endif
/* DebugSetRunState()
*
* This function sets the run state of the R4300 CPU emulator.
*/
typedef m64p_error (*ptr_DebugSetRunState)(int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL DebugSetRunState(int);
#endif
/* DebugGetState()
*
* This function reads and returns a debugger state variable, which are
* enumerated in m64p_types.h.
*/
typedef int (*ptr_DebugGetState)(m64p_dbg_state);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL DebugGetState(m64p_dbg_state);
#endif
/* DebugStep()
*
* This function signals the debugger to advance one instruction when in the
* stepping mode.
*/
typedef m64p_error (*ptr_DebugStep)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL DebugStep(void);
#endif
/* DebugDecodeOp()
*
* This is a helper function for the debugger front-end. This instruction takes
* a PC value and an R4300 instruction opcode and writes the disassembled
* instruction mnemonic and arguments into character buffers. This is intended
* to be used to display disassembled code.
*/
typedef void (*ptr_DebugDecodeOp)(unsigned int, char *, char *, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void CALL DebugDecodeOp(unsigned int, char *, char *, int);
#endif
/* DebugMemGetRecompInfo()
*
* This function is used by the front-end to retrieve disassembly information
* about recompiled code. For example, the dynamic recompiler may take a single
* R4300 instruction and compile it into 10 x86 instructions. This function may
* then be used to retrieve the disassembled code of the 10 x86 instructions.
*/
typedef void * (*ptr_DebugMemGetRecompInfo)(m64p_dbg_mem_info, unsigned int, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void * CALL DebugMemGetRecompInfo(m64p_dbg_mem_info, unsigned int, int);
#endif
/* DebugMemGetMemInfo()
*
* This function returns an integer value regarding the memory location address,
* corresponding to the information requested by mem_info_type, which is a type
* enumerated in m64p_types.h.
*/
typedef int (*ptr_DebugMemGetMemInfo)(m64p_dbg_mem_info, unsigned int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL DebugMemGetMemInfo(m64p_dbg_mem_info, unsigned int);
#endif
/* DebugMemGetPointer()
*
* This function returns a memory pointer (in x86 memory space) to a block of
* emulated N64 memory. This may be used to retrieve a pointer to a special N64
* block (such as the serial, video, or audio registers) or the RDRAM.
*/
typedef void * (*ptr_DebugMemGetPointer)(m64p_dbg_memptr_type);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void * CALL DebugMemGetPointer(m64p_dbg_memptr_type);
#endif
/* DebugMemRead**()
*
* These functions retrieve a value from the emulated N64 memory. The returned
* value will be correctly byte-swapped for the host architecture.
*/
typedef unsigned long long (*ptr_DebugMemRead64)(unsigned int);
typedef unsigned int (*ptr_DebugMemRead32)(unsigned int);
typedef unsigned short (*ptr_DebugMemRead16)(unsigned int);
typedef unsigned char (*ptr_DebugMemRead8)(unsigned int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT unsigned long long CALL DebugMemRead64(unsigned int);
EXPORT unsigned int CALL DebugMemRead32(unsigned int);
EXPORT unsigned short CALL DebugMemRead16(unsigned int);
EXPORT unsigned char CALL DebugMemRead8(unsigned int);
#endif
/* DebugMemWrite**()
*
* These functions write a value into the emulated N64 memory. The given value
* will be correctly byte-swapped before storage.
*/
typedef void (*ptr_DebugMemWrite64)(unsigned int, unsigned long long);
typedef void (*ptr_DebugMemWrite32)(unsigned int, unsigned int);
typedef void (*ptr_DebugMemWrite16)(unsigned int, unsigned short);
typedef void (*ptr_DebugMemWrite8)(unsigned int, unsigned char);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void CALL DebugMemWrite64(unsigned int, unsigned long long);
EXPORT void CALL DebugMemWrite32(unsigned int, unsigned int);
EXPORT void CALL DebugMemWrite16(unsigned int, unsigned short);
EXPORT void CALL DebugMemWrite8(unsigned int, unsigned char);
#endif
/* DebugGetCPUDataPtr()
*
* This function returns a memory pointer (in x86 memory space) to a specific
* register in the emulated R4300 CPU.
*/
typedef void * (*ptr_DebugGetCPUDataPtr)(m64p_dbg_cpu_data);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void * CALL DebugGetCPUDataPtr(m64p_dbg_cpu_data);
#endif
/* DebugBreakpointLookup()
*
* This function searches through all current breakpoints in the debugger to
* find one that matches the given input parameters. If a matching breakpoint
* is found, the index number is returned. If no breakpoints are found, -1 is
* returned.
*/
typedef int (*ptr_DebugBreakpointLookup)(unsigned int, unsigned int, unsigned int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL DebugBreakpointLookup(unsigned int, unsigned int, unsigned int);
#endif
/* DebugBreakpointCommand()
*
* This function is used to process common breakpoint commands, such as adding,
* removing, or searching the breakpoints. The meanings of the index and ptr
* input parameters vary by command.
*/
typedef int (*ptr_DebugBreakpointCommand)(m64p_dbg_bkp_command, unsigned int, void *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL DebugBreakpointCommand(m64p_dbg_bkp_command, unsigned int, void *);
#endif
#ifdef __cplusplus
}
#endif
#endif /* #define M64P_DEBUGGER_H */

View File

@ -0,0 +1,141 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_frontend.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This header file defines typedefs for function pointers to Core functions
* designed for use by the front-end user interface.
*/
#if !defined(M64P_FRONTEND_H)
#define M64P_FRONTEND_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* pointer types to the callback functions in the front-end application */
typedef void (*ptr_DebugCallback)(void *Context, int level, const char *message);
typedef void (*ptr_StateCallback)(void *Context, m64p_core_param param_type, int new_value);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void CALL DebugCallback(void *Context, int level, const char *message);
EXPORT void CALL StateCallback(void *Context, m64p_core_param param_type, int new_value);
#endif
/* CoreStartup()
*
* This function initializes libmupen64plus for use by allocating memory,
* creating data structures, and loading the configuration file.
*/
typedef m64p_error (*ptr_CoreStartup)(int, const char *, const char *, void *, ptr_DebugCallback, void *, ptr_StateCallback);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreStartup(int, const char *, const char *, void *, ptr_DebugCallback, void *, ptr_StateCallback);
#endif
/* CoreShutdown()
*
* This function saves the configuration file, then destroys data structures
* and releases memory allocated by the core library.
*/
typedef m64p_error (*ptr_CoreShutdown)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreShutdown(void);
#endif
/* CoreAttachPlugin()
*
* This function attaches the given plugin to the emulator core. There can only
* be one plugin of each type attached to the core at any given time.
*/
typedef m64p_error (*ptr_CoreAttachPlugin)(m64p_plugin_type, m64p_dynlib_handle);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type, m64p_dynlib_handle);
#endif
/* CoreDetachPlugin()
*
* This function detaches the given plugin from the emulator core, and re-attaches
* the 'dummy' plugin functions.
*/
typedef m64p_error (*ptr_CoreDetachPlugin)(m64p_plugin_type);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreDetachPlugin(m64p_plugin_type);
#endif
/* CoreDoCommand()
*
* This function sends a command to the emulator core.
*/
typedef m64p_error (*ptr_CoreDoCommand)(m64p_command, int, void *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreDoCommand(m64p_command, int, void *);
#endif
/* CoreOverrideVidExt()
*
* This function overrides the core's internal SDL-based OpenGL functions. This
* override functionality allows a front-end to define its own video extension
* functions to be used instead of the SDL functions. If any of the function
* pointers in the structure are NULL, the override function will be disabled
* and the core's internal SDL functions will be used.
*/
typedef m64p_error (*ptr_CoreOverrideVidExt)(m64p_video_extension_functions *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreOverrideVidExt(m64p_video_extension_functions *);
#endif
/* CoreAddCheat()
*
* This function will add a Cheat Function to a list of currently active cheats
* which are applied to the open ROM.
*/
typedef m64p_error (*ptr_CoreAddCheat)(const char *, m64p_cheat_code *, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreAddCheat(const char *, m64p_cheat_code *, int);
#endif
/* CoreCheatEnabled()
*
* This function will enable or disable a Cheat Function which is in the list of
* currently active cheats.
*/
typedef m64p_error (*ptr_CoreCheatEnabled)(const char *, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreCheatEnabled(const char *, int);
#endif
/* CoreGetRomSettings()
*
* This function will retrieve the ROM settings from the mupen64plus INI file for
* the ROM image corresponding to the given CRC values.
*/
typedef m64p_error (*ptr_CoreGetRomSettings)(m64p_rom_settings *, int, int, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *, int, int, int);
#endif
#ifdef __cplusplus
}
#endif
#endif /* #define M64P_FRONTEND_H */

View File

@ -0,0 +1,269 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_plugin.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2002 Hacktarux *
* 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(M64P_PLUGIN_H)
#define M64P_PLUGIN_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*** Controller plugin's ****/
#define PLUGIN_NONE 1
#define PLUGIN_MEMPAK 2
#define PLUGIN_RUMBLE_PAK 3 /* not implemented for non raw data */
#define PLUGIN_TRANSFER_PAK 4 /* not implemented for non raw data */
#define PLUGIN_RAW 5 /* the controller plugin is passed in raw data */
/***** Structures *****/
typedef struct {
unsigned char * RDRAM;
unsigned char * DMEM;
unsigned char * IMEM;
unsigned int * MI_INTR_REG;
unsigned int * SP_MEM_ADDR_REG;
unsigned int * SP_DRAM_ADDR_REG;
unsigned int * SP_RD_LEN_REG;
unsigned int * SP_WR_LEN_REG;
unsigned int * SP_STATUS_REG;
unsigned int * SP_DMA_FULL_REG;
unsigned int * SP_DMA_BUSY_REG;
unsigned int * SP_PC_REG;
unsigned int * SP_SEMAPHORE_REG;
unsigned int * DPC_START_REG;
unsigned int * DPC_END_REG;
unsigned int * DPC_CURRENT_REG;
unsigned int * DPC_STATUS_REG;
unsigned int * DPC_CLOCK_REG;
unsigned int * DPC_BUFBUSY_REG;
unsigned int * DPC_PIPEBUSY_REG;
unsigned int * DPC_TMEM_REG;
void (*CheckInterrupts)(void);
void (*ProcessDlistList)(void);
void (*ProcessAlistList)(void);
void (*ProcessRdpList)(void);
void (*ShowCFB)(void);
} RSP_INFO;
typedef struct {
unsigned char * HEADER; /* This is the rom header (first 40h bytes of the rom) */
unsigned char * RDRAM;
unsigned char * DMEM;
unsigned char * IMEM;
unsigned int * MI_INTR_REG;
unsigned int * DPC_START_REG;
unsigned int * DPC_END_REG;
unsigned int * DPC_CURRENT_REG;
unsigned int * DPC_STATUS_REG;
unsigned int * DPC_CLOCK_REG;
unsigned int * DPC_BUFBUSY_REG;
unsigned int * DPC_PIPEBUSY_REG;
unsigned int * DPC_TMEM_REG;
unsigned int * VI_STATUS_REG;
unsigned int * VI_ORIGIN_REG;
unsigned int * VI_WIDTH_REG;
unsigned int * VI_INTR_REG;
unsigned int * VI_V_CURRENT_LINE_REG;
unsigned int * VI_TIMING_REG;
unsigned int * VI_V_SYNC_REG;
unsigned int * VI_H_SYNC_REG;
unsigned int * VI_LEAP_REG;
unsigned int * VI_H_START_REG;
unsigned int * VI_V_START_REG;
unsigned int * VI_V_BURST_REG;
unsigned int * VI_X_SCALE_REG;
unsigned int * VI_Y_SCALE_REG;
void (*CheckInterrupts)(void);
} GFX_INFO;
typedef struct {
unsigned char * RDRAM;
unsigned char * DMEM;
unsigned char * IMEM;
unsigned int * MI_INTR_REG;
unsigned int * AI_DRAM_ADDR_REG;
unsigned int * AI_LEN_REG;
unsigned int * AI_CONTROL_REG;
unsigned int * AI_STATUS_REG;
unsigned int * AI_DACRATE_REG;
unsigned int * AI_BITRATE_REG;
void (*CheckInterrupts)(void);
} AUDIO_INFO;
typedef struct {
int Present;
int RawData;
int Plugin;
} CONTROL;
typedef union {
unsigned int Value;
struct {
unsigned R_DPAD : 1;
unsigned L_DPAD : 1;
unsigned D_DPAD : 1;
unsigned U_DPAD : 1;
unsigned START_BUTTON : 1;
unsigned Z_TRIG : 1;
unsigned B_BUTTON : 1;
unsigned A_BUTTON : 1;
unsigned R_CBUTTON : 1;
unsigned L_CBUTTON : 1;
unsigned D_CBUTTON : 1;
unsigned U_CBUTTON : 1;
unsigned R_TRIG : 1;
unsigned L_TRIG : 1;
unsigned Reserved1 : 1;
unsigned Reserved2 : 1;
signed X_AXIS : 8;
signed Y_AXIS : 8;
};
} BUTTONS;
typedef struct {
CONTROL *Controls; /* A pointer to an array of 4 controllers .. eg:
CONTROL Controls[4]; */
} CONTROL_INFO;
/* common plugin function pointer types */
typedef void (*ptr_RomClosed)(void);
typedef int (*ptr_RomOpen)(void);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT int CALL RomOpen(void);
EXPORT void CALL RomClosed(void);
#endif
/* video plugin function pointer types */
typedef void (*ptr_ChangeWindow)(void);
typedef int (*ptr_InitiateGFX)(GFX_INFO Gfx_Info);
typedef void (*ptr_MoveScreen)(int x, int y);
typedef void (*ptr_ProcessDList)(void);
typedef void (*ptr_ProcessRDPList)(void);
typedef void (*ptr_ShowCFB)(void);
typedef void (*ptr_UpdateScreen)(void);
typedef void (*ptr_ViStatusChanged)(void);
typedef void (*ptr_ViWidthChanged)(void);
typedef void (*ptr_ReadScreen2)(void *dest, int *width, int *height, int front);
typedef void (*ptr_SetRenderingCallback)(void (*callback)(int));
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT void CALL ChangeWindow(void);
EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info);
EXPORT void CALL MoveScreen(int x, int y);
EXPORT void CALL ProcessDList(void);
EXPORT void CALL ProcessRDPList(void);
EXPORT void CALL ShowCFB(void);
EXPORT void CALL UpdateScreen(void);
EXPORT void CALL ViStatusChanged(void);
EXPORT void CALL ViWidthChanged(void);
EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front);
EXPORT void CALL SetRenderingCallback(void (*callback)(int));
#endif
/* frame buffer plugin spec extension */
typedef struct
{
unsigned int addr;
unsigned int size;
unsigned int width;
unsigned int height;
} FrameBufferInfo;
typedef void (*ptr_FBRead)(unsigned int addr);
typedef void (*ptr_FBWrite)(unsigned int addr, unsigned int size);
typedef void (*ptr_FBGetFrameBufferInfo)(void *p);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT void CALL FBRead(unsigned int addr);
EXPORT void CALL FBWrite(unsigned int addr, unsigned int size);
EXPORT void CALL FBGetFrameBufferInfo(void *p);
#endif
/* audio plugin function pointers */
typedef void (*ptr_AiDacrateChanged)(int SystemType);
typedef void (*ptr_AiLenChanged)(void);
typedef int (*ptr_InitiateAudio)(AUDIO_INFO Audio_Info);
typedef void (*ptr_ProcessAList)(void);
typedef void (*ptr_SetSpeedFactor)(int percent);
typedef void (*ptr_VolumeUp)(void);
typedef void (*ptr_VolumeDown)(void);
typedef int (*ptr_VolumeGetLevel)(void);
typedef void (*ptr_VolumeSetLevel)(int level);
typedef void (*ptr_VolumeMute)(void);
typedef const char * (*ptr_VolumeGetString)(void);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT void CALL AiDacrateChanged(int SystemType);
EXPORT void CALL AiLenChanged(void);
EXPORT int CALL InitiateAudio(AUDIO_INFO Audio_Info);
EXPORT void CALL ProcessAList(void);
EXPORT void CALL SetSpeedFactor(int percent);
EXPORT void CALL VolumeUp(void);
EXPORT void CALL VolumeDown(void);
EXPORT int CALL VolumeGetLevel(void);
EXPORT void CALL VolumeSetLevel(int level);
EXPORT void CALL VolumeMute(void);
EXPORT const char * CALL VolumeGetString(void);
#endif
/* input plugin function pointers */
typedef void (*ptr_ControllerCommand)(int Control, unsigned char *Command);
typedef void (*ptr_GetKeys)(int Control, BUTTONS *Keys);
typedef void (*ptr_InitiateControllers)(CONTROL_INFO ControlInfo);
typedef void (*ptr_ReadController)(int Control, unsigned char *Command);
typedef void (*ptr_SDL_KeyDown)(int keymod, int keysym);
typedef void (*ptr_SDL_KeyUp)(int keymod, int keysym);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT void CALL ControllerCommand(int Control, unsigned char *Command);
EXPORT void CALL GetKeys(int Control, BUTTONS *Keys);
EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo);
EXPORT void CALL ReadController(int Control, unsigned char *Command);
EXPORT void CALL SDL_KeyDown(int keymod, int keysym);
EXPORT void CALL SDL_KeyUp(int keymod, int keysym);
#endif
/* RSP plugin function pointers */
typedef unsigned int (*ptr_DoRspCycles)(unsigned int Cycles);
typedef void (*ptr_InitiateRSP)(RSP_INFO Rsp_Info, unsigned int *CycleCount);
#if defined(M64P_PLUGIN_PROTOTYPES)
EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles);
EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount);
#endif
#ifdef __cplusplus
}
#endif
#endif /* M64P_PLUGIN_H */

View File

@ -0,0 +1,346 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_types.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* 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(M64P_TYPES_H)
#define M64P_TYPES_H
/* ----------------------------------------- */
/* Platform-specific stuff */
/* ----------------------------------------- */
/* necessary headers */
#if defined(WIN32)
#include <windows.h>
#endif
/* DLL handles and function declaration specifiers */
#if defined(WIN32)
#define IMPORT extern "C" __declspec(dllimport)
#define EXPORT __declspec(dllexport)
#define CALL __cdecl
typedef HMODULE m64p_dynlib_handle;
#else
#define IMPORT extern "C"
#define EXPORT __attribute__((visibility("default")))
#define CALL
typedef void * m64p_dynlib_handle;
#endif
/* ----------------------------------------- */
/* Structures and Types for Core library API */
/* ----------------------------------------- */
typedef void * m64p_handle;
typedef void (*m64p_frame_callback)(unsigned int FrameIndex);
typedef void (*m64p_input_callback)(void);
typedef void (*m64p_audio_callback)(void);
typedef void (*m64p_vi_callback)(void);
typedef enum {
M64TYPE_INT = 1,
M64TYPE_FLOAT,
M64TYPE_BOOL,
M64TYPE_STRING
} m64p_type;
typedef enum {
M64MSG_ERROR = 1,
M64MSG_WARNING,
M64MSG_INFO,
M64MSG_STATUS,
M64MSG_VERBOSE
} m64p_msg_level;
typedef enum {
M64ERR_SUCCESS = 0,
M64ERR_NOT_INIT, /* Function is disallowed before InitMupen64Plus() is called */
M64ERR_ALREADY_INIT, /* InitMupen64Plus() was called twice */
M64ERR_INCOMPATIBLE, /* API versions between components are incompatible */
M64ERR_INPUT_ASSERT, /* Invalid parameters for function call, such as ParamValue=NULL for GetCoreParameter() */
M64ERR_INPUT_INVALID, /* Invalid input data, such as ParamValue="maybe" for SetCoreParameter() to set a BOOL-type value */
M64ERR_INPUT_NOT_FOUND, /* The input parameter(s) specified a particular item which was not found */
M64ERR_NO_MEMORY, /* Memory allocation failed */
M64ERR_FILES, /* Error opening, creating, reading, or writing to a file */
M64ERR_INTERNAL, /* Internal error (bug) */
M64ERR_INVALID_STATE, /* Current program state does not allow operation */
M64ERR_PLUGIN_FAIL, /* A plugin function returned a fatal error */
M64ERR_SYSTEM_FAIL, /* A system function call, such as an SDL or file operation, failed */
M64ERR_UNSUPPORTED, /* Function call is not supported (ie, core not built with debugger) */
M64ERR_WRONG_TYPE /* A given input type parameter cannot be used for desired operation */
} m64p_error;
typedef enum {
M64CAPS_DYNAREC = 1,
M64CAPS_DEBUGGER = 2,
M64CAPS_CORE_COMPARE = 4
} m64p_core_caps;
typedef enum {
M64PLUGIN_NULL = 0,
M64PLUGIN_RSP = 1,
M64PLUGIN_GFX,
M64PLUGIN_AUDIO,
M64PLUGIN_INPUT,
M64PLUGIN_CORE
} m64p_plugin_type;
typedef enum {
M64EMU_STOPPED = 1,
M64EMU_RUNNING,
M64EMU_PAUSED
} m64p_emu_state;
typedef enum {
M64VIDEO_NONE = 1,
M64VIDEO_WINDOWED,
M64VIDEO_FULLSCREEN
} m64p_video_mode;
typedef enum {
M64CORE_EMU_STATE = 1,
M64CORE_VIDEO_MODE,
M64CORE_SAVESTATE_SLOT,
M64CORE_SPEED_FACTOR,
M64CORE_SPEED_LIMITER,
M64CORE_VIDEO_SIZE,
M64CORE_AUDIO_VOLUME,
M64CORE_AUDIO_MUTE,
M64CORE_INPUT_GAMESHARK,
M64CORE_STATE_LOADCOMPLETE,
M64CORE_STATE_SAVECOMPLETE
} m64p_core_param;
typedef enum {
M64CMD_NOP = 0,
M64CMD_ROM_OPEN,
M64CMD_ROM_CLOSE,
M64CMD_ROM_GET_HEADER,
M64CMD_ROM_GET_SETTINGS,
M64CMD_EXECUTE,
M64CMD_STOP,
M64CMD_PAUSE,
M64CMD_RESUME,
M64CMD_CORE_STATE_QUERY,
M64CMD_STATE_LOAD,
M64CMD_STATE_SAVE,
M64CMD_STATE_SET_SLOT,
M64CMD_SEND_SDL_KEYDOWN,
M64CMD_SEND_SDL_KEYUP,
M64CMD_SET_FRAME_CALLBACK,
M64CMD_TAKE_NEXT_SCREENSHOT,
M64CMD_CORE_STATE_SET,
M64CMD_READ_SCREEN,
M64CMD_RESET,
M64CMD_ADVANCE_FRAME
} m64p_command;
typedef struct {
unsigned int address;
int value;
} m64p_cheat_code;
/* ----------------------------------------- */
/* Structures to hold ROM image information */
/* ----------------------------------------- */
typedef enum
{
SYSTEM_NTSC = 0,
SYSTEM_PAL,
SYSTEM_MPAL
} m64p_system_type;
typedef struct
{
unsigned char init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
unsigned char init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
unsigned char init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
unsigned char init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
unsigned int ClockRate; /* 0x04 */
unsigned int PC; /* 0x08 */
unsigned int Release; /* 0x0C */
unsigned int CRC1; /* 0x10 */
unsigned int CRC2; /* 0x14 */
unsigned int Unknown[2]; /* 0x18 */
unsigned char Name[20]; /* 0x20 */
unsigned int unknown; /* 0x34 */
unsigned int Manufacturer_ID; /* 0x38 */
unsigned short Cartridge_ID; /* 0x3C - Game serial number */
unsigned short Country_code; /* 0x3E */
} m64p_rom_header;
typedef struct
{
char goodname[256];
char MD5[33];
unsigned char savetype;
unsigned char status; /* Rom status on a scale from 0-5. */
unsigned char players; /* Local players 0-4, 2/3/4 way Netplay indicated by 5/6/7. */
unsigned char rumble; /* 0 - No, 1 - Yes boolean for rumble support. */
} m64p_rom_settings;
/* ----------------------------------------- */
/* Structures and Types for the Debugger */
/* ----------------------------------------- */
typedef enum {
M64P_DBG_RUN_STATE = 1,
M64P_DBG_PREVIOUS_PC,
M64P_DBG_NUM_BREAKPOINTS,
M64P_DBG_CPU_DYNACORE,
M64P_DBG_CPU_NEXT_INTERRUPT
} m64p_dbg_state;
typedef enum {
M64P_DBG_MEM_TYPE = 1,
M64P_DBG_MEM_FLAGS,
M64P_DBG_MEM_HAS_RECOMPILED,
M64P_DBG_MEM_NUM_RECOMPILED,
M64P_DBG_RECOMP_OPCODE = 16,
M64P_DBG_RECOMP_ARGS,
M64P_DBG_RECOMP_ADDR
} m64p_dbg_mem_info;
typedef enum {
M64P_MEM_NOMEM = 0,
M64P_MEM_NOTHING,
M64P_MEM_RDRAM,
M64P_MEM_RDRAMREG,
M64P_MEM_RSPMEM,
M64P_MEM_RSPREG,
M64P_MEM_RSP,
M64P_MEM_DP,
M64P_MEM_DPS,
M64P_MEM_VI,
M64P_MEM_AI,
M64P_MEM_PI,
M64P_MEM_RI,
M64P_MEM_SI,
M64P_MEM_FLASHRAMSTAT,
M64P_MEM_ROM,
M64P_MEM_PIF,
M64P_MEM_MI,
M64P_MEM_BREAKPOINT
} m64p_dbg_mem_type;
typedef enum {
M64P_MEM_FLAG_READABLE = 0x01,
M64P_MEM_FLAG_WRITABLE = 0x02,
M64P_MEM_FLAG_READABLE_EMUONLY = 0x04, // the EMUONLY flags signify that emulated code can read/write here, but debugger cannot
M64P_MEM_FLAG_WRITABLE_EMUONLY = 0x08
} m64p_dbg_mem_flags;
typedef enum {
M64P_DBG_PTR_RDRAM = 1,
M64P_DBG_PTR_PI_REG,
M64P_DBG_PTR_SI_REG,
M64P_DBG_PTR_VI_REG,
M64P_DBG_PTR_RI_REG,
M64P_DBG_PTR_AI_REG
} m64p_dbg_memptr_type;
typedef enum {
M64P_CPU_PC = 1,
M64P_CPU_REG_REG,
M64P_CPU_REG_HI,
M64P_CPU_REG_LO,
M64P_CPU_REG_COP0,
M64P_CPU_REG_COP1_DOUBLE_PTR,
M64P_CPU_REG_COP1_SIMPLE_PTR,
M64P_CPU_REG_COP1_FGR_64,
M64P_CPU_TLB
} m64p_dbg_cpu_data;
typedef enum {
M64P_BKP_CMD_ADD_ADDR = 1,
M64P_BKP_CMD_ADD_STRUCT,
M64P_BKP_CMD_REPLACE,
M64P_BKP_CMD_REMOVE_ADDR,
M64P_BKP_CMD_REMOVE_IDX,
M64P_BKP_CMD_ENABLE,
M64P_BKP_CMD_DISABLE,
M64P_BKP_CMD_CHECK
} m64p_dbg_bkp_command;
#define M64P_MEM_INVALID 0xFFFFFFFF // invalid memory read will return this
#define BREAKPOINTS_MAX_NUMBER 128
#define BPT_FLAG_ENABLED 0x01
#define BPT_FLAG_CONDITIONAL 0x02
#define BPT_FLAG_COUNTER 0x04
#define BPT_FLAG_READ 0x08
#define BPT_FLAG_WRITE 0x10
#define BPT_FLAG_EXEC 0x20
#define BPT_FLAG_LOG 0x40 //Log to the console when this breakpoint hits.
#define BPT_CHECK_FLAG(a, b) ((a.flags & b) == b)
#define BPT_SET_FLAG(a, b) a.flags = (a.flags | b);
#define BPT_CLEAR_FLAG(a, b) a.flags = (a.flags & (~b));
#define BPT_TOGGLE_FLAG(a, b) a.flags = (a.flags ^ b);
typedef struct _breakpoint {
unsigned int address;
unsigned int endaddr;
unsigned int flags;
//unsigned int condition; //Placeholder for breakpoint condition
} breakpoint;
/* ------------------------------------------------- */
/* Structures and Types for Core Video Extension API */
/* ------------------------------------------------- */
typedef struct {
unsigned int uiWidth;
unsigned int uiHeight;
} m64p_2d_size;
typedef enum {
M64P_GL_DOUBLEBUFFER = 1,
M64P_GL_BUFFER_SIZE,
M64P_GL_DEPTH_SIZE,
M64P_GL_RED_SIZE,
M64P_GL_GREEN_SIZE,
M64P_GL_BLUE_SIZE,
M64P_GL_ALPHA_SIZE,
M64P_GL_SWAP_CONTROL,
M64P_GL_MULTISAMPLEBUFFERS,
M64P_GL_MULTISAMPLESAMPLES
} m64p_GLattr;
typedef struct {
unsigned int Functions;
m64p_error (*VidExtFuncInit)(void);
m64p_error (*VidExtFuncQuit)(void);
m64p_error (*VidExtFuncListModes)(m64p_2d_size *, int *);
m64p_error (*VidExtFuncSetMode)(int, int, int, int);
void * (*VidExtFuncGLGetProc)(const char*);
m64p_error (*VidExtFuncGLSetAttr)(m64p_GLattr, int);
m64p_error (*VidExtFuncGLGetAttr)(m64p_GLattr, int *);
m64p_error (*VidExtFuncGLSwapBuf)(void);
m64p_error (*VidExtFuncSetCaption)(const char *);
m64p_error (*VidExtFuncToggleFS)(void);
} m64p_video_extension_functions;
#endif /* define M64P_TYPES_H */

View File

@ -0,0 +1,145 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - m64p_vidext.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This header file defines typedefs for function pointers to the core's
* video extension functions.
*/
#if !defined(M64P_VIDEXT_H)
#define M64P_VIDEXT_H
#include "m64p_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* VidExt_Init()
*
* This function should be called from within the InitiateGFX() video plugin
* function call. The default SDL implementation of this function simply calls
* SDL_InitSubSystem(SDL_INIT_VIDEO). It does not open a rendering window or
* switch video modes.
*/
typedef m64p_error (*ptr_VidExt_Init)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_Init(void);
#endif
/* VidExt_Quit()
*
* This function closes any open rendering window and shuts down the video
* system. The default SDL implementation of this function calls
* SDL_QuitSubSystem(SDL_INIT_VIDEO). This function should be called from
* within the RomClose() video plugin function.
*/
typedef m64p_error (*ptr_VidExt_Quit)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_Quit(void);
#endif
/* VidExt_ListFullscreenModes()
*
* This function is used to enumerate the available resolutions for fullscreen
* video modes. A pointer to an array is passed into the function, which is
* then filled with resolution sizes.
*/
typedef m64p_error (*ptr_VidExt_ListFullscreenModes)(m64p_2d_size *, int *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *, int *);
#endif
/* VidExt_SetVideoMode()
*
* This function creates a rendering window or switches into a fullscreen
* video mode. Any desired OpenGL attributes should be set before calling
* this function.
*/
typedef m64p_error (*ptr_VidExt_SetVideoMode)(int, int, int, m64p_video_mode);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_SetVideoMode(int, int, int, m64p_video_mode);
#endif
/* VidExt_SetCaption()
*
* This function sets the caption text of the emulator rendering window.
*/
typedef m64p_error (*ptr_VidExt_SetCaption)(const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_SetCaption(const char *);
#endif
/* VidExt_ToggleFullScreen()
*
* This function toggles between fullscreen and windowed rendering modes.
*/
typedef m64p_error (*ptr_VidExt_ToggleFullScreen)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_ToggleFullScreen(void);
#endif
/* VidExt_GL_GetProcAddress()
*
* This function is used to get a pointer to an OpenGL extension function. This
* is only necessary on the Windows platform, because the OpenGL implementation
* shipped with Windows only supports OpenGL version 1.1.
*/
typedef void * (*ptr_VidExt_GL_GetProcAddress)(const char *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT void * CALL VidExt_GL_GetProcAddress(const char *);
#endif
/* VidExt_GL_SetAttribute()
*
* This function is used to set certain OpenGL attributes which must be
* specified before creating the rendering window with VidExt_SetVideoMode.
*/
typedef m64p_error (*ptr_VidExt_GL_SetAttribute)(m64p_GLattr, int);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr, int);
#endif
/* VidExt_GL_GetAttribute()
*
* This function is used to get the value of OpenGL attributes. These values may
* be changed when calling VidExt_SetVideoMode.
*/
typedef m64p_error (*ptr_VidExt_GL_GetAttribute)(m64p_GLattr, int *);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr, int *);
#endif
/* VidExt_GL_SwapBuffers()
*
* This function is used to swap the front/back buffers after rendering an
* output video frame.
*/
typedef m64p_error (*ptr_VidExt_GL_SwapBuffers)(void);
#if defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* #define M64P_VIDEXT_H */

View File

@ -0,0 +1,390 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/vidext.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the Core video extension functions which will be exported
* outside of the core library.
*/
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#define M64P_CORE_PROTOTYPES 1
#include "m64p_types.h"
#include "m64p_vidext.h"
#include "vidext.h"
#include "callbacks.h"
#if SDL_VERSION_ATLEAST(2,0,0)
#include "vidext_sdl2_compat.h"
#endif
/* local variables */
static m64p_video_extension_functions l_ExternalVideoFuncTable = {10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static int l_VideoExtensionActive = 0;
static int l_VideoOutputActive = 0;
static int l_Fullscreen = 0;
static SDL_Surface *l_pScreen = NULL;
/* global function for use by frontend.c */
m64p_error OverrideVideoFunctions(m64p_video_extension_functions *VideoFunctionStruct)
{
/* check input data */
if (VideoFunctionStruct == NULL)
return M64ERR_INPUT_ASSERT;
if (VideoFunctionStruct->Functions < 10)
return M64ERR_INPUT_INVALID;
/* disable video extension if any of the function pointers are NULL */
if (VideoFunctionStruct->VidExtFuncInit == NULL ||
VideoFunctionStruct->VidExtFuncQuit == NULL ||
VideoFunctionStruct->VidExtFuncListModes == NULL ||
VideoFunctionStruct->VidExtFuncSetMode == NULL ||
VideoFunctionStruct->VidExtFuncGLGetProc == NULL ||
VideoFunctionStruct->VidExtFuncGLSetAttr == NULL ||
VideoFunctionStruct->VidExtFuncGLGetAttr == NULL ||
VideoFunctionStruct->VidExtFuncGLSwapBuf == NULL ||
VideoFunctionStruct->VidExtFuncSetCaption == NULL ||
VideoFunctionStruct->VidExtFuncToggleFS == NULL)
{
l_ExternalVideoFuncTable.Functions = 10;
memset(&l_ExternalVideoFuncTable.VidExtFuncInit, 0, 10 * sizeof(void *));
l_VideoExtensionActive = 0;
return M64ERR_SUCCESS;
}
/* otherwise copy in the override function pointers */
memcpy(&l_ExternalVideoFuncTable, VideoFunctionStruct, sizeof(m64p_video_extension_functions));
l_VideoExtensionActive = 1;
return M64ERR_SUCCESS;
}
int VidExt_InFullscreenMode(void)
{
return l_Fullscreen;
}
int VidExt_VideoRunning(void)
{
return l_VideoOutputActive;
}
/* video extension functions to be called by the video plugin */
EXPORT m64p_error CALL VidExt_Init(void)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncInit)();
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
{
DebugMessage(M64MSG_ERROR, "SDL video subsystem init failed: %s", SDL_GetError());
return M64ERR_SYSTEM_FAIL;
}
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL VidExt_Quit(void)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
{
m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncQuit)();
if (rval == M64ERR_SUCCESS)
{
l_VideoOutputActive = 0;
StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE);
}
return rval;
}
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
SDL_ShowCursor(SDL_ENABLE);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
l_pScreen = NULL;
l_VideoOutputActive = 0;
StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE);
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *SizeArray, int *NumSizes)
{
const SDL_VideoInfo *videoInfo;
unsigned int videoFlags;
SDL_Rect **modes;
int i;
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncListModes)(SizeArray, NumSizes);
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
/* get a list of SDL video modes */
videoFlags = SDL_OPENGL | SDL_FULLSCREEN;
if ((videoInfo = SDL_GetVideoInfo()) == NULL)
{
DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
return M64ERR_SYSTEM_FAIL;
}
if(videoInfo->hw_available)
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
modes = SDL_ListModes(NULL, videoFlags);
if (modes == (SDL_Rect **) 0 || modes == (SDL_Rect **) -1)
{
DebugMessage(M64MSG_WARNING, "No fullscreen SDL video modes available");
*NumSizes = 0;
return M64ERR_SUCCESS;
}
i = 0;
while (i < *NumSizes && modes[i] != NULL)
{
SizeArray[i].uiWidth = modes[i]->w;
SizeArray[i].uiHeight = modes[i]->h;
i++;
}
*NumSizes = i;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL VidExt_SetVideoMode(int Width, int Height, int BitsPerPixel, m64p_video_mode ScreenMode)
{
const SDL_VideoInfo *videoInfo;
int videoFlags = 0;
/* call video extension override if necessary */
if (l_VideoExtensionActive)
{
m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncSetMode)(Width, Height, BitsPerPixel, ScreenMode);
l_Fullscreen = (rval == M64ERR_SUCCESS && ScreenMode == M64VIDEO_FULLSCREEN);
l_VideoOutputActive = (rval == M64ERR_SUCCESS);
if (l_VideoOutputActive)
{
StateChanged(M64CORE_VIDEO_MODE, ScreenMode);
StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
}
return rval;
}
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
/* Get SDL video flags to use */
if (ScreenMode == M64VIDEO_WINDOWED)
videoFlags = SDL_OPENGL;
else if (ScreenMode == M64VIDEO_FULLSCREEN)
videoFlags = SDL_OPENGL | SDL_FULLSCREEN;
else
return M64ERR_INPUT_INVALID;
if ((videoInfo = SDL_GetVideoInfo()) == NULL)
{
DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
return M64ERR_SYSTEM_FAIL;
}
if (videoInfo->hw_available)
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
/* set the mode */
if (BitsPerPixel > 0)
DebugMessage(M64MSG_INFO, "Setting %i-bit video mode: %ix%i", BitsPerPixel, Width, Height);
else
DebugMessage(M64MSG_INFO, "Setting video mode: %ix%i", Width, Height);
l_pScreen = SDL_SetVideoMode(Width, Height, BitsPerPixel, videoFlags);
if (l_pScreen == NULL)
{
DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s", SDL_GetError());
return M64ERR_SYSTEM_FAIL;
}
SDL_ShowCursor(SDL_DISABLE);
l_Fullscreen = (ScreenMode == M64VIDEO_FULLSCREEN);
l_VideoOutputActive = 1;
StateChanged(M64CORE_VIDEO_MODE, ScreenMode);
StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL VidExt_SetCaption(const char *Title)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncSetCaption)(Title);
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
SDL_WM_SetCaption(Title, "M64+ Video");
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL VidExt_ToggleFullScreen(void)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
{
m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncToggleFS)();
if (rval == M64ERR_SUCCESS)
{
l_Fullscreen = !l_Fullscreen;
StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED);
}
return rval;
}
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
/* TODO:
* SDL_WM_ToggleFullScreen doesn't work under Windows and others
* (see http://wiki.libsdl.org/moin.cgi/FAQWindows for explanation).
* Instead, we should call SDL_SetVideoMode with the SDL_FULLSCREEN flag.
* (see http://sdl.beuc.net/sdl.wiki/SDL_SetVideoMode), but on Windows
* this resets the OpenGL context and video plugins don't support it yet.
* Uncomment the next line to test it: */
//return VidExt_SetVideoMode(l_pScreen->w, l_pScreen->h, l_pScreen->format->BitsPerPixel, l_Fullscreen ? M64VIDEO_WINDOWED : M64VIDEO_FULLSCREEN);
if (SDL_WM_ToggleFullScreen(l_pScreen) == 1)
{
l_Fullscreen = !l_Fullscreen;
StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED);
return M64ERR_SUCCESS;
}
return M64ERR_SYSTEM_FAIL;
}
EXPORT void * CALL VidExt_GL_GetProcAddress(const char* Proc)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncGLGetProc)(Proc);
if (!SDL_WasInit(SDL_INIT_VIDEO))
return NULL;
return SDL_GL_GetProcAddress(Proc);
}
typedef struct {
m64p_GLattr m64Attr;
SDL_GLattr sdlAttr;
} GLAttrMapNode;
static const GLAttrMapNode GLAttrMap[] = {
{ M64P_GL_DOUBLEBUFFER, SDL_GL_DOUBLEBUFFER },
{ M64P_GL_BUFFER_SIZE, SDL_GL_BUFFER_SIZE },
{ M64P_GL_DEPTH_SIZE, SDL_GL_DEPTH_SIZE },
{ M64P_GL_RED_SIZE, SDL_GL_RED_SIZE },
{ M64P_GL_GREEN_SIZE, SDL_GL_GREEN_SIZE },
{ M64P_GL_BLUE_SIZE, SDL_GL_BLUE_SIZE },
{ M64P_GL_ALPHA_SIZE, SDL_GL_ALPHA_SIZE },
#if SDL_VERSION_ATLEAST(1,3,0)
{ M64P_GL_SWAP_CONTROL, SDL_RENDERER_PRESENTVSYNC },
#else
{ M64P_GL_SWAP_CONTROL, SDL_GL_SWAP_CONTROL },
#endif
{ M64P_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLEBUFFERS },
{ M64P_GL_MULTISAMPLESAMPLES, SDL_GL_MULTISAMPLESAMPLES }};
static const int mapSize = sizeof(GLAttrMap) / sizeof(GLAttrMapNode);
EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value)
{
int i;
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncGLSetAttr)(Attr, Value);
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
for (i = 0; i < mapSize; i++)
{
if (GLAttrMap[i].m64Attr == Attr)
{
if (SDL_GL_SetAttribute(GLAttrMap[i].sdlAttr, Value) != 0)
return M64ERR_SYSTEM_FAIL;
return M64ERR_SUCCESS;
}
}
return M64ERR_INPUT_INVALID;
}
EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue)
{
int i;
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncGLGetAttr)(Attr, pValue);
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
for (i = 0; i < mapSize; i++)
{
if (GLAttrMap[i].m64Attr == Attr)
{
int NewValue = 0;
if (SDL_GL_GetAttribute(GLAttrMap[i].sdlAttr, &NewValue) != 0)
return M64ERR_SYSTEM_FAIL;
*pValue = NewValue;
return M64ERR_SUCCESS;
}
}
return M64ERR_INPUT_INVALID;
}
EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void)
{
/* call video extension override if necessary */
if (l_VideoExtensionActive)
return (*l_ExternalVideoFuncTable.VidExtFuncGLSwapBuf)();
if (!SDL_WasInit(SDL_INIT_VIDEO))
return M64ERR_NOT_INIT;
SDL_GL_SwapBuffers();
return M64ERR_SUCCESS;
}

View File

@ -0,0 +1,38 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus-core - api/vidext.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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains the definitions for the video extension functions which
* will be called from other Core modules.
*/
#if !defined(API_VIDEXT_H)
#define API_VIDEXT_H
#include "m64p_types.h"
/* global function for use by frontend.c */
extern m64p_error OverrideVideoFunctions(m64p_video_extension_functions *VideoFunctionStruct);
/* these functions are only used by the core */
extern int VidExt_InFullscreenMode(void);
extern int VidExt_VideoRunning(void);
#endif /* API_VIDEXT_H */

View File

@ -0,0 +1,802 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <SDL_surface.h>
typedef struct
{
Uint8 *src;
int src_w, src_h;
int src_pitch;
int src_skip;
Uint8 *dst;
int dst_w, dst_h;
int dst_pitch;
int dst_skip;
SDL_PixelFormat *src_fmt;
SDL_PixelFormat *dst_fmt;
Uint8 *table;
int flags;
Uint32 colorkey;
Uint8 r, g, b, a;
} SDL_BlitInfo;
/* Blit mapping definition */
typedef struct SDL_BlitMap
{
SDL_Surface *dst;
int identity;
SDL_blit blit;
void *data;
SDL_BlitInfo info;
/* the version count matches the destination; mismatch indicates
an invalid mapping */
Uint32 dst_palette_version;
Uint32 src_palette_version;
} SDL_BlitMap;
typedef struct SDL_VideoInfo
{
Uint32 hw_available:1;
Uint32 wm_available:1;
Uint32 UnusedBits1:6;
Uint32 UnusedBits2:1;
Uint32 blit_hw:1;
Uint32 blit_hw_CC:1;
Uint32 blit_hw_A:1;
Uint32 blit_sw:1;
Uint32 blit_sw_CC:1;
Uint32 blit_sw_A:1;
Uint32 blit_fill:1;
Uint32 UnusedBits3:16;
Uint32 video_mem;
SDL_PixelFormat *vfmt;
int current_w;
int current_h;
} SDL_VideoInfo;
#define SDL_ANYFORMAT 0x00100000
#define SDL_HWPALETTE 0x00200000
#define SDL_FULLSCREEN 0x00800000
#define SDL_RESIZABLE 0x01000000
#define SDL_NOFRAME 0x02000000
#define SDL_OPENGL 0x04000000
#define SDL_HWSURFACE 0x08000001 /**< \note Not used */
#define SDL_BUTTON_WHEELUP 4
#define SDL_BUTTON_WHEELDOWN 5
int initialized_video = 0;
static SDL_Window *SDL_VideoWindow = NULL;
static SDL_Surface *SDL_WindowSurface = NULL;
static SDL_Surface *SDL_VideoSurface = NULL;
static SDL_Surface *SDL_ShadowSurface = NULL;
static SDL_Surface *SDL_PublicSurface = NULL;
static SDL_Rect SDL_VideoViewport;
static char *wm_title = NULL;
static Uint32 SDL_VideoFlags = 0;
static SDL_GLContext *SDL_VideoContext = NULL;
static SDL_Surface *SDL_VideoIcon;
static void
SDL_WM_SetCaption(const char *title, const char *icon)
{
if (wm_title) {
SDL_free(wm_title);
}
if (title) {
wm_title = SDL_strdup(title);
} else {
wm_title = NULL;
}
SDL_SetWindowTitle(SDL_VideoWindow, wm_title);
}
static int
GetVideoDisplay()
{
const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
if ( !variable ) {
variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
}
if ( variable ) {
return SDL_atoi(variable);
} else {
return 0;
}
}
static const SDL_VideoInfo *
SDL_GetVideoInfo(void)
{
static SDL_VideoInfo info;
SDL_DisplayMode mode;
/* Memory leak, compatibility code, who cares? */
if (!info.vfmt && SDL_GetDesktopDisplayMode(GetVideoDisplay(), &mode) == 0) {
info.vfmt = SDL_AllocFormat(mode.format);
info.current_w = mode.w;
info.current_h = mode.h;
}
return &info;
}
static SDL_Rect **
SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags)
{
int i, nmodes;
SDL_Rect **modes;
if (!initialized_video) {
return NULL;
}
if (!(flags & SDL_FULLSCREEN)) {
return (SDL_Rect **) (-1);
}
if (!format) {
format = SDL_GetVideoInfo()->vfmt;
}
/* Memory leak, but this is a compatibility function, who cares? */
nmodes = 0;
modes = NULL;
for (i = 0; i < SDL_GetNumDisplayModes(GetVideoDisplay()); ++i) {
SDL_DisplayMode mode;
int bpp;
SDL_GetDisplayMode(GetVideoDisplay(), i, &mode);
if (!mode.w || !mode.h) {
return (SDL_Rect **) (-1);
}
/* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
bpp = SDL_BITSPERPIXEL(mode.format);
} else {
bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
}
if (bpp != format->BitsPerPixel) {
continue;
}
if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
&& modes[nmodes - 1]->h == mode.h) {
continue;
}
modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes));
if (!modes) {
return NULL;
}
modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
if (!modes[nmodes]) {
return NULL;
}
modes[nmodes]->x = 0;
modes[nmodes]->y = 0;
modes[nmodes]->w = mode.w;
modes[nmodes]->h = mode.h;
++nmodes;
}
if (modes) {
modes[nmodes] = NULL;
}
return modes;
}
static void
SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
{
int i;
if (screen == SDL_ShadowSurface) {
for (i = 0; i < numrects; ++i) {
SDL_BlitSurface(SDL_ShadowSurface, &rects[i], SDL_VideoSurface,
&rects[i]);
}
/* Fall through to video surface update */
screen = SDL_VideoSurface;
}
if (screen == SDL_VideoSurface) {
if (SDL_VideoViewport.x || SDL_VideoViewport.y) {
SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
SDL_Rect *stackrect;
const SDL_Rect *rect;
/* Offset all the rectangles before updating */
for (i = 0; i < numrects; ++i) {
rect = &rects[i];
stackrect = &stackrects[i];
stackrect->x = SDL_VideoViewport.x + rect->x;
stackrect->y = SDL_VideoViewport.y + rect->y;
stackrect->w = rect->w;
stackrect->h = rect->h;
}
SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, stackrects, numrects);
SDL_stack_free(stackrects);
} else {
SDL_UpdateWindowSurfaceRects(SDL_VideoWindow, rects, numrects);
}
}
}
static void
SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
{
if (screen) {
SDL_Rect rect;
/* Fill the rectangle */
rect.x = (int) x;
rect.y = (int) y;
rect.w = (int) (w ? w : screen->w);
rect.h = (int) (h ? h : screen->h);
SDL_UpdateRects(screen, 1, &rect);
}
}
static int
SDL_Flip(SDL_Surface * screen)
{
SDL_UpdateRect(screen, 0, 0, 0, 0);
return 0;
}
/*
* Calculate the pad-aligned scanline width of a surface
*/
static int
SDL_CalculatePitch(SDL_Surface * surface)
{
int pitch;
/* Surface should be 4-byte aligned for speed */
pitch = surface->w * surface->format->BytesPerPixel;
switch (surface->format->BitsPerPixel) {
case 1:
pitch = (pitch + 7) / 8;
break;
case 4:
pitch = (pitch + 1) / 2;
break;
default:
break;
}
pitch = (pitch + 3) & ~3; /* 4-byte aligning */
return (pitch);
}
static void
SDL_InvalidateMap(SDL_BlitMap * map)
{
if (!map) {
return;
}
if (map->dst) {
/* Release our reference to the surface - see the note below */
if (--map->dst->refcount <= 0) {
SDL_FreeSurface(map->dst);
}
}
map->dst = NULL;
map->src_palette_version = 0;
map->dst_palette_version = 0;
if (map->info.table) {
SDL_free(map->info.table);
map->info.table = NULL;
}
}
static void
SDL_GL_SwapBuffers(void)
{
SDL_GL_SwapWindow(SDL_VideoWindow);
}
static int
SDL_WM_ToggleFullScreen(SDL_Surface * surface)
{
int length;
void *pixels;
Uint8 *src, *dst;
int row;
int window_w;
int window_h;
if (!SDL_PublicSurface) {
SDL_SetError("SDL_SetVideoMode() hasn't been called");
return 0;
}
/* Copy the old bits out */
length = SDL_PublicSurface->w * SDL_PublicSurface->format->BytesPerPixel;
pixels = SDL_malloc(SDL_PublicSurface->h * length);
if (pixels && SDL_PublicSurface->pixels) {
src = (Uint8*)SDL_PublicSurface->pixels;
dst = (Uint8*)pixels;
for (row = 0; row < SDL_PublicSurface->h; ++row) {
SDL_memcpy(dst, src, length);
src += SDL_PublicSurface->pitch;
dst += length;
}
}
/* Do the physical mode switch */
if (SDL_GetWindowFlags(SDL_VideoWindow) & SDL_WINDOW_FULLSCREEN) {
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 0) < 0) {
return 0;
}
SDL_PublicSurface->flags &= ~SDL_FULLSCREEN;
} else {
if (SDL_SetWindowFullscreen(SDL_VideoWindow, 1) < 0) {
return 0;
}
SDL_PublicSurface->flags |= SDL_FULLSCREEN;
}
/* Recreate the screen surface */
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
if (!SDL_WindowSurface) {
/* We're totally hosed... */
return 0;
}
/* Center the public surface in the window surface */
SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
SDL_VideoViewport.x = (window_w - SDL_VideoSurface->w)/2;
SDL_VideoViewport.y = (window_h - SDL_VideoSurface->h)/2;
SDL_VideoViewport.w = SDL_VideoSurface->w;
SDL_VideoViewport.h = SDL_VideoSurface->h;
/* Do some shuffling behind the application's back if format changes */
if (SDL_VideoSurface->format->format != SDL_WindowSurface->format->format) {
if (SDL_ShadowSurface) {
if (SDL_ShadowSurface->format->format == SDL_WindowSurface->format->format) {
/* Whee! We don't need a shadow surface anymore! */
SDL_VideoSurface->flags &= ~SDL_DONTFREE;
SDL_FreeSurface(SDL_VideoSurface);
SDL_free(SDL_ShadowSurface->pixels);
SDL_VideoSurface = SDL_ShadowSurface;
SDL_VideoSurface->flags |= SDL_PREALLOC;
SDL_ShadowSurface = NULL;
} else {
/* No problem, just change the video surface format */
SDL_FreeFormat(SDL_VideoSurface->format);
SDL_VideoSurface->format = SDL_WindowSurface->format;
SDL_VideoSurface->format->refcount++;
SDL_InvalidateMap(SDL_ShadowSurface->map);
}
} else {
/* We can make the video surface the shadow surface */
SDL_ShadowSurface = SDL_VideoSurface;
SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
SDL_ShadowSurface->pixels = SDL_malloc(SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
if (!SDL_ShadowSurface->pixels) {
/* Uh oh, we're hosed */
SDL_ShadowSurface = NULL;
return 0;
}
SDL_ShadowSurface->flags &= ~SDL_PREALLOC;
SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
SDL_VideoSurface->flags = SDL_ShadowSurface->flags;
SDL_VideoSurface->flags |= SDL_PREALLOC;
SDL_FreeFormat(SDL_VideoSurface->format);
SDL_VideoSurface->format = SDL_WindowSurface->format;
SDL_VideoSurface->format->refcount++;
SDL_VideoSurface->w = SDL_ShadowSurface->w;
SDL_VideoSurface->h = SDL_ShadowSurface->h;
}
}
/* Update the video surface */
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
SDL_VideoViewport.y * SDL_VideoSurface->pitch +
SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
SDL_SetClipRect(SDL_VideoSurface, NULL);
/* Copy the old bits back */
if (pixels) {
src = (Uint8*)pixels;
dst = (Uint8*)SDL_PublicSurface->pixels;
for (row = 0; row < SDL_PublicSurface->h; ++row) {
SDL_memcpy(dst, src, length);
src += length;
dst += SDL_PublicSurface->pitch;
}
SDL_Flip(SDL_PublicSurface);
SDL_free(pixels);
}
/* We're done! */
return 1;
}
static void
ClearVideoSurface()
{
if (SDL_ShadowSurface) {
SDL_FillRect(SDL_ShadowSurface, NULL,
SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
}
SDL_FillRect(SDL_WindowSurface, NULL, 0);
SDL_UpdateWindowSurface(SDL_VideoWindow);
}
static int
SDL_ResizeVideoMode(int width, int height, int bpp, Uint32 flags)
{
int w, h;
/* We can't resize something we don't have... */
if (!SDL_VideoSurface) {
return -1;
}
/* We probably have to recreate the window in fullscreen mode */
if (flags & SDL_FULLSCREEN) {
return -1;
}
/* I don't think there's any change we can gracefully make in flags */
if (flags != SDL_VideoFlags) {
return -1;
}
if (bpp != SDL_VideoSurface->format->BitsPerPixel) {
return -1;
}
/* Resize the window */
SDL_GetWindowSize(SDL_VideoWindow, &w, &h);
if (w != width || h != height) {
SDL_SetWindowSize(SDL_VideoWindow, width, height);
}
/* If we're in OpenGL mode, just resize the stub surface and we're done! */
if (flags & SDL_OPENGL) {
SDL_VideoSurface->w = width;
SDL_VideoSurface->h = height;
return 0;
}
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
if (!SDL_WindowSurface) {
return -1;
}
if (SDL_VideoSurface->format != SDL_WindowSurface->format) {
return -1;
}
SDL_VideoSurface->w = width;
SDL_VideoSurface->h = height;
SDL_VideoSurface->pixels = SDL_WindowSurface->pixels;
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
SDL_SetClipRect(SDL_VideoSurface, NULL);
if (SDL_ShadowSurface) {
SDL_ShadowSurface->w = width;
SDL_ShadowSurface->h = height;
SDL_ShadowSurface->pitch = SDL_CalculatePitch(SDL_ShadowSurface);
SDL_ShadowSurface->pixels =
SDL_realloc(SDL_ShadowSurface->pixels,
SDL_ShadowSurface->h * SDL_ShadowSurface->pitch);
SDL_SetClipRect(SDL_ShadowSurface, NULL);
SDL_InvalidateMap(SDL_ShadowSurface->map);
} else {
SDL_PublicSurface = SDL_VideoSurface;
}
ClearVideoSurface();
return 0;
}
static int
SDL_CompatEventFilter(void *userdata, SDL_Event * event)
{
SDL_Event fake;
switch (event->type) {
case SDL_WINDOWEVENT:
switch (event->window.event) {
case SDL_WINDOWEVENT_CLOSE:
fake.type = SDL_QUIT;
SDL_PushEvent(&fake);
break;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
Uint32 unicode = 0;
if (event->key.type == SDL_KEYDOWN && event->key.keysym.sym < 256) {
unicode = event->key.keysym.sym;
if (unicode >= 'a' && unicode <= 'z') {
int shifted = !!(event->key.keysym.mod & KMOD_SHIFT);
int capslock = !!(event->key.keysym.mod & KMOD_CAPS);
if ((shifted ^ capslock) != 0) {
unicode = SDL_toupper(unicode);
}
}
}
if (unicode) {
event->key.keysym.unicode = unicode;
}
break;
}
case SDL_TEXTINPUT:
{
/* FIXME: Generate an old style key repeat event if needed */
//printf("TEXTINPUT: '%s'\n", event->text.text);
break;
}
case SDL_MOUSEMOTION:
{
event->motion.x -= SDL_VideoViewport.x;
event->motion.y -= SDL_VideoViewport.y;
break;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
event->button.x -= SDL_VideoViewport.x;
event->button.y -= SDL_VideoViewport.y;
break;
}
case SDL_MOUSEWHEEL:
{
Uint8 button;
int x, y;
if (event->wheel.y == 0) {
break;
}
SDL_GetMouseState(&x, &y);
if (event->wheel.y > 0) {
button = SDL_BUTTON_WHEELUP;
} else {
button = SDL_BUTTON_WHEELDOWN;
}
fake.button.button = button;
fake.button.x = x;
fake.button.y = y;
fake.button.windowID = event->wheel.windowID;
fake.type = SDL_MOUSEBUTTONDOWN;
fake.button.state = SDL_PRESSED;
SDL_PushEvent(&fake);
fake.type = SDL_MOUSEBUTTONUP;
fake.button.state = SDL_RELEASED;
SDL_PushEvent(&fake);
break;
}
}
return 1;
}
static void
GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
{
int display = GetVideoDisplay();
const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
if (window) {
if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
return;
}
if (SDL_strcmp(window, "center") == 0) {
center = window;
}
}
if (center) {
*x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
*y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
}
}
static SDL_Surface *
SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
{
SDL_DisplayMode desktop_mode;
int display = GetVideoDisplay();
int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
int window_w;
int window_h;
Uint32 window_flags;
Uint32 surface_flags;
if (!initialized_video) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
return NULL;
}
initialized_video = 1;
}
SDL_GetDesktopDisplayMode(display, &desktop_mode);
if (width == 0) {
width = desktop_mode.w;
}
if (height == 0) {
height = desktop_mode.h;
}
if (bpp == 0) {
bpp = SDL_BITSPERPIXEL(desktop_mode.format);
}
/* See if we can simply resize the existing window and surface */
if (SDL_ResizeVideoMode(width, height, bpp, flags) == 0) {
return SDL_PublicSurface;
}
/* Destroy existing window */
SDL_PublicSurface = NULL;
if (SDL_ShadowSurface) {
SDL_ShadowSurface->flags &= ~SDL_DONTFREE;
SDL_FreeSurface(SDL_ShadowSurface);
SDL_ShadowSurface = NULL;
}
if (SDL_VideoSurface) {
SDL_VideoSurface->flags &= ~SDL_DONTFREE;
SDL_FreeSurface(SDL_VideoSurface);
SDL_VideoSurface = NULL;
}
if (SDL_VideoContext) {
/* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
SDL_GL_DeleteContext(SDL_VideoContext);
SDL_VideoContext = NULL;
}
if (SDL_VideoWindow) {
SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y);
SDL_DestroyWindow(SDL_VideoWindow);
}
/* Set up the event filter */
if (!SDL_GetEventFilter(NULL, NULL)) {
SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
}
/* Create a new window */
window_flags = SDL_WINDOW_SHOWN;
if (flags & SDL_FULLSCREEN) {
window_flags |= SDL_WINDOW_FULLSCREEN;
}
if (flags & SDL_OPENGL) {
window_flags |= SDL_WINDOW_OPENGL;
}
if (flags & SDL_RESIZABLE) {
window_flags |= SDL_WINDOW_RESIZABLE;
}
if (flags & SDL_NOFRAME) {
window_flags |= SDL_WINDOW_BORDERLESS;
}
GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
SDL_VideoWindow =
SDL_CreateWindow(wm_title, window_x, window_y, width, height,
window_flags);
if (!SDL_VideoWindow) {
return NULL;
}
SDL_SetWindowIcon(SDL_VideoWindow, SDL_VideoIcon);
window_flags = SDL_GetWindowFlags(SDL_VideoWindow);
surface_flags = 0;
if (window_flags & SDL_WINDOW_FULLSCREEN) {
surface_flags |= SDL_FULLSCREEN;
}
if ((window_flags & SDL_WINDOW_OPENGL) && (flags & SDL_OPENGL)) {
surface_flags |= SDL_OPENGL;
}
if (window_flags & SDL_WINDOW_RESIZABLE) {
surface_flags |= SDL_RESIZABLE;
}
if (window_flags & SDL_WINDOW_BORDERLESS) {
surface_flags |= SDL_NOFRAME;
}
SDL_VideoFlags = flags;
/* If we're in OpenGL mode, just create a stub surface and we're done! */
if (flags & SDL_OPENGL) {
SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
if (!SDL_VideoContext) {
return NULL;
}
if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
return NULL;
}
SDL_VideoSurface =
SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
if (!SDL_VideoSurface) {
return NULL;
}
SDL_VideoSurface->flags |= surface_flags;
SDL_PublicSurface = SDL_VideoSurface;
return SDL_PublicSurface;
}
/* Create the screen surface */
SDL_WindowSurface = SDL_GetWindowSurface(SDL_VideoWindow);
if (!SDL_WindowSurface) {
return NULL;
}
/* Center the public surface in the window surface */
SDL_GetWindowSize(SDL_VideoWindow, &window_w, &window_h);
SDL_VideoViewport.x = (window_w - width)/2;
SDL_VideoViewport.y = (window_h - height)/2;
SDL_VideoViewport.w = width;
SDL_VideoViewport.h = height;
SDL_VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
SDL_VideoSurface->flags |= surface_flags;
SDL_VideoSurface->flags |= SDL_DONTFREE;
SDL_FreeFormat(SDL_VideoSurface->format);
SDL_VideoSurface->format = SDL_WindowSurface->format;
SDL_VideoSurface->format->refcount++;
SDL_VideoSurface->w = width;
SDL_VideoSurface->h = height;
SDL_VideoSurface->pitch = SDL_WindowSurface->pitch;
SDL_VideoSurface->pixels = (void *)((Uint8 *)SDL_WindowSurface->pixels +
SDL_VideoViewport.y * SDL_VideoSurface->pitch +
SDL_VideoViewport.x * SDL_VideoSurface->format->BytesPerPixel);
SDL_SetClipRect(SDL_VideoSurface, NULL);
/* Create a shadow surface if necessary */
if ((bpp != SDL_VideoSurface->format->BitsPerPixel)
&& !(flags & SDL_ANYFORMAT)) {
SDL_ShadowSurface =
SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
if (!SDL_ShadowSurface) {
return NULL;
}
SDL_ShadowSurface->flags |= surface_flags;
SDL_ShadowSurface->flags |= SDL_DONTFREE;
/* 8-bit SDL_ShadowSurface surfaces report that they have exclusive palette */
if (SDL_ShadowSurface->format->palette) {
SDL_ShadowSurface->flags |= SDL_HWPALETTE;
//TODO SDL_DitherColors(SDL_ShadowSurface->format->palette->colors,
// SDL_ShadowSurface->format->BitsPerPixel);
}
SDL_FillRect(SDL_ShadowSurface, NULL,
SDL_MapRGB(SDL_ShadowSurface->format, 0, 0, 0));
}
SDL_PublicSurface =
(SDL_ShadowSurface ? SDL_ShadowSurface : SDL_VideoSurface);
ClearVideoSurface();
/* We're finally done! */
return SDL_PublicSurface;
}

View File

@ -0,0 +1,217 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dbg_breakpoints.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 DarkJeztr HyperHacker *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <SDL.h>
#include <SDL_thread.h>
#include "dbg_types.h"
#include "debugger.h"
#include "dbg_breakpoints.h"
#include "dbg_memory.h"
#include "api/m64p_types.h"
#include "api/callbacks.h"
int g_NumBreakpoints=0;
breakpoint g_Breakpoints[BREAKPOINTS_MAX_NUMBER];
int add_breakpoint( uint32 address )
{
if( g_NumBreakpoints == BREAKPOINTS_MAX_NUMBER ) {
DebugMessage(M64MSG_ERROR, "BREAKPOINTS_MAX_NUMBER have been reached.");
return -1;
}
g_Breakpoints[g_NumBreakpoints].address=address;
g_Breakpoints[g_NumBreakpoints].endaddr=address;
BPT_SET_FLAG(g_Breakpoints[g_NumBreakpoints], BPT_FLAG_EXEC);
enable_breakpoint(g_NumBreakpoints);
return g_NumBreakpoints++;
}
int add_breakpoint_struct(breakpoint* newbp)
{
if( g_NumBreakpoints == BREAKPOINTS_MAX_NUMBER ) {
DebugMessage(M64MSG_ERROR, "BREAKPOINTS_MAX_NUMBER have been reached.");
return -1;
}
memcpy(&g_Breakpoints[g_NumBreakpoints], newbp, sizeof(breakpoint));
if(BPT_CHECK_FLAG(g_Breakpoints[g_NumBreakpoints], BPT_FLAG_ENABLED))
{
BPT_CLEAR_FLAG(g_Breakpoints[g_NumBreakpoints], BPT_FLAG_ENABLED);
enable_breakpoint( g_NumBreakpoints );
}
return g_NumBreakpoints++;
}
void enable_breakpoint( int bpt)
{
breakpoint *curBpt = g_Breakpoints + bpt;
uint64 bptAddr;
if(BPT_CHECK_FLAG((*curBpt), BPT_FLAG_READ)) {
for(bptAddr = curBpt->address; bptAddr <= (curBpt->endaddr | 0xFFFF); bptAddr+=0x10000)
if(lookup_breakpoint((uint32) bptAddr & 0xFFFF0000, 0x10000, BPT_FLAG_ENABLED | BPT_FLAG_READ) == -1)
activate_memory_break_read((uint32) bptAddr);
}
if(BPT_CHECK_FLAG((*curBpt), BPT_FLAG_WRITE)) {
for(bptAddr = curBpt->address; bptAddr <= (curBpt->endaddr | 0xFFFF); bptAddr+=0x10000)
if(lookup_breakpoint((uint32) bptAddr & 0xFFFF0000, 0x10000, BPT_FLAG_ENABLED | BPT_FLAG_WRITE) == -1)
activate_memory_break_write((uint32) bptAddr);
}
BPT_SET_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED);
}
void disable_breakpoint( int bpt )
{
breakpoint *curBpt = g_Breakpoints + bpt;
uint64 bptAddr;
BPT_CLEAR_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED);
if(BPT_CHECK_FLAG((*curBpt), BPT_FLAG_READ)) {
for(bptAddr = curBpt->address; bptAddr <= ((unsigned long)(curBpt->endaddr | 0xFFFF)); bptAddr+=0x10000)
if(lookup_breakpoint((uint32) bptAddr & 0xFFFF0000, 0x10000, BPT_FLAG_ENABLED | BPT_FLAG_READ) == -1)
deactivate_memory_break_read((uint32) bptAddr);
}
if(BPT_CHECK_FLAG((*curBpt), BPT_FLAG_WRITE)) {
for(bptAddr = curBpt->address; bptAddr <= ((unsigned long)(curBpt->endaddr | 0xFFFF)); bptAddr+=0x10000)
if(lookup_breakpoint((uint32) bptAddr & 0xFFFF0000, 0x10000, BPT_FLAG_ENABLED | BPT_FLAG_WRITE) == -1)
deactivate_memory_break_write((uint32) bptAddr);
}
BPT_CLEAR_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED);
}
void remove_breakpoint_by_num( int bpt )
{
int curBpt;
if(BPT_CHECK_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED))
disable_breakpoint( bpt );
for(curBpt=bpt+1; curBpt<g_NumBreakpoints; curBpt++)
g_Breakpoints[curBpt-1]=g_Breakpoints[curBpt];
g_NumBreakpoints--;
}
void remove_breakpoint_by_address( uint32 address )
{
int bpt = lookup_breakpoint( address, 1, 0 );
if(bpt==-1)
{
DebugMessage(M64MSG_ERROR, "Tried to remove Nonexistant breakpoint %x!", address);
}
else
remove_breakpoint_by_num( bpt );
}
void replace_breakpoint_num( int bpt, breakpoint* copyofnew )
{
if(BPT_CHECK_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED))
disable_breakpoint( bpt );
memcpy(&(g_Breakpoints[bpt]), copyofnew, sizeof(breakpoint));
if(BPT_CHECK_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED))
{
BPT_CLEAR_FLAG(g_Breakpoints[bpt], BPT_FLAG_ENABLED);
enable_breakpoint( bpt );
}
}
int lookup_breakpoint( uint32 address, uint32 size, uint32 flags)
{
int i;
uint64 endaddr = ((uint64)address) + ((uint64)size) - 1;
for( i=0; i < g_NumBreakpoints; i++)
{
if((g_Breakpoints[i].flags & flags) == flags)
{
if(g_Breakpoints[i].endaddr < g_Breakpoints[i].address)
{
if((endaddr >= g_Breakpoints[i].address) ||
(address <= g_Breakpoints[i].endaddr))
return i;
}
else // endaddr >= address
{
if((endaddr >= g_Breakpoints[i].address) &&
(address <= g_Breakpoints[i].endaddr))
return i;
}
}
}
return -1;
}
int check_breakpoints( uint32 address )
{
return lookup_breakpoint( address, 1, BPT_FLAG_ENABLED | BPT_FLAG_EXEC );
}
int check_breakpoints_on_mem_access( uint32 pc, uint32 address, uint32 size, uint32 flags )
{
//This function handles memory read/write breakpoints. size specifies the address
//range to check, flags specifies the flags that all need to be set.
//It automatically stops and updates the debugger on hit, so the memory access
//functions only need to call it and can discard the result.
int bpt;
if(run == 2)
{
bpt=lookup_breakpoint( address, size, flags );
if(bpt != -1)
{
if(BPT_CHECK_FLAG(g_Breakpoints[bpt], BPT_FLAG_LOG))
log_breakpoint(pc, flags, address);
run = 0;
update_debugger(pc);
return bpt;
}
}
return -1;
}
int log_breakpoint(uint32 PC, uint32 Flag, uint32 Access)
{
char msg[32];
if(Flag & BPT_FLAG_READ) sprintf(msg, "0x%08X read 0x%08X", PC, Access);
else if(Flag & BPT_FLAG_WRITE) sprintf(msg, "0x%08X wrote 0x%08X", PC, Access);
else sprintf(msg, "0x%08X executed", PC);
DebugMessage(M64MSG_INFO, "BPT: %s", msg);
return 0;
}

View File

@ -0,0 +1,43 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dbg_breakpoints.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 DarkJeztr HyperHacker *
* *
* 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 __BREAKPOINTS_H__
#define __BREAKPOINTS_H__
#include "../api/m64p_types.h"
extern int g_NumBreakpoints;
extern breakpoint g_Breakpoints[];
int add_breakpoint( uint32 address );
int add_breakpoint_struct(breakpoint* newbp);
void remove_breakpoint_by_address( uint32 address );
void remove_breakpoint_by_num( int bpt );
void enable_breakpoint( int breakpoint );
void disable_breakpoint( int breakpoint );
int check_breakpoints( uint32 address );
int check_breakpoints_on_mem_access( uint32 pc, uint32 address, uint32 size, uint32 flags );
int lookup_breakpoint( uint32 address, uint32 size, uint32 flags );
int log_breakpoint(uint32 PC, uint32 Flag, uint32 Access);
void replace_breakpoint_num( int, breakpoint* );
#endif /* __BREAKPOINTS_H__ */

View File

@ -0,0 +1,822 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus -- dbg_decoder.c *
* Copyright (c) 2010 Marshall B. Rogers <mbr@64.vg> *
* http://64.vg/ *
* *
* 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 is a heavily modified reentrant version of the MIPS disassembler found
* in the NetBSD operating system. I chose to use this as a base due to the
* small, compact, and easily manageable code.
*
* Original copyright/license information is contained below.
*/
/* $NetBSD: db_disasm.c,v 1.21 2009/12/14 00:46:06 matt Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#ifndef MIPS32
#define MIPS32
#endif
#include "dbg_decoder.h"
#include "dbg_decoder_local.h"
#include "osal/preproc.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Data types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
typedef uint32_t db_addr_t;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Local variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
static const char * const r4k_str_op_name[64] =
{
/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
};
static const char * const r4k_str_spec_name[64] =
{
/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync",
/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
};
static const char * const r4k_str_spec2_name[4] = /* QED RM4650, R5000, etc. */
{
/* 0 */ "mad", "madu", "mul", "spec3"
};
static const char * const r4k_str_bcond_name[32] =
{
/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
};
static const char * const r4k_str_cop1_name[64] =
{
/* 0 */ "add", "sub", "mul", "div", "sqrt","abs", "mov", "neg",
/* 8 */ "fop08", "trunc.l","fop0a","fop0b","fop0c","trunc.w","fop0e","fop0f",
/*16 */ "fop10", "fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18", "fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "cvt.s", "cvt.d","fop22","fop23","cvt.w","cvt.l","fop26","fop27",
/*40 */ "fop28", "fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "c.f", "c.un","c.eq","c.ueq","c.olt","c.ult",
"c.ole", "c.ule",
/*56 */ "c.sf", "c.ngle","c.seq","c.ngl","c.lt","c.nge",
"c.le", "c.ngt"
};
static const char * const r4k_str_fmt_name[16] =
{
"s", "d", "e", "fmt3",
"w", "l", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
static const char * const r4k_str_reg_name[32] =
{
"$zero", "$at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "$gp", "$sp", "s8", "$ra"
};
static const char * const r4k_str_c0_opname[64] =
{
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
"eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
};
static const char * const r4k_str_c0_reg[32] =
{
"C0_INX", "C0_RAND", "C0_ENTRYLO0", "C0_ENTRYLO1",
"C0_CONTEXT", "C0_PAGEMASK", "C0_WIRED", "cp0r7",
"C0_BADVADDR", "C0_COUNT", "C0_ENTRYHI", "C0_COMPARE",
"C0_SR", "C0_CAUSE", "C0_EPC", "C0_PRID",
"C0_CONFIG", "C0_LLADDR", "C0_WATCHLO", "C0_WATCHHI",
"xcontext", "cp0r21", "cp0r22", "debug",
"depc", "perfcnt", "C0_ECC", "C0_CACHE_ERR",
"C0_TAGLO", "C0_TAGHI", "C0_ERROR_EPC", "desave"
};
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Local functions - lookup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Look up a symbol */
static char *
lookup_sym ( struct r4k_dis_t * state,
uint32_t address )
{
if( state->lookup_sym )
return state->lookup_sym( address, state->lookup_sym_d );
return NULL;
}
/* Look up an upper 16-bits relocation */
static char *
lookup_rel_hi16 ( struct r4k_dis_t * state,
uint32_t address )
{
if( state->lookup_rel_hi16 )
return state->lookup_rel_hi16( address, state->lookup_rel_hi16_d );
return NULL;
}
/* Look up a lower 16-bits relocation */
static char *
lookup_rel_lo16 ( struct r4k_dis_t * state,
uint32_t address )
{
if( state->lookup_rel_lo16 )
return state->lookup_rel_lo16( address, state->lookup_rel_lo16_d );
return NULL;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Local functions - disassembler
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Print text into the destination buffer */
static int
db_printf ( struct r4k_dis_t * state,
char * fmt,
... )
{
int l;
va_list ap;
char buffer[1024];
/* Prepare user provided */
va_start( ap, fmt );
l = vsnprintf( buffer, sizeof(buffer), fmt, ap );
va_end( ap );
/* Add it to our string */
state->dest += sprintf(
state->dest,
"%s",
buffer
);
state->length += l;
return l;
}
/* Print an address to a string. If there's a symbol, the name will be printed */
static int
print_addr ( struct r4k_dis_t * state,
uint32_t address )
{
int len;
char * sym;
/* Try to lookup symbol */
if( (sym = lookup_sym(state, address)) )
{
len = db_printf( state, "%s", sym );
}
else
{
len = db_printf( state, "0x%08X", address );
}
return len;
}
/* Disassemble an instruction */
static db_addr_t
db_disasm_insn ( struct r4k_dis_t * state,
int insn,
db_addr_t loc,
bool altfmt )
{
char * rel;
InstFmt i;
i.word = insn;
switch (i.JType.op) {
case OP_SPECIAL:
if (i.word == 0) {
db_printf(state, "nop");
break;
}
/* XXX
* "addu" is a "move" only in 32-bit mode. What's the correct
* answer - never decode addu/daddu as "move"?
*/
if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
db_printf(state, "%-16s%s,%s",
"move",
r4k_str_reg_name[i.RType.rd],
r4k_str_reg_name[i.RType.rs]);
break;
}
db_printf(state, "%-16s", r4k_str_spec_name[i.RType.func]);
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
case OP_SRA:
case OP_DSLL:
case OP_DSRL:
case OP_DSRA:
case OP_DSLL32:
case OP_DSRL32:
case OP_DSRA32:
db_printf(state, "%s,%s,%d",
r4k_str_reg_name[i.RType.rd],
r4k_str_reg_name[i.RType.rt],
i.RType.shamt);
break;
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf(state, "%s,%s,%s",
r4k_str_reg_name[i.RType.rd],
r4k_str_reg_name[i.RType.rt],
r4k_str_reg_name[i.RType.rs]);
break;
case OP_MFHI:
case OP_MFLO:
db_printf(state, "%s", r4k_str_reg_name[i.RType.rd]);
break;
case OP_JR:
case OP_JALR:
db_printf(state, "%s", r4k_str_reg_name[i.RType.rs]);
break;
case OP_MTLO:
case OP_MTHI:
db_printf(state, "%s", r4k_str_reg_name[i.RType.rs]);
break;
case OP_MULT:
case OP_MULTU:
case OP_DMULT:
case OP_DMULTU:
db_printf(state, "%s,%s",
r4k_str_reg_name[i.RType.rs],
r4k_str_reg_name[i.RType.rt]);
break;
case OP_DIV:
case OP_DIVU:
case OP_DDIV:
case OP_DDIVU:
db_printf(state, "$zero,%s,%s",
r4k_str_reg_name[i.RType.rs],
r4k_str_reg_name[i.RType.rt]);
break;
case OP_SYSCALL:
case OP_SYNC:
break;
case OP_BREAK:
db_printf(state, "%d", (i.RType.rs << 5) | i.RType.rt);
break;
default:
db_printf(state, "%s,%s,%s",
r4k_str_reg_name[i.RType.rd],
r4k_str_reg_name[i.RType.rs],
r4k_str_reg_name[i.RType.rt]);
}
break;
case OP_SPECIAL2:
if (i.RType.func == OP_MUL)
db_printf(state, "%s\t%s,%s,%s",
r4k_str_spec2_name[i.RType.func & 0x3],
r4k_str_reg_name[i.RType.rd],
r4k_str_reg_name[i.RType.rs],
r4k_str_reg_name[i.RType.rt]);
else
db_printf(state, "%s\t%s,%s",
r4k_str_spec2_name[i.RType.func & 0x3],
r4k_str_reg_name[i.RType.rs],
r4k_str_reg_name[i.RType.rt]);
break;
case OP_BCOND:
db_printf(state, "%-16s%s,", r4k_str_bcond_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs]);
goto pr_displ;
case OP_BLEZ:
case OP_BLEZL:
case OP_BGTZ:
case OP_BGTZL:
db_printf(state, "%-16s%s,", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rs]);
goto pr_displ;
case OP_BEQ:
case OP_BEQL:
if (i.IType.rs == 0 && i.IType.rt == 0) {
db_printf(state, "%-16s", "b");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
case OP_BNEL:
db_printf(state, "%-16s%s,%s,", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rs],
r4k_str_reg_name[i.IType.rt]);
pr_displ:
print_addr( state, loc + 4 + ((short)i.IType.imm << 2) );
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf(state, "bc0%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf(state, "%-16s%s,%s",
"mtc0",
r4k_str_reg_name[i.RType.rt],
r4k_str_c0_reg[i.RType.rd]);
break;
case OP_DMT:
db_printf(state, "%-16s%s,%s",
"dmtc0",
r4k_str_reg_name[i.RType.rt],
r4k_str_c0_reg[i.RType.rd]);
break;
case OP_MF:
db_printf(state, "%-16s%s,%s", "mfc0",
r4k_str_reg_name[i.RType.rt],
r4k_str_c0_reg[i.RType.rd]);
break;
case OP_DMF:
db_printf(state, "%-16s%s,%s","dmfc0",
r4k_str_reg_name[i.RType.rt],
r4k_str_c0_reg[i.RType.rd]);
break;
default:
db_printf(state, "%s", r4k_str_c0_opname[i.FRType.func]);
}
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf(state, "bc1%c%s\t\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK],
(insn >> 16 & 0x1F) == 2 || (insn >> 16 & 0x1F) == 3 ? "l" : "");
goto pr_displ;
case OP_MT:
db_printf(state, "mtc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MF:
db_printf(state, "mfc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CT:
db_printf(state, "ctc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CF:
db_printf(state, "cfc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_DMT:
db_printf(state, "dmtc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_DMF:
db_printf(state, "dmfc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MTH:
db_printf(state, "mthc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MFH:
db_printf(state, "mfhc1\t\t%s,$f%d",
r4k_str_reg_name[i.RType.rt],
i.RType.rd);
break;
default:
if( i.FRType.func == 0x21 || i.FRType.func == 0x20 || i.FRType.func == 0x24 || i.FRType.func == 0x25 ||
i.FRType.func == 7 || i.FRType.func == 6 || i.FRType.func == 0xd ||
i.FRType.func == 4 || i.FRType.func == 5 || i.FRType.func == 9 )
{/*NEG.fmt fd, fs*/
db_printf(state, "%s.%s\t\t$f%d,$f%d",
r4k_str_cop1_name[i.FRType.func],
r4k_str_fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs);
}
else if( i.FRType.func != 1 && i.FRType.func != 2 && (insn & 0x3F) && !(insn >> 6 & 0x1F) ) /* C */
{
db_printf(state, "%s.%s\t\t$f%d,$f%d",
r4k_str_cop1_name[i.FRType.func],
r4k_str_fmt_name[i.FRType.fmt],
i.FRType.fs, i.FRType.ft);
}
else
{
db_printf(state, "%s.%s\t\t$f%d,$f%d,$f%d",
r4k_str_cop1_name[i.FRType.func],
r4k_str_fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs, i.FRType.ft);
}
}
break;
case OP_J:
case OP_JAL:
db_printf(state, "%-16s", r4k_str_op_name[i.JType.op]);
print_addr(state, (loc & 0xF0000000) | (i.JType.target << 2));
break;
case OP_LDC1:
case OP_LWC1:
case OP_SWC1:
case OP_SDC1:
db_printf(state, "%-16s$f%d,", r4k_str_op_name[i.IType.op],
i.IType.rt);
goto loadstore;
case OP_LB:
case OP_LH:
case OP_LW:
case OP_LWL:
case OP_LWR:
case OP_LD:
case OP_LBU:
case OP_LHU:
case OP_LWU:
case OP_SB:
case OP_SH:
case OP_SW:
case OP_SWL:
case OP_SWR:
case OP_SD:
db_printf(state, "%-16s%s,", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt]);
loadstore:
/* Part of a relocation? */
if( (rel = lookup_rel_lo16(state, loc)) )
{
/* Yes. */
db_printf(state,
"%%lo(%s)(%s)",
rel,
r4k_str_reg_name[i.IType.rs]
);
break;
}
db_printf(state, "%d(%s)", (short)i.IType.imm,
r4k_str_reg_name[i.IType.rs]);
break;
case OP_ORI:
case OP_XORI:
if( i.IType.op == OP_ORI )
{
/* Part of a relocation? */
if( (rel = lookup_rel_lo16(state, loc)) )
{
/* Yes. */
db_printf(state,
"%-16s%s,%s,%%lo(%s)",
r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs],
rel
);
break;
}
else
{
db_printf(state, "%-16s%s,%s,0x%x", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs],
i.IType.imm);
break;
}
}
else
if (i.IType.rs == 0) {
db_printf(state, "%-16s%s,0x%x",
"li",
r4k_str_reg_name[i.IType.rt],
i.IType.imm);
break;
}
/* FALLTHROUGH */
case OP_ANDI:
db_printf(state, "%-16s%s,%s,0x%x", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs],
i.IType.imm);
break;
case OP_LUI:
{
/* Part of a relocation? */
if( (rel = lookup_rel_hi16(state, loc)) )
{
/* Yes. */
db_printf(state,
"%-16s%s,%%hi(%s)",
r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
rel
);
}
else
{
db_printf(state, "%-16s%s,0x%x", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
i.IType.imm);
}
}
break;
case OP_CACHE:
db_printf(state, "%-16s0x%x,0x%x(%s)",
r4k_str_op_name[i.IType.op],
i.IType.rt,
i.IType.imm,
r4k_str_reg_name[i.IType.rs]);
break;
case OP_ADDI:
case OP_DADDI:
case OP_ADDIU:
case OP_DADDIU:
{
/* Part of a relocation? */
if( (rel = lookup_rel_lo16(state, loc)) )
{
/* Yes. */
db_printf(state,
"%-16s%s,%s,%%lo(%s)",
r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs],
rel
);
break;
}
if (i.IType.rs == 0) {
db_printf(state, "%-16s%s,%d", "li",
r4k_str_reg_name[i.IType.rt],
(short)i.IType.imm);
break;
}
/* FALLTHROUGH */
default:
db_printf(state, "%-16s%s,%s,%d", r4k_str_op_name[i.IType.op],
r4k_str_reg_name[i.IType.rt],
r4k_str_reg_name[i.IType.rs],
(short)i.IType.imm);
} }
/*db_printf(state, "\n");*/
return (loc + 4);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Global functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Disassemble an instruction with state */
static int
r4k_disassemble ( struct r4k_dis_t * state,
uint32_t instruction,
uint32_t location,
char * dest )
{
state->dest = dest;
db_disasm_insn( state, instruction, location, 0 );
return state->length;
}
/* Disassemble an instruction but split the opcode/operands into two char *'s */
static int
r4k_disassemble_split ( struct r4k_dis_t * state,
uint32_t instruction,
uint32_t location,
char ** opcode,
char ** operands )
{
int v, i;
char buff[128], * dupd;
v = r4k_disassemble(
state,
instruction,
location,
buff
);
dupd = strdup( buff );
*opcode = &dupd[0];
for( i = 0; buff[i] && buff[i] != ' '; i++ );
dupd[i] = '\0';
for( ; buff[i] && buff[i] == ' '; i++ );
*operands = &dupd[i];
return v;
}
/* Disassemble an instruction with a blank state but split op/operands */
static int
r4k_disassemble_split_quick ( uint32_t instruction,
uint32_t location,
char ** opcode,
char ** operands )
{
struct r4k_dis_t state;
/* Init state */
memset( &state, 0, sizeof(state) );
/* Perform */
return r4k_disassemble_split(
&state,
instruction,
location,
opcode,
operands
);
}
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[ DECODE_OP ]=-=-=-=-=-=-=-=-=-=-=-=-=-=-=[//
void r4300_decode_op ( uint32 instr, char * opcode, char * arguments, int counter )
{
char * _op, * _args;
_op = NULL;
_args = NULL;
r4k_disassemble_split_quick(
instr,
counter,
&_op,
&_args
);
strcpy( opcode, _op );
strcpy( arguments, _args );
free( _op );
}

View File

@ -0,0 +1,61 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dbg_decoder.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2010 Marshall B. Rogers <mbr@64.vg> *
* *
* 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 __DECODER_H__
#define __DECODER_H__
#include "dbg_types.h"
#if defined(WIN32)
typedef unsigned int uint32_t;
typedef unsigned char bool;
#define false 0
#define true 1
#else
#include <stdint.h>
#include <stdbool.h>
#endif
/* Disassembler lookup handler */
typedef char * (*r4k_lookup_func)(uint32_t, void *);
/* Disassembler state */
typedef
struct r4k_dis_t
{
r4k_lookup_func lookup_sym;
void * lookup_sym_d;
r4k_lookup_func lookup_rel_hi16;
void * lookup_rel_hi16_d;
r4k_lookup_func lookup_rel_lo16;
void * lookup_rel_lo16_d;
/* Private */
char * dest;
int length;
}
R4kDis;
extern void r4300_decode_op ( uint32, char *, char *, int );
#endif /* __DECODER_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dbg_memory.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 DarkJeztr *
* Copyright (C) 2002 davFr *
* *
* 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 __DEBUGGER_MEMORY_H__
#define __DEBUGGER_MEMORY_H__
#define MAX_DISASSEMBLY 64
/* The following three macros create all the function calls for catching memory breakpoints
* these do not occur until after the PC is incremented, but jumps & branches are not yet taken.
*/
#define MEMBREAKREAD(name,size) \
void name##_break(void) { \
check_breakpoints_on_mem_access((PC->addr)-0x4, address, size, BPT_FLAG_ENABLED | BPT_FLAG_READ); \
name (); \
}
#define MEMBREAKWRITE(name,size) \
void name##_break(void) { \
check_breakpoints_on_mem_access((PC->addr)-0x4, address, size, BPT_FLAG_ENABLED | BPT_FLAG_WRITE); \
name (); \
}
#define MEMBREAKALL(name) \
MEMBREAKREAD( read_##name , 4); \
MEMBREAKREAD( read_##name##b , 1); \
MEMBREAKREAD( read_##name##h , 2); \
MEMBREAKREAD( read_##name##d , 8); \
MEMBREAKWRITE( write_##name , 4); \
MEMBREAKWRITE( write_##name##b , 1); \
MEMBREAKWRITE( write_##name##h , 2); \
MEMBREAKWRITE( write_##name##d , 8);
#define MEMBREAKALL_local(name) \
static MEMBREAKREAD( read_##name , 4); \
static MEMBREAKREAD( read_##name##b , 1); \
static MEMBREAKREAD( read_##name##h , 2); \
static MEMBREAKREAD( read_##name##d , 8); \
static MEMBREAKWRITE( write_##name , 4); \
static MEMBREAKWRITE( write_##name##b , 1); \
static MEMBREAKWRITE( write_##name##h , 2); \
static MEMBREAKWRITE( write_##name##d , 8);
void init_host_disassembler(void);
char* get_recompiled_opcode( uint32 address, int index );
char* get_recompiled_args( uint32 address, int index );
void* get_recompiled_addr( uint32 address, int index );
int get_num_recompiled( uint32 address );
int get_has_recompiled( uint32 address );
uint64 read_memory_64(uint32 addr);
uint64 read_memory_64_unaligned(uint32 addr);
void write_memory_64(uint32 addr, uint64 value);
void write_memory_64_unaligned(uint32 addr, uint64 value);
uint32 read_memory_32(uint32);
uint32 read_memory_32_unaligned(uint32 addr);
void write_memory_32(uint32, uint32);
void write_memory_32_unaligned(uint32 addr, uint32 value);
uint16 read_memory_16(uint32 addr);
void write_memory_16(uint32 addr, uint16 value);
uint8 read_memory_8(uint32 addr);
void write_memory_8(uint32 addr, uint8 value);
uint32 get_memory_flags(uint32);
int get_memory_type(uint32);
void activate_memory_break_read(uint32 addr);
void deactivate_memory_break_read(uint32 addr);
void activate_memory_break_write(uint32 addr);
void deactivate_memory_break_write(uint32 addr);
/* Following are the prototypes for the memory breakpoint functions */
void read_rdram_break(void);
void read_rdramb_break(void);
void read_rdramh_break(void);
void read_rdramd_break(void);
void read_rdramFB_break(void);
void read_rdramFBb_break(void);
void read_rdramFBh_break(void);
void read_rdramFBd_break(void);
void write_rdram_break(void);
void write_rdramb_break(void);
void write_rdramh_break(void);
void write_rdramd_break(void);
void write_rdramFB_break(void);
void write_rdramFBb_break(void);
void write_rdramFBh_break(void);
void write_rdramFBd_break(void);
#endif /* __DEBUGGER_MEMORY_H__ */

View File

@ -0,0 +1,31 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dbg_types.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2002 davFr *
* *
* 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 __TYPES_H__
#define __TYPES_H__
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
#endif /* __TYPES_H__ */

View File

@ -0,0 +1,104 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - debugger.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 DarkJeztr *
* Copyright (C) 2002 davFr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <SDL.h>
#include "api/debugger.h"
#include "dbg_types.h"
#include "debugger.h"
#include "dbg_breakpoints.h"
#include "dbg_memory.h"
// State of the Emulation Thread:
// 0 -> pause, 2 -> run.
int g_DebuggerActive = 0; // whether the debugger is enabled or not
int run;
static SDL_cond *debugger_done_cond;
static SDL_mutex *mutex;
uint32 previousPC;
//]=-=-=-=-=-=-=-=-=-=-=[ Initialisation du Debugger ]=-=-=-=-=-=-=-=-=-=-=-=[
void init_debugger()
{
g_DebuggerActive = 1;
run = 0;
DebuggerCallback(DEBUG_UI_INIT, 0); /* call front-end to initialize user interface */
init_host_disassembler();
mutex = SDL_CreateMutex();
debugger_done_cond = SDL_CreateCond();
}
void destroy_debugger()
{
SDL_DestroyMutex(mutex);
mutex = NULL;
SDL_DestroyCond(debugger_done_cond);
debugger_done_cond = NULL;
g_DebuggerActive = 0;
}
//]=-=-=-=-=-=-=-=-=-=-=-=-=[ Mise-a-Jour Debugger ]=-=-=-=-=-=-=-=-=-=-=-=-=[
void update_debugger(uint32 pc)
// Update debugger state and display.
// Should be called after each R4300 instruction
// Checks for breakpoint hits on PC
{
int bpt;
if(run!=0) {//check if we hit a breakpoint
bpt = check_breakpoints(pc);
if( bpt!=-1 ) {
run = 0;
if(BPT_CHECK_FLAG(g_Breakpoints[bpt], BPT_FLAG_LOG))
log_breakpoint(pc, BPT_FLAG_EXEC, 0);
}
}
if(run!=2) {
DebuggerCallback(DEBUG_UI_UPDATE, pc); /* call front-end to notify user interface to update */
}
if(run==0) {
// Emulation thread is blocked until a button is clicked.
SDL_mutexP(mutex);
SDL_CondWait(debugger_done_cond, mutex);
SDL_mutexV(mutex);
}
previousPC = pc;
}
void debugger_step()
{
SDL_CondSignal(debugger_done_cond);
}

View File

@ -0,0 +1,40 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - debugger.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 DarkJeztr *
* Copyright (C) 2002 davFr *
* *
* 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 __DEBUGGER_H__
#define __DEBUGGER_H__
extern int g_DebuggerActive; /* True if the debugger is running */
/* State of the Emulation Thread:
0 -> pause, 1 -> step, 2 -> run. */
extern int run;
extern uint32 previousPC;
void init_debugger(void);
void update_debugger(uint32 pc);
void destroy_debugger(void);
void debugger_step(void);
#endif /* __DEBUGGER_H__ */

View File

@ -0,0 +1,457 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - cheat.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2009 Richard Goedeken *
* Copyright (C) 2008 Okaygo *
* *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html
#include <SDL.h>
#include <SDL_thread.h>
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "api/config.h"
#include "memory/memory.h"
#include "osal/preproc.h"
#include "cheat.h"
#include "main.h"
#include "rom.h"
#include "eventloop.h"
#include "list.h"
#include <stdio.h>
#include <string.h>
// local definitions
#define CHEAT_CODE_MAGIC_VALUE 0xDEAD0000
typedef struct cheat_code {
unsigned int address;
int value;
int old_value;
struct list_head list;
} cheat_code_t;
typedef struct cheat {
char *name;
int enabled;
int was_enabled;
struct list_head cheat_codes;
struct list_head list;
} cheat_t;
// local variables
static LIST_HEAD(active_cheats);
static SDL_mutex *cheat_mutex = NULL;
// private functions
static unsigned short read_address_16bit(unsigned int address)
{
return *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
}
static unsigned char read_address_8bit(unsigned int address)
{
return *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
}
static void update_address_16bit(unsigned int address, unsigned short new_value)
{
*(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16))) = new_value;
}
static void update_address_8bit(unsigned int address, unsigned char new_value)
{
*(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8))) = new_value;
}
static int address_equal_to_8bit(unsigned int address, unsigned char value)
{
unsigned char value_read;
value_read = *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
return value_read == value;
}
static int address_equal_to_16bit(unsigned int address, unsigned short value)
{
unsigned short value_read;
value_read = *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
return value_read == value;
}
// individual application - returns 0 if we are supposed to skip the next cheat
// (only really used on conditional codes)
static int execute_cheat(unsigned int address, unsigned short value, int *old_value)
{
switch (address & 0xFF000000)
{
case 0x80000000:
case 0x88000000:
case 0xA0000000:
case 0xA8000000:
case 0xF0000000:
// if pointer to old value is valid and uninitialized, write current value to it
if(old_value && (*old_value == CHEAT_CODE_MAGIC_VALUE))
*old_value = (int) read_address_8bit(address);
update_address_8bit(address,(unsigned char) value);
return 1;
case 0x81000000:
case 0x89000000:
case 0xA1000000:
case 0xA9000000:
case 0xF1000000:
// if pointer to old value is valid and uninitialized, write current value to it
if(old_value && (*old_value == CHEAT_CODE_MAGIC_VALUE))
*old_value = (int) read_address_16bit(address);
update_address_16bit(address,value);
return 1;
case 0xD0000000:
case 0xD8000000:
return address_equal_to_8bit(address,(unsigned char) value);
case 0xD1000000:
case 0xD9000000:
return address_equal_to_16bit(address,value);
case 0xD2000000:
case 0xDB000000:
return !(address_equal_to_8bit(address,(unsigned char) value));
case 0xD3000000:
case 0xDA000000:
return !(address_equal_to_16bit(address,value));
case 0xEE000000:
// most likely, this doesnt do anything.
execute_cheat(0xF1000318, 0x0040, NULL);
execute_cheat(0xF100031A, 0x0000, NULL);
return 1;
default:
return 1;
}
}
static cheat_t *find_or_create_cheat(const char *name)
{
cheat_t *cheat;
int found = 0;
list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
if (strcmp(cheat->name, name) == 0) {
found = 1;
break;
}
}
if (found)
{
/* delete any pre-existing cheat codes */
cheat_code_t *code, *safe;
list_for_each_entry_safe(code, safe, &cheat->cheat_codes, cheat_code_t, list) {
list_del(&code->list);
free(code);
}
cheat->enabled = 0;
cheat->was_enabled = 0;
}
else
{
cheat = malloc(sizeof(*cheat));
cheat->name = strdup(name);
cheat->enabled = 0;
cheat->was_enabled = 0;
INIT_LIST_HEAD(&cheat->cheat_codes);
list_add_tail(&cheat->list, &active_cheats);
}
return cheat;
}
// public functions
void cheat_init(void)
{
cheat_mutex = SDL_CreateMutex();
}
void cheat_uninit(void)
{
if (cheat_mutex != NULL)
SDL_DestroyMutex(cheat_mutex);
cheat_mutex = NULL;
}
void cheat_apply_cheats(int entry)
{
cheat_t *cheat;
cheat_code_t *code;
int skip;
int execute_next;
// If game is Zelda OOT, apply subscreen delay fix
if (strncmp((char *)ROM_HEADER.Name, "THE LEGEND OF ZELDA", 19) == 0 && entry == ENTRY_VI) {
if (sl(ROM_HEADER.CRC1) == 0xEC7011B7 && sl(ROM_HEADER.CRC2) == 0x7616D72B) {
// Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.0)
execute_cheat(0x801DA5CB, 0x0002, NULL);
} else if (sl(ROM_HEADER.CRC1) == 0xD43DA81F && sl(ROM_HEADER.CRC2) == 0x021E1E19) {
// Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.1)
execute_cheat(0x801DA78B, 0x0002, NULL);
} else if (sl(ROM_HEADER.CRC1) == 0x693BA2AE && sl(ROM_HEADER.CRC2) == 0xB7F14E9F) {
// Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.2)
execute_cheat(0x801DAE8B, 0x0002, NULL);
} else if (sl(ROM_HEADER.CRC1) == 0xB044B569 && sl(ROM_HEADER.CRC2) == 0x373C1985) {
// Legend of Zelda, The - Ocarina of Time (E) (V1.0)
execute_cheat(0x801D860B, 0x0002, NULL);
} else if (sl(ROM_HEADER.CRC1) == 0xB2055FBD && sl(ROM_HEADER.CRC2) == 0x0BAB4E0C) {
// Legend of Zelda, The - Ocarina of Time (E) (V1.1)
execute_cheat(0x801D864B, 0x0002, NULL);
} else {
// Legend of Zelda, The - Ocarina of Time Master Quest
execute_cheat(0x801D8F4B, 0x0002, NULL);
}
}
if (list_empty(&active_cheats))
return;
if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
{
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_apply_cheats()");
return;
}
list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
if (cheat->enabled)
{
cheat->was_enabled = 1;
switch(entry)
{
case ENTRY_BOOT:
list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
// code should only be written once at boot time
if((code->address & 0xF0000000) == 0xF0000000)
execute_cheat(code->address, code->value, &code->old_value);
}
break;
case ENTRY_VI:
skip = 0;
execute_next = 0;
list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
if (skip) {
skip = 0;
continue;
}
if (execute_next) {
execute_next = 0;
// if code needs GS button pressed, don't save old value
if(((code->address & 0xFF000000) == 0xD8000000 ||
(code->address & 0xFF000000) == 0xD9000000 ||
(code->address & 0xFF000000) == 0xDA000000 ||
(code->address & 0xFF000000) == 0xDB000000))
execute_cheat(code->address, code->value, NULL);
else
execute_cheat(code->address, code->value, &code->old_value);
continue;
}
// conditional cheat codes
if((code->address & 0xF0000000) == 0xD0000000)
{
// if code needs GS button pressed and it's not, skip it
if(((code->address & 0xFF000000) == 0xD8000000 ||
(code->address & 0xFF000000) == 0xD9000000 ||
(code->address & 0xFF000000) == 0xDA000000 ||
(code->address & 0xFF000000) == 0xDB000000) &&
!event_gameshark_active())
{
// skip next code
skip = 1;
continue;
}
if (execute_cheat(code->address, code->value, NULL)) {
// if condition true, execute next cheat code
execute_next = 1;
} else {
// if condition false, skip next code
skip = 1;
continue;
}
}
// GS button triggers cheat code
else if((code->address & 0xFF000000) == 0x88000000 ||
(code->address & 0xFF000000) == 0x89000000 ||
(code->address & 0xFF000000) == 0xA8000000 ||
(code->address & 0xFF000000) == 0xA9000000)
{
if(event_gameshark_active())
execute_cheat(code->address, code->value, NULL);
}
// normal cheat code
else
{
// exclude boot-time cheat codes
if((code->address & 0xF0000000) != 0xF0000000)
execute_cheat(code->address, code->value, &code->old_value);
}
}
break;
default:
break;
}
}
// if cheat was enabled, but is now disabled, restore old memory values
else if (cheat->was_enabled)
{
cheat->was_enabled = 0;
switch(entry)
{
case ENTRY_VI:
list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
// set memory back to old value and clear saved copy of old value
if(code->old_value != CHEAT_CODE_MAGIC_VALUE)
{
execute_cheat(code->address, code->old_value, NULL);
code->old_value = CHEAT_CODE_MAGIC_VALUE;
}
}
break;
default:
break;
}
}
}
SDL_UnlockMutex(cheat_mutex);
}
void cheat_delete_all(void)
{
cheat_t *cheat, *safe_cheat;
cheat_code_t *code, *safe_code;
if (list_empty(&active_cheats))
return;
if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
{
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_delete_all()");
return;
}
list_for_each_entry_safe(cheat, safe_cheat, &active_cheats, cheat_t, list) {
free(cheat->name);
list_for_each_entry_safe(code, safe_code, &cheat->cheat_codes, cheat_code_t, list) {
list_del(&code->list);
free(code);
}
list_del(&cheat->list);
free(cheat);
}
SDL_UnlockMutex(cheat_mutex);
}
int cheat_set_enabled(const char *name, int enabled)
{
cheat_t *cheat = NULL;
if (list_empty(&active_cheats))
return 0;
if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
{
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_set_enabled()");
return 0;
}
list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
if (strcmp(name, cheat->name) == 0)
{
cheat->enabled = enabled;
SDL_UnlockMutex(cheat_mutex);
return 1;
}
}
SDL_UnlockMutex(cheat_mutex);
return 0;
}
int cheat_add_new(const char *name, m64p_cheat_code *code_list, int num_codes)
{
cheat_t *cheat;
int i, j;
if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
{
DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_add_new()");
return 0;
}
/* create a new cheat function or erase the codes in an existing cheat function */
cheat = find_or_create_cheat(name);
if (cheat == NULL)
{
SDL_UnlockMutex(cheat_mutex);
return 0;
}
cheat->enabled = 1; /* default for new cheats is enabled */
for (i = 0; i < num_codes; i++)
{
/* if this is a 'patch' code, convert it and dump out all of the individual codes */
if ((code_list[i].address & 0xFFFF0000) == 0x50000000 && i < num_codes - 1)
{
int code_count = ((code_list[i].address & 0xFF00) >> 8);
int incr_addr = code_list[i].address & 0xFF;
int incr_value = code_list[i].value;
int cur_addr = code_list[i+1].address;
int cur_value = code_list[i+1].value;
i += 1;
for (j = 0; j < code_count; j++)
{
cheat_code_t *code = malloc(sizeof(*code));
code->address = cur_addr;
code->value = cur_value;
code->old_value = CHEAT_CODE_MAGIC_VALUE;
list_add_tail(&code->list, &cheat->cheat_codes);
cur_addr += incr_addr;
cur_value += incr_value;
}
}
else
{ /* just a normal code */
cheat_code_t *code = malloc(sizeof(*code));
code->address = code_list[i].address;
code->value = code_list[i].value;
code->old_value = CHEAT_CODE_MAGIC_VALUE;
list_add_tail(&code->list, &cheat->cheat_codes);
}
}
SDL_UnlockMutex(cheat_mutex);
return 1;
}

View File

@ -0,0 +1,40 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - cheat.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 Okaygo *
* *
* 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 CHEAT_H
#define CHEAT_H
#include "api/m64p_types.h"
#define ENTRY_BOOT 0
#define ENTRY_VI 1
void cheat_apply_cheats(int entry);
void cheat_init(void);
void cheat_uninit(void);
int cheat_add_new(const char *name, m64p_cheat_code *code_list, int num_codes);
int cheat_set_enabled(const char *name, int enabled);
void cheat_delete_all(void);
#endif // #define CHEAT_H

View File

@ -0,0 +1,512 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - eventloop.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008-2009 Richard Goedeken *
* Copyright (C) 2008 Ebenblues Nmn Okaygo Tillin9 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#include <SDL.h>
#if ! SDL_VERSION_ATLEAST(1,3,0)
#define SDL_SCANCODE_ESCAPE SDLK_ESCAPE
#define SDL_NUM_SCANCODES SDLK_LAST
#define SDL_SCANCODE_F5 SDLK_F5
#define SDL_SCANCODE_F7 SDLK_F7
#define SDL_SCANCODE_F9 SDLK_F9
#define SDL_SCANCODE_F10 SDLK_F10
#define SDL_SCANCODE_F11 SDLK_F11
#define SDL_SCANCODE_F12 SDLK_F12
#define SDL_SCANCODE_P SDLK_p
#define SDL_SCANCODE_M SDLK_m
#define SDL_SCANCODE_RIGHTBRACKET SDLK_RIGHTBRACKET
#define SDL_SCANCODE_LEFTBRACKET SDLK_LEFTBRACKET
#define SDL_SCANCODE_F SDLK_f
#define SDL_SCANCODE_SLASH SDLK_SLASH
#define SDL_SCANCODE_G SDLK_g
#define SDL_SCANCODE_RETURN SDLK_RETURN
#define SDL_SCANCODE_0 SDLK_0
#define SDL_SCANCODE_9 SDLK_9
#define SDL_SetEventFilter(func, data) SDL_SetEventFilter(func)
#define event_sdl_filter(userdata, event) event_sdl_filter(const event)
#endif
#define M64P_CORE_PROTOTYPES 1
#include "main.h"
#include "eventloop.h"
#include "util.h"
#include "api/callbacks.h"
#include "api/config.h"
#include "api/m64p_config.h"
#include "plugin/plugin.h"
#include "r4300/interupt.h"
#include "r4300/reset.h"
/* version number for CoreEvents config section */
#define CONFIG_PARAM_VERSION 1.00
static m64p_handle l_CoreEventsConfig = NULL;
/*********************************************************************************************************
* static variables and definitions for eventloop.c
*/
#define kbdFullscreen "Kbd Mapping Fullscreen"
#define kbdStop "Kbd Mapping Stop"
#define kbdPause "Kbd Mapping Pause"
#define kbdSave "Kbd Mapping Save State"
#define kbdLoad "Kbd Mapping Load State"
#define kbdIncrement "Kbd Mapping Increment Slot"
#define kbdReset "Kbd Mapping Reset"
#define kbdSpeeddown "Kbd Mapping Speed Down"
#define kbdSpeedup "Kbd Mapping Speed Up"
#define kbdScreenshot "Kbd Mapping Screenshot"
#define kbdMute "Kbd Mapping Mute"
#define kbdIncrease "Kbd Mapping Increase Volume"
#define kbdDecrease "Kbd Mapping Decrease Volume"
#define kbdForward "Kbd Mapping Fast Forward"
#define kbdAdvance "Kbd Mapping Frame Advance"
#define kbdGameshark "Kbd Mapping Gameshark"
typedef enum {joyFullscreen,
joyStop,
joyPause,
joySave,
joyLoad,
joyIncrement,
joyScreenshot,
joyMute,
joyIncrease,
joyDecrease,
joyForward,
joyGameshark
} eJoyCommand;
static const char *JoyCmdName[] = { "Joy Mapping Fullscreen",
"Joy Mapping Stop",
"Joy Mapping Pause",
"Joy Mapping Save State",
"Joy Mapping Load State",
"Joy Mapping Increment Slot",
"Joy Mapping Screenshot",
"Joy Mapping Mute",
"Joy Mapping Increase Volume",
"Joy Mapping Decrease Volume",
"Joy Mapping Fast Forward",
"Joy Mapping Gameshark"};
static const int NumJoyCommands = sizeof(JoyCmdName) / sizeof(const char *);
static int JoyCmdActive[16]; /* if extra joystick commands are added above, make sure there is enough room in this array */
static int GamesharkActive = 0;
/*********************************************************************************************************
* static functions for eventloop.c
*/
/** MatchJoyCommand
* This function processes an SDL event and updates the JoyCmdActive array if the
* event matches with the given command.
*
* If the event activates a joystick command which was not previously active, then
* a 1 is returned. If the event de-activates an command, a -1 is returned. Otherwise
* (if the event does not match the command or active status didn't change), a 0 is returned.
*/
static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd)
{
const char *event_str = ConfigGetParamString(l_CoreEventsConfig, JoyCmdName[cmd]);
int dev_number, input_number, input_value;
char axis_direction;
/* Empty string or non-joystick command */
if (event_str == NULL || strlen(event_str) < 4 || event_str[0] != 'J')
return 0;
/* Evaluate event based on type of joystick input expected by the given command */
switch (event_str[2])
{
/* Axis */
case 'A':
if (event->type != SDL_JOYAXISMOTION)
return 0;
if (sscanf(event_str, "J%dA%d%c", &dev_number, &input_number, &axis_direction) != 3)
return 0;
if (dev_number != event->jaxis.which || input_number != event->jaxis.axis)
return 0;
if (axis_direction == '+')
{
if (event->jaxis.value >= 15000 && JoyCmdActive[cmd] == 0)
{
JoyCmdActive[cmd] = 1;
return 1;
}
else if (event->jaxis.value <= 8000 && JoyCmdActive[cmd] == 1)
{
JoyCmdActive[cmd] = 0;
return -1;
}
return 0;
}
else if (axis_direction == '-')
{
if (event->jaxis.value <= -15000 && JoyCmdActive[cmd] == 0)
{
JoyCmdActive[cmd] = 1;
return 1;
}
else if (event->jaxis.value >= -8000 && JoyCmdActive[cmd] == 1)
{
JoyCmdActive[cmd] = 0;
return -1;
}
return 0;
}
else return 0; /* invalid axis direction in configuration parameter */
break;
/* Hat */
case 'H':
if (event->type != SDL_JOYHATMOTION)
return 0;
if (sscanf(event_str, "J%dH%dV%d", &dev_number, &input_number, &input_value) != 3)
return 0;
if (dev_number != event->jhat.which || input_number != event->jhat.hat)
return 0;
if ((event->jhat.value & input_value) == input_value && JoyCmdActive[cmd] == 0)
{
JoyCmdActive[cmd] = 1;
return 1;
}
else if ((event->jhat.value & input_value) != input_value && JoyCmdActive[cmd] == 1)
{
JoyCmdActive[cmd] = 0;
return -1;
}
return 0;
break;
/* Button. */
case 'B':
if (event->type != SDL_JOYBUTTONDOWN && event->type != SDL_JOYBUTTONUP)
return 0;
if (sscanf(event_str, "J%dB%d", &dev_number, &input_number) != 2)
return 0;
if (dev_number != event->jbutton.which || input_number != event->jbutton.button)
return 0;
if (event->type == SDL_JOYBUTTONDOWN && JoyCmdActive[cmd] == 0)
{
JoyCmdActive[cmd] = 1;
return 1;
}
else if (event->type == SDL_JOYBUTTONUP && JoyCmdActive[cmd] == 1)
{
JoyCmdActive[cmd] = 0;
return -1;
}
return 0;
break;
default:
/* bad configuration parameter */
return 0;
}
/* impossible to reach this point */
return 0;
}
/*********************************************************************************************************
* sdl event filter
*/
static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event)
{
int cmd, action;
switch(event->type)
{
// user clicked on window close button
case SDL_QUIT:
main_stop();
break;
case SDL_KEYDOWN:
#if SDL_VERSION_ATLEAST(1,3,0)
event_sdl_keydown(event->key.keysym.scancode, event->key.keysym.mod);
#else
event_sdl_keydown(event->key.keysym.sym, event->key.keysym.mod);
#endif
return 0;
case SDL_KEYUP:
#if SDL_VERSION_ATLEAST(1,3,0)
event_sdl_keyup(event->key.keysym.scancode, event->key.keysym.mod);
#else
event_sdl_keyup(event->key.keysym.sym, event->key.keysym.mod);
#endif
return 0;
// if joystick action is detected, check if it's mapped to a special function
case SDL_JOYAXISMOTION:
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
case SDL_JOYHATMOTION:
for (cmd = 0; cmd < NumJoyCommands; cmd++)
{
action = MatchJoyCommand(event, (eJoyCommand) cmd);
if (action == 1) /* command was just activated (button down, etc) */
{
if (cmd == joyFullscreen)
gfx.changeWindow();
else if (cmd == joyStop)
main_stop();
else if (cmd == joyPause)
main_toggle_pause();
else if (cmd == joySave)
main_state_save(1, NULL); /* save in mupen64plus format using current slot */
else if (cmd == joyLoad)
main_state_load(NULL); /* load using current slot */
else if (cmd == joyIncrement)
main_state_inc_slot();
else if (cmd == joyScreenshot)
main_take_next_screenshot();
else if (cmd == joyMute)
main_volume_mute();
else if (cmd == joyDecrease)
main_volume_down();
else if (cmd == joyIncrease)
main_volume_up();
else if (cmd == joyForward)
main_set_fastforward(1);
else if (cmd == joyGameshark)
event_set_gameshark(1);
}
else if (action == -1) /* command was just de-activated (button up, etc) */
{
if (cmd == joyForward)
main_set_fastforward(0);
else if (cmd == joyGameshark)
event_set_gameshark(0);
}
}
return 0;
break;
}
return 1;
}
/*********************************************************************************************************
* global functions
*/
void event_initialize(void)
{
const char *event_str = NULL;
int i;
/* set initial state of all joystick commands to 'off' */
for (i = 0; i < NumJoyCommands; i++)
JoyCmdActive[i] = 0;
/* activate any joysticks which are referenced in the joystick event command strings */
for (i = 0; i < NumJoyCommands; i++)
{
event_str = ConfigGetParamString(l_CoreEventsConfig, JoyCmdName[i]);
if (event_str != NULL && strlen(event_str) >= 4 && event_str[0] == 'J' && event_str[1] >= '0' && event_str[1] <= '9')
{
int device = event_str[1] - '0';
if (!SDL_WasInit(SDL_INIT_JOYSTICK))
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
#if SDL_VERSION_ATLEAST(2,0,0)
#warning SDL_JoystickOpened unsupported
#else
if (!SDL_JoystickOpened(device))
SDL_JoystickOpen(device);
#endif
}
}
/* set up SDL event filter and disable key repeat */
#if SDL_VERSION_ATLEAST(2,0,0)
#warning SDL_EnableKeyRepeat unsupported
#else
SDL_EnableKeyRepeat(0, 0);
#endif
SDL_SetEventFilter(event_sdl_filter, NULL);
}
int event_set_core_defaults(void)
{
float fConfigParamsVersion;
int bSaveConfig = 0;
if (ConfigOpenSection("CoreEvents", &l_CoreEventsConfig) != M64ERR_SUCCESS || l_CoreEventsConfig == NULL)
{
DebugMessage(M64MSG_ERROR, "Failed to open CoreEvents config section.");
return 0; /* fail */
}
if (ConfigGetParameter(l_CoreEventsConfig, "Version", M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS)
{
DebugMessage(M64MSG_WARNING, "No version number in 'CoreEvents' config section. Setting defaults.");
ConfigDeleteSection("CoreEvents");
ConfigOpenSection("CoreEvents", &l_CoreEventsConfig);
bSaveConfig = 1;
}
else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION))
{
DebugMessage(M64MSG_WARNING, "Incompatible version %.2f in 'CoreEvents' config section: current is %.2f. Setting defaults.", fConfigParamsVersion, (float) CONFIG_PARAM_VERSION);
ConfigDeleteSection("CoreEvents");
ConfigOpenSection("CoreEvents", &l_CoreEventsConfig);
bSaveConfig = 1;
}
else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f)
{
/* handle upgrades */
float fVersion = CONFIG_PARAM_VERSION;
ConfigSetParameter(l_CoreEventsConfig, "Version", M64TYPE_FLOAT, &fVersion);
DebugMessage(M64MSG_INFO, "Updating parameter set version in 'CoreEvents' config section to %.2f", fVersion);
bSaveConfig = 1;
}
ConfigSetDefaultFloat(l_CoreEventsConfig, "Version", CONFIG_PARAM_VERSION, "Mupen64Plus CoreEvents config parameter set version number. Please don't change this version number.");
/* Keyboard presses mapped to core functions */
ConfigSetDefaultInt(l_CoreEventsConfig, kbdStop, SDL_SCANCODE_ESCAPE, "SDL keysym for stopping the emulator");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdFullscreen, SDL_NUM_SCANCODES, "SDL keysym for switching between fullscreen/windowed modes");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdSave, SDL_SCANCODE_F5, "SDL keysym for saving the emulator state");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdLoad, SDL_SCANCODE_F7, "SDL keysym for loading the emulator state");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdIncrement, 0, "SDL keysym for advancing the save state slot");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdReset, SDL_SCANCODE_F9, "SDL keysym for resetting the emulator");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdSpeeddown, SDL_SCANCODE_F10, "SDL keysym for slowing down the emulator");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdSpeedup, SDL_SCANCODE_F11, "SDL keysym for speeding up the emulator");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdScreenshot, SDL_SCANCODE_F12, "SDL keysym for taking a screenshot");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdPause, SDL_SCANCODE_P, "SDL keysym for pausing the emulator");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdMute, SDL_SCANCODE_M, "SDL keysym for muting/unmuting the sound");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdIncrease, SDL_SCANCODE_RIGHTBRACKET,"SDL keysym for increasing the volume");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdDecrease, SDL_SCANCODE_LEFTBRACKET, "SDL keysym for decreasing the volume");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdForward, SDL_SCANCODE_F, "SDL keysym for temporarily going really fast");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdAdvance, SDL_SCANCODE_SLASH, "SDL keysym for advancing by one frame when paused");
ConfigSetDefaultInt(l_CoreEventsConfig, kbdGameshark, SDL_SCANCODE_G, "SDL keysym for pressing the game shark button");
/* Joystick events mapped to core functions */
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyStop], "", "Joystick event string for stopping the emulator");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyFullscreen], "", "Joystick event string for switching between fullscreen/windowed modes");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joySave], "", "Joystick event string for saving the emulator state");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyLoad], "", "Joystick event string for loading the emulator state");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyIncrement], "", "Joystick event string for advancing the save state slot");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyScreenshot], "", "Joystick event string for taking a screenshot");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyPause], "", "Joystick event string for pausing the emulator");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyMute], "", "Joystick event string for muting/unmuting the sound");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyIncrease], "", "Joystick event string for increasing the volume");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyDecrease], "", "Joystick event string for decreasing the volume");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyForward], "", "Joystick event string for fast-forward");
ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyGameshark], "", "Joystick event string for pressing the game shark button");
if (bSaveConfig)
ConfigSaveSection("CoreEvents");
return 1;
}
/*********************************************************************************************************
* sdl keyup/keydown handlers
*/
void event_sdl_keydown(int keysym, int keymod)
{
/* check for the only 2 hard-coded key commands: Alt-enter for fullscreen and 0-9 for save state slot */
if (keysym == SDL_SCANCODE_RETURN && keymod & (KMOD_LALT | KMOD_RALT))
gfx.changeWindow();
else if (keysym >= SDL_SCANCODE_0 && keysym <= SDL_SCANCODE_9)
main_state_set_slot(keysym - SDL_SCANCODE_0);
/* check all of the configurable commands */
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdStop))
main_stop();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdFullscreen))
gfx.changeWindow();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdSave))
main_state_save(0, NULL); /* save in mupen64plus format using current slot */
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdLoad))
main_state_load(NULL); /* load using current slot */
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdIncrement))
main_state_inc_slot();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdReset))
reset_soft();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdSpeeddown))
main_speeddown(5);
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdSpeedup))
main_speedup(5);
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdScreenshot))
main_take_next_screenshot(); /* screenshot will be taken at the end of frame rendering */
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdPause))
main_toggle_pause();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdMute))
main_volume_mute();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdIncrease))
main_volume_up();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdDecrease))
main_volume_down();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdForward))
main_set_fastforward(1);
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdAdvance))
main_advance_one();
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdGameshark))
event_set_gameshark(1);
else
{
/* pass all other keypresses to the input plugin */
input.keyDown(keymod, keysym);
}
}
void event_sdl_keyup(int keysym, int keymod)
{
if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdStop))
{
return;
}
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdForward))
{
main_set_fastforward(0);
}
else if (keysym == ConfigGetParamInt(l_CoreEventsConfig, kbdGameshark))
{
event_set_gameshark(0);
}
else input.keyUp(keymod, keysym);
}
int event_gameshark_active(void)
{
return GamesharkActive;
}
void event_set_gameshark(int active)
{
// if boolean value doesn't change then just return
if (!active == !GamesharkActive)
return;
// set the button state
GamesharkActive = (active ? 1 : 0);
// notify front-end application that gameshark button state has changed
StateChanged(M64CORE_INPUT_GAMESHARK, GamesharkActive);
}

View File

@ -0,0 +1,34 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - eventloop.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(EVENTLOOP_H)
#define EVENTLOOP_H
extern int event_set_core_defaults(void);
extern void event_initialize(void);
extern void event_sdl_keydown(int keysym, int keymod);
extern void event_sdl_keyup(int keysym, int keymod);
extern int event_gameshark_active(void);
extern void event_set_gameshark(int active);
#endif /* define(EVENTLOOP_H) */

View File

@ -0,0 +1,127 @@
/***************************************************************************
lirc.c - handle lirc input events to Mupen64Plus
-------------------
begin : Friday 11 Jan 2008
copyright : (C) 2008 by DarkJezter
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
// Functions for LIRC support
#ifdef WITH_LIRC
#include <stdlib.h>
#include <sys/poll.h>
#include <string.h>
#include <ctype.h>
#include <lirc/lirc_client.h>
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "plugin/plugin.h"
#include "lirc.h"
#include "main.h"
#include "savestates.h"
static struct lirc_config *g_config;
static int g_lircfd = 0;
void lircStart(void)
{
if((g_lircfd = lirc_init("mupen64plus", 1)) != -1)
{
g_config = NULL;
if(lirc_readconfig(NULL, &g_config, NULL) == 0)
DebugMessage(M64MSG_INFO, "LIRC input system started successfully");
else
DebugMessage(M64MSG_WARNING, "LIRC disabled: Error reading lircrc!");
}
else
DebugMessage(M64MSG_WARNING, "LIRC disabled: Error contacting daemon!");
}
void lircStop(void)
{
if(g_lircfd!=-1)
{
if(g_config != NULL)
{
lirc_freeconfig(g_config);
g_config = NULL;
}
lirc_deinit();
DebugMessage(M64MSG_INFO, "LIRC system shut down");
}
}
void lircCheckInput(void)
{
struct pollfd lircpoll;
lircpoll.fd = g_lircfd;
lircpoll.events = POLLIN;
if(poll(&lircpoll, 1, 0) > 0)
{
char *code;
char *c;
int ret;
if(lirc_nextcode(&code) == 0 && code != NULL)
{
while((ret = lirc_code2char(g_config, code, &c)) == 0 && c!=NULL)
{
char *c_ind = c;
while(*c_ind != '\0')
{
*c_ind = toupper(*c_ind);
c_ind++;
}
DebugMessage(M64MSG_VERBOSE, "LIRC Execing command \"%s\"", c);
if(strcmp(c, "SAVE") == 0)
main_state_save(1, NULL); /* save in mupen64plus format using current slot */
else if(strcmp(c, "LOAD") == 0)
main_state_load(NULL); /* load using current slot */
else if(strcmp(c, "QUIT") == 0)
main_stop();
else if(strcmp(c, "FULLSCREEN") == 0)
gfx.changeWindow();
else if(strcmp(c, "MUTE") == 0)
main_volume_mute();
else if(strcmp(c, "VOL+") == 0)
main_volume_up();
else if(strcmp(c, "VOL-") == 0)
main_volume_down();
else if(strcmp(c, "SCREENSHOT") == 0)
main_take_next_screenshot();
else if(strcmp(c, "SPEED+") == 0)
main_speedup(5);
else if(strcmp(c, "SPEED-") == 0)
main_speeddown(5);
else if(strcmp(c, "ADVANCE") == 0)
main_advance_one();
else if(strcmp(c, "PAUSE") == 0)
main_toggle_pause();
else
{
int val = ((int)c[0])-((int) '0');
if (val >= 0 && val <= 9)
savestates_select_slot( val );
}
}
free(code);
}
}
}
#endif //WITH_LIRC

View File

@ -0,0 +1,25 @@
/***************************************************************************
lirc.h - description
-------------------
begin : Friday 11 Jan 2008
copyright : (C) 2008 by DarkJezter
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __LIRC_H__
#define __LIRC_H__
extern void lircStart(void);
extern void lircStop(void);
extern void lircCheckInput(void);
#endif //__LIRC_H__

View File

@ -0,0 +1,126 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - util.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 Mupen64plus development team *
* *
* 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 __LIST_H__
#define __LIST_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
struct list_head {
struct list_head *prev;
struct list_head *next;
};
#define LIST_HEAD(list) \
struct list_head list = { &(list), &(list) }
static inline void INIT_LIST_HEAD(struct list_head *head)
{
head->next = head;
head->prev = head;
}
static inline void list_add(struct list_head *new_item, struct list_head *head)
{
struct list_head *next = head->next;
next->prev = new_item;
new_item->next = next;
new_item->prev = head;
head->next = new_item;
}
static inline void list_add_tail(struct list_head *new_item, struct list_head *head)
{
struct list_head *prev = head->prev;
prev->next = new_item;
new_item->next = head;
new_item->prev = prev;
head->prev = new_item;
}
static inline void list_del(struct list_head *entry)
{
struct list_head *next = entry->next;
struct list_head *prev = entry->prev;
next->prev = prev;
prev->next = next;
}
static inline void list_del_init(struct list_head *entry)
{
list_del(entry);
INIT_LIST_HEAD(entry);
}
static inline int list_empty(const struct list_head *head)
{
return (head->next == head);
}
#ifdef __GNUC__
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#else
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
#endif
#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_entry(pos, head, type, member) \
for (pos = list_entry((head)->next, type, member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
#define list_for_each_safe(pos, safe, head) \
for (pos = (head)->next, safe = pos->next; pos != (head); \
pos = safe, safe = pos->next)
#define list_for_each_entry_safe(pos, safe, head, type, member) \
for (pos = list_entry((head)->next, type, member), \
safe = list_entry(pos->member.next, type, member); \
&pos->member != (head); \
pos = safe, \
safe = list_entry(safe->member.next, type, member))
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,859 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - main.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* Copyright (C) 2008-2009 Richard Goedeken *
* Copyright (C) 2008 Ebenblues Nmn Okaygo Tillin9 *
* 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 is MUPEN64's main entry point. It contains code that is common
* to both the gui and non-gui versions of mupen64. See
* gui subdirectories for the gui-specific code.
* if you want to implement an interface, you should look here
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#define M64P_CORE_PROTOTYPES 1
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "api/config.h"
#include "api/m64p_config.h"
#include "api/debugger.h"
#include "api/vidext.h"
#include "main.h"
#include "eventloop.h"
#include "rom.h"
#include "savestates.h"
#include "util.h"
#include "memory/memory.h"
#include "osal/files.h"
#include "osal/preproc.h"
#include "osd/osd.h"
#include "osd/screenshot.h"
#include "plugin/plugin.h"
#include "r4300/r4300.h"
#include "r4300/interupt.h"
#include "r4300/reset.h"
#ifdef DBG
#include "debugger/dbg_types.h"
#include "debugger/debugger.h"
#endif
#ifdef WITH_LIRC
#include "lirc.h"
#endif //WITH_LIRC
/* version number for Core config section */
#define CONFIG_PARAM_VERSION 1.01
/** globals **/
m64p_handle g_CoreConfig = NULL;
m64p_frame_callback g_FrameCallback = NULL;
int g_MemHasBeenBSwapped = 0; // store byte-swapped flag so we don't swap twice when re-playing game
int g_EmulatorRunning = 0; // need separate boolean to tell if emulator is running, since --nogui doesn't use a thread
/** static (local) variables **/
static int l_CurrentFrame = 0; // frame counter
static int l_TakeScreenshot = 0; // Tell OSD Rendering callback to take a screenshot just before drawing the OSD
static int l_SpeedFactor = 100; // percentage of nominal game speed at which emulator is running
static int l_FrameAdvance = 0; // variable to check if we pause on next frame
static int l_MainSpeedLimit = 1; // insert delay during vi_interrupt to keep speed at real-time
static osd_message_t *l_msgVol = NULL;
static osd_message_t *l_msgFF = NULL;
static osd_message_t *l_msgPause = NULL;
/*********************************************************************************************************
* static functions
*/
static const char *get_savepathdefault(const char *configpath)
{
static char path[1024];
if (!configpath || (strlen(configpath) == 0)) {
snprintf(path, 1024, "%ssave%c", ConfigGetUserDataPath(), OSAL_DIR_SEPARATORS[0]);
path[1023] = 0;
} else {
snprintf(path, 1024, "%s%c", configpath, OSAL_DIR_SEPARATORS[0]);
path[1023] = 0;
}
/* create directory if it doesn't exist */
osal_mkdirp(path, 0700);
return path;
}
/*********************************************************************************************************
* helper functions
*/
const char *get_savestatepath(void)
{
/* try to get the SaveStatePath string variable in the Core configuration section */
return get_savepathdefault(ConfigGetParamString(g_CoreConfig, "SaveStatePath"));
}
const char *get_savesrampath(void)
{
/* try to get the SaveSRAMPath string variable in the Core configuration section */
return get_savepathdefault(ConfigGetParamString(g_CoreConfig, "SaveSRAMPath"));
}
void main_message(m64p_msg_level level, unsigned int corner, const char *format, ...)
{
va_list ap;
char buffer[2049];
va_start(ap, format);
vsnprintf(buffer, 2047, format, ap);
buffer[2048]='\0';
va_end(ap);
/* send message to on-screen-display if enabled */
if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay"))
osd_new_message((enum osd_corner) corner, "%s", buffer);
/* send message to front-end */
DebugMessage(level, "%s", buffer);
}
/*********************************************************************************************************
* global functions, for adjusting the core emulator behavior
*/
int main_set_core_defaults(void)
{
float fConfigParamsVersion;
int bSaveConfig = 0, bUpgrade = 0;
if (ConfigGetParameter(g_CoreConfig, "Version", M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS)
{
DebugMessage(M64MSG_WARNING, "No version number in 'Core' config section. Setting defaults.");
ConfigDeleteSection("Core");
ConfigOpenSection("Core", &g_CoreConfig);
bSaveConfig = 1;
}
else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION))
{
DebugMessage(M64MSG_WARNING, "Incompatible version %.2f in 'Core' config section: current is %.2f. Setting defaults.", fConfigParamsVersion, (float) CONFIG_PARAM_VERSION);
ConfigDeleteSection("Core");
ConfigOpenSection("Core", &g_CoreConfig);
bSaveConfig = 1;
}
else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f)
{
float fVersion = (float) CONFIG_PARAM_VERSION;
ConfigSetParameter(g_CoreConfig, "Version", M64TYPE_FLOAT, &fVersion);
DebugMessage(M64MSG_INFO, "Updating parameter set version in 'Core' config section to %.2f", fVersion);
bUpgrade = 1;
bSaveConfig = 1;
}
/* parameters controlling the operation of the core */
ConfigSetDefaultFloat(g_CoreConfig, "Version", (float) CONFIG_PARAM_VERSION, "Mupen64Plus Core config parameter set version number. Please don't change this version number.");
ConfigSetDefaultBool(g_CoreConfig, "OnScreenDisplay", 1, "Draw on-screen display if True, otherwise don't draw OSD");
#if defined(DYNAREC)
ConfigSetDefaultInt(g_CoreConfig, "R4300Emulator", 2, "Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more");
#else
ConfigSetDefaultInt(g_CoreConfig, "R4300Emulator", 1, "Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more");
#endif
ConfigSetDefaultBool(g_CoreConfig, "NoCompiledJump", 0, "Disable compiled jump commands in dynamic recompiler (should be set to False) ");
ConfigSetDefaultBool(g_CoreConfig, "DisableExtraMem", 0, "Disable 4MB expansion RAM pack. May be necessary for some games");
ConfigSetDefaultBool(g_CoreConfig, "AutoStateSlotIncrement", 0, "Increment the save state slot after each save operation");
ConfigSetDefaultBool(g_CoreConfig, "EnableDebugger", 0, "Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support");
ConfigSetDefaultInt(g_CoreConfig, "CurrentStateSlot", 0, "Save state slot (0-9) to use when saving/loading the emulator state");
ConfigSetDefaultString(g_CoreConfig, "ScreenshotPath", "", "Path to directory where screenshots are saved. If this is blank, the default value of ${UserConfigPath}/screenshot will be used");
ConfigSetDefaultString(g_CoreConfig, "SaveStatePath", "", "Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of ${UserConfigPath}/save will be used");
ConfigSetDefaultString(g_CoreConfig, "SaveSRAMPath", "", "Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of ${UserConfigPath}/save will be used");
ConfigSetDefaultString(g_CoreConfig, "SharedDataPath", "", "Path to a directory to search when looking for shared data files");
/* handle upgrades */
if (bUpgrade)
{
if (fConfigParamsVersion < 1.01f)
{ // added separate SaveSRAMPath parameter in v1.01
const char *pccSaveStatePath = ConfigGetParamString(g_CoreConfig, "SaveStatePath");
if (pccSaveStatePath != NULL)
ConfigSetParameter(g_CoreConfig, "SaveSRAMPath", M64TYPE_STRING, pccSaveStatePath);
}
}
if (bSaveConfig)
ConfigSaveSection("Core");
/* set config parameters for keyboard and joystick commands */
return event_set_core_defaults();
}
void main_speeddown(int percent)
{
if (l_SpeedFactor - percent > 10) /* 10% minimum speed */
{
l_SpeedFactor -= percent;
main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor);
audio.setSpeedFactor(l_SpeedFactor);
StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor);
}
}
void main_speedup(int percent)
{
if (l_SpeedFactor + percent < 300) /* 300% maximum speed */
{
l_SpeedFactor += percent;
main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor);
audio.setSpeedFactor(l_SpeedFactor);
StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor);
}
}
static void main_speedset(int percent)
{
if (percent < 1 || percent > 1000)
{
DebugMessage(M64MSG_WARNING, "Invalid speed setting %i percent", percent);
return;
}
// disable fast-forward if it's enabled
main_set_fastforward(0);
// set speed
l_SpeedFactor = percent;
main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor);
audio.setSpeedFactor(l_SpeedFactor);
StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor);
}
void main_set_fastforward(int enable)
{
static int ff_state = 0;
static int SavedSpeedFactor = 100;
if (enable && !ff_state)
{
ff_state = 1; /* activate fast-forward */
SavedSpeedFactor = l_SpeedFactor;
l_SpeedFactor = 250;
audio.setSpeedFactor(l_SpeedFactor);
StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor);
// set fast-forward indicator
l_msgFF = osd_new_message(OSD_TOP_RIGHT, "Fast Forward");
osd_message_set_static(l_msgFF);
osd_message_set_user_managed(l_msgFF);
}
else if (!enable && ff_state)
{
ff_state = 0; /* de-activate fast-forward */
l_SpeedFactor = SavedSpeedFactor;
audio.setSpeedFactor(l_SpeedFactor);
StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor);
// remove message
osd_delete_message(l_msgFF);
l_msgFF = NULL;
}
}
static void main_set_speedlimiter(int enable)
{
l_MainSpeedLimit = enable ? 1 : 0;
}
static int main_is_paused(void)
{
return (g_EmulatorRunning && rompause);
}
void main_toggle_pause(void)
{
if (!g_EmulatorRunning)
return;
if (rompause)
{
DebugMessage(M64MSG_STATUS, "Emulation continued.");
if(l_msgPause)
{
osd_delete_message(l_msgPause);
l_msgPause = NULL;
}
StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING);
}
else
{
if(l_msgPause)
osd_delete_message(l_msgPause);
DebugMessage(M64MSG_STATUS, "Emulation paused.");
l_msgPause = osd_new_message(OSD_MIDDLE_CENTER, "Paused");
osd_message_set_static(l_msgPause);
osd_message_set_user_managed(l_msgPause);
StateChanged(M64CORE_EMU_STATE, M64EMU_PAUSED);
}
rompause = !rompause;
l_FrameAdvance = 0;
}
void main_advance_one(void)
{
l_FrameAdvance = 1;
rompause = 0;
StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING);
}
static void main_draw_volume_osd(void)
{
char msgString[64];
const char *volString;
// this calls into the audio plugin
volString = audio.volumeGetString();
if (volString == NULL)
{
strcpy(msgString, "Volume Not Supported.");
}
else
{
sprintf(msgString, "%s: %s", "Volume", volString);
}
// create a new message or update an existing one
if (l_msgVol != NULL)
osd_update_message(l_msgVol, "%s", msgString);
else {
l_msgVol = osd_new_message(OSD_MIDDLE_CENTER, "%s", msgString);
osd_message_set_user_managed(l_msgVol);
}
}
/* this function could be called as a result of a keypress, joystick/button movement,
LIRC command, or 'testshots' command-line option timer */
void main_take_next_screenshot(void)
{
l_TakeScreenshot = l_CurrentFrame + 1;
}
void main_state_set_slot(int slot)
{
if (slot < 0 || slot > 9)
{
DebugMessage(M64MSG_WARNING, "Invalid savestate slot '%i' in main_state_set_slot(). Using 0", slot);
slot = 0;
}
savestates_select_slot(slot);
StateChanged(M64CORE_SAVESTATE_SLOT, slot);
}
void main_state_inc_slot(void)
{
savestates_inc_slot();
}
static unsigned char StopRumble[64] = {0x23, 0x01, 0x03, 0xc0, 0x1b, 0x00, 0x00, 0x00,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
void main_state_load(const char *filename)
{
input.controllerCommand(0, StopRumble);
input.controllerCommand(1, StopRumble);
input.controllerCommand(2, StopRumble);
input.controllerCommand(3, StopRumble);
if (filename == NULL) // Save to slot
savestates_set_job(savestates_job_load, savestates_type_m64p, NULL);
else
savestates_set_job(savestates_job_load, savestates_type_unknown, filename);
}
void main_state_save(int format, const char *filename)
{
if (filename == NULL) // Save to slot
savestates_set_job(savestates_job_save, savestates_type_m64p, NULL);
else // Save to file
savestates_set_job(savestates_job_save, (savestates_type)format, filename);
}
m64p_error main_core_state_query(m64p_core_param param, int *rval)
{
switch (param)
{
case M64CORE_EMU_STATE:
if (!g_EmulatorRunning)
*rval = M64EMU_STOPPED;
else if (rompause)
*rval = M64EMU_PAUSED;
else
*rval = M64EMU_RUNNING;
break;
case M64CORE_VIDEO_MODE:
if (!VidExt_VideoRunning())
*rval = M64VIDEO_NONE;
else if (VidExt_InFullscreenMode())
*rval = M64VIDEO_FULLSCREEN;
else
*rval = M64VIDEO_WINDOWED;
break;
case M64CORE_SAVESTATE_SLOT:
*rval = savestates_get_slot();
break;
case M64CORE_SPEED_FACTOR:
*rval = l_SpeedFactor;
break;
case M64CORE_SPEED_LIMITER:
*rval = l_MainSpeedLimit;
break;
case M64CORE_VIDEO_SIZE:
{
int width, height;
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
main_get_screen_size(&width, &height);
*rval = (width << 16) + height;
break;
}
case M64CORE_AUDIO_VOLUME:
{
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
return main_volume_get_level(rval);
}
case M64CORE_AUDIO_MUTE:
*rval = main_volume_get_muted();
break;
case M64CORE_INPUT_GAMESHARK:
*rval = event_gameshark_active();
break;
// these are only used for callbacks; they cannot be queried or set
case M64CORE_STATE_LOADCOMPLETE:
case M64CORE_STATE_SAVECOMPLETE:
return M64ERR_INPUT_INVALID;
default:
return M64ERR_INPUT_INVALID;
}
return M64ERR_SUCCESS;
}
m64p_error main_core_state_set(m64p_core_param param, int val)
{
switch (param)
{
case M64CORE_EMU_STATE:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (val == M64EMU_STOPPED)
{
/* this stop function is asynchronous. The emulator may not terminate until later */
main_stop();
return M64ERR_SUCCESS;
}
else if (val == M64EMU_RUNNING)
{
if (main_is_paused())
main_toggle_pause();
return M64ERR_SUCCESS;
}
else if (val == M64EMU_PAUSED)
{
if (!main_is_paused())
main_toggle_pause();
return M64ERR_SUCCESS;
}
return M64ERR_INPUT_INVALID;
case M64CORE_VIDEO_MODE:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (val == M64VIDEO_WINDOWED)
{
if (VidExt_InFullscreenMode())
gfx.changeWindow();
return M64ERR_SUCCESS;
}
else if (val == M64VIDEO_FULLSCREEN)
{
if (!VidExt_InFullscreenMode())
gfx.changeWindow();
return M64ERR_SUCCESS;
}
return M64ERR_INPUT_INVALID;
case M64CORE_SAVESTATE_SLOT:
if (val < 0 || val > 9)
return M64ERR_INPUT_INVALID;
savestates_select_slot(val);
return M64ERR_SUCCESS;
case M64CORE_SPEED_FACTOR:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
main_speedset(val);
return M64ERR_SUCCESS;
case M64CORE_SPEED_LIMITER:
main_set_speedlimiter(val);
return M64ERR_SUCCESS;
case M64CORE_VIDEO_SIZE:
// you cannot force the screen size using this function
return M64ERR_INPUT_INVALID;
case M64CORE_AUDIO_VOLUME:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
if (val < 0 || val > 100)
return M64ERR_INPUT_INVALID;
return main_volume_set_level(val);
case M64CORE_AUDIO_MUTE:
if ((main_volume_get_muted() && !val) || (!main_volume_get_muted() && val))
return main_volume_mute();
return M64ERR_SUCCESS;
case M64CORE_INPUT_GAMESHARK:
if (!g_EmulatorRunning)
return M64ERR_INVALID_STATE;
event_set_gameshark(val);
return M64ERR_SUCCESS;
// these are only used for callbacks; they cannot be queried or set
case M64CORE_STATE_LOADCOMPLETE:
case M64CORE_STATE_SAVECOMPLETE:
return M64ERR_INPUT_INVALID;
default:
return M64ERR_INPUT_INVALID;
}
}
m64p_error main_get_screen_size(int *width, int *height)
{
gfx.readScreen(NULL, width, height, 0);
return M64ERR_SUCCESS;
}
m64p_error main_read_screen(void *pixels, int bFront)
{
int width_trash, height_trash;
gfx.readScreen(pixels, &width_trash, &height_trash, bFront);
return M64ERR_SUCCESS;
}
m64p_error main_volume_up(void)
{
int level = 0;
audio.volumeUp();
main_draw_volume_osd();
main_volume_get_level(&level);
StateChanged(M64CORE_AUDIO_VOLUME, level);
return M64ERR_SUCCESS;
}
m64p_error main_volume_down(void)
{
int level = 0;
audio.volumeDown();
main_draw_volume_osd();
main_volume_get_level(&level);
StateChanged(M64CORE_AUDIO_VOLUME, level);
return M64ERR_SUCCESS;
}
m64p_error main_volume_get_level(int *level)
{
*level = audio.volumeGetLevel();
return M64ERR_SUCCESS;
}
m64p_error main_volume_set_level(int level)
{
audio.volumeSetLevel(level);
main_draw_volume_osd();
level = audio.volumeGetLevel();
StateChanged(M64CORE_AUDIO_VOLUME, level);
return M64ERR_SUCCESS;
}
m64p_error main_volume_mute(void)
{
audio.volumeMute();
main_draw_volume_osd();
StateChanged(M64CORE_AUDIO_MUTE, main_volume_get_muted());
return M64ERR_SUCCESS;
}
int main_volume_get_muted(void)
{
return (audio.volumeGetLevel() == 0);
}
m64p_error main_reset(int do_hard_reset)
{
if (do_hard_reset)
reset_hard_job |= 1;
else
reset_soft();
return M64ERR_SUCCESS;
}
/*********************************************************************************************************
* global functions, callbacks from the r4300 core or from other plugins
*/
static void video_plugin_render_callback(int bScreenRedrawn)
{
int bOSD = ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay");
// if the flag is set to take a screenshot, then grab it now
if (l_TakeScreenshot != 0)
{
// if the OSD is enabled, and the screen has not been recently redrawn, then we cannot take a screenshot now because
// it contains the OSD text. Wait until the next redraw
if (!bOSD || bScreenRedrawn)
{
TakeScreenshot(l_TakeScreenshot - 1); // current frame number +1 is in l_TakeScreenshot
l_TakeScreenshot = 0; // reset flag
}
}
// if the OSD is enabled, then draw it now
if (bOSD)
{
osd_render();
}
}
void new_frame(void)
{
if (g_FrameCallback != NULL)
(*g_FrameCallback)(l_CurrentFrame);
/* advance the current frame */
l_CurrentFrame++;
if (l_FrameAdvance) {
rompause = 1;
l_FrameAdvance = 0;
StateChanged(M64CORE_EMU_STATE, M64EMU_PAUSED);
}
}
void new_vi(void)
{
int Dif;
unsigned int CurrentFPSTime;
static unsigned int LastFPSTime = 0;
static unsigned int CounterTime = 0;
static unsigned int CalculatedTime ;
static int VI_Counter = 0;
double VILimitMilliseconds = 1000.0 / ROM_PARAMS.vilimit;
double AdjustedLimit = VILimitMilliseconds * 100.0 / l_SpeedFactor; // adjust for selected emulator speed
int time;
start_section(IDLE_SECTION);
VI_Counter++;
#ifdef DBG
if(g_DebuggerActive) DebuggerCallback(DEBUG_UI_VI, 0);
#endif
if(LastFPSTime == 0)
{
LastFPSTime = CounterTime = SDL_GetTicks();
return;
}
CurrentFPSTime = SDL_GetTicks();
Dif = CurrentFPSTime - LastFPSTime;
if (Dif < AdjustedLimit)
{
CalculatedTime = (unsigned int) (CounterTime + AdjustedLimit * VI_Counter);
time = (int)(CalculatedTime - CurrentFPSTime);
if (time > 0 && l_MainSpeedLimit)
{
DebugMessage(M64MSG_VERBOSE, " new_vi(): Waiting %ims", time);
SDL_Delay(time);
}
CurrentFPSTime = CurrentFPSTime + time;
}
if (CurrentFPSTime - CounterTime >= 1000.0 )
{
CounterTime = SDL_GetTicks();
VI_Counter = 0 ;
}
LastFPSTime = CurrentFPSTime ;
end_section(IDLE_SECTION);
}
/*********************************************************************************************************
* emulation thread - runs the core
*/
m64p_error main_run(void)
{
/* take the r4300 emulator mode from the config file at this point and cache it in a global variable */
r4300emu = ConfigGetParamInt(g_CoreConfig, "R4300Emulator");
/* set some other core parameters based on the config file values */
savestates_set_autoinc_slot(ConfigGetParamBool(g_CoreConfig, "AutoStateSlotIncrement"));
savestates_select_slot(ConfigGetParamInt(g_CoreConfig, "CurrentStateSlot"));
no_compiled_jump = ConfigGetParamBool(g_CoreConfig, "NoCompiledJump");
// initialize memory, and do byte-swapping if it's not been done yet
if (g_MemHasBeenBSwapped == 0)
{
init_memory(1);
g_MemHasBeenBSwapped = 1;
}
else
{
init_memory(0);
}
// Attach rom to plugins
if (!gfx.romOpen())
{
free_memory(); return M64ERR_PLUGIN_FAIL;
}
if (!audio.romOpen())
{
gfx.romClosed(); free_memory(); return M64ERR_PLUGIN_FAIL;
}
if (!input.romOpen())
{
audio.romClosed(); gfx.romClosed(); free_memory(); return M64ERR_PLUGIN_FAIL;
}
/* set up the SDL key repeat and event filter to catch keyboard/joystick commands for the core */
event_initialize();
/* initialize the on-screen display */
if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay"))
{
// init on-screen display
int width = 640, height = 480;
gfx.readScreen(NULL, &width, &height, 0); // read screen to get width and height
osd_init(width, height);
}
// setup rendering callback from video plugin to the core, for screenshots and On-Screen-Display
gfx.setRenderingCallback(video_plugin_render_callback);
#ifdef WITH_LIRC
lircStart();
#endif // WITH_LIRC
#ifdef DBG
if (ConfigGetParamBool(g_CoreConfig, "EnableDebugger"))
init_debugger();
#endif
/* Startup message on the OSD */
osd_new_message(OSD_MIDDLE_CENTER, "Mupen64Plus Started...");
g_EmulatorRunning = 1;
StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING);
/* call r4300 CPU core and run the game */
r4300_reset_hard();
r4300_reset_soft();
r4300_execute();
/* now begin to shut down */
#ifdef WITH_LIRC
lircStop();
#endif // WITH_LIRC
#ifdef DBG
if (g_DebuggerActive)
destroy_debugger();
#endif
if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay"))
{
osd_exit();
}
rsp.romClosed();
input.romClosed();
audio.romClosed();
gfx.romClosed();
free_memory();
// clean up
g_EmulatorRunning = 0;
StateChanged(M64CORE_EMU_STATE, M64EMU_STOPPED);
return M64ERR_SUCCESS;
}
void main_stop(void)
{
/* note: this operation is asynchronous. It may be called from a thread other than the
main emulator thread, and may return before the emulator is completely stopped */
if (!g_EmulatorRunning)
return;
DebugMessage(M64MSG_STATUS, "Stopping emulation.");
if(l_msgPause)
{
osd_delete_message(l_msgPause);
l_msgPause = NULL;
}
if(l_msgFF)
{
osd_delete_message(l_msgFF);
l_msgFF = NULL;
}
if(l_msgVol)
{
osd_delete_message(l_msgVol);
l_msgVol = NULL;
}
if (rompause)
{
rompause = 0;
StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING);
}
stop = 1;
#ifdef DBG
if(g_DebuggerActive)
{
debugger_step();
}
#endif
}
/*********************************************************************************************************
* main function
*/
int main(int argc, char *argv[])
{
return 1;
}

View File

@ -0,0 +1,77 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - main.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* 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 __MAIN_H__
#define __MAIN_H__
#include "api/m64p_types.h"
/* globals */
extern m64p_handle g_CoreConfig;
extern int g_MemHasBeenBSwapped;
extern int g_EmulatorRunning;
extern m64p_frame_callback g_FrameCallback;
const char* get_savestatepath(void);
const char* get_savesrampath(void);
void new_frame(void);
void new_vi(void);
int main_set_core_defaults(void);
void main_message(m64p_msg_level level, unsigned int osd_corner, const char *format, ...);
m64p_error main_run(void);
void main_stop(void);
void main_toggle_pause(void);
void main_advance_one(void);
void main_speedup(int percent);
void main_speeddown(int percent);
void main_set_fastforward(int enable);
void main_take_next_screenshot(void);
void main_state_set_slot(int slot);
void main_state_inc_slot(void);
void main_state_load(const char *filename);
void main_state_save(int format, const char *filename);
m64p_error main_core_state_query(m64p_core_param param, int *rval);
m64p_error main_core_state_set(m64p_core_param param, int val);
m64p_error main_get_screen_size(int *width, int *height);
m64p_error main_read_screen(void *pixels, int bFront);
m64p_error main_volume_up(void);
m64p_error main_volume_down(void);
m64p_error main_volume_get_level(int *level);
m64p_error main_volume_set_level(int level);
m64p_error main_volume_mute(void);
int main_volume_get_muted(void);
m64p_error main_reset(int do_hard_reset);
#endif /* __MAIN_H__ */

View File

@ -0,0 +1,382 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

View File

@ -0,0 +1,92 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

View File

@ -0,0 +1,536 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - rom.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 Tillin9 *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define M64P_CORE_PROTOTYPES 1
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "api/config.h"
#include "api/m64p_config.h"
#include "md5.h"
#include "rom.h"
#include "main.h"
#include "util.h"
#include "memory/memory.h"
#include "osal/preproc.h"
#include "osd/osd.h"
#define DEFAULT 16
#define CHUNKSIZE 1024*128 /* Read files 128KB at a time. */
static romdatabase_entry* ini_search_by_md5(md5_byte_t* md5);
static _romdatabase g_romdatabase;
/* Global loaded rom memory space. */
unsigned char* rom = NULL;
/* Global loaded rom size. */
int rom_size = 0;
unsigned char isGoldeneyeRom = 0;
m64p_rom_header ROM_HEADER;
rom_params ROM_PARAMS;
m64p_rom_settings ROM_SETTINGS;
static m64p_system_type rom_country_code_to_system_type(char country_code);
static int rom_system_type_to_ai_dac_rate(m64p_system_type system_type);
static int rom_system_type_to_vi_limit(m64p_system_type system_type);
/* Tests if a file is a valid N64 rom by checking the first 4 bytes. */
static int is_valid_rom(const unsigned char *buffer)
{
/* Test if rom is a native .z64 image with header 0x80371240. [ABCD] */
if((buffer[0]==0x80)&&(buffer[1]==0x37)&&(buffer[2]==0x12)&&(buffer[3]==0x40))
return 1;
/* Test if rom is a byteswapped .v64 image with header 0x37804012. [BADC] */
else if((buffer[0]==0x37)&&(buffer[1]==0x80)&&(buffer[2]==0x40)&&(buffer[3]==0x12))
return 1;
/* Test if rom is a wordswapped .n64 image with header 0x40123780. [DCBA] */
else if((buffer[0]==0x40)&&(buffer[1]==0x12)&&(buffer[2]==0x37)&&(buffer[3]==0x80))
return 1;
else
return 0;
}
/* If rom is a .v64 or .n64 image, byteswap or wordswap loadlength amount of
* rom data to native .z64 before forwarding. Makes sure that data extraction
* and MD5ing routines always deal with a .z64 image.
*/
static void swap_rom(unsigned char* localrom, unsigned char* imagetype, int loadlength)
{
unsigned char temp;
int i;
/* Btyeswap if .v64 image. */
if(localrom[0]==0x37)
{
*imagetype = V64IMAGE;
for (i = 0; i < loadlength; i+=2)
{
temp=localrom[i];
localrom[i]=localrom[i+1];
localrom[i+1]=temp;
}
}
/* Wordswap if .n64 image. */
else if(localrom[0]==0x40)
{
*imagetype = N64IMAGE;
for (i = 0; i < loadlength; i+=4)
{
temp=localrom[i];
localrom[i]=localrom[i+3];
localrom[i+3]=temp;
temp=localrom[i+1];
localrom[i+1]=localrom[i+2];
localrom[i+2]=temp;
}
}
else
*imagetype = Z64IMAGE;
}
m64p_error open_rom(const unsigned char* romimage, unsigned int size)
{
md5_state_t state;
md5_byte_t digest[16];
romdatabase_entry* entry;
char buffer[256];
unsigned char imagetype;
int i;
/* check input requirements */
if (rom != NULL)
{
DebugMessage(M64MSG_ERROR, "open_rom(): previous ROM image was not freed");
return M64ERR_INTERNAL;
}
if (romimage == NULL || !is_valid_rom(romimage))
{
DebugMessage(M64MSG_ERROR, "open_rom(): not a valid ROM image");
return M64ERR_INPUT_INVALID;
}
/* Clear Byte-swapped flag, since ROM is now deleted. */
g_MemHasBeenBSwapped = 0;
/* allocate new buffer for ROM and copy into this buffer */
rom_size = size;
rom = (unsigned char *) malloc(size);
if (rom == NULL)
return M64ERR_NO_MEMORY;
memcpy(rom, romimage, size);
swap_rom(rom, &imagetype, rom_size);
memcpy(&ROM_HEADER, rom, sizeof(m64p_rom_header));
/* Calculate MD5 hash */
md5_init(&state);
md5_append(&state, (const md5_byte_t*)rom, rom_size);
md5_finish(&state, digest);
for ( i = 0; i < 16; ++i )
sprintf(buffer+i*2, "%02X", digest[i]);
buffer[32] = '\0';
strcpy(ROM_SETTINGS.MD5, buffer);
/* add some useful properties to ROM_PARAMS */
ROM_PARAMS.systemtype = rom_country_code_to_system_type(ROM_HEADER.Country_code);
ROM_PARAMS.vilimit = rom_system_type_to_vi_limit(ROM_PARAMS.systemtype);
ROM_PARAMS.aidacrate = rom_system_type_to_ai_dac_rate(ROM_PARAMS.systemtype);
memcpy(ROM_PARAMS.headername, ROM_HEADER.Name, 20);
ROM_PARAMS.headername[20] = '\0';
trim(ROM_PARAMS.headername); /* Remove trailing whitespace from ROM name. */
/* Look up this ROM in the .ini file and fill in goodname, etc */
if ((entry=ini_search_by_md5(digest)) != NULL ||
(entry=ini_search_by_crc(sl(ROM_HEADER.CRC1),sl(ROM_HEADER.CRC2))) != NULL)
{
strncpy(ROM_SETTINGS.goodname, entry->goodname, 255);
ROM_SETTINGS.goodname[255] = '\0';
ROM_SETTINGS.savetype = entry->savetype;
ROM_SETTINGS.status = entry->status;
ROM_SETTINGS.players = entry->players;
ROM_SETTINGS.rumble = entry->rumble;
}
else
{
strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername);
strcat(ROM_SETTINGS.goodname, " (unknown rom)");
ROM_SETTINGS.savetype = NONE;
ROM_SETTINGS.status = 0;
ROM_SETTINGS.players = 0;
ROM_SETTINGS.rumble = 0;
}
/* print out a bunch of info about the ROM */
DebugMessage(M64MSG_INFO, "Goodname: %s", ROM_SETTINGS.goodname);
DebugMessage(M64MSG_INFO, "Name: %s", ROM_HEADER.Name);
imagestring(imagetype, buffer);
DebugMessage(M64MSG_INFO, "MD5: %s", ROM_SETTINGS.MD5);
DebugMessage(M64MSG_INFO, "CRC: %x %x", sl(ROM_HEADER.CRC1), sl(ROM_HEADER.CRC2));
DebugMessage(M64MSG_INFO, "Imagetype: %s", buffer);
DebugMessage(M64MSG_INFO, "Rom size: %d bytes (or %d Mb or %d Megabits)", rom_size, rom_size/1024/1024, rom_size/1024/1024*8);
DebugMessage(M64MSG_VERBOSE, "ClockRate = %x", sl(ROM_HEADER.ClockRate));
DebugMessage(M64MSG_INFO, "Version: %x", sl(ROM_HEADER.Release));
if(sl(ROM_HEADER.Manufacturer_ID) == 'N')
DebugMessage(M64MSG_INFO, "Manufacturer: Nintendo");
else
DebugMessage(M64MSG_INFO, "Manufacturer: %x", sl(ROM_HEADER.Manufacturer_ID));
DebugMessage(M64MSG_VERBOSE, "Cartridge_ID: %x", ROM_HEADER.Cartridge_ID);
countrycodestring(ROM_HEADER.Country_code, buffer);
DebugMessage(M64MSG_INFO, "Country: %s", buffer);
DebugMessage(M64MSG_VERBOSE, "PC = %x", sl((unsigned int)ROM_HEADER.PC));
DebugMessage(M64MSG_VERBOSE, "Save type: %d", ROM_SETTINGS.savetype);
//Prepare Hack for GOLDENEYE
isGoldeneyeRom = 0;
if(strcmp(ROM_PARAMS.headername, "GOLDENEYE") == 0)
isGoldeneyeRom = 1;
return M64ERR_SUCCESS;
}
m64p_error close_rom(void)
{
if (rom == NULL)
return M64ERR_INVALID_STATE;
free(rom);
rom = NULL;
/* Clear Byte-swapped flag, since ROM is now deleted. */
g_MemHasBeenBSwapped = 0;
DebugMessage(M64MSG_STATUS, "Rom closed.");
return M64ERR_SUCCESS;
}
/********************************************************************************************/
/* ROM utility functions */
// Get the system type associated to a ROM country code.
static m64p_system_type rom_country_code_to_system_type(char country_code)
{
switch (country_code)
{
// PAL codes
case 0x44:
case 0x46:
case 0x49:
case 0x50:
case 0x53:
case 0x55:
case 0x58:
case 0x59:
return SYSTEM_PAL;
// NTSC codes
case 0x37:
case 0x41:
case 0x45:
case 0x4a:
default: // Fallback for unknown codes
return SYSTEM_NTSC;
}
}
// Get the VI (vertical interrupt) limit associated to a ROM system type.
static int rom_system_type_to_vi_limit(m64p_system_type system_type)
{
switch (system_type)
{
case SYSTEM_PAL:
case SYSTEM_MPAL:
return 50;
case SYSTEM_NTSC:
default:
return 60;
}
}
static int rom_system_type_to_ai_dac_rate(m64p_system_type system_type)
{
switch (system_type)
{
case SYSTEM_PAL:
return 49656530;
case SYSTEM_MPAL:
return 48628316;
case SYSTEM_NTSC:
default:
return 48681812;
}
}
/********************************************************************************************/
/* INI Rom database functions */
void romdatabase_open(void)
{
FILE *fPtr;
char buffer[256];
romdatabase_search* search = NULL;
romdatabase_search** next_search;
int counter, value, lineno;
unsigned char index;
const char *pathname = ConfigGetSharedDataFilepath("mupen64plus.ini");
if(g_romdatabase.have_database)
return;
/* Open romdatabase. */
if (pathname == NULL || (fPtr = fopen(pathname, "rb")) == NULL)
{
DebugMessage(M64MSG_ERROR, "Unable to open rom database file '%s'.", pathname);
return;
}
g_romdatabase.have_database = 1;
/* Clear premade indices. */
for(counter = 0; counter < 255; ++counter)
g_romdatabase.crc_lists[counter] = NULL;
for(counter = 0; counter < 255; ++counter)
g_romdatabase.md5_lists[counter] = NULL;
g_romdatabase.list = NULL;
next_search = &g_romdatabase.list;
/* Parse ROM database file */
for (lineno = 1; fgets(buffer, 255, fPtr) != NULL; lineno++)
{
char *line = buffer;
ini_line l = ini_parse_line(&line);
switch (l.type)
{
case INI_SECTION:
{
md5_byte_t md5[16];
if (!parse_hex(l.name, md5, 16))
{
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid MD5 on line %i", lineno);
search = NULL;
continue;
}
*next_search = (romdatabase_search*)malloc(sizeof(romdatabase_search));
search = *next_search;
next_search = &search->next_entry;
search->entry.goodname = NULL;
memcpy(search->entry.md5, md5, 16);
search->entry.refmd5 = NULL;
search->entry.crc1 = 0;
search->entry.crc2 = 0;
search->entry.status = 0; /* Set default to 0 stars. */
search->entry.savetype = DEFAULT;
search->entry.players = DEFAULT;
search->entry.rumble = DEFAULT;
search->next_entry = NULL;
search->next_crc = NULL;
/* Index MD5s by first 8 bits. */
index = search->entry.md5[0];
search->next_md5 = g_romdatabase.md5_lists[index];
g_romdatabase.md5_lists[index] = search;
break;
}
case INI_PROPERTY:
// This happens if there's stray properties before any section,
// or if some error happened on INI_SECTION (e.g. parsing).
if (search == NULL)
{
DebugMessage(M64MSG_WARNING, "ROM Database: Ignoring property on line %i", lineno);
continue;
}
if(!strcmp(l.name, "GoodName"))
{
search->entry.goodname = strdup(l.value);
}
else if(!strcmp(l.name, "CRC"))
{
char garbage_sweeper;
if (sscanf(l.value, "%X %X%c", &search->entry.crc1,
&search->entry.crc2, &garbage_sweeper) == 2)
{
/* Index CRCs by first 8 bits. */
index = search->entry.crc1 >> 24;
search->next_crc = g_romdatabase.crc_lists[index];
g_romdatabase.crc_lists[index] = search;
}
else
{
search->entry.crc1 = search->entry.crc2 = 0;
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid CRC on line %i", lineno);
}
}
else if(!strcmp(l.name, "RefMD5"))
{
md5_byte_t md5[16];
if (parse_hex(l.value, md5, 16))
{
search->entry.refmd5 = (md5_byte_t*)malloc(16*sizeof(md5_byte_t));
memcpy(search->entry.refmd5, md5, 16);
}
else
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid RefMD5 on line %i", lineno);
}
else if(!strcmp(l.name, "SaveType"))
{
if(!strcmp(l.value, "Eeprom 4KB"))
search->entry.savetype = EEPROM_4KB;
else if(!strcmp(l.value, "Eeprom 16KB"))
search->entry.savetype = EEPROM_16KB;
else if(!strcmp(l.value, "SRAM"))
search->entry.savetype = SRAM;
else if(!strcmp(l.value, "Flash RAM"))
search->entry.savetype = FLASH_RAM;
else if(!strcmp(l.value, "Controller Pack"))
search->entry.savetype = CONTROLLER_PACK;
else if(!strcmp(l.value, "None"))
search->entry.savetype = NONE;
else
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid save type on line %i", lineno);
}
else if(!strcmp(l.name, "Status"))
{
if (string_to_int(l.value, &value) && value >= 0 && value < 6)
search->entry.status = value;
else
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid status on line %i", lineno);
}
else if(!strcmp(l.name, "Players"))
{
if (string_to_int(l.value, &value) && value >= 0 && value < 8)
search->entry.players = value;
else
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid player count on line %i", lineno);
}
else if(!strcmp(l.name, "Rumble"))
{
if(!strcmp(l.value, "Yes"))
search->entry.rumble = 1;
else if(!strcmp(l.value, "No"))
search->entry.rumble = 0;
else
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid rumble string on line %i", lineno);
}
else
{
DebugMessage(M64MSG_WARNING, "ROM Database: Unknown property on line %i", lineno);
}
break;
default:
break;
}
}
fclose(fPtr);
/* Resolve RefMD5 references */
for (search = g_romdatabase.list; search != NULL; search = search->next_entry)
{
if (search->entry.refmd5 != NULL)
{
romdatabase_entry *ref = ini_search_by_md5(search->entry.refmd5);
if (ref != NULL)
{
if(ref->savetype!=DEFAULT)
search->entry.savetype = ref->savetype;
if(ref->status!=0)
search->entry.status = ref->status;
if(ref->players!=DEFAULT)
search->entry.players = ref->players;
if(ref->rumble!=DEFAULT)
search->entry.rumble = ref->rumble;
}
else
DebugMessage(M64MSG_WARNING, "ROM Database: Error solving RefMD5s");
}
}
}
void romdatabase_close(void)
{
if (!g_romdatabase.have_database)
return;
while (g_romdatabase.list != NULL)
{
romdatabase_search* search = g_romdatabase.list->next_entry;
if(g_romdatabase.list->entry.goodname)
free(g_romdatabase.list->entry.goodname);
if(g_romdatabase.list->entry.refmd5)
free(g_romdatabase.list->entry.refmd5);
free(g_romdatabase.list);
g_romdatabase.list = search;
}
}
static romdatabase_entry* ini_search_by_md5(md5_byte_t* md5)
{
romdatabase_search* search;
if(!g_romdatabase.have_database)
return NULL;
search = g_romdatabase.md5_lists[md5[0]];
while (search != NULL && memcmp(search->entry.md5, md5, 16) != 0)
search = search->next_md5;
if(search==NULL)
return NULL;
return &(search->entry);
}
romdatabase_entry* ini_search_by_crc(unsigned int crc1, unsigned int crc2)
{
romdatabase_search* search;
if(!g_romdatabase.have_database)
return NULL;
search = g_romdatabase.crc_lists[((crc1 >> 24) & 0xff)];
while (search != NULL && search->entry.crc1 != crc1 && search->entry.crc2 != crc2)
search = search->next_crc;
if(search == NULL)
return NULL;
return &(search->entry);
}

View File

@ -0,0 +1,140 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - rom.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008 Tillin9 *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef __ROM_H__
#define __ROM_H__
#include "api/m64p_types.h"
#include "md5.h"
/* ROM Loading and Saving functions */
m64p_error open_rom(const unsigned char* romimage, unsigned int size);
m64p_error close_rom(void);
extern unsigned char* rom;
extern int rom_size;
extern unsigned char isGoldeneyeRom;
typedef struct _rom_params
{
m64p_system_type systemtype;
int vilimit;
int aidacrate;
char headername[21]; /* ROM Name as in the header, removing trailing whitespace */
} rom_params;
extern m64p_rom_header ROM_HEADER;
extern rom_params ROM_PARAMS;
extern m64p_rom_settings ROM_SETTINGS;
/* Supported rom compressiontypes. */
enum
{
UNCOMPRESSED,
ZIP_COMPRESSION,
GZIP_COMPRESSION,
BZIP2_COMPRESSION,
LZMA_COMPRESSION,
SZIP_COMPRESSION
};
/* Supported rom image types. */
enum
{
Z64IMAGE,
V64IMAGE,
N64IMAGE
};
/* Supported CIC chips. */
enum
{
CIC_NUS_6101,
CIC_NUS_6102,
CIC_NUS_6103,
CIC_NUS_6105,
CIC_NUS_6106
};
/* Supported save types. */
enum
{
EEPROM_4KB,
EEPROM_16KB,
SRAM,
FLASH_RAM,
CONTROLLER_PACK,
NONE
};
/* Rom INI database structures and functions */
/* The romdatabase contains the items mupen64plus indexes for each rom. These
* include the goodname (from the GoodN64 project), the current status of the rom
* in mupen, the N64 savetype used in the original cartridge (often necessary for
* booting the rom in mupen), the number of players (including netplay options),
* and whether the rom can make use of the N64's rumble feature. Md5, crc1, and
* crc2 used for rom lookup. Md5s are unique hashes of the ENTIRE rom. Crcs are not
* unique and read from the rom header, meaning corrupt crcs are also a problem.
* Crcs were widely used (mainly in the cheat system). Refmd5s allows for a smaller
* database file and need not be used outside database loading.
*/
typedef struct
{
char* goodname;
md5_byte_t md5[16];
md5_byte_t* refmd5;
unsigned int crc1;
unsigned int crc2;
unsigned char status; /* Rom status on a scale from 0-5. */
unsigned char savetype;
unsigned char players; /* Local players 0-4, 2/3/4 way Netplay indicated by 5/6/7. */
unsigned char rumble; /* 0 - No, 1 - Yes boolean for rumble support. */
} romdatabase_entry;
typedef struct _romdatabase_search
{
romdatabase_entry entry;
struct _romdatabase_search* next_entry;
struct _romdatabase_search* next_crc;
struct _romdatabase_search* next_md5;
} romdatabase_search;
typedef struct
{
int have_database;
romdatabase_search* crc_lists[256];
romdatabase_search* md5_lists[256];
romdatabase_search* list;
} _romdatabase;
void romdatabase_open(void);
void romdatabase_close(void);
/* Should be used by current cheat system (isn't), when cheat system is
* migrated to md5s, will be fully depreciated.
*/
romdatabase_entry* ini_search_by_crc(unsigned int crc1, unsigned int crc2);
#endif /* __ROM_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - savestates.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* Copyright (C) 2009 Olejl Tillin9 *
* Copyright (C) 2008 Richard42 Tillin9 *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef __SAVESTAVES_H__
#define __SAVESTAVES_H__
typedef enum _savestates_job
{
savestates_job_nothing,
savestates_job_load,
savestates_job_save
} savestates_job;
typedef enum _savestates_type
{
savestates_type_unknown,
savestates_type_m64p,
savestates_type_pj64_zip,
savestates_type_pj64_unc
} savestates_type;
savestates_job savestates_get_job(void);
void savestates_set_job(savestates_job j, savestates_type t, const char *fn);
void savestates_init(void);
void savestates_deinit(void);
int savestates_load(void);
int savestates_save(void);
void savestates_select_slot(unsigned int s);
unsigned int savestates_get_slot(void);
void savestates_set_autoinc_slot(int b);
void savestates_inc_slot(void);
#endif /* __SAVESTAVES_H__ */

View File

@ -0,0 +1,404 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - util.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* Provides common utilities to the rest of the code:
* -String functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <limits.h>
#include "rom.h"
#include "util.h"
#include "osal/files.h"
#include "osal/preproc.h"
/**********************
File utilities
**********************/
file_status_t read_from_file(const char *filename, void *data, size_t size)
{
FILE *f = fopen(filename, "rb");
if (f == NULL)
{
return file_open_error;
}
if (fread(data, 1, size, f) != size)
{
fclose(f);
return file_read_error;
}
fclose(f);
return file_ok;
}
file_status_t write_to_file(const char *filename, const void *data, size_t size)
{
FILE *f = fopen(filename, "wb");
if (f == NULL)
{
return file_open_error;
}
if (fwrite(data, 1, size, f) != size)
{
fclose(f);
return file_read_error;
}
fclose(f);
return file_ok;
}
/**********************
Byte swap utilities
**********************/
void swap_buffer(void *buffer, size_t length, size_t count)
{
size_t i;
if (length == 2)
{
unsigned short *pun = (unsigned short *)buffer;
for (i = 0; i < count; i++)
pun[i] = m64p_swap16(pun[i]);
}
else if (length == 4)
{
unsigned int *pun = (unsigned int *)buffer;
for (i = 0; i < count; i++)
pun[i] = m64p_swap32(pun[i]);
}
else if (length == 8)
{
unsigned long long *pun = (unsigned long long *)buffer;
for (i = 0; i < count; i++)
pun[i] = m64p_swap64(pun[i]);
}
}
void to_little_endian_buffer(void *buffer, size_t length, size_t count)
{
#ifdef M64P_BIG_ENDIAN
swap_buffer(buffer, length, count);
#endif
}
void to_big_endian_buffer(void *buffer, size_t length, size_t count)
{
#ifndef M64P_BIG_ENDIAN
swap_buffer(buffer, length, count);
#endif
}
/**********************
GUI utilities
**********************/
void countrycodestring(char countrycode, char *string)
{
switch (countrycode)
{
case 0: /* Demo */
strcpy(string, "Demo");
break;
case '7': /* Beta */
strcpy(string, "Beta");
break;
case 0x41: /* Japan / USA */
strcpy(string, "USA/Japan");
break;
case 0x44: /* Germany */
strcpy(string, "Germany");
break;
case 0x45: /* USA */
strcpy(string, "USA");
break;
case 0x46: /* France */
strcpy(string, "France");
break;
case 'I': /* Italy */
strcpy(string, "Italy");
break;
case 0x4A: /* Japan */
strcpy(string, "Japan");
break;
case 'S': /* Spain */
strcpy(string, "Spain");
break;
case 0x55: case 0x59: /* Australia */
sprintf(string, "Australia (0x%02X)", countrycode);
break;
case 0x50: case 0x58: case 0x20:
case 0x21: case 0x38: case 0x70:
sprintf(string, "Europe (0x%02X)", countrycode);
break;
default:
sprintf(string, "Unknown (0x%02X)", countrycode);
break;
}
}
void imagestring(unsigned char imagetype, char *string)
{
switch (imagetype)
{
case Z64IMAGE:
strcpy(string, ".z64 (native)");
break;
case V64IMAGE:
strcpy(string, ".v64 (byteswapped)");
break;
case N64IMAGE:
strcpy(string, ".n64 (wordswapped)");
break;
default:
string[0] = '\0';
}
}
/**********************
Path utilities
**********************/
/* Looks for an instance of ANY of the characters in 'needles' in 'haystack',
* starting from the end of 'haystack'. Returns a pointer to the last position
* of some character on 'needles' on 'haystack'. If not found, returns NULL.
*/
static const char* strpbrk_reverse(const char* needles, const char* haystack)
{
size_t stringlength = strlen(haystack), counter;
for (counter = stringlength; counter > 0; --counter)
{
if (strchr(needles, haystack[counter-1]))
break;
}
if (counter == 0)
return NULL;
return haystack + counter - 1;
}
const char* namefrompath(const char* path)
{
const char* last_separator_ptr = strpbrk_reverse(OSAL_DIR_SEPARATORS, path);
if (last_separator_ptr != NULL)
return last_separator_ptr + 1;
else
return path;
}
static int is_path_separator(char c)
{
return strchr(OSAL_DIR_SEPARATORS, c) != NULL;
}
char* combinepath(const char* first, const char *second)
{
size_t len_first = strlen(first), off_second = 0;
if (first == NULL || second == NULL)
return NULL;
while (is_path_separator(first[len_first-1]))
len_first--;
while (is_path_separator(second[off_second]))
off_second++;
return formatstr("%.*s%c%s", (int) len_first, first, OSAL_DIR_SEPARATORS[0], second + off_second);
}
/**********************
String utilities
**********************/
char *trim(char *str)
{
char *start = str, *end = str + strlen(str);
while (start < end && isspace(*start))
start++;
while (end > start && isspace(*(end-1)))
end--;
memmove(str, start, end - start);
str[end - start] = '\0';
return str;
}
int string_to_int(const char *str, int *result)
{
char *endptr;
long int n;
if (*str == '\0' || isspace(*str))
return 0;
errno = 0;
n = strtol(str, &endptr, 10);
if (*endptr != '\0' || errno != 0 || n < INT_MIN || n > INT_MAX)
return 0;
*result = (int)n;
return 1;
}
static unsigned char char2hex(char c)
{
c = tolower(c);
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return 0xFF;
}
int parse_hex(const char *str, unsigned char *output, size_t output_size)
{
size_t i, j;
for (i = 0; i < output_size; i++)
{
output[i] = 0;
for (j = 0; j < 2; j++)
{
unsigned char h = char2hex(*str++);
if (h == 0xFF)
return 0;
output[i] = (output[i] << 4) | h;
}
}
if (*str != '\0')
return 0;
return 1;
}
char *formatstr(const char *fmt, ...)
{
int size = 128, ret;
char *str = (char *)malloc(size), *newstr;
va_list args;
/* There are two implementations of vsnprintf we have to deal with:
* C99 version: Returns the number of characters which would have been written
* if the buffer had been large enough, and -1 on failure.
* Windows version: Returns the number of characters actually written,
* and -1 on failure or truncation.
* NOTE: An implementation equivalent to the Windows one appears in glibc <2.1.
*/
while (str != NULL)
{
va_start(args, fmt);
ret = vsnprintf(str, size, fmt, args);
va_end(args);
// Successful result?
if (ret >= 0 && ret < size)
return str;
// Increment the capacity of the buffer
if (ret >= size)
size = ret + 1; // C99 version: We got the needed buffer size
else
size *= 2; // Windows version: Keep guessing
newstr = (char *)realloc(str, size);
if (newstr == NULL)
free(str);
str = newstr;
}
return NULL;
}
ini_line ini_parse_line(char **lineptr)
{
char *line = *lineptr, *endline = strchr(*lineptr, '\n'), *equal;
ini_line l;
// Null terminate the current line and point to the next line
if (endline != NULL)
*endline = '\0';
*lineptr = line + strlen(line) + 1;
// Parse the line contents
trim(line);
if (line[0] == '#' || line[0] == ';')
{
line++;
l.type = INI_COMMENT;
l.name = NULL;
l.value = trim(line);
}
else if (line[0] == '[' && line[strlen(line)-1] == ']')
{
line[strlen(line)-1] = '\0';
line++;
l.type = INI_SECTION;
l.name = trim(line);
l.value = NULL;
}
else if ((equal = strchr(line, '=')) != NULL)
{
char *name = line, *value = equal + 1;
*equal = '\0';
l.type = INI_PROPERTY;
l.name = trim(name);
l.value = trim(value);
}
else
{
l.type = (*line == '\0') ? INI_BLANK : INI_TRASH;
l.name = NULL;
l.value = NULL;
}
return l;
}

View File

@ -0,0 +1,212 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - util.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef __UTIL_H__
#define __UTIL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
/**********************
File utilities
**********************/
typedef enum _file_status
{
file_ok,
file_open_error,
file_read_error,
file_write_error
} file_status_t;
/** read_from_file
* opens a file and reads the specified number of bytes.
* returns zero on success, nonzero on failure
*/
file_status_t read_from_file(const char *filename, void *data, size_t size);
/** write_to_file
* opens a file and writes the specified number of bytes.
* returns zero on sucess, nonzero on failure
*/
file_status_t write_to_file(const char *filename, const void *data, size_t size);
/**********************
Byte swap utilities
**********************/
#ifdef _MSC_VER
#include <stdlib.h>
#endif
/* GCC has also byte swap intrinsics (__builtin_bswap32, etc.), but they were
* added in relatively recent versions. In addition, GCC can detect the byte
* swap code and optimize it with a high enough optimization level. */
static inline unsigned short m64p_swap16(unsigned short x)
{
#ifdef _MSC_VER
return _byteswap_ushort(x);
#else
return ((x & 0x00FF) << 8) |
((x & 0xFF00) >> 8);
#endif
}
static inline unsigned int m64p_swap32(unsigned int x)
{
#ifdef _MSC_VER
return _byteswap_ulong(x); // long is always 32-bit in Windows
#else
return ((x & 0x000000FF) << 24) |
((x & 0x0000FF00) << 8) |
((x & 0x00FF0000) >> 8) |
((x & 0xFF000000) >> 24);
#endif
}
static inline unsigned long long int m64p_swap64(unsigned long long int x)
{
#ifdef _MSC_VER
return _byteswap_uint64(x);
#else
return ((x & 0x00000000000000FFULL) << 56) |
((x & 0x000000000000FF00ULL) << 40) |
((x & 0x0000000000FF0000ULL) << 24) |
((x & 0x00000000FF000000ULL) << 8) |
((x & 0x000000FF00000000ULL) >> 8) |
((x & 0x0000FF0000000000ULL) >> 24) |
((x & 0x00FF000000000000ULL) >> 40) |
((x & 0xFF00000000000000ULL) >> 56);
#endif
}
#ifdef M64P_BIG_ENDIAN
#define big16(x) (x)
#define big32(x) (x)
#define big64(x) (x)
#define little16(x) m64p_swap16(x)
#define little32(x) m64p_swap32(x)
#define little64(x) m64p_swap64(x)
#else
#define big16(x) m64p_swap16(x)
#define big32(x) m64p_swap32(x)
#define big64(x) m64p_swap64(x)
#define little16(x) (x)
#define little32(x) (x)
#define little64(x) (x)
#endif
/* Byte swaps, converts to little endian or converts to big endian a buffer,
* containing 'count' elements, each of size 'length'. */
void swap_buffer(void *buffer, size_t length, size_t count);
void to_little_endian_buffer(void *buffer, size_t length, size_t count);
void to_big_endian_buffer(void *buffer, size_t length, size_t count);
/**********************
GUI utilities
**********************/
void countrycodestring(char countrycode, char *string);
void imagestring(unsigned char imagetype, char *string);
/**********************
Path utilities
**********************/
/* Extracts the full file name (with extension) from a path string.
* Returns the same string, advanced until the file name. */
const char* namefrompath(const char* path);
/* Creates a path string by joining two path strings.
* The given path strings may or may not start or end with a path separator.
* Returns a malloc'd string with the resulting path. */
char* combinepath(const char* first, const char *second);
/**********************
String utilities
**********************/
/** trim
* Removes leading and trailing whitespace from str. Function modifies str
* and also returns modified string.
*/
char *trim(char *str);
/* Converts an string to an integer.
* Returns 1 on success, 0 on failure. 'result' is undefined on failure.
*
* The following conditions cause this function to fail:
* - Empty string
* - Leading characters (including whitespace)
* - Trailing characters (including whitespace)
* - Overflow or underflow.
*/
int string_to_int(const char *str, int *result);
/* Converts an string of hexadecimal characters to a byte array.
* 'output_size' is the number of bytes (hex digraphs) to convert.
* Returns 1 on success, 0 on failure. 'output' is undefined on failure. */
int parse_hex(const char *str, unsigned char *output, size_t output_size);
/* Formats an string, using the same syntax as printf.
* Returns the result in a malloc'd string. */
char* formatstr(const char* fmt, ...);
typedef enum _ini_line_type
{
INI_BLANK,
INI_COMMENT,
INI_SECTION,
INI_PROPERTY,
INI_TRASH
} ini_line_type;
typedef struct _ini_line
{
ini_line_type type;
char *name;
char *value;
} ini_line;
/* Parses the INI file line pointer by 'lineptr'.
* The first line pointed by 'lineptr' may be modifed.
* 'lineptr' will point to the next line after this function runs.
*
* Returns a ini_line structure with information about the line.
* For INI_COMMENT, the value field contains the comment.
* For INI_SECTION, the name field contains the section name.
* For INI_PROPERTY, the name and value fields contain the property parameters.
* The line type is INI_BLANK if the line is blank or invalid.
*
* The name and value fields (if any) of ini_line point to 'lineptr'
* (so their lifetime is associated to that of 'lineptr').
*/
ini_line ini_parse_line(char **lineptr);
#ifdef __cplusplus
}
#endif
#endif // __UTIL_H__

View File

@ -0,0 +1,39 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - version.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2008-2012 Richard42 DarkJeztr Tillin9 *
* *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Version macros automatically replaced by Makefiles. */
#ifndef __VERSION_H__
#define __VERSION_H__
#define MUPEN_CORE_NAME "Mupen64Plus Core"
#define MUPEN_CORE_VERSION 0x016305
#define FRONTEND_API_VERSION 0x020100
#define CONFIG_API_VERSION 0x020200
#define DEBUG_API_VERSION 0x020000
#define VIDEXT_API_VERSION 0x020000
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
#endif /* __VERSION_H__ */

View File

@ -0,0 +1,185 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - util.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 Mupen64plus development team *
* *
* 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 "workqueue.h"
#include "api/callbacks.h"
#include <SDL.h>
#include <SDL_thread.h>
#define WORKQUEUE_THREADS 1
struct workqueue_mgmt_globals {
struct list_head work_queue;
struct list_head thread_queue;
struct list_head thread_list;
SDL_mutex *lock;
};
struct workqueue_thread {
SDL_Thread *thread;
SDL_cond *work_avail;
struct list_head list;
struct list_head list_mgmt;
};
static struct workqueue_mgmt_globals workqueue_mgmt;
static void workqueue_dismiss(struct work_struct *work)
{
}
static struct work_struct *workqueue_get_work(struct workqueue_thread *thread)
{
int found = 0;
struct work_struct *work;
while (1) {
SDL_LockMutex(workqueue_mgmt.lock);
list_del_init(&thread->list);
if (!list_empty(&workqueue_mgmt.work_queue)) {
found = 1;
work = list_first_entry(&workqueue_mgmt.work_queue, struct work_struct, list);
list_del_init(&work->list);
} else {
list_add(&thread->list, &workqueue_mgmt.thread_queue);
SDL_CondWait(thread->work_avail, workqueue_mgmt.lock);
}
SDL_UnlockMutex(workqueue_mgmt.lock);
if (found)
break;
}
return work;
}
static int workqueue_thread_handler(void *data)
{
struct workqueue_thread *thread = data;
struct work_struct *work;
while (1) {
work = workqueue_get_work(thread);
if (work->func == workqueue_dismiss) {
free(work);
break;
}
work->func(work);
}
return 0;
}
int workqueue_init(void)
{
size_t i;
struct workqueue_thread *thread;
memset(&workqueue_mgmt, 0, sizeof(workqueue_mgmt));
INIT_LIST_HEAD(&workqueue_mgmt.work_queue);
INIT_LIST_HEAD(&workqueue_mgmt.thread_queue);
INIT_LIST_HEAD(&workqueue_mgmt.thread_list);
workqueue_mgmt.lock = SDL_CreateMutex();
if (!workqueue_mgmt.lock) {
DebugMessage(M64MSG_ERROR, "Could not create workqueue management");
return -1;
}
SDL_LockMutex(workqueue_mgmt.lock);
for (i = 0; i < WORKQUEUE_THREADS; i++) {
thread = malloc(sizeof(*thread));
if (!thread) {
DebugMessage(M64MSG_ERROR, "Could not create workqueue thread management data");
SDL_UnlockMutex(workqueue_mgmt.lock);
return -1;
}
memset(thread, 0, sizeof(*thread));
list_add(&thread->list_mgmt, &workqueue_mgmt.thread_list);
INIT_LIST_HEAD(&thread->list);
thread->work_avail = SDL_CreateCond();
if (!thread->work_avail) {
DebugMessage(M64MSG_ERROR, "Could not create workqueue thread work_avail condition");
SDL_UnlockMutex(workqueue_mgmt.lock);
return -1;
}
#if SDL_VERSION_ATLEAST(2,0,0)
thread->thread = SDL_CreateThread(workqueue_thread_handler, "m64pwq", thread);
#else
thread->thread = SDL_CreateThread(workqueue_thread_handler, thread);
#endif
if (!thread->thread) {
DebugMessage(M64MSG_ERROR, "Could not create workqueue thread handler");
SDL_UnlockMutex(workqueue_mgmt.lock);
return -1;
}
}
SDL_UnlockMutex(workqueue_mgmt.lock);
return 0;
}
void workqueue_shutdown(void)
{
size_t i;
int status;
struct work_struct *work;
struct workqueue_thread *thread, *safe;
for (i = 0; i < WORKQUEUE_THREADS; i++) {
work = malloc(sizeof(*work));
init_work(work, workqueue_dismiss);
queue_work(work);
}
list_for_each_entry_safe(thread, safe, &workqueue_mgmt.thread_list, struct workqueue_thread, list_mgmt) {
list_del(&thread->list_mgmt);
SDL_WaitThread(thread->thread, &status);
SDL_DestroyCond(thread->work_avail);
free(thread);
}
if (!list_empty(&workqueue_mgmt.work_queue))
DebugMessage(M64MSG_WARNING, "Stopped workqueue with work still pending");
SDL_DestroyMutex(workqueue_mgmt.lock);
}
int queue_work(struct work_struct *work)
{
struct workqueue_thread *thread;
SDL_LockMutex(workqueue_mgmt.lock);
list_add_tail(&work->list, &workqueue_mgmt.work_queue);
if (!list_empty(&workqueue_mgmt.thread_queue)) {
thread = list_first_entry(&workqueue_mgmt.thread_queue, struct workqueue_thread, list);
list_del_init(&thread->list);
SDL_CondSignal(thread->work_avail);
}
SDL_UnlockMutex(workqueue_mgmt.lock);
return 0;
}

View File

@ -0,0 +1,65 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - util.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 Mupen64plus development team *
* *
* 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 __WORKQUEUE_H__
#define __WORKQUEUE_H__
#include "list.h"
struct work_struct *work;
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
work_func_t func;
struct list_head list;
};
static inline void init_work(struct work_struct *work, work_func_t func)
{
INIT_LIST_HEAD(&work->list);
work->func = func;
}
#ifdef M64P_PARALLEL
int workqueue_init(void);
void workqueue_shutdown(void);
int queue_work(struct work_struct *work);
#else
static inline int workqueue_init(void)
{
return 0;
}
static inline void workqueue_shutdown(void)
{
}
static inline int queue_work(struct work_struct *work)
{
work->func(work);
return 0;
}
#endif
#endif

View File

@ -0,0 +1,131 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static int crypthead(const char* passwd, /* password string */
unsigned char* buf, /* where to write header */
int bufSize,
unsigned long* pkeys,
const unsigned long* pcrc_32_tab,
unsigned long crcForCrypting)
{
int n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

View File

@ -0,0 +1,247 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
*/
#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
#define _CRT_SECURE_NO_WARNINGS
#endif
#if defined(__APPLE__) || defined(IOAPI_NO_64)
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif
#include "ioapi.h"
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
{
if (pfilefunc->zfile_func64.zopen64_file != NULL)
return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
else
{
return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
}
}
long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
{
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
else
{
uLong offsetTruncated = (uLong)offset;
if (offsetTruncated != offset)
return -1;
else
return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
}
}
ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
{
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
else
{
uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
if ((tell_uLong) == MAXU32)
return (ZPOS64_T)-1;
else
return tell_uLong;
}
}
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
{
p_filefunc64_32->zfile_func64.zopen64_file = NULL;
p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
p_filefunc64_32->zfile_func64.ztell64_file = NULL;
p_filefunc64_32->zfile_func64.zseek64_file = NULL;
p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
}
static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = FOPEN_FUNC((const char*)filename, mode_fopen);
return file;
}
static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
{
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
{
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
{
long ret;
ret = ftell((FILE *)stream);
return ret;
}
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
{
ZPOS64_T ret;
ret = FTELLO_FUNC((FILE *)stream);
return ret;
}
static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if (fseek((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
{
int ret;
ret = fclose((FILE *)stream);
return ret;
}
static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
{
int ret;
ret = ferror((FILE *)stream);
return ret;
}
void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
{
pzlib_filefunc_def->zopen64_file = fopen64_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell64_file = ftell64_file_func;
pzlib_filefunc_def->zseek64_file = fseek64_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}

View File

@ -0,0 +1,212 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
Changes
Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
More if/def section may be needed to support other platforms
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
(but you should use iowin32.c for windows instead)
*/
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
// Linux needs this to support file operation on files larger then 4+GB
// But might need better if/def to select just the platforms that needs them.
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#ifndef OF
#define OF _Z_OF
#endif
#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#ifdef __FreeBSD__
#define fopen64 fopen
#define ftello64 ftello
#define fseeko64 fseeko
#endif
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#else // old MSC
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif
#endif
/*
#ifndef ZPOS64_T
#ifdef _WIN32
#define ZPOS64_T fpos_t
#else
#include <stdint.h>
#define ZPOS64_T uint64_t
#endif
#endif
*/
#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif
/* a type choosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else
/* Maximum unsigned 32-bit value used as placeholder for zip64 */
#define MAXU32 0xffffffff
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
/* here is the "old" 32 bits structure structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc64_def;
void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
zlib_filefunc64_def zfile_func64;
open_file_func zopen32_file;
tell_file_func ztell32_file;
seek_file_func zseek32_file;
} zlib_filefunc64_32_def;
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
/* unzip.h -- IO for uncompress .zip files using zlib
Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications of Unzip for Zip64
Copyright (C) 2007-2008 Even Rouault
Modifications for Zip64 support on both zip and unzip
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------------
Changes
See header of unzip64.c
*/
#ifndef _unz64_H
#define _unz64_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unzFile__;
typedef unzFile__ *unzFile;
#else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info64_s
{
ZPOS64_T number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info64;
typedef struct unz_global_info_s
{
uLong number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info64_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
ZPOS64_T compressed_size; /* compressed size 8 bytes */
ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info64;
typedef struct unz_file_info_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
uLong compressed_size; /* compressed size 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
extern unzFile ZEXPORT unzOpen64 OF((const void *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
"zlib/zlib113.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
the "64" function take a const void* pointer, because the path is just the
value passed to the open64_file_func callback.
Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
does not describe the reality
*/
extern unzFile ZEXPORT unzOpen2 OF((const char *path,
zlib_filefunc_def* pzlib_filefunc_def));
/*
Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
zlib_filefunc64_def* pzlib_filefunc_def));
/*
Open a Zip file, like unz64Open, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
unz_global_info *pglobal_info));
extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
unz_global_info64 *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
/* ****************************************** */
/* Ryan supplied functions */
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_pos_s
{
uLong pos_in_zip_directory; /* offset in zip file directory */
uLong num_of_file; /* # of file */
} unz_file_pos;
extern int ZEXPORT unzGetFilePos(
unzFile file,
unz_file_pos* file_pos);
extern int ZEXPORT unzGoToFilePos(
unzFile file,
unz_file_pos* file_pos);
typedef struct unz64_file_pos_s
{
ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
ZPOS64_T num_of_file; /* # of file */
} unz64_file_pos;
extern int ZEXPORT unzGetFilePos64(
unzFile file,
unz64_file_pos* file_pos);
extern int ZEXPORT unzGoToFilePos64(
unzFile file,
const unz64_file_pos* file_pos);
/* ****************************************** */
extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
unz_file_info64 *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/** Addition for GDAL : START */
extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
/** Addition for GDAL : END */
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
const char* password));
/*
Open for reading data the current file in the zipfile.
password is a crypting password
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int* method,
int* level,
int raw));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int* method,
int* level,
int raw,
const char* password));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of byte copied if somes bytes are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern z_off_t ZEXPORT unztell OF((unzFile file));
extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
/*
Give the current position in uncompressed data
*/
extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf, or (if <0)
the error code
*/
/***************************************************************************/
/* Get the current file offset */
extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
extern uLong ZEXPORT unzGetOffset (unzFile file);
/* Set the current file offset */
extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
#ifdef __cplusplus
}
#endif
#endif /* _unz64_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
/* zip.h -- IO on .zip files using zlib
Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------
Changes
See header of zip.h
*/
#ifndef _zip12_H
#define _zip12_H
#ifdef __cplusplus
extern "C" {
#endif
//#define HAVE_BZIP2
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc64_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level));
extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int zip64));
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
this MUST be '1' if the uncompressed size is >= 0xffffffff.
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw));
extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int zip64));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting));
extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
int zip64
));
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCrypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase
));
extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase,
int zip64
));
/*
Same than zipOpenNewFileInZip4, except
versionMadeBy : value for Version made by field
flag : value for flag field (compression level info will be added)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf,
unsigned len));
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size,
uLong crc32));
extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
ZPOS64_T uncompressed_size,
uLong crc32));
/*
Close the current file in the zipfile, for file opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment));
/*
Close the zipfile
*/
extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
/*
zipRemoveExtraInfoBlock - Added by Mathias Svensson
Remove extra information block from a extra information data for the local file header or central directory header
It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
0x0001 is the signature header for the ZIP64 extra information blocks
usage.
Remove ZIP64 Extra information from a central director extra field data
zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
Remove ZIP64 Extra information from a Local File Header extra field data
zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip64_H */

View File

@ -0,0 +1,387 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dma.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "api/m64p_types.h"
#include "dma.h"
#include "memory.h"
#include "pif.h"
#include "flashram.h"
#include "r4300/r4300.h"
#include "r4300/interupt.h"
#include "r4300/macros.h"
#include "r4300/ops.h"
#include "../r4300/new_dynarec/new_dynarec.h"
#define M64P_CORE_PROTOTYPES 1
#include "api/m64p_config.h"
#include "api/config.h"
#include "api/callbacks.h"
#include "main/main.h"
#include "main/rom.h"
#include "main/util.h"
static unsigned char sram[0x8000];
static char *get_sram_path(void)
{
return formatstr("%s%s.sra", get_savesrampath(), ROM_SETTINGS.goodname);
}
static void sram_format(void)
{
memset(sram, 0, sizeof(sram));
}
static void sram_read_file(void)
{
char *filename = get_sram_path();
sram_format();
switch (read_from_file(filename, sram, sizeof(sram)))
{
case file_open_error:
DebugMessage(M64MSG_VERBOSE, "couldn't open sram file '%s' for reading", filename);
sram_format();
break;
case file_read_error:
DebugMessage(M64MSG_WARNING, "fread() failed on 32kb read from sram file '%s'", filename);
sram_format();
break;
default: break;
}
free(filename);
}
static void sram_write_file(void)
{
char *filename = get_sram_path();
switch (write_to_file(filename, sram, sizeof(sram)))
{
case file_open_error:
DebugMessage(M64MSG_WARNING, "couldn't open sram file '%s' for writing.", filename);
break;
case file_write_error:
DebugMessage(M64MSG_WARNING, "fwrite() failed on 32kb write to sram file '%s'", filename);
break;
default: break;
}
free(filename);
}
void dma_pi_read(void)
{
unsigned int i;
if (pi_register.pi_cart_addr_reg >= 0x08000000
&& pi_register.pi_cart_addr_reg < 0x08010000)
{
if (flashram_info.use_flashram != 1)
{
sram_read_file();
for (i=0; i < (pi_register.pi_rd_len_reg & 0xFFFFFF)+1; i++)
{
sram[((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8] =
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8];
}
sram_write_file();
flashram_info.use_flashram = -1;
}
else
{
dma_write_flashram();
}
}
else
{
DebugMessage(M64MSG_WARNING, "Unknown dma read in dma_pi_read()");
}
pi_register.read_pi_status_reg |= 1;
update_count();
add_interupt_event(PI_INT, 0x1000/*pi_register.pi_rd_len_reg*/);
}
void dma_pi_write(void)
{
unsigned int longueur;
int i;
if (pi_register.pi_cart_addr_reg < 0x10000000)
{
if (pi_register.pi_cart_addr_reg >= 0x08000000
&& pi_register.pi_cart_addr_reg < 0x08010000)
{
if (flashram_info.use_flashram != 1)
{
int i;
sram_read_file();
for (i=0; i<(int)(pi_register.pi_wr_len_reg & 0xFFFFFF)+1; i++)
{
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8];
}
flashram_info.use_flashram = -1;
}
else
{
dma_read_flashram();
}
}
else if (pi_register.pi_cart_addr_reg >= 0x06000000
&& pi_register.pi_cart_addr_reg < 0x08000000)
{
}
else
{
DebugMessage(M64MSG_WARNING, "Unknown dma write 0x%x in dma_pi_write()", (int)pi_register.pi_cart_addr_reg);
}
pi_register.read_pi_status_reg |= 1;
update_count();
add_interupt_event(PI_INT, /*pi_register.pi_wr_len_reg*/0x1000);
return;
}
if (pi_register.pi_cart_addr_reg >= 0x1fc00000) // for paper mario
{
pi_register.read_pi_status_reg |= 1;
update_count();
add_interupt_event(PI_INT, 0x1000);
return;
}
longueur = (pi_register.pi_wr_len_reg & 0xFFFFFF)+1;
i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF;
longueur = (i + (int) longueur) > rom_size ?
(rom_size - i) : longueur;
longueur = (pi_register.pi_dram_addr_reg + longueur) > 0x7FFFFF ?
(0x7FFFFF - pi_register.pi_dram_addr_reg) : longueur;
if (i>rom_size || pi_register.pi_dram_addr_reg > 0x7FFFFF)
{
pi_register.read_pi_status_reg |= 3;
update_count();
add_interupt_event(PI_INT, longueur/8);
return;
}
if (r4300emu != CORE_PURE_INTERPRETER)
{
for (i=0; i<(int)longueur; i++)
{
unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000;
unsigned long rdram_address2 = pi_register.pi_dram_addr_reg+i+0xa0000000;
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
if (!invalid_code[rdram_address1>>12])
{
if (!blocks[rdram_address1>>12] ||
blocks[rdram_address1>>12]->block[(rdram_address1&0xFFF)/4].ops !=
current_instruction_table.NOTCOMPILED)
{
invalid_code[rdram_address1>>12] = 1;
}
#ifdef NEW_DYNAREC
invalidate_block(rdram_address1>>12);
#endif
}
if (!invalid_code[rdram_address2>>12])
{
if (!blocks[rdram_address1>>12] ||
blocks[rdram_address2>>12]->block[(rdram_address2&0xFFF)/4].ops !=
current_instruction_table.NOTCOMPILED)
{
invalid_code[rdram_address2>>12] = 1;
}
}
}
}
else
{
for (i=0; i<(int)longueur; i++)
{
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
}
}
// Set the RDRAM memory size when copying main ROM code
// (This is just a convenient way to run this code once at the beginning)
if (pi_register.pi_cart_addr_reg == 0x10001000)
{
switch (CIC_Chip)
{
case 1:
case 2:
case 3:
case 6:
{
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
{
rdram[0x318/4] = 0x400000;
}
else
{
rdram[0x318/4] = 0x800000;
}
break;
}
case 5:
{
if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
{
rdram[0x3F0/4] = 0x400000;
}
else
{
rdram[0x3F0/4] = 0x800000;
}
break;
}
}
}
pi_register.read_pi_status_reg |= 3;
update_count();
add_interupt_event(PI_INT, longueur/8);
return;
}
void dma_sp_write(void)
{
unsigned int i,j;
unsigned int l = sp_register.sp_rd_len_reg;
unsigned int length = ((l & 0xfff) | 7) + 1;
unsigned int count = ((l >> 12) & 0xff) + 1;
unsigned int skip = ((l >> 20) & 0xfff);
unsigned int memaddr = sp_register.sp_mem_addr_reg & 0xfff;
unsigned int dramaddr = sp_register.sp_dram_addr_reg & 0xffffff;
unsigned char *spmem = ((sp_register.sp_mem_addr_reg & 0x1000) != 0) ? (unsigned char*)SP_IMEM : (unsigned char*)SP_DMEM;
unsigned char *dram = (unsigned char*)rdram;
for(j=0; j<count; j++) {
for(i=0; i<length; i++) {
spmem[memaddr^S8] = dram[dramaddr^S8];
memaddr++;
dramaddr++;
}
dramaddr+=skip;
}
}
void dma_sp_read(void)
{
unsigned int i,j;
unsigned int l = sp_register.sp_wr_len_reg;
unsigned int length = ((l & 0xfff) | 7) + 1;
unsigned int count = ((l >> 12) & 0xff) + 1;
unsigned int skip = ((l >> 20) & 0xfff);
unsigned int memaddr = sp_register.sp_mem_addr_reg & 0xfff;
unsigned int dramaddr = sp_register.sp_dram_addr_reg & 0xffffff;
unsigned char *spmem = ((sp_register.sp_mem_addr_reg & 0x1000) != 0) ? (unsigned char*)SP_IMEM : (unsigned char*)SP_DMEM;
unsigned char *dram = (unsigned char*)rdram;
for(j=0; j<count; j++) {
for(i=0; i<length; i++) {
dram[dramaddr^S8] = spmem[memaddr^S8];
memaddr++;
dramaddr++;
}
dramaddr+=skip;
}
}
void dma_si_write(void)
{
int i;
if (si_register.si_pif_addr_wr64b != 0x1FC007C0)
{
DebugMessage(M64MSG_ERROR, "dma_si_write(): unknown SI use");
stop=1;
}
for (i=0; i<(64/4); i++)
{
PIF_RAM[i] = sl(rdram[si_register.si_dram_addr/4+i]);
}
update_pif_write();
// TODO: under what circumstances should bits 1 or 3 be set?
si_register.si_stat |= 1;
update_count();
add_interupt_event(SI_INT, /*0x100*/0x900);
}
void dma_si_read(void)
{
int i;
if (si_register.si_pif_addr_rd64b != 0x1FC007C0)
{
DebugMessage(M64MSG_ERROR, "dma_si_read(): unknown SI use");
stop=1;
}
update_pif_read();
for (i=0; i<(64/4); i++)
{
rdram[si_register.si_dram_addr/4+i] = sl(PIF_RAM[i]);
}
// TODO: under what circumstances should bits 1 or 3 be set?
si_register.si_stat |= 1;
update_count();
add_interupt_event(SI_INT, /*0x100*/0x900);
}

View File

@ -0,0 +1,33 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dma.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DMA_H
#define DMA_H
void dma_pi_write(void);
void dma_pi_read(void);
void dma_si_write(void);
void dma_si_read(void);
void dma_sp_write(void);
void dma_sp_read(void);
#endif

View File

@ -0,0 +1,216 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - flashram.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "memory.h"
#include "flashram.h"
#include "r4300/r4300.h"
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "main/main.h"
#include "main/rom.h"
#include "main/util.h"
Flashram_info flashram_info;
typedef enum flashram_mode
{
NOPES_MODE = 0,
ERASE_MODE,
WRITE_MODE,
READ_MODE,
STATUS_MODE
} Flashram_mode;
static unsigned char flashram[0x20000];
static char *get_flashram_path(void)
{
return formatstr("%s%s.fla", get_savesrampath(), ROM_SETTINGS.goodname);
}
static void flashram_format(void)
{
memset(flashram, 0xff, sizeof(flashram));
}
static void flashram_read_file(void)
{
char *filename = get_flashram_path();
flashram_format();
switch (read_from_file(filename, flashram, sizeof(flashram)))
{
case file_open_error:
DebugMessage(M64MSG_WARNING, "couldn't open flash ram file '%s' for reading", filename);
flashram_format();
break;
case file_read_error:
DebugMessage(M64MSG_WARNING, "couldn't read 128kb flash ram file '%s'", filename);
break;
default: break;
}
free(filename);
}
static void flashram_write_file(void)
{
char *filename = get_flashram_path();
switch (write_to_file(filename, flashram, sizeof(flashram)))
{
case file_open_error:
DebugMessage(M64MSG_WARNING, "couldn't open flash ram file '%s' for writing", filename);
break;
case file_write_error:
DebugMessage(M64MSG_WARNING, "couldn't write 128kb flash ram file '%s'", filename);
break;
default: break;
}
free(filename);
}
void init_flashram(void)
{
flashram_info.mode = NOPES_MODE;
flashram_info.status = 0;
}
unsigned int flashram_status(void)
{
return (unsigned int) (flashram_info.status >> 32);
}
void flashram_command(unsigned int command)
{
switch (command & 0xff000000)
{
case 0x4b000000:
flashram_info.erase_offset = (command & 0xffff) * 128;
break;
case 0x78000000:
flashram_info.mode = ERASE_MODE;
flashram_info.status = 0x1111800800c20000LL;
break;
case 0xa5000000:
flashram_info.erase_offset = (command & 0xffff) * 128;
flashram_info.status = 0x1111800400c20000LL;
break;
case 0xb4000000:
flashram_info.mode = WRITE_MODE;
break;
case 0xd2000000: // execute
switch (flashram_info.mode)
{
case NOPES_MODE:
break;
case ERASE_MODE:
{
unsigned int i;
flashram_read_file();
for (i=flashram_info.erase_offset; i<(flashram_info.erase_offset+128); i++)
{
flashram[i^S8] = 0xff;
}
flashram_write_file();
}
break;
case WRITE_MODE:
{
int i;
flashram_read_file();
for (i=0; i<128; i++)
{
flashram[(flashram_info.erase_offset+i)^S8]=
((unsigned char*)rdram)[(flashram_info.write_pointer+i)^S8];
}
flashram_write_file();
}
break;
case STATUS_MODE:
break;
default:
DebugMessage(M64MSG_WARNING, "unknown flashram command with mode:%x", (int)flashram_info.mode);
stop=1;
break;
}
flashram_info.mode = NOPES_MODE;
break;
case 0xe1000000:
flashram_info.mode = STATUS_MODE;
flashram_info.status = 0x1111800100c20000LL;
break;
case 0xf0000000:
flashram_info.mode = READ_MODE;
flashram_info.status = 0x11118004f0000000LL;
break;
default:
DebugMessage(M64MSG_WARNING, "unknown flashram command: %x", (int)command);
break;
}
}
void dma_read_flashram(void)
{
unsigned int i;
switch (flashram_info.mode)
{
case STATUS_MODE:
rdram[pi_register.pi_dram_addr_reg/4] = (unsigned int)(flashram_info.status >> 32);
rdram[pi_register.pi_dram_addr_reg/4+1] = (unsigned int)(flashram_info.status);
break;
case READ_MODE:
flashram_read_file();
for (i=0; i<(pi_register.pi_wr_len_reg & 0x0FFFFFF)+1; i++)
{
((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8];
}
break;
default:
DebugMessage(M64MSG_WARNING, "unknown dma_read_flashram: %x", flashram_info.mode);
stop=1;
break;
}
}
void dma_write_flashram(void)
{
switch (flashram_info.mode)
{
case WRITE_MODE:
flashram_info.write_pointer = pi_register.pi_dram_addr_reg;
break;
default:
DebugMessage(M64MSG_ERROR, "unknown dma_write_flashram: %x", flashram_info.mode);
stop=1;
break;
}
}

View File

@ -0,0 +1,36 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - flashram.h *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef struct _flashram_info
{
int use_flashram;
int mode;
unsigned long long status;
unsigned int erase_offset, write_pointer;
} Flashram_info;
extern Flashram_info flashram_info;
void init_flashram(void);
void flashram_command(unsigned int command);
unsigned int flashram_status(void);
void dma_read_flashram(void);
void dma_write_flashram(void);

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