From: ptitSeb Date: Sat, 9 Aug 2014 07:14:20 +0000 (+0200) Subject: Added missing launcher X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=mupen64plus-pandora.git Added missing launcher --- diff --git a/source/front-end/.hgignore b/source/front-end/.hgignore new file mode 100644 index 0000000..35d414e --- /dev/null +++ b/source/front-end/.hgignore @@ -0,0 +1,4 @@ +syntax: regexp + +^projects/unix/_obj/ +^projects/unix/mupen64plus$ diff --git a/source/front-end/INSTALL b/source/front-end/INSTALL new file mode 100644 index 0000000..51c97ce --- /dev/null +++ b/source/front-end/INSTALL @@ -0,0 +1,26 @@ +Mupen64Plus-UI-Console INSTALL +------------------------------ + +This text file was written to explain the installation process of the +Mupen64Plus-UI-Console front-end 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 program +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-UI-Console for installation in a home +folder for a single user, you may build it like this (replacing +with your desired local installation path): + +$ cd projects/unix +$ make all COREDIR= PLUGINDIR= +$ make install BINDIR= MANDIR= + + diff --git a/source/front-end/LICENSES b/source/front-end/LICENSES new file mode 100644 index 0000000..346a181 --- /dev/null +++ b/source/front-end/LICENSES @@ -0,0 +1,358 @@ +Mupen64Plus-ui-console LICENSE +------------------------------ + +Mupen64Plus-ui-console is licensed under the GNU General Public License version 2. + +The authors of Mupen64Plus-ui-console are: + * Richard Goedeken (Richard42) + +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. + + + Copyright (C) 19yy + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/source/front-end/README b/source/front-end/README new file mode 100644 index 0000000..5c0caca --- /dev/null +++ b/source/front-end/README @@ -0,0 +1,81 @@ +=============================================================================== +------------------------------------------------------------------------------- +Mupen64plus-ui-console README v2.0 +------------------------------------------------------------------------------- +=============================================================================== + +The latest documentation for this plugin can be found at: + +https://code.google.com/p/mupen64plus/wiki/UIConsoleUsage + +------------------------------------------------------------------------------- +Console Options +------------------------------------------------------------------------------- + +At startup, the mupen64plus program will look for a user configuration file +called 'mupen64plus.cfg'. If this file does not exist, it will be created and +default settings will be written. If desired, an alternate config directory can +be specified using the --configdir commandline option. + +Run 'mupen64plus --help' for a complete list of commandline options: + + $ mupen64plus --help +Usage: mupen64plus [parameter(s)] [romfile] + +Parameters: + --noosd : disable onscreen display + --osd : enable onscreen display + --fullscreen : use fullscreen display mode + --windowed : use windowed display mode + --resolution (res) : display resolution (640x480, 800x600, 1024x768, etc) + --nospeedlimit : disable core speed limiter (should be used with dummy audio plugin) + --cheats (cheat-spec) : enable or list cheat codes for the given rom file + --corelib (filepath) : use core library (filepath) (can be only filename or full path) + --configdir (dir) : force configation directory to (dir); should contain mupen64plus.cfg + --datadir (dir) : search for shared data files (.ini files, languages, etc) in (dir) + --plugindir (dir) : search for plugins in (dir) + --sshotdir (dir) : set screenshot directory to (dir) + --gfx (plugin-spec) : use gfx plugin given by (plugin-spec) + --audio (plugin-spec) : use audio plugin given by (plugin-spec) + --input (plugin-spec) : use input plugin given by (plugin-spec) + --rsp (plugin-spec) : use rsp plugin given by (plugin-spec) + --emumode (mode) : set emu mode to: 0=Pure Interpreter 1=Interpreter 2=DynaRec + --testshots (list) : take screenshots at frames given in comma-separated (list), then quit + --set (param-spec) : set a configuration variable, format: ParamSection[ParamName]=Value + --core-compare-send : use the Core Comparison debugging feature, in data sending mode + --core-compare-recv : use the Core Comparison debugging feature, in data receiving mode + --nosaveoptions : do not save the given command-line options in configuration file + --verbose : print lots of information + --help : see this help message + +(plugin-spec): + (pluginname) : filename (without path) of plugin to find in plugin directory + (pluginpath) : full path and filename of plugin + 'dummy' : use dummy plugin + +(cheat-spec): + 'list' : show all of the available cheat codes + 'all' : enable all of the available cheat codes + (codelist) : a comma-separated list of cheat code numbers to enable, + with dashes to use code variables (ex 1-2 to use cheat 1 option 2) + +------------------------------------------------------------------------------- +Cheats +------------------------------------------------------------------------------- + +To list the available cheats in the rom: + +mupen64plus --cheats list "/path/to/my/rom.v64" + +If there are cheats in the rom, you will get (in the output console): + +UI-Console: 3 cheat code(s) found for ROM 'MY ROM' + 0: [Enable All Levels] (This is needed to be able to Play all Levels of the Game) + 1: [Enable All Weapons] (This is needed to be able to Play with all Weapons of the Game) + 2: etc... + +All you have to do to use this cheats is: + +mupen64plus --cheats 0,1,2 "/path/to/my/rom.v64" + + diff --git a/source/front-end/RELEASE b/source/front-end/RELEASE new file mode 100644 index 0000000..e2b6666 --- /dev/null +++ b/source/front-end/RELEASE @@ -0,0 +1,46 @@ +Mupen64Plus-UI-Console RELEASE +------------------------------ + +Mupen64Plus-UI-Console Front-End v2.0 - July 4, 2013 +---------------------------------------------------- + - Project files for Visual Studio 2012 + - Makefile changes + - add support for PowerPC and MinGW32 builds + - add cross-compiling support to build Win32 executables (MXE) under Linux + +Mupen64Plus-UI-Console Front-End v1.99.5 - March 10, 2012 +--------------------------------------------------------- + - New option to disable internal core speed limiter (for benchmarking) + - Updated Console-UI front-end for new Mupen64plus 2.0 API versioning + - Added config version number for UI-Console section + - makefile fixes and improvements + +Mupen64Plus-UI-Console Front-End v1.99.4 - November 22, 2010 +------------------------------------------------------------ + - add some parameter checking for --emumode option + - new cheat file format from spinout182 + - makefile fixes and improvements + +Mupen64Plus-UI-Console Front-End v1.99.3 - February 13, 2010 +------------------------------------------------------------ + - New feature: command-line option --set for setting arbitrary configuration variables + - updated MAN pgae for all the changes made in the 2.0 re-architecture + - Makefile improvements: + - added OS type GNU/kFreeBSD + - add -lpthread to LIBS so that GDB will run the emulator without throwing a warning right after starting + +Mupen64Plus-UI-Console Front-End v1.99.2 - January 6, 2010 +------------------------------------------------------------ + - new feature: added MSVC8 project/solution files, minor refactoring for VC compatibility + - Makefile improvements: + - throw error if OS/CPU not supported + - use DESTDIR in install/uninstall paths + - Allow user-specified CC/CXX/LD paths + +Mupen64Plus-UI-Console Front-End v1.99.1 - December 14, 2009 +------------------------------------------------------------ + - Brand new Console-based front-end for Mupen64Plus 2.0 + - New feature: R4300 Core Comparison for debugging + - New feature: Cheat code support from command-line + + diff --git a/source/front-end/doc/mupen64plus.6 b/source/front-end/doc/mupen64plus.6 new file mode 100644 index 0000000..64ded01 --- /dev/null +++ b/source/front-end/doc/mupen64plus.6 @@ -0,0 +1,217 @@ +.Dd September 20, 2013 +.Dt MUPEN64PLUS 6 +.Os +.Sh NAME +.Nm mupen64plus +.Nd console front\(hyend for the Mupen64Plus N64 emulator +.Sh SYNOPSIS +.Nm +.Op parameters +.Ar romfile +.Sh DESCRIPTION +.Nm +is a plugin\(hybased N64 emulator for Linux/Unix, OSX, and Windows which is capable of accurately playing many games. +Included are four MIPS R4300 CPU emulators, with dynamic recompilers for 32\(hybit x86 and 64\(hybit amd64 systems, and necessary plugins for audio, graphical rendering (RDP), signal co\(hyprocessor (RSP), and input. +There are several OpenGL video plugins available: +.Bl -bullet +.It +Rice, included with the distribution +.It +Glide64Mk2, included with the distribution +.It +.Lk https://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid Arachnoid +.It +.Lk https://bitbucket.org/wahrhaft/mupen64plus-video-glide64 Glide64 +(old) +.It +.Lk https://bitbucket.org/wahrhaft/mupen64plus-video-z64 Z64 +(must be used with the rsp-z64 plugin) +.El +.Pp +The most current documentation can be found at the project's +.Lk https://code.google.com/p/mupen64plus/ homepage . +.Pp +The options are as follows: +.Bl -tag -width x +.It Fl h , Fl -help +Print help message. +.It Fl -noosd +Disable onscreen display. +.It Fl -osd +Enable onscreen display. +.It Fl -fullscreen +Run emulator in fullscreen display mode. +.It Fl -windowed +Run emulator in windowed display mode. +.It Fl -resolution Ar res +Display resolution (640\(mu480, 800\(mu600, 1024\(mu768, etc) +.It Fl -nospeedlimit +Disable core speed limiter. +This should be used with the dummy audio plugin. +.It Fl -cheats Ar cheat-spec +Enable or list cheat codes for the given rom file. +.It Fl -corelib Ar filepath +Specifies a filename (optionally with a preceding directory path) to load a specific +.Nm +core library. +.It Fl -configdir Ar directory +Specifies a directory to look for the +.Pa mupen64plus.cfg +file. +Default is +.Pa ~/.config/mupen64plus/ . +.It Fl -datadir Ar directory +Specifies a directory to search for shared data files (fonts, cheat codes, .ini files). +Default is +.Pa ${PREFIX}/share/mupen64plus/ . +.It Fl -plugindir Ar directory +Specifies a directory to search for plugin files. +Default is +.Pa ${PREFIX}/lib/mupen64plus/ . +.It Fl -sshotdir Ar directory +Specifies a directory to save screenshots captured during gameplay. +Default is +.Pa ~/.local/share/mupen64plus/screenshot/ . +.It Fl -gfx Ar plugin\(hyspec +Specifies a +.Ar plugin\(hyspec +to select a graphics plugin for use during emulation. +.It Fl -audio Ar plugin\(hyspec +Specifies a +.Ar plugin\(hyspec +to select an audio plugin for use during emulation. +.It Fl -input Ar plugin\(hyspec +Specifies a +.Ar plugin\(hyspec +to select an input plugin for use during emulation. +.It Fl -rsp Ar plugin\(hyspec +Specifies a +.Ar plugin\(hyspec +to select an RSP plugin for use during emulation. +.It Fl -emumode Ar mode +Specifies which mode the emulator core should run in. +.Ar mode +should be set to one of the following numbers: +.Bl -inset +.It 0 +Pure Interpreter +.It 1 +Cached Interpreter +.It 2 +Dynamic Recompiler (DynaRec) +.El +.It Fl -testshots Ar list +Take screenshots at frames given in the comma\(hyseparated +.Ar list , +then quit. +.It Fl -core-compare-send +Use the core comparison debugging feature, in data sending mode. +If the core was not compiled with support for the Core Comparison feature, then the emulator will exit with an error. +.It Fl -core-compare-recv +Use the core comparison debugging feature, in data receiving mode. +If the core was not compiled with support for the Core Comparison feature, then the emulator will exit with an error. +.It Fl -set Ar param\(hyspec +Set the value of a +.Nm +configuration parameter. +This option may be used multiple times. +The format of +.Ar param\(hyspec +is +.Dl Section\(hyName[Param\(hyName]=Value +.It Fl -nosaveoptions +Do not save the given command\(hyline options into the +.Nm +configuration file to use as defaults in the future. +.It Fl -verbose +Print lots of information. +Useful for debugging but unnecessary for normal use. +.El +.Sh plugin\(hyspec +.Bl -ohang +.It (plugin\(hyname) +Filename (without path) of plugin to use. +Application will search through several directories to look for a matching plugin name. +.It (plugin\(hypath) +Full directory path and filename of plugin. +.It Sq dummy +Use the dummy plugin. +.El +.Sh cheat\(hyspec +.Bl -ohang +.It Sq list +Show all of the available cheat codes. +.It Sq all +Enable all of the available cheat codes. +.It (codelist) +A comma separated list of cheat code numbers to enable. +.El +.Sh KEY COMMANDS +The following shortcut keys can be used during emulation. +These are the default key values; nearly all of them may be set to different keys by editing the +.Nm +configuration file. +.Bl -tag -width Alt-Enter +.It Escape +Quit the emulator. +.It 0\(en9 +Select virtual +.Sq slot +for save/load state. +.It F5 +Save emulator state to current slot. +.It F7 +Load emulator state from current slot. +.It F9 +Reset emulator. +.It F10 +Slow down emulator speed by 5 percent. +.It F11 +Speed up emulator speed by 5 percent. +.It F12 +Take screenshot. +.It Alt\(hyEnter +Toggle fullscreen mode. +This is not supported on Windows. +.It p or P +Pause/continue emulation. +.It m or M +Mute/unmute sound. +.It f or F +Fast Forward (playback at 250% normal speed as long as key is pressed). +.It g or G +Press GameShark button (if cheats are enabled). +.It / or \&? +Advance one frame if paused. +.It \(lB +Decrease volume. +.It \(rB +Increase volume. +.El +.Sh FILES +The default location for the +.Nm +configuration file is +.Pa ~/.config/mupen64plus/ . +The default location of the saved screenshots is +.Pa ~/.local/share/mupen64plus/screenshot/ . +The default location of the save states is +.Pa ~/.local/share/mupen64plus/save/ . +.Sh AUTHORS +.Nm +was originally started by Richard42 and nmn, and is based on Mupen64 (originally written by Hacktarux). +.Pp +This man page was written by ebenblues, and updated by Richard42 and bentley. +.Sh COPYRIGHT +Mupen64plus is \(co 2008\(en2013 The Mupen64plus Team +.Pp +License GPLv2+, +.Lk https://gnu.org/licenses/gpl.html GNU GPL version 2 or later +.Pp +This is free software: you are free to change and redistribute it. +There is +.Em no warranty , +to the extent permitted by law. +.Sh BUGS +To report bugs or make feature requests, use the +.Lk https://code.google.com/p/mupen64plus/issues/list "issue tracker" diff --git a/source/front-end/projects/android/Android.mk b/source/front-end/projects/android/Android.mk new file mode 100644 index 0000000..af42b4b --- /dev/null +++ b/source/front-end/projects/android/Android.mk @@ -0,0 +1,36 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +SRCDIR := ../../src + +LOCAL_MODULE := front-end +LOCAL_SHARED_LIBRARIES := ae-imports SDL2 core +#LOCAL_ARM_MODE := arm + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/$(SRCDIR) \ + $(M64P_API_INCLUDES) \ + $(SDL_INCLUDES) \ + $(AE_BRIDGE_INCLUDES) \ + +LOCAL_SRC_FILES := \ + $(SDL_MAIN_ENTRY) \ + $(SRCDIR)/cheat.c \ + $(SRCDIR)/compare_core.c \ + $(SRCDIR)/core_interface.c \ + $(SRCDIR)/main.c \ + $(SRCDIR)/osal_dynamiclib_unix.c \ + $(SRCDIR)/osal_files_unix.c \ + $(SRCDIR)/plugin.c \ + +LOCAL_CFLAGS := \ + $(COMMON_CFLAGS) \ + -DANDROID \ + -DNO_ASM \ + -DPAULSCODE \ + +LOCAL_CPPFLAGS := $(COMMON_CPPFLAGS) + +LOCAL_LDLIBS := -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/source/front-end/projects/msvc11/mupen64plus-ui-console.sln b/source/front-end/projects/msvc11/mupen64plus-ui-console.sln new file mode 100644 index 0000000..b61e7db --- /dev/null +++ b/source/front-end/projects/msvc11/mupen64plus-ui-console.sln @@ -0,0 +1,55 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-ui-console", "mupen64plus-ui-console.vcxproj", "{0E29D9F8-C675-4D21-AF16-AA80EDDB264E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-core", "..\..\..\mupen64plus-core\projects\msvc11\mupen64plus-core.vcxproj", "{92D3FEB9-2129-41C5-8577-BCD7D961EF41}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-input-sdl", "..\..\..\mupen64plus-input-sdl\projects\msvc11\mupen64plus-input-sdl.vcxproj", "{7F3178D0-0E2E-471B-9160-69F0354F9DE9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-rsp-hle", "..\..\..\mupen64plus-rsp-hle\projects\msvc11\mupen64plus-rsp-hle.vcxproj", "{2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-rice", "..\..\..\mupen64plus-video-rice\projects\msvc11\mupen64plus-video-rice.vcxproj", "{7D4AFF6A-B7D9-4C25-975A-038B8079098E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-audio-sdl", "..\..\..\mupen64plus-audio-sdl\projects\msvc11\mupen64plus-audio-sdl.vcxproj", "{96969748-EA54-43FC-8103-A346E9AD98E7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-glide64mk2", "..\..\..\mupen64plus-video-glide64mk2\projects\msvc11\mupen64plus-video-glide64mk2.vcxproj", "{A4D13408-A794-4199-8FC7-4A9A32505005}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Debug|Win32.Build.0 = Debug|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Release|Win32.ActiveCfg = Release|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Release|Win32.Build.0 = Release|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Debug|Win32.ActiveCfg = Debug|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Debug|Win32.Build.0 = Debug|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Release|Win32.ActiveCfg = Release|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Release|Win32.Build.0 = Release|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Debug|Win32.Build.0 = Debug|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Release|Win32.ActiveCfg = Release|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Release|Win32.Build.0 = Release|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Debug|Win32.Build.0 = Debug|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Release|Win32.ActiveCfg = Release|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Release|Win32.Build.0 = Release|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Debug|Win32.ActiveCfg = Debug|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Debug|Win32.Build.0 = Debug|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Release|Win32.ActiveCfg = Release|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Release|Win32.Build.0 = Release|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Debug|Win32.Build.0 = Debug|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Release|Win32.ActiveCfg = Release|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Release|Win32.Build.0 = Release|Win32 + {A4D13408-A794-4199-8FC7-4A9A32505005}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4D13408-A794-4199-8FC7-4A9A32505005}.Debug|Win32.Build.0 = Debug|Win32 + {A4D13408-A794-4199-8FC7-4A9A32505005}.Release|Win32.ActiveCfg = Release|Win32 + {A4D13408-A794-4199-8FC7-4A9A32505005}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/source/front-end/projects/msvc11/mupen64plus-ui-console.vcxproj b/source/front-end/projects/msvc11/mupen64plus-ui-console.vcxproj new file mode 100644 index 0000000..c20ba03 --- /dev/null +++ b/source/front-end/projects/msvc11/mupen64plus-ui-console.vcxproj @@ -0,0 +1,143 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E} + mupen64plusuiconsole + Win32Proj + + + + Application + MultiByte + true + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + CompileAsCpp + + + ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDLmain.lib;%(AdditionalDependencies) + true + Console + MachineX86 + + + Copying shared data and libraries to build directory... + copy ..\..\..\mupen64plus-core\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-video-rice\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-video-glide64mk2\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-input-sdl\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\bin\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\libpng-1.2.37\bin\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\zlib-1.2.3\bin\*.dll "$(OutDir)" + + + + + + ..\..\..\mupen64plus-core\src\api;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + CompileAsCpp + + + ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDLmain.lib;%(AdditionalDependencies) + true + Console + true + true + MachineX86 + + + Copying shared data and libraries to build directory... + copy ..\..\..\mupen64plus-core\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-video-rice\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-video-glide64mk2\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-input-sdl\data\* "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\freetype-2.3.5-1\bin\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\libpng-1.2.37\bin\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\*.dll "$(OutDir)" +copy ..\..\..\mupen64plus-win32-deps\zlib-1.2.3\bin\*.dll "$(OutDir)" + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/front-end/projects/msvc8/mupen64plus-ui-console.sln b/source/front-end/projects/msvc8/mupen64plus-ui-console.sln new file mode 100644 index 0000000..f442c9c --- /dev/null +++ b/source/front-end/projects/msvc8/mupen64plus-ui-console.sln @@ -0,0 +1,56 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-ui-console", "mupen64plus-ui-console.vcproj", "{0E29D9F8-C675-4D21-AF16-AA80EDDB264E}" + ProjectSection(ProjectDependencies) = postProject + {96969748-EA54-43FC-8103-A346E9AD98E7} = {96969748-EA54-43FC-8103-A346E9AD98E7} + {7D4AFF6A-B7D9-4C25-975A-038B8079098E} = {7D4AFF6A-B7D9-4C25-975A-038B8079098E} + {92D3FEB9-2129-41C5-8577-BCD7D961EF41} = {92D3FEB9-2129-41C5-8577-BCD7D961EF41} + {7F3178D0-0E2E-471B-9160-69F0354F9DE9} = {7F3178D0-0E2E-471B-9160-69F0354F9DE9} + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A} = {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-core", "..\..\..\mupen64plus-core\projects\msvc8\mupen64plus-core.vcproj", "{92D3FEB9-2129-41C5-8577-BCD7D961EF41}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-rice", "..\..\..\mupen64plus-video-rice\projects\msvc8\mupen64plus-video-rice.vcproj", "{7D4AFF6A-B7D9-4C25-975A-038B8079098E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-rsp-hle", "..\..\..\mupen64plus-rsp-hle\projects\msvc8\mupen64plus-rsp-hle.vcproj", "{2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-input-sdl", "..\..\..\mupen64plus-input-sdl\projects\msvc8\mupen64plus-input-sdl.vcproj", "{7F3178D0-0E2E-471B-9160-69F0354F9DE9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-audio-sdl", "..\..\..\mupen64plus-audio-sdl\projects\msvc8\mupen64plus-audio-sdl.vcproj", "{96969748-EA54-43FC-8103-A346E9AD98E7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Debug|Win32.ActiveCfg = Debug|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Debug|Win32.Build.0 = Debug|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Release|Win32.ActiveCfg = Release|Win32 + {0E29D9F8-C675-4D21-AF16-AA80EDDB264E}.Release|Win32.Build.0 = Release|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Debug|Win32.ActiveCfg = Debug|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Debug|Win32.Build.0 = Debug|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Release|Win32.ActiveCfg = Release|Win32 + {92D3FEB9-2129-41C5-8577-BCD7D961EF41}.Release|Win32.Build.0 = Release|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Debug|Win32.ActiveCfg = Debug|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Debug|Win32.Build.0 = Debug|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Release|Win32.ActiveCfg = Release|Win32 + {7D4AFF6A-B7D9-4C25-975A-038B8079098E}.Release|Win32.Build.0 = Release|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Debug|Win32.ActiveCfg = Debug|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Debug|Win32.Build.0 = Debug|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Release|Win32.ActiveCfg = Release|Win32 + {2EC7CEE3-C7A7-4F2E-B2C8-4DF6AFEC3E9A}.Release|Win32.Build.0 = Release|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Debug|Win32.Build.0 = Debug|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Release|Win32.ActiveCfg = Release|Win32 + {7F3178D0-0E2E-471B-9160-69F0354F9DE9}.Release|Win32.Build.0 = Release|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Debug|Win32.Build.0 = Debug|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Release|Win32.ActiveCfg = Release|Win32 + {96969748-EA54-43FC-8103-A346E9AD98E7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/source/front-end/projects/msvc8/mupen64plus-ui-console.vcproj b/source/front-end/projects/msvc8/mupen64plus-ui-console.vcproj new file mode 100644 index 0000000..13d894f --- /dev/null +++ b/source/front-end/projects/msvc8/mupen64plus-ui-console.vcproj @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/front-end/projects/unix/Makefile b/source/front-end/projects/unix/Makefile new file mode 100755 index 0000000..1948d08 --- /dev/null +++ b/source/front-end/projects/unix/Makefile @@ -0,0 +1,320 @@ +#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +# * Mupen64plus - Makefile * +# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * +# * Copyright (C) 2009 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. * +# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +# Makefile for Mupen64plus-ui-console + +# detect operation 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 + $(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 +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 + else + ARCH_DETECTED := 64BITS + endif +endif +ifneq ("$(filter pentium i%86,$(HOST_CPU))","") + CPU := X86 + ARCH_DETECTED := 32BITS +endif +ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","") + CPU := PPC + ARCH_DETECTED := 32BITS + BIG_ENDIAN := 1 + $(warning Architecture "$(HOST_CPU)" not officially supported.') +endif +ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","") + CPU := PPC + ARCH_DETECTED := 64BITS + BIG_ENDIAN := 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 + CFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -mtune=cortex-a8 -fsigned-char -ffast-math +# CFLAGS += -DANDROID +# CFLAGS += -DPAULSCODE + $(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 -I../../src +ifeq ($(OS), MINGW) + CFLAGS += -lpthread + LDLIBS += -lpthread +else + CFLAGS += -pthread + LDLIBS += -pthread +endif + +ifeq ($(PIE), 1) + CFLAGS += -fPIE + LDFLAGS += -pie +else + CFLAGS += -fno-PIE +endif + +# set special flags per-system +ifeq ($(OS), LINUX) + LDLIBS += -ldl +endif +ifeq ($(OS), OSX) + #xcode-select has been around since XCode 3.0, i.e. OS X 10.5 + OSX_SDK_ROOT = $(shell xcode-select -print-path)/Platforms/MacOSX.platform/Developer/SDKs + OSX_SDK_PATH = $(OSX_SDK_ROOT)/$(shell ls $(OSX_SDK_ROOT) | tail -1) + + ifeq ($(CPU), X86) + ifeq ($(ARCH_DETECTED), 64BITS) + CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=10.5 -isysroot $(OSX_SDK_PATH) + else + CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=10.5 -isysroot $(OSX_SDK_PATH) + endif + endif +endif + +# test for presence of SDL +ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined) + SDL_CONFIG = $(CROSS_COMPILE)sdl-config + ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) + $(error No SDL development libraries found!) + endif + SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags) + SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs) +endif +CFLAGS += $(SDL_CFLAGS) +LDLIBS += $(SDL_LDLIBS) + +ifeq ($(OS), MINGW) + LDLIBS += -mconsole +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 += -Wl,-m,elf_i386 +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 +CXX = $(CROSS_COMPILE)g++ +RM ?= rm -f +INSTALL ?= install +MKDIR ?= mkdir -p +COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH) + +# set special flags for given Makefile parameters +# note: COREDIR _must_ end in a slash if you want it to work; not necessary for the others +ifneq ($(PLUGINDIR),) + CFLAGS += '-DPLUGINDIR="$(PLUGINDIR)"' +endif +ifneq ($(COREDIR),) + CFLAGS += '-DCOREDIR="$(COREDIR)"' +endif +ifneq ($(SHAREDIR),) + CFLAGS += '-DSHAREDIR="$(SHAREDIR)"' +endif +ifeq ($(DEBUG),1) + CFLAGS += -g -gdwarf-2 + INSTALL_STRIP_FLAG ?= +else + INSTALL_STRIP_FLAG ?= -s +endif + +# set installation options +ifeq ($(PREFIX),) + PREFIX := /usr/local +endif +ifeq ($(BINDIR),) + BINDIR := $(PREFIX)/bin +endif +ifeq ($(MANDIR),) + MANDIR := $(PREFIX)/share/man +endif + +SRCDIR = ../../src +OBJDIR = _obj$(POSTFIX) + +ifeq ("$(OS)","MINGW") + EXEEXT = .exe +else + EXEEXT = +endif + +# list of source files to compile +SOURCE = \ + $(SRCDIR)/cheat.c \ + $(SRCDIR)/compare_core.c \ + $(SRCDIR)/core_interface.c \ + $(SRCDIR)/main.c \ + $(SRCDIR)/plugin.c + +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 + +# 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$(POSTFIX)$(EXEEXT) + +targets: + @echo "Mupen64Plus-ui-console makefile." + @echo " Targets:" + @echo " all == Build Mupen64Plus console front-end application" + @echo " clean == remove object files and build products" + @echo " rebuild == clean and re-build all" + @echo " install == Install Mupen64Plus console front-end application" + @echo " uninstall == Uninstall Mupen64Plus console front-end application" + @echo " Options:" + @echo " COREDIR=path == default path to search for Mupen64Plus Core (must end with slash)" + @echo " PLUGINDIR=path == default path to search for plugins" + @echo " SHAREDIR=path == default path to search for shared data files" + @echo " APIDIR=path == path to find Mupen64Plus Core headers" + @echo " OPTFLAGS=flags == compiler optimization (default: -O3 -flto)" + @echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)" + @echo " PIE=(1|0) == Force enable/disable of position independent executables" + @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 " BINDIR=path == path to install mupen64plus binary (default: PREFIX/bin/)" + @echo " MANDIR=path == path to install mupen64plus manual page (default: PREFIX/share/man)" + @echo " DESTDIR=path == path to prepend to all installation paths (only for packagers)" + @echo " Debugging Options:" + @echo " DEBUG=1 == add debugging symbols to application binary" + @echo " V=1 == show verbose compiler output" + +all: $(TARGET) + +clean: + $(RM) -r $(OBJDIR) $(TARGET) + +rebuild: clean all + +install: $(TARGET) + $(INSTALL) -d "$(DESTDIR)$(BINDIR)" + $(INSTALL) -m 0755 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(BINDIR)" + $(INSTALL) -d "$(DESTDIR)$(MANDIR)/man6" + $(INSTALL) -m 0644 ../../doc/mupen64plus.6 "$(DESTDIR)$(MANDIR)/man6" + +uninstall: + $(RM) "$(DESTDIR)$(BINDIR)/$(TARGET)" "$(DESTDIR)$(MANDIR)/man6/mupen64plus.6" + +# build dependency files +CFLAGS += -MD -MP +-include $(OBJECTS:.o=.d) + +# standard build rules +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(COMPILE.c) -o $@ $< + +$(TARGET): $(OBJECTS) + $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ + +.PHONY: all clean install uninstall targets diff --git a/source/front-end/projects/unix/Makefile.orig b/source/front-end/projects/unix/Makefile.orig new file mode 100755 index 0000000..b079269 --- /dev/null +++ b/source/front-end/projects/unix/Makefile.orig @@ -0,0 +1,328 @@ +#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +# * Mupen64plus - Makefile * +# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * +# * Copyright (C) 2009 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. * +# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +# Makefile for Mupen64plus-ui-console + +# detect operation 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 + $(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 +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 + else + ARCH_DETECTED := 64BITS + endif +endif +ifneq ("$(filter pentium i%86,$(HOST_CPU))","") + CPU := X86 + ARCH_DETECTED := 32BITS +endif +ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","") + CPU := PPC + ARCH_DETECTED := 32BITS + BIG_ENDIAN := 1 + $(warning Architecture "$(HOST_CPU)" not officially supported.') +endif +ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","") + CPU := PPC + ARCH_DETECTED := 64BITS + BIG_ENDIAN := 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 + CFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -mtune=cortex-a8 -fsigned-char -ffast-math +# CFLAGS += -DANDROID +# CFLAGS += -DPAULSCODE + $(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 -I../../src +ifeq ($(OS), MINGW) + CFLAGS += -lpthread + LDLIBS += -lpthread +else + CFLAGS += -pthread + LDLIBS += -pthread +endif + +ifeq ($(PIE), 1) + CFLAGS += -fPIE + LDFLAGS += -pie +else + CFLAGS += -fno-PIE +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 + else + CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk + endif + endif +endif + +# test for presence of SDL +ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined) + SDL_CONFIG = $(CROSS_COMPILE)sdl-config + ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) + $(error No SDL development libraries found!) + endif + SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags) + SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs) +endif +CFLAGS += $(SDL_CFLAGS) +LDLIBS += $(SDL_LDLIBS) + +ifeq ($(OS), MINGW) + LDLIBS += -mconsole +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 += -Wl,-m,elf_i386 +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 +CXX = $(CROSS_COMPILE)g++ +RM ?= rm -f +INSTALL ?= install +MKDIR ?= mkdir -p +COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH) + +# set special flags for given Makefile parameters +# note: COREDIR _must_ end in a slash if you want it to work; not necessary for the others +ifneq ($(PLUGINDIR),) + CFLAGS += '-DPLUGINDIR="$(PLUGINDIR)"' +endif +ifneq ($(COREDIR),) + CFLAGS += '-DCOREDIR="$(COREDIR)"' +endif +ifneq ($(SHAREDIR),) + CFLAGS += '-DSHAREDIR="$(SHAREDIR)"' +endif +ifeq ($(DEBUG),1) + CFLAGS += -g -gdwarf-2 + INSTALL_STRIP_FLAG ?= +else + INSTALL_STRIP_FLAG ?= -s +endif + +# set installation options +ifeq ($(PREFIX),) + PREFIX := /usr/local +endif +ifeq ($(BINDIR),) + BINDIR := $(PREFIX)/bin +endif +ifeq ($(MANDIR),) + MANDIR := $(PREFIX)/share/man +endif + +SRCDIR = ../../src +OBJDIR = _obj$(POSTFIX) + +ifeq ("$(OS)","MINGW") + EXEEXT = .exe +else + EXEEXT = +endif + +# list of source files to compile +SOURCE = \ + $(SRCDIR)/cheat.c \ + $(SRCDIR)/compare_core.c \ + $(SRCDIR)/core_interface.c \ + $(SRCDIR)/main.c \ + $(SRCDIR)/plugin.c + +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 + +# 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$(POSTFIX)$(EXEEXT) + +targets: + @echo "Mupen64Plus-ui-console makefile." + @echo " Targets:" + @echo " all == Build Mupen64Plus console front-end application" + @echo " clean == remove object files and build products" + @echo " rebuild == clean and re-build all" + @echo " install == Install Mupen64Plus console front-end application" + @echo " uninstall == Uninstall Mupen64Plus console front-end application" + @echo " Options:" + @echo " COREDIR=path == default path to search for Mupen64Plus Core (must end with slash)" + @echo " PLUGINDIR=path == default path to search for plugins" + @echo " SHAREDIR=path == default path to search for shared data files" + @echo " APIDIR=path == path to find Mupen64Plus Core headers" + @echo " OPTFLAGS=flags == compiler optimization (default: -O3 -flto)" + @echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)" + @echo " PIE=(1|0) == Force enable/disable of position independent executables" + @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 " BINDIR=path == path to install mupen64plus binary (default: PREFIX/bin/)" + @echo " MANDIR=path == path to install mupen64plus manual page (default: PREFIX/share/man)" + @echo " DESTDIR=path == path to prepend to all installation paths (only for packagers)" + @echo " Debugging Options:" + @echo " DEBUG=1 == add debugging symbols to application binary" + @echo " V=1 == show verbose compiler output" + +all: $(TARGET) + +clean: + $(RM) -r $(OBJDIR) $(TARGET) + +rebuild: clean all + +install: $(TARGET) + $(INSTALL) -d "$(DESTDIR)$(BINDIR)" + $(INSTALL) -m 0755 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(BINDIR)" + $(INSTALL) -d "$(DESTDIR)$(MANDIR)/man6" + $(INSTALL) -m 0644 ../../doc/mupen64plus.6 "$(DESTDIR)$(MANDIR)/man6" + +uninstall: + $(RM) "$(DESTDIR)$(BINDIR)/$(TARGET)" "$(DESTDIR)$(MANDIR)/man6/mupen64plus.6" + +# build dependency files +CFLAGS += -MD +-include $(OBJECTS:.o=.d) + +# standard build rules +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(COMPILE.c) -o $@ $< + +$(TARGET): $(OBJECTS) + $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ + +.PHONY: all clean install uninstall targets diff --git a/source/front-end/src/cheat.c b/source/front-end/src/cheat.c new file mode 100644 index 0000000..d491cbf --- /dev/null +++ b/source/front-end/src/cheat.c @@ -0,0 +1,458 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - cheat.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009-2010 Richard Goedeken * + * Copyright (C) 2010 Rhett Osborne (spinout) * + * * + * 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 +#include +#include + +#include "m64p_types.h" + +#include "main.h" +#include "cheat.h" +#include "core_interface.h" + +/* local definitions */ +#define CHEAT_FILE "mupencheat.txt" + +typedef struct { + int address; + int *variables; + char **variable_names; + int var_to_use; + int var_count; +} cheat_code; + +typedef struct _sCheatInfo { + int Number; + int Count; + int VariableLine; + const char *Name; + const char *Description; + cheat_code *Codes; + struct _sCheatInfo *Next; + } sCheatInfo; + +/* local variables */ +static m64p_rom_header l_RomHeader; +static char *l_IniText = NULL; +static char *l_CheatGameName = NULL; +static sCheatInfo *l_CheatList = NULL; +static int l_CheatCodesFound = 0; +static int l_RomFound = 0; + +/********************************************************************************************************* + * Static (Local) functions + */ + +static int isSpace(char ch) +{ + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); +} + +/* Find cheat code */ +static sCheatInfo *CheatFindCode(int Number) +{ + sCheatInfo *pCur = l_CheatList; + while (pCur != NULL) + { + if (pCur->Number == Number) break; + pCur = pCur->Next; + } + return pCur; +} + + +/* Activate a code */ +static void CheatActivate(sCheatInfo *pCheat) +{ + int i; + + /* Get a m64p_cheat_code object */ + m64p_cheat_code * code = (m64p_cheat_code*) calloc(pCheat->Count, sizeof(m64p_cheat_code)); + if (code == NULL) + { + DebugMessage(M64MSG_WARNING, "could not allocate memory for code '%s'", pCheat->Name); + return; + } + /* Fill in members */ + for (i = 0; i < pCheat->Count; i++) + { + code[i].address = pCheat->Codes[i].address; + code[i].value = pCheat->Codes[i].variables[pCheat->Codes[i].var_to_use]; + } + /* Enable cheat */ + if (CoreAddCheat(pCheat->Name, code, pCheat->Count) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_WARNING, "CoreAddCheat() failed for cheat code %i (%s)", pCheat->Number, pCheat->Name); + free(code); + return; + } + + free(code); + DebugMessage(M64MSG_STATUS, "activated cheat code %i: %s", pCheat->Number, pCheat->Name); +} + +static void CheatFreeAll(void) +{ + if (l_IniText != NULL) + free(l_IniText); + l_IniText = NULL; + + sCheatInfo *pCur = l_CheatList; + while (pCur != NULL) + { + sCheatInfo *pNext = pCur->Next; + if (pCur->Codes != NULL) + { + int i; + for (i=0; i < pCur->Count; i++) + { + if (pCur->Codes[i].variables != NULL) + free(pCur->Codes[i].variables); + if (pCur->Codes[i].variable_names != NULL) + free(pCur->Codes[i].variable_names); + } + free(pCur->Codes); + } + free(pCur); + pCur = pNext; + } + + l_CheatList = NULL; +} + +/* Append new code */ +static sCheatInfo * NewCode(char *CheatName, int CheatNum) +{ + /* allocate memory for a new sCheatInfo struct */ + sCheatInfo *pNew = (sCheatInfo *) malloc(sizeof(sCheatInfo)); + if (pNew == NULL) return NULL; + + /* fill in the data members */ + pNew->Number = CheatNum; + pNew->Count = 0; + pNew->VariableLine = -1; + pNew->Name = CheatName; + pNew->Description = NULL; + pNew->Codes = NULL; + pNew->Next = NULL; + + l_CheatCodesFound++; + + /* stick it at the end of the list */ + if (l_CheatList == NULL) + { + l_CheatList = pNew; + return pNew; + } + sCheatInfo *pLast = l_CheatList; + while (pLast->Next != NULL) pLast = pLast->Next; + pLast->Next = pNew; + return pNew; +} + +static void CheatAddVariables(cheat_code * Code, char *varlist) +{ + /* needs to be more verbose? */ + Code->variables = NULL; + Code->variable_names = NULL; + Code->var_count = 0; + while (*varlist != 0) + { + if ((Code->variables = (int*) realloc(Code->variables, sizeof(int) * (Code->var_count + 1))) == NULL) + return; + if ((Code->variable_names = (char**) realloc(Code->variable_names, sizeof(char*) * (Code->var_count + 1))) == NULL) + return; + if (sscanf(varlist, "%04X", &Code->variables[Code->var_count]) != 1) + Code->variables[Code->var_count] = 0; + if (strchr(varlist, '"') == NULL) + return; + Code->variable_names[Code->var_count] = strchr(varlist, '"') + 1; + if ((varlist = strchr(Code->variable_names[Code->var_count], '"')) == NULL) + return; + *varlist++ = 0; + if (*varlist == ',') + varlist++; + Code->var_count++; + } +} + +/********************************************************************************************************* +* global functions +*/ + +static void ReadCheats(char *RomSection) +{ + sCheatInfo *curr_code = NULL; + const char *romdbpath = ConfigGetSharedDataFilepath(CHEAT_FILE); + if (romdbpath == NULL) + { + DebugMessage(M64MSG_WARNING, "cheat code database file '%s' not found.", CHEAT_FILE); + return; + } + + /* read the INI file into a new buffer */ + FILE *fPtr = NULL; + fPtr = fopen(romdbpath, "rb"); + if (fPtr == NULL) + { + DebugMessage(M64MSG_WARNING, "Couldn't open cheat code database file '%s'.", romdbpath); + return; + } + fseek(fPtr, 0L, SEEK_END); + long IniLength = ftell(fPtr); + fseek(fPtr, 0L, SEEK_SET); + l_IniText = (char *) malloc(IniLength + 1); + if (l_IniText == NULL) + { + DebugMessage(M64MSG_WARNING, "Couldn't allocate %li bytes of memory to read cheat file.", IniLength); + fclose(fPtr); + return; + } + if (fread(l_IniText, 1, IniLength, fPtr) != IniLength) + { + DebugMessage(M64MSG_WARNING, "Couldn't read %li bytes from cheat file.", IniLength); + free(l_IniText); + l_IniText = NULL; + fclose(fPtr); + return; + } + fclose(fPtr); + l_IniText[IniLength] = 0; /* null-terminate the text data */ + + /* parse lines from cheat database */ + char *curline = NULL; + char *nextline = l_IniText; + + while(nextline != NULL && *nextline != 0) + { + curline = nextline; + /* get pointer to next line and NULL-terminate the current line */ + nextline = strchr(curline, '\n'); + if (nextline != NULL) + { + *nextline = 0; + nextline++; + } + + /* remove leading and trailing white space */ + while(isSpace(*curline)) curline++; + char *endptr = curline + strlen(curline) - 1; + while(isSpace(*endptr)) *endptr-- = 0; + + /* ignore line if comment or empty */ + if (*curline == '#' || strncmp(curline, "//", 2) == 0 || *curline == 0) + continue; + + /* handle beginning of new rom section */ + if (strncmp(curline, "crc ", 4) == 0) + { + /* if we have already found cheats for the given ROM file, then exit upon encountering a new ROM section */ + if (l_RomFound && (l_CheatGameName != NULL || l_CheatList != NULL)) + return; + /* else see if this Rom Section matches */ + if (strcmp(curline+4, RomSection) == 0) + l_RomFound = 1; + continue; + } + + /* if we haven't found the specified ROM section, then continue looking */ + if (!l_RomFound) + continue; + + /* Game name */ + if (strncmp(curline, "gn ", 3) == 0) + { + l_CheatGameName = curline+3; + continue; + } + + /* code name */ + if (strncmp(curline, "cn ", 3) == 0) + { + curr_code = NewCode(curline + 3, l_CheatCodesFound); + if (curr_code == NULL) + DebugMessage(M64MSG_WARNING, "error getting new code (%s)", curline+3); + continue; + } + + /* if curr_code is NULL, don't do these checks */ + if (curr_code == NULL) + continue; + + /* code description */ + if (strncmp(curline, "cd ", 3) == 0) + { + curr_code->Description = curline+3; + continue; + } + + /* code line */ + int address; + if (sscanf(curline, "%8X %*s", &address) == 1) + { + curr_code->Codes = (cheat_code*) realloc(curr_code->Codes, sizeof(cheat_code) * (curr_code->Count + 1)); + if (strncmp(curline+9, "????", 4) == 0) + { + curr_code->Codes[curr_code->Count].var_count = 0; + CheatAddVariables(&curr_code->Codes[curr_code->Count], curline+14); + curr_code->VariableLine = curr_code->Count; + } + else + { + int var; + curr_code->Codes[curr_code->Count].var_count = 1; + curr_code->Codes[curr_code->Count].variables = (int*) malloc(sizeof(int)); + if(curr_code->Codes[curr_code->Count].variables == NULL) + { + DebugMessage(M64MSG_WARNING, "couldn't allocate memory; ignoring line: '%s'", curline); + continue; + } + if (sscanf(curline+9, "%04X", &var) != 1) + var = 0; + curr_code->Codes[curr_code->Count].variables[0] = var; + curr_code->Codes[curr_code->Count].variable_names = NULL; + } + curr_code->Codes[curr_code->Count].var_to_use = 0; + curr_code->Codes[curr_code->Count].address = address; + curr_code->Count++; + continue; + } + + /* otherwise we don't know what this line is */ + DebugMessage(M64MSG_WARNING, "unrecognized line in cheat file: '%s'", curline); + } + +} + +void CheatStart(eCheatMode CheatMode, char *CheatNumList) +{ + /* if cheat codes are disabled, then we don't have to do anything */ + if (CheatMode == CHEAT_DISABLE || (CheatMode == CHEAT_LIST && strlen(CheatNumList) == 0)) + { + DebugMessage(M64MSG_STATUS, "Cheat codes disabled."); + return; + } + + /* get the ROM header for the currently loaded ROM image from the core */ + if ((*CoreDoCommand)(M64CMD_ROM_GET_HEADER, sizeof(l_RomHeader), &l_RomHeader) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_WARNING, "couldn't get ROM header information from core library"); + return; + } + + /* generate section name from ROM's CRC and country code */ + char RomSection[24]; + sprintf(RomSection, "%08X-%08X-C:%X", sl(l_RomHeader.CRC1), sl(l_RomHeader.CRC2), l_RomHeader.Country_code & 0xff); + + /* parse through the cheat INI file and load up any cheat codes found for this ROM */ + ReadCheats(RomSection); + if (!l_RomFound || l_CheatCodesFound == 0) + { + DebugMessage(M64MSG_WARNING, "no cheat codes found for ROM image '%.20s'", l_RomHeader.Name); + CheatFreeAll(); + return; + } + + /* handle the list command */ + if (CheatMode == CHEAT_SHOW_LIST) + { + DebugMessage(M64MSG_INFO, "%i cheat code(s) found for ROM '%s'", l_CheatCodesFound, l_CheatGameName); + sCheatInfo *pCur = l_CheatList; + while (pCur != NULL) + { + if (pCur->Description == NULL) + DebugMessage(M64MSG_INFO, " %i: %s", pCur->Number, pCur->Name); + else + DebugMessage(M64MSG_INFO, " %i: %s (%s)", pCur->Number, pCur->Name, pCur->Description); + if(pCur->VariableLine != -1) + { + int i; + for (i = 0; i < pCur->Codes[pCur->VariableLine].var_count; i++) + DebugMessage(M64MSG_INFO, " %i: %s", i, pCur->Codes[pCur->VariableLine].variable_names[i]); + } + pCur = pCur->Next; + } + CheatFreeAll(); + return; + } + + /* handle all cheats enabled mode */ + if (CheatMode == CHEAT_ALL) + { + sCheatInfo *pCur = l_CheatList; + while (pCur != NULL) + { + CheatActivate(pCur); + pCur = pCur->Next; + } + CheatFreeAll(); + return; + } + + /* handle list of cheats enabled mode */ + if (CheatMode == CHEAT_LIST) + { + int option, number; + char *cheat_next; + sCheatInfo *pCheat; + while(CheatNumList != NULL && *CheatNumList) + { + if ((cheat_next = strchr(CheatNumList, ',')) != NULL) + { + *cheat_next = 0; + cheat_next ++; + } + + if (strchr(CheatNumList, '-') != NULL) + { + sscanf(CheatNumList, "%i-%i", &number, &option); /* option */ + } + else + { + option=0; + sscanf(CheatNumList, "%i", &number); + } + + pCheat = CheatFindCode(number); + if (pCheat == NULL) + DebugMessage(M64MSG_WARNING, "invalid cheat code number %i", number); + else + { + if (pCheat->VariableLine != -1 && pCheat->Count > pCheat->VariableLine && option < pCheat->Codes[pCheat->VariableLine].var_count) + pCheat->Codes[pCheat->VariableLine].var_to_use = option; + CheatActivate(pCheat); + } + + CheatNumList = cheat_next; + } + CheatFreeAll(); + + return; + } + + /* otherwise the mode is invalid */ + DebugMessage(M64MSG_WARNING, "internal error; invalid CheatMode in CheatStart()"); + + return; +} + diff --git a/source/front-end/src/cheat.h b/source/front-end/src/cheat.h new file mode 100644 index 0000000..e44ac05 --- /dev/null +++ b/source/front-end/src/cheat.h @@ -0,0 +1,41 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - cheat.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef CHEAT_H +#define CHEAT_H + +#ifdef M64P_BIG_ENDIAN + #define sl(mot) mot +#else + #define sl(mot) (((mot & 0xFF) << 24) | ((mot & 0xFF00) << 8) | ((mot & 0xFF0000) >> 8) | ((mot & 0xFF000000) >> 24)) +#endif + +typedef enum { + CHEAT_DISABLE, + CHEAT_LIST, + CHEAT_ALL, + CHEAT_SHOW_LIST + } eCheatMode; + +void CheatStart(eCheatMode CheatMode, char *CheatNumList); + +#endif // #define CHEAT_H + diff --git a/source/front-end/src/compare_core.c b/source/front-end/src/compare_core.c new file mode 100644 index 0000000..bdc4f87 --- /dev/null +++ b/source/front-end/src/compare_core.c @@ -0,0 +1,230 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - compare_core.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * Copyright (C) 2002 Hacktarux * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +#include "m64p_types.h" +#include "main.h" +#include "compare_core.h" +#include "core_interface.h" + +/* local variables */ + +static FILE *fPipe = NULL; +static int comp_reg_32[32]; +static long long comp_reg_64[32]; +static unsigned int old_op = 0; +static int l_CoreCompareMode = CORE_COMPARE_DISABLE; + +static long long *ptr_reg = NULL; /* pointer to the 64-bit general purpose registers in the core */ +static int *ptr_cop0 = NULL; /* pointer to the 32-bit Co-processor 0 registers in the core */ +static long long *ptr_fgr = NULL; /* pointer to the 64-bit floating-point registers in the core */ +static int *ptr_PC = NULL; /* pointer to 32-bit R4300 Program Counter */ + +/* local functions */ +static void stop_it(void) +{ + static int errors = 0; + + (*CoreDoCommand)(M64CMD_STOP, 0, NULL); + + errors++; +#if !defined(WIN32) + #if defined(__i386__) || defined(__x86_64__) + if (errors > 7) + asm("int $3;"); + #endif +#endif +} + +static void display_error(char *txt) +{ + int i; + + printf("err: %6s addr:%x\t ", txt, *ptr_PC); + + if (!strcmp(txt, "PC")) + { + printf("My PC: %x Ref PC: %x\t ", *ptr_PC, *comp_reg_32); + } + else if (!strcmp(txt, "gpr")) + { + for (i=0; i<32; i++) + { + if (ptr_reg[i] != comp_reg_64[i]) + printf("My: reg[%d]=%llx\t Ref: reg[%d]=%llx\t ", i, ptr_reg[i], i, comp_reg_64[i]); + } + } + else if (!strcmp(txt, "cop0")) + { + for (i=0; i<32; i++) + { + if (ptr_cop0[i] != comp_reg_32[i]) + printf("My: reg_cop0[%d]=%x\t Ref: reg_cop0[%d]=%x\t ", i, (unsigned int)ptr_cop0[i], i, (unsigned int)comp_reg_32[i]); + } + } + else if (!strcmp(txt, "cop1")) + { + for (i=0; i<32; i++) + { + if (ptr_fgr[i] != comp_reg_64[i]) + printf("My: reg[%d]=%llx\t Ref: reg[%d]=%llx\t ", i, ptr_fgr[i], i, comp_reg_64[i]); + } + } + printf("\n"); + /*for (i=0; i<32; i++) + { + if (reg_cop0[i] != comp_reg[i]) + printf("reg_cop0[%d]=%llx != reg[%d]=%llx\n", + i, reg_cop0[i], i, comp_reg[i]); + }*/ + + stop_it(); +} + +static void compare_core_sync_data(int length, void *value) +{ + if (l_CoreCompareMode == CORE_COMPARE_RECV) + { + if (fread(value, 1, length, fPipe) != length) + stop_it(); + } + else if (l_CoreCompareMode == CORE_COMPARE_SEND) + { + if (fwrite(value, 1, length, fPipe) != length) + stop_it(); + } +} + +static void compare_core_check(unsigned int cur_opcode) +{ + static int comparecnt = 0; + int iFirst = 1; + char errHead[128]; + sprintf(errHead, "Compare #%i old_op: %x op: %x\n", comparecnt++, old_op, cur_opcode); + + /* get pointer to current R4300 Program Counter address */ + ptr_PC = (int *) DebugGetCPUDataPtr(M64P_CPU_PC); /* this changes for every instruction */ + + if (l_CoreCompareMode == CORE_COMPARE_RECV) + { + if (fread(comp_reg_32, sizeof(int), 4, fPipe) != 4) + printf("compare_core_check: fread() failed"); + if (*ptr_PC != *comp_reg_32) + { + if (iFirst) + { + printf("%s", errHead); + iFirst = 0; + } + display_error("PC"); + } + if (fread (comp_reg_64, sizeof(long long int), 32, fPipe) != 32) + printf("compare_core_check: fread() failed"); + if (memcmp(ptr_reg, comp_reg_64, 32*sizeof(long long int)) != 0) + { + if (iFirst) + { + printf("%s", errHead); + iFirst = 0; + } + display_error("gpr"); + } + if (fread(comp_reg_32, sizeof(int), 32, fPipe) != 32) + printf("compare_core_check: fread() failed"); + if (memcmp(ptr_cop0, comp_reg_32, 32*sizeof(int)) != 0) + { + if (iFirst) + { + printf("%s", errHead); + iFirst = 0; + } + display_error("cop0"); + } + if (fread(comp_reg_64, sizeof(long long int), 32, fPipe) != 32) + printf("compare_core_check: fread() failed"); + if (memcmp(ptr_fgr, comp_reg_64, 32*sizeof(long long int))) + { + if (iFirst) + { + printf("%s", errHead); + iFirst = 0; + } + display_error("cop1"); + } + /*fread(comp_reg, 1, sizeof(int), f); + if (memcmp(&rdram[0x31280/4], comp_reg, sizeof(int))) + display_error("mem");*/ + /*fread (comp_reg, 4, 1, f); + if (memcmp(&FCR31, comp_reg, 4)) + display_error();*/ + old_op = cur_opcode; + } + else if (l_CoreCompareMode == CORE_COMPARE_SEND) + { + if (fwrite(ptr_PC, sizeof(int), 4, fPipe) != 4 || + fwrite(ptr_reg, sizeof(long long int), 32, fPipe) != 32 || + fwrite(ptr_cop0, sizeof(int), 32, fPipe) != 32 || + fwrite(ptr_fgr, sizeof(long long int), 32, fPipe) != 32) + printf("compare_core_check: fwrite() failed"); + /*fwrite(&rdram[0x31280/4], 1, sizeof(int), f); + fwrite(&FCR31, 4, 1, f);*/ + } +} + +/* global functions */ +void compare_core_init(int mode) +{ +#if defined(WIN32) + DebugMessage(M64MSG_VERBOSE, "core comparison feature not supported on Windows platform."); + return; +#else + /* set mode */ + l_CoreCompareMode = mode; + /* set callback functions in core */ + if (DebugSetCoreCompare(compare_core_check, compare_core_sync_data) != M64ERR_SUCCESS) + { + l_CoreCompareMode = CORE_COMPARE_DISABLE; + DebugMessage(M64MSG_WARNING, "DebugSetCoreCompare() failed, core comparison disabled."); + return; + } + /* get pointers to emulated R4300 CPU registers */ + ptr_reg = (long long *) DebugGetCPUDataPtr(M64P_CPU_REG_REG); + ptr_cop0 = (int *) DebugGetCPUDataPtr(M64P_CPU_REG_COP0); + ptr_fgr = (long long *) DebugGetCPUDataPtr(M64P_CPU_REG_COP1_FGR_64); + /* open file handle to FIFO pipe */ + if (l_CoreCompareMode == CORE_COMPARE_RECV) + { + mkfifo("compare_pipe", 0600); + DebugMessage(M64MSG_INFO, "Core Comparison Waiting to read pipe."); + fPipe = fopen("compare_pipe", "r"); + } + else if (l_CoreCompareMode == CORE_COMPARE_SEND) + { + DebugMessage(M64MSG_INFO, "Core Comparison Waiting to write pipe."); + fPipe = fopen("compare_pipe", "w"); + } +#endif +} + diff --git a/source/front-end/src/compare_core.h b/source/front-end/src/compare_core.h new file mode 100644 index 0000000..1d54c8d --- /dev/null +++ b/source/front-end/src/compare_core.h @@ -0,0 +1,34 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - compare_core.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(COMPARE_CORE_H) +#define COMPARE_CORE_H + +typedef enum { + CORE_COMPARE_DISABLE = 0, + CORE_COMPARE_SEND = 1, + CORE_COMPARE_RECV = 2 +} CoreCompareMode; + +void compare_core_init(int mode); + +#endif /* COMPARE_CORE_H */ + diff --git a/source/front-end/src/core_interface.c b/source/front-end/src/core_interface.c new file mode 100644 index 0000000..09dd817 --- /dev/null +++ b/source/front-end/src/core_interface.c @@ -0,0 +1,344 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - core_interface.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 routines for attaching to the Mupen64Plus core + * library and pointers to the core functions + */ + +#include + +#include "m64p_types.h" +#include "m64p_common.h" +#include "m64p_frontend.h" +#include "m64p_config.h" +#include "m64p_debugger.h" + +#include "osal_preproc.h" +#include "osal_dynamiclib.h" + +#include "main.h" +#include "version.h" +#include "core_interface.h" + +/* global data definitions */ +int g_CoreCapabilities; +int g_CoreAPIVersion; + +/* definitions of pointers to Core common functions */ +ptr_CoreErrorMessage CoreErrorMessage = NULL; + +/* definitions of pointers to Core front-end functions */ +ptr_CoreStartup CoreStartup = NULL; +ptr_CoreShutdown CoreShutdown = NULL; +ptr_CoreAttachPlugin CoreAttachPlugin = NULL; +ptr_CoreDetachPlugin CoreDetachPlugin = NULL; +ptr_CoreDoCommand CoreDoCommand = NULL; +ptr_CoreOverrideVidExt CoreOverrideVidExt = NULL; +ptr_CoreAddCheat CoreAddCheat = NULL; +ptr_CoreCheatEnabled CoreCheatEnabled = NULL; + +/* definitions of pointers to Core config functions */ +ptr_ConfigListSections ConfigListSections = NULL; +ptr_ConfigOpenSection ConfigOpenSection = NULL; +ptr_ConfigDeleteSection ConfigDeleteSection = NULL; +ptr_ConfigSaveSection ConfigSaveSection = NULL; +ptr_ConfigListParameters ConfigListParameters = NULL; +ptr_ConfigSaveFile ConfigSaveFile = NULL; +ptr_ConfigSetParameter ConfigSetParameter = NULL; +ptr_ConfigGetParameter ConfigGetParameter = NULL; +ptr_ConfigGetParameterType ConfigGetParameterType = NULL; +ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; +ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; +ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; +ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; +ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; +ptr_ConfigGetParamInt ConfigGetParamInt = NULL; +ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; +ptr_ConfigGetParamBool ConfigGetParamBool = NULL; +ptr_ConfigGetParamString ConfigGetParamString = NULL; + +ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; +ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; +ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; +ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; + +/* definitions of pointers to Core debugger functions */ +ptr_DebugSetCallbacks DebugSetCallbacks = NULL; +ptr_DebugSetCoreCompare DebugSetCoreCompare = NULL; +ptr_DebugSetRunState DebugSetRunState = NULL; +ptr_DebugGetState DebugGetState = NULL; +ptr_DebugStep DebugStep = NULL; +ptr_DebugDecodeOp DebugDecodeOp = NULL; +ptr_DebugMemGetRecompInfo DebugMemGetRecompInfo = NULL; +ptr_DebugMemGetMemInfo DebugMemGetMemInfo = NULL; +ptr_DebugMemGetPointer DebugMemGetPointer = NULL; + +ptr_DebugMemRead64 DebugMemRead64 = NULL; +ptr_DebugMemRead32 DebugMemRead32 = NULL; +ptr_DebugMemRead16 DebugMemRead16 = NULL; +ptr_DebugMemRead8 DebugMemRead8 = NULL; + +ptr_DebugMemWrite64 DebugMemWrite64 = NULL; +ptr_DebugMemWrite32 DebugMemWrite32 = NULL; +ptr_DebugMemWrite16 DebugMemWrite16 = NULL; +ptr_DebugMemWrite8 DebugMemWrite8 = NULL; + +ptr_DebugGetCPUDataPtr DebugGetCPUDataPtr = NULL; +ptr_DebugBreakpointLookup DebugBreakpointLookup = NULL; +ptr_DebugBreakpointCommand DebugBreakpointCommand = NULL; + +/* global variables */ +m64p_dynlib_handle CoreHandle = NULL; + +/* functions */ +m64p_error AttachCoreLib(const char *CoreLibFilepath) +{ + /* check if Core DLL is already attached */ + if (CoreHandle != NULL) + return M64ERR_INVALID_STATE; + + /* load the DLL */ + m64p_error rval = M64ERR_INTERNAL; + /* first, try a library path+name that was given on the command-line */ + if (CoreLibFilepath != NULL) + { + rval = osal_dynlib_open(&CoreHandle, CoreLibFilepath); + } + /* then try a library path that was given at compile time */ +#if defined(COREDIR) + if (rval != M64ERR_SUCCESS || CoreHandle == NULL) + { + rval = osal_dynlib_open(&CoreHandle, COREDIR OSAL_DEFAULT_DYNLIB_FILENAME); + } +#endif + /* then try just the filename of the shared library, to let dlopen() look through the system lib dirs */ + if (rval != M64ERR_SUCCESS || CoreHandle == NULL) + { + rval = osal_dynlib_open(&CoreHandle, OSAL_DEFAULT_DYNLIB_FILENAME); + } + /* as a last-ditch effort, try loading library in current directory */ + if (rval != M64ERR_SUCCESS || CoreHandle == NULL) + { + rval = osal_dynlib_open(&CoreHandle, OSAL_CURRENT_DIR OSAL_DEFAULT_DYNLIB_FILENAME); + } + /* if we haven't found a good core library by now, then we're screwed */ + if (rval != M64ERR_SUCCESS || CoreHandle == NULL) + { + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: failed to find Mupen64Plus Core library"); + CoreHandle = NULL; + return M64ERR_INPUT_NOT_FOUND; + } + + /* attach and call the PluginGetVersion function, check the Core and API versions for compatibility with this front-end */ + ptr_PluginGetVersion CoreVersionFunc; + CoreVersionFunc = (ptr_PluginGetVersion) osal_dynlib_getproc(CoreHandle, "PluginGetVersion"); + if (CoreVersionFunc == NULL) + { + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' invalid; no PluginGetVersion() function found.", CoreLibFilepath); + osal_dynlib_close(CoreHandle); + CoreHandle = NULL; + return M64ERR_INPUT_INVALID; + } + m64p_plugin_type PluginType = (m64p_plugin_type) 0; + int Compatible = 0; + int CoreVersion = 0; + const char *CoreName = NULL; + (*CoreVersionFunc)(&PluginType, &CoreVersion, &g_CoreAPIVersion, &CoreName, &g_CoreCapabilities); + if (PluginType != M64PLUGIN_CORE) + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' invalid; this is not the emulator core.", CoreLibFilepath); + else if (CoreVersion < MINIMUM_CORE_VERSION) + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' incompatible; core version %i.%i.%i is below minimum supported %i.%i.%i", + CoreLibFilepath, VERSION_PRINTF_SPLIT(CoreVersion), VERSION_PRINTF_SPLIT(MINIMUM_CORE_VERSION)); + else if ((g_CoreAPIVersion & 0xffff0000) != (CORE_API_VERSION & 0xffff0000)) + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' incompatible; core API major version %i.%i.%i doesn't match with this application (%i.%i.%i)", + CoreLibFilepath, VERSION_PRINTF_SPLIT(g_CoreAPIVersion), VERSION_PRINTF_SPLIT(CORE_API_VERSION)); + else + Compatible = 1; + /* exit if not compatible */ + if (Compatible == 0) + { + osal_dynlib_close(CoreHandle); + CoreHandle = NULL; + return M64ERR_INCOMPATIBLE; + } + + /* attach and call the CoreGetAPIVersion function, check Config API version for compatibility */ + ptr_CoreGetAPIVersions CoreAPIVersionFunc; + CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreHandle, "CoreGetAPIVersions"); + if (CoreAPIVersionFunc == NULL) + { + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Library '%s' broken; no CoreAPIVersionFunc() function found.", CoreLibFilepath); + osal_dynlib_close(CoreHandle); + CoreHandle = NULL; + return M64ERR_INPUT_INVALID; + } + int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion; + (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL); + if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000)) + { + DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Emulator core '%s' incompatible; Config API major version %i.%i.%i doesn't match application: %i.%i.%i", + CoreLibFilepath, VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION)); + osal_dynlib_close(CoreHandle); + CoreHandle = NULL; + return M64ERR_INCOMPATIBLE; + } + + /* print some information about the core library */ + DebugMessage(M64MSG_INFO, "attached to core library '%s' version %i.%i.%i", CoreName, VERSION_PRINTF_SPLIT(CoreVersion)); + if (g_CoreCapabilities & M64CAPS_DYNAREC) + DebugMessage(M64MSG_INFO, " Includes support for Dynamic Recompiler."); + if (g_CoreCapabilities & M64CAPS_DEBUGGER) + DebugMessage(M64MSG_INFO, " Includes support for MIPS r4300 Debugger."); + if (g_CoreCapabilities & M64CAPS_CORE_COMPARE) + DebugMessage(M64MSG_INFO, " Includes support for r4300 Core Comparison."); + + /* get function pointers to the common and front-end functions */ + CoreErrorMessage = (ptr_CoreErrorMessage) osal_dynlib_getproc(CoreHandle, "CoreErrorMessage"); + CoreStartup = (ptr_CoreStartup) osal_dynlib_getproc(CoreHandle, "CoreStartup"); + CoreShutdown = (ptr_CoreShutdown) osal_dynlib_getproc(CoreHandle, "CoreShutdown"); + CoreAttachPlugin = (ptr_CoreAttachPlugin) osal_dynlib_getproc(CoreHandle, "CoreAttachPlugin"); + CoreDetachPlugin = (ptr_CoreDetachPlugin) osal_dynlib_getproc(CoreHandle, "CoreDetachPlugin"); + CoreDoCommand = (ptr_CoreDoCommand) osal_dynlib_getproc(CoreHandle, "CoreDoCommand"); + CoreOverrideVidExt = (ptr_CoreOverrideVidExt) osal_dynlib_getproc(CoreHandle, "CoreOverrideVidExt"); + CoreAddCheat = (ptr_CoreAddCheat) osal_dynlib_getproc(CoreHandle, "CoreAddCheat"); + CoreCheatEnabled = (ptr_CoreCheatEnabled) osal_dynlib_getproc(CoreHandle, "CoreCheatEnabled"); + + /* get function pointers to the configuration functions */ + ConfigListSections = (ptr_ConfigListSections) osal_dynlib_getproc(CoreHandle, "ConfigListSections"); + ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreHandle, "ConfigOpenSection"); + ConfigDeleteSection = (ptr_ConfigDeleteSection) osal_dynlib_getproc(CoreHandle, "ConfigDeleteSection"); + ConfigSaveSection = (ptr_ConfigSaveSection) osal_dynlib_getproc(CoreHandle, "ConfigSaveSection"); + ConfigListParameters = (ptr_ConfigListParameters) osal_dynlib_getproc(CoreHandle, "ConfigListParameters"); + ConfigSaveFile = (ptr_ConfigSaveFile) osal_dynlib_getproc(CoreHandle, "ConfigSaveFile"); + ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreHandle, "ConfigSetParameter"); + ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreHandle, "ConfigGetParameter"); + ConfigGetParameterType = (ptr_ConfigGetParameterType) osal_dynlib_getproc(CoreHandle, "ConfigGetParameterType"); + ConfigGetParameterHelp = (ptr_ConfigGetParameterHelp) osal_dynlib_getproc(CoreHandle, "ConfigGetParameterHelp"); + ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultInt"); + ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultFloat"); + ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultBool"); + ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultString"); + ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreHandle, "ConfigGetParamInt"); + ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreHandle, "ConfigGetParamFloat"); + ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreHandle, "ConfigGetParamBool"); + ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreHandle, "ConfigGetParamString"); + + ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreHandle, "ConfigGetSharedDataFilepath"); + ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserConfigPath"); + ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserDataPath"); + ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserCachePath"); + + /* get function pointers to the debugger functions */ + DebugSetCallbacks = (ptr_DebugSetCallbacks) osal_dynlib_getproc(CoreHandle, "DebugSetCallbacks"); + DebugSetCoreCompare = (ptr_DebugSetCoreCompare) osal_dynlib_getproc(CoreHandle, "DebugSetCoreCompare"); + DebugSetRunState = (ptr_DebugSetRunState) osal_dynlib_getproc(CoreHandle, "DebugSetRunState"); + DebugGetState = (ptr_DebugGetState) osal_dynlib_getproc(CoreHandle, "DebugGetState"); + DebugStep = (ptr_DebugStep) osal_dynlib_getproc(CoreHandle, "DebugStep"); + DebugDecodeOp = (ptr_DebugDecodeOp) osal_dynlib_getproc(CoreHandle, "DebugDecodeOp"); + DebugMemGetRecompInfo = (ptr_DebugMemGetRecompInfo) osal_dynlib_getproc(CoreHandle, "DebugMemGetRecompInfo"); + DebugMemGetMemInfo = (ptr_DebugMemGetMemInfo) osal_dynlib_getproc(CoreHandle, "DebugMemGetMemInfo"); + DebugMemGetPointer = (ptr_DebugMemGetPointer) osal_dynlib_getproc(CoreHandle, "DebugMemGetPointer"); + + DebugMemRead64 = (ptr_DebugMemRead64) osal_dynlib_getproc(CoreHandle, "DebugMemRead64"); + DebugMemRead32 = (ptr_DebugMemRead32) osal_dynlib_getproc(CoreHandle, "DebugMemRead32"); + DebugMemRead16 = (ptr_DebugMemRead16) osal_dynlib_getproc(CoreHandle, "DebugMemRead16"); + DebugMemRead8 = (ptr_DebugMemRead8) osal_dynlib_getproc(CoreHandle, "DebugMemRead8"); + + DebugMemWrite64 = (ptr_DebugMemWrite64) osal_dynlib_getproc(CoreHandle, "DebugMemRead64"); + DebugMemWrite32 = (ptr_DebugMemWrite32) osal_dynlib_getproc(CoreHandle, "DebugMemRead32"); + DebugMemWrite16 = (ptr_DebugMemWrite16) osal_dynlib_getproc(CoreHandle, "DebugMemRead16"); + DebugMemWrite8 = (ptr_DebugMemWrite8) osal_dynlib_getproc(CoreHandle, "DebugMemRead8"); + + DebugGetCPUDataPtr = (ptr_DebugGetCPUDataPtr) osal_dynlib_getproc(CoreHandle, "DebugGetCPUDataPtr"); + DebugBreakpointLookup = (ptr_DebugBreakpointLookup) osal_dynlib_getproc(CoreHandle, "DebugBreakpointLookup"); + DebugBreakpointCommand = (ptr_DebugBreakpointCommand) osal_dynlib_getproc(CoreHandle, "DebugBreakpointCommand"); + + return M64ERR_SUCCESS; +} + +m64p_error DetachCoreLib(void) +{ + if (CoreHandle == NULL) + return M64ERR_INVALID_STATE; + + /* set the core function pointers to NULL */ + CoreErrorMessage = NULL; + CoreStartup = NULL; + CoreShutdown = NULL; + CoreAttachPlugin = NULL; + CoreDetachPlugin = NULL; + CoreDoCommand = NULL; + CoreOverrideVidExt = NULL; + CoreAddCheat = NULL; + CoreCheatEnabled = NULL; + + ConfigListSections = NULL; + ConfigOpenSection = NULL; + ConfigDeleteSection = NULL; + ConfigSaveSection = NULL; + ConfigListParameters = NULL; + ConfigSetParameter = NULL; + ConfigGetParameter = NULL; + ConfigGetParameterType = NULL; + ConfigGetParameterHelp = NULL; + ConfigSetDefaultInt = NULL; + ConfigSetDefaultBool = NULL; + ConfigSetDefaultString = NULL; + ConfigGetParamInt = NULL; + ConfigGetParamBool = NULL; + ConfigGetParamString = NULL; + + ConfigGetSharedDataFilepath = NULL; + ConfigGetUserDataPath = NULL; + ConfigGetUserCachePath = NULL; + + DebugSetCallbacks = NULL; + DebugSetCoreCompare = NULL; + DebugSetRunState = NULL; + DebugGetState = NULL; + DebugStep = NULL; + DebugDecodeOp = NULL; + DebugMemGetRecompInfo = NULL; + DebugMemGetMemInfo = NULL; + DebugMemGetPointer = NULL; + + DebugMemRead64 = NULL; + DebugMemRead32 = NULL; + DebugMemRead16 = NULL; + DebugMemRead8 = NULL; + + DebugMemWrite64 = NULL; + DebugMemWrite32 = NULL; + DebugMemWrite16 = NULL; + DebugMemWrite8 = NULL; + + DebugGetCPUDataPtr = NULL; + DebugBreakpointLookup = NULL; + DebugBreakpointCommand = NULL; + + /* detach the shared library */ + osal_dynlib_close(CoreHandle); + CoreHandle = NULL; + + return M64ERR_SUCCESS; +} + + diff --git a/source/front-end/src/core_interface.h b/source/front-end/src/core_interface.h new file mode 100644 index 0000000..295daae --- /dev/null +++ b/source/front-end/src/core_interface.h @@ -0,0 +1,104 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - core_interface.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(CORE_INTERFACE_H) +#define CORE_INTERFACE_H + +#include "m64p_types.h" +#include "m64p_common.h" +#include "m64p_frontend.h" +#include "m64p_config.h" +#include "m64p_debugger.h" + +/* function declarations */ +extern m64p_error AttachCoreLib(const char *CoreLibFilepath); +extern m64p_error DetachCoreLib(void); + +/* global variables from core_interface.c */ +extern int g_CoreCapabilities; +extern int g_CoreAPIVersion; + +/* declarations of Core library handle and pointers to common functions */ +extern m64p_dynlib_handle CoreHandle; +extern ptr_CoreErrorMessage CoreErrorMessage; + +/* declarations of pointers to Core front-end functions */ +extern ptr_CoreStartup CoreStartup; +extern ptr_CoreShutdown CoreShutdown; +extern ptr_CoreAttachPlugin CoreAttachPlugin; +extern ptr_CoreDetachPlugin CoreDetachPlugin; +extern ptr_CoreDoCommand CoreDoCommand; +extern ptr_CoreOverrideVidExt CoreOverrideVidExt; +extern ptr_CoreAddCheat CoreAddCheat; +extern ptr_CoreCheatEnabled CoreCheatEnabled; + +/* 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_ConfigGetParameterType ConfigGetParameterType; +extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp; +extern ptr_ConfigSetDefaultInt ConfigSetDefaultInt; +extern ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat; +extern ptr_ConfigSetDefaultBool ConfigSetDefaultBool; +extern ptr_ConfigSetDefaultString ConfigSetDefaultString; +extern ptr_ConfigGetParamInt ConfigGetParamInt; +extern ptr_ConfigGetParamFloat ConfigGetParamFloat; +extern ptr_ConfigGetParamBool ConfigGetParamBool; +extern ptr_ConfigGetParamString ConfigGetParamString; + +extern ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath; +extern ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath; +extern ptr_ConfigGetUserDataPath ConfigGetUserDataPath; +extern ptr_ConfigGetUserCachePath ConfigGetUserCachePath; + +/* declarations of pointers to Core debugger functions */ +extern ptr_DebugSetCallbacks DebugSetCallbacks; +extern ptr_DebugSetCoreCompare DebugSetCoreCompare; +extern ptr_DebugSetRunState DebugSetRunState; +extern ptr_DebugGetState DebugGetState; +extern ptr_DebugStep DebugStep; +extern ptr_DebugDecodeOp DebugDecodeOp; +extern ptr_DebugMemGetRecompInfo DebugMemGetRecompInfo; +extern ptr_DebugMemGetMemInfo DebugMemGetMemInfo; +extern ptr_DebugMemGetPointer DebugMemGetPointer; + +extern ptr_DebugMemRead64 DebugMemRead64; +extern ptr_DebugMemRead32 DebugMemRead32; +extern ptr_DebugMemRead16 DebugMemRead16; +extern ptr_DebugMemRead8 DebugMemRead8; + +extern ptr_DebugMemWrite64 DebugMemWrite64; +extern ptr_DebugMemWrite32 DebugMemWrite32; +extern ptr_DebugMemWrite16 DebugMemWrite16; +extern ptr_DebugMemWrite8 DebugMemWrite8; + +extern ptr_DebugGetCPUDataPtr DebugGetCPUDataPtr; +extern ptr_DebugBreakpointLookup DebugBreakpointLookup; +extern ptr_DebugBreakpointCommand DebugBreakpointCommand; + +#endif /* #define CORE_INTERFACE_H */ + diff --git a/source/front-end/src/main.c b/source/front-end/src/main.c new file mode 100755 index 0000000..a0ff193 --- /dev/null +++ b/source/front-end/src/main.c @@ -0,0 +1,819 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - main.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2007-2010 Richard42 * + * 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 the main application entry point for the console-only front-end + * for Mupen64Plus v2.0. + */ + +#include +#include +#include +#include + +#include + +#include "cheat.h" +#include "main.h" +#include "plugin.h" +#include "version.h" +#include "core_interface.h" +#include "compare_core.h" +#include "osal_preproc.h" + +#ifdef PAULSCODE +//#include "ae_bridge.h" +#endif + +/* Version number for UI-Console config section parameters */ +#define CONFIG_PARAM_VERSION 1.00 + +/** global variables **/ +int g_Verbose = 0; + +/** static (local) variables **/ +static m64p_handle l_ConfigCore = NULL; +static m64p_handle l_ConfigVideo = NULL; +static m64p_handle l_ConfigUI = NULL; + +static const char *l_CoreLibPath = NULL; +static const char *l_ConfigDirPath = NULL; +static const char *l_ROMFilepath = NULL; // filepath of ROM to load & run at startup + +#if defined(SHAREDIR) + static const char *l_DataDirPath = SHAREDIR; +#else + static const char *l_DataDirPath = NULL; +#endif + +static int *l_TestShotList = NULL; // list of screenshots to take for regression test support +static int l_TestShotIdx = 0; // index of next screenshot frame in list +static int l_SaveOptions = 1; // save command-line options in configuration file (enabled by default) +static int l_CoreCompareMode = 0; // 0 = disable, 1 = send, 2 = receive + +static eCheatMode l_CheatMode = CHEAT_DISABLE; +static char *l_CheatNumList = NULL; + +/********************************************************************************************************* + * Callback functions from the core + */ + +void DebugMessage(int level, const char *message, ...) +{ + char msgbuf[1024]; + va_list args; + + va_start(args, message); + vsnprintf(msgbuf, 1024, message, args); + + DebugCallback("UI-Console", level, msgbuf); + + va_end(args); +} + +void DebugCallback(void *Context, int level, const char *message) +{ +#ifdef ANDROID0 + if (level == M64MSG_ERROR) + __android_log_print(ANDROID_LOG_ERROR, (const char *) Context, "%s", message); + else if (level == M64MSG_WARNING) + __android_log_print(ANDROID_LOG_WARN, (const char *) Context, "%s", message); + else if (level == M64MSG_INFO) + __android_log_print(ANDROID_LOG_INFO, (const char *) Context, "%s", message); + else if (level == M64MSG_STATUS) + __android_log_print(ANDROID_LOG_DEBUG, (const char *) Context, "%s", message); + else if (level == M64MSG_VERBOSE) + { + if (g_Verbose) + __android_log_print(ANDROID_LOG_VERBOSE, (const char *) Context, "%s", message); + } + else + __android_log_print(ANDROID_LOG_ERROR, (const char *) Context, "Unknown: %s", message); +#else + if (level == M64MSG_ERROR) + printf("%s Error: %s\n", (const char *) Context, message); + else if (level == M64MSG_WARNING) + printf("%s Warning: %s\n", (const char *) Context, message); + else if (level == M64MSG_INFO) + printf("%s: %s\n", (const char *) Context, message); + else if (level == M64MSG_STATUS) + printf("%s Status: %s\n", (const char *) Context, message); + else if (level == M64MSG_VERBOSE) + { + if (g_Verbose) + printf("%s: %s\n", (const char *) Context, message); + } + else + printf("%s Unknown: %s\n", (const char *) Context, message); +#endif +} + +static void FrameCallback(unsigned int FrameIndex) +{ + // take a screenshot if we need to + if (l_TestShotList != NULL) + { + int nextshot = l_TestShotList[l_TestShotIdx]; + if (nextshot == FrameIndex) + { + (*CoreDoCommand)(M64CMD_TAKE_NEXT_SCREENSHOT, 0, NULL); /* tell the core take a screenshot */ + // advance list index to next screenshot frame number. If it's 0, then quit + l_TestShotIdx++; + } + else if (nextshot == 0) + { + (*CoreDoCommand)(M64CMD_STOP, 0, NULL); /* tell the core to shut down ASAP */ + free(l_TestShotList); + l_TestShotList = NULL; + } + } +} + +#ifdef PAULSCODE +void StateCallback( void *Context, m64p_core_param ParamChanged, int NewValue ) +{ + /*----ParamChanged----------------- + * --------NewValue-------- + * M64CORE_EMU_STATE 1 + * M64EMU_STOPPED 1 + * M64EMU_RUNNING 2 + * M64EMU_PAUSED 3 + * M64CORE_VIDEO_MODE 2 + * M64CORE_SAVESTATE_SLOT 3 + * M64CORE_SPEED_FACTOR 4 + * M64CORE_SPEED_LIMITER 5 + * M64CORE_VIDEO_SIZE 6 + * M64CORE_AUDIO_VOLUME 7 + * M64CORE_AUDIO_MUTE 8 + * M64CORE_INPUT_GAMESHARK 9 + * M64CORE_STATE_LOADCOMPLETE 10 + * (successful) 1 + * (unsuccessful) 0 + * M64CORE_STATE_SAVECOMPLETE 11 + * (successful) 1 + * (unsuccessful) 0 + */ + + if( ParamChanged == M64CORE_EMU_STATE || ParamChanged == M64CORE_STATE_SAVECOMPLETE || ParamChanged == M64CORE_STATE_LOADCOMPLETE ) + Android_JNI_State_Callback( ParamChanged, NewValue ); +} +#endif + +/********************************************************************************************************* + * Configuration handling + */ + +static m64p_error OpenConfigurationHandles(void) +{ + float fConfigParamsVersion; + int bSaveConfig = 0; + m64p_error rval; + + /* Open Configuration sections for core library and console User Interface */ + rval = (*ConfigOpenSection)("Core", &l_ConfigCore); + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "failed to open 'Core' configuration section"); + return rval; + } + + rval = (*ConfigOpenSection)("Video-General", &l_ConfigVideo); + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "failed to open 'Video-General' configuration section"); + return rval; + } + + rval = (*ConfigOpenSection)("UI-Console", &l_ConfigUI); + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "failed to open 'UI-Console' configuration section"); + return rval; + } + + if ((*ConfigGetParameter)(l_ConfigUI, "Version", M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_WARNING, "No version number in 'UI-Console' config section. Setting defaults."); + (*ConfigDeleteSection)("UI-Console"); + (*ConfigOpenSection)("UI-Console", &l_ConfigUI); + bSaveConfig = 1; + } + else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION)) + { + DebugMessage(M64MSG_WARNING, "Incompatible version %.2f in 'UI-Console' config section: current is %.2f. Setting defaults.", fConfigParamsVersion, (float) CONFIG_PARAM_VERSION); + (*ConfigDeleteSection)("UI-Console"); + (*ConfigOpenSection)("UI-Console", &l_ConfigUI); + bSaveConfig = 1; + } + else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f) + { + /* handle upgrades */ + float fVersion = CONFIG_PARAM_VERSION; + ConfigSetParameter(l_ConfigUI, "Version", M64TYPE_FLOAT, &fVersion); + DebugMessage(M64MSG_INFO, "Updating parameter set version in 'UI-Console' config section to %.2f", fVersion); + bSaveConfig = 1; + } + + /* Set default values for my Config parameters */ + (*ConfigSetDefaultFloat)(l_ConfigUI, "Version", CONFIG_PARAM_VERSION, "Mupen64Plus UI-Console config parameter set version number. Please don't change this version number."); + (*ConfigSetDefaultString)(l_ConfigUI, "PluginDir", OSAL_CURRENT_DIR, "Directory in which to search for plugins"); + (*ConfigSetDefaultString)(l_ConfigUI, "VideoPlugin", "mupen64plus-video-rice" OSAL_DLL_EXTENSION, "Filename of video plugin"); + (*ConfigSetDefaultString)(l_ConfigUI, "AudioPlugin", "mupen64plus-audio-sdl" OSAL_DLL_EXTENSION, "Filename of audio plugin"); + (*ConfigSetDefaultString)(l_ConfigUI, "InputPlugin", "mupen64plus-input-sdl" OSAL_DLL_EXTENSION, "Filename of input plugin"); + (*ConfigSetDefaultString)(l_ConfigUI, "RspPlugin", "mupen64plus-rsp-hle" OSAL_DLL_EXTENSION, "Filename of RSP plugin"); + + if (bSaveConfig && ConfigSaveSection != NULL) /* ConfigSaveSection was added in Config API v2.1.0 */ + (*ConfigSaveSection)("UI-Console"); + + return M64ERR_SUCCESS; +} + +static m64p_error SaveConfigurationOptions(void) +{ + /* if shared data directory was given on the command line, write it into the config file */ + if (l_DataDirPath != NULL) + (*ConfigSetParameter)(l_ConfigCore, "SharedDataPath", M64TYPE_STRING, l_DataDirPath); + + /* if any plugin filepaths were given on the command line, write them into the config file */ + if (g_PluginDir != NULL) + (*ConfigSetParameter)(l_ConfigUI, "PluginDir", M64TYPE_STRING, g_PluginDir); + if (g_GfxPlugin != NULL) + (*ConfigSetParameter)(l_ConfigUI, "VideoPlugin", M64TYPE_STRING, g_GfxPlugin); + if (g_AudioPlugin != NULL) + (*ConfigSetParameter)(l_ConfigUI, "AudioPlugin", M64TYPE_STRING, g_AudioPlugin); + if (g_InputPlugin != NULL) + (*ConfigSetParameter)(l_ConfigUI, "InputPlugin", M64TYPE_STRING, g_InputPlugin); + if (g_RspPlugin != NULL) + (*ConfigSetParameter)(l_ConfigUI, "RspPlugin", M64TYPE_STRING, g_RspPlugin); + + return (*ConfigSaveFile)(); +} + +/********************************************************************************************************* + * Command-line parsing + */ + +static void printUsage(const char *progname) +{ + printf("Usage: %s [parameters] [romfile]\n" + "\n" + "Parameters:\n" + " --noosd : disable onscreen display\n" + " --osd : enable onscreen display\n" + " --fullscreen : use fullscreen display mode\n" + " --windowed : use windowed display mode\n" + " --resolution (res) : display resolution (640x480, 800x600, 1024x768, etc)\n" + " --nospeedlimit : disable core speed limiter (should be used with dummy audio plugin)\n" + " --cheats (cheat-spec) : enable or list cheat codes for the given rom file\n" + " --corelib (filepath) : use core library (filepath) (can be only filename or full path)\n" + " --configdir (dir) : force configation directory to (dir); should contain mupen64plus.cfg\n" + " --datadir (dir) : search for shared data files (.ini files, languages, etc) in (dir)\n" + " --plugindir (dir) : search for plugins in (dir)\n" + " --sshotdir (dir) : set screenshot directory to (dir)\n" + " --gfx (plugin-spec) : use gfx plugin given by (plugin-spec)\n" + " --audio (plugin-spec) : use audio plugin given by (plugin-spec)\n" + " --input (plugin-spec) : use input plugin given by (plugin-spec)\n" + " --rsp (plugin-spec) : use rsp plugin given by (plugin-spec)\n" + " --emumode (mode) : set emu mode to: 0=Pure Interpreter 1=Interpreter 2=DynaRec\n" + " --testshots (list) : take screenshots at frames given in comma-separated (list), then quit\n" + " --set (param-spec) : set a configuration variable, format: ParamSection[ParamName]=Value\n" + " --core-compare-send : use the Core Comparison debugging feature, in data sending mode\n" + " --core-compare-recv : use the Core Comparison debugging feature, in data receiving mode\n" + " --nosaveoptions : do not save the given command-line options in configuration file\n" + " --verbose : print lots of information\n" + " --help : see this help message\n\n" + "(plugin-spec):\n" + " (pluginname) : filename (without path) of plugin to find in plugin directory\n" + " (pluginpath) : full path and filename of plugin\n" + " 'dummy' : use dummy plugin\n\n" + "(cheat-spec):\n" + " 'list' : show all of the available cheat codes\n" + " 'all' : enable all of the available cheat codes\n" + " (codelist) : a comma-separated list of cheat code numbers to enable,\n" + " with dashes to use code variables (ex 1-2 to use cheat 1 option 2)\n" + "\n", progname); + + return; +} + +static int SetConfigParameter(const char *ParamSpec) +{ + char *ParsedString, *VarName, *VarValue=NULL; + m64p_handle ConfigSection; + m64p_type VarType; + m64p_error rval; + + if (ParamSpec == NULL) + { + DebugMessage(M64MSG_ERROR, "ParamSpec is NULL in SetConfigParameter()"); + return 1; + } + + /* make a copy of the input string */ + ParsedString = (char *) malloc(strlen(ParamSpec) + 1); + if (ParsedString == NULL) + { + DebugMessage(M64MSG_ERROR, "SetConfigParameter() couldn't allocate memory for temporary string."); + return 2; + } + strcpy(ParsedString, ParamSpec); + + /* parse it for the simple section[name]=value format */ + VarName = strchr(ParsedString, '['); + if (VarName != NULL) + { + *VarName++ = 0; + VarValue = strchr(VarName, ']'); + if (VarValue != NULL) + { + *VarValue++ = 0; + } + } + if (VarName == NULL || VarValue == NULL || *VarValue != '=') + { + DebugMessage(M64MSG_ERROR, "invalid (param-spec) '%s'", ParamSpec); + free(ParsedString); + return 3; + } + VarValue++; + + /* then set the value */ + rval = (*ConfigOpenSection)(ParsedString, &ConfigSection); + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "SetConfigParameter failed to open config section '%s'", ParsedString); + free(ParsedString); + return 4; + } + if ((*ConfigGetParameterType)(ConfigSection, VarName, &VarType) == M64ERR_SUCCESS) + { + switch(VarType) + { + int ValueInt; + float ValueFloat; + case M64TYPE_INT: + ValueInt = atoi(VarValue); + ConfigSetParameter(ConfigSection, VarName, M64TYPE_INT, &ValueInt); + break; + case M64TYPE_FLOAT: + ValueFloat = (float) atof(VarValue); + ConfigSetParameter(ConfigSection, VarName, M64TYPE_FLOAT, &ValueFloat); + break; + case M64TYPE_BOOL: + ValueInt = (int) (osal_insensitive_strcmp(VarValue, "true") == 0); + ConfigSetParameter(ConfigSection, VarName, M64TYPE_BOOL, &ValueInt); + break; + case M64TYPE_STRING: + ConfigSetParameter(ConfigSection, VarName, M64TYPE_STRING, VarValue); + break; + default: + DebugMessage(M64MSG_ERROR, "invalid VarType in SetConfigParameter()"); + return 5; + } + } + else + { + ConfigSetParameter(ConfigSection, VarName, M64TYPE_STRING, VarValue); + } + + free(ParsedString); + return 0; +} + +static int *ParseNumberList(const char *InputString, int *ValuesFound) +{ + const char *str; + int *OutputList; + + /* count the number of integers in the list */ + int values = 1; + str = InputString; + while ((str = strchr(str, ',')) != NULL) + { + str++; + values++; + } + + /* create a list and populate it with the frame counter values at which to take screenshots */ + if ((OutputList = (int *) malloc(sizeof(int) * (values + 1))) != NULL) + { + int idx = 0; + str = InputString; + while (str != NULL) + { + OutputList[idx++] = atoi(str); + str = strchr(str, ','); + if (str != NULL) str++; + } + OutputList[idx] = 0; + } + + if (ValuesFound != NULL) + *ValuesFound = values; + return OutputList; +} + +static int ParseCommandLineInitial(int argc, const char **argv) +{ + int i; + + /* look through commandline options */ + for (i = 1; i < argc; i++) + { + int ArgsLeft = argc - i - 1; + + if (strcmp(argv[i], "--corelib") == 0 && ArgsLeft >= 1) + { + l_CoreLibPath = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--configdir") == 0 && ArgsLeft >= 1) + { + l_ConfigDirPath = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--datadir") == 0 && ArgsLeft >= 1) + { + l_DataDirPath = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) + { + printUsage(argv[0]); + return 1; + } + } + + return 0; +} + +static m64p_error ParseCommandLineFinal(int argc, const char **argv) +{ + int i; + + /* parse commandline options */ + for (i = 1; i < argc; i++) + { + int ArgsLeft = argc - i - 1; + if (strcmp(argv[i], "--noosd") == 0) + { + int Osd = 0; + (*ConfigSetParameter)(l_ConfigCore, "OnScreenDisplay", M64TYPE_BOOL, &Osd); + } + else if (strcmp(argv[i], "--osd") == 0) + { + int Osd = 1; + (*ConfigSetParameter)(l_ConfigCore, "OnScreenDisplay", M64TYPE_BOOL, &Osd); + } + else if (strcmp(argv[i], "--fullscreen") == 0) + { + int Fullscreen = 1; + (*ConfigSetParameter)(l_ConfigVideo, "Fullscreen", M64TYPE_BOOL, &Fullscreen); + } + else if (strcmp(argv[i], "--windowed") == 0) + { + int Fullscreen = 0; + (*ConfigSetParameter)(l_ConfigVideo, "Fullscreen", M64TYPE_BOOL, &Fullscreen); + } + else if (strcmp(argv[i], "--nospeedlimit") == 0) + { + int EnableSpeedLimit = 0; + if (g_CoreAPIVersion < 0x020001) + DebugMessage(M64MSG_WARNING, "core library doesn't support --nospeedlimit"); + else + { + if ((*CoreDoCommand)(M64CMD_CORE_STATE_SET, M64CORE_SPEED_LIMITER, &EnableSpeedLimit) != M64ERR_SUCCESS) + DebugMessage(M64MSG_ERROR, "core gave error while setting --nospeedlimit option"); + } + } + else if ((strcmp(argv[i], "--corelib") == 0 || strcmp(argv[i], "--configdir") == 0 || + strcmp(argv[i], "--datadir") == 0) && ArgsLeft >= 1) + { /* these are handled in ParseCommandLineInitial */ + i++; + } + else if (strcmp(argv[i], "--resolution") == 0 && ArgsLeft >= 1) + { + const char *res = argv[i+1]; + int xres, yres; + i++; + if (sscanf(res, "%ix%i", &xres, &yres) != 2) + DebugMessage(M64MSG_WARNING, "couldn't parse resolution '%s'", res); + else + { + (*ConfigSetParameter)(l_ConfigVideo, "ScreenWidth", M64TYPE_INT, &xres); + (*ConfigSetParameter)(l_ConfigVideo, "ScreenHeight", M64TYPE_INT, &yres); + } + } + else if (strcmp(argv[i], "--cheats") == 0 && ArgsLeft >= 1) + { + if (strcmp(argv[i+1], "all") == 0) + l_CheatMode = CHEAT_ALL; + else if (strcmp(argv[i+1], "list") == 0) + l_CheatMode = CHEAT_SHOW_LIST; + else + { + l_CheatMode = CHEAT_LIST; + l_CheatNumList = (char*) argv[i+1]; + } + i++; + } + else if (strcmp(argv[i], "--plugindir") == 0 && ArgsLeft >= 1) + { + g_PluginDir = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--sshotdir") == 0 && ArgsLeft >= 1) + { + (*ConfigSetParameter)(l_ConfigCore, "ScreenshotPath", M64TYPE_STRING, argv[i+1]); + i++; + } + else if (strcmp(argv[i], "--gfx") == 0 && ArgsLeft >= 1) + { + g_GfxPlugin = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--audio") == 0 && ArgsLeft >= 1) + { + g_AudioPlugin = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--input") == 0 && ArgsLeft >= 1) + { + g_InputPlugin = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--rsp") == 0 && ArgsLeft >= 1) + { + g_RspPlugin = argv[i+1]; + i++; + } + else if (strcmp(argv[i], "--emumode") == 0 && ArgsLeft >= 1) + { + int emumode = atoi(argv[i+1]); + i++; + if (emumode < 0 || emumode > 2) + { + DebugMessage(M64MSG_WARNING, "invalid --emumode value '%i'", emumode); + continue; + } + if (emumode == 2 && !(g_CoreCapabilities & M64CAPS_DYNAREC)) + { + DebugMessage(M64MSG_WARNING, "Emulator core doesn't support Dynamic Recompiler."); + emumode = 1; + } + (*ConfigSetParameter)(l_ConfigCore, "R4300Emulator", M64TYPE_INT, &emumode); + } + else if (strcmp(argv[i], "--testshots") == 0 && ArgsLeft >= 1) + { + l_TestShotList = ParseNumberList(argv[i+1], NULL); + i++; + } + else if (strcmp(argv[i], "--set") == 0 && ArgsLeft >= 1) + { + if (SetConfigParameter(argv[i+1]) != 0) + return M64ERR_INPUT_INVALID; + i++; + } + else if (strcmp(argv[i], "--core-compare-send") == 0) + { + l_CoreCompareMode = 1; + } + else if (strcmp(argv[i], "--core-compare-recv") == 0) + { + l_CoreCompareMode = 2; + } + else if (strcmp(argv[i], "--nosaveoptions") == 0) + { + l_SaveOptions = 0; + } + else if (ArgsLeft == 0) + { + /* this is the last arg, it should be a ROM filename */ + l_ROMFilepath = argv[i]; + return M64ERR_SUCCESS; + } + else if (strcmp(argv[i], "--verbose") == 0) + { + g_Verbose = 1; + } + else + { + DebugMessage(M64MSG_WARNING, "unrecognized command-line parameter '%s'", argv[i]); + } + /* continue argv loop */ + } + + /* missing ROM filepath */ + DebugMessage(M64MSG_ERROR, "no ROM filepath given"); + return M64ERR_INPUT_INVALID; +} + +/********************************************************************************************************* +* main function +*/ +int main(int argc, char *argv[]) +{ + int i; + + printf(" __ __ __ _ _ ____ _ \n"); + printf("| \\/ |_ _ _ __ ___ _ __ / /_ | || | | _ \\| |_ _ ___ \n"); + printf("| |\\/| | | | | '_ \\ / _ \\ '_ \\| '_ \\| || |_| |_) | | | | / __| \n"); + printf("| | | | |_| | |_) | __/ | | | (_) |__ _| __/| | |_| \\__ \\ \n"); + printf("|_| |_|\\__,_| .__/ \\___|_| |_|\\___/ |_| |_| |_|\\__,_|___/ \n"); + printf(" |_| http://code.google.com/p/mupen64plus/ \n"); + printf("%s Version %i.%i.%i\n\n", CONSOLE_UI_NAME, VERSION_PRINTF_SPLIT(CONSOLE_UI_VERSION)); + + /* bootstrap some special parameters from the command line */ + if (ParseCommandLineInitial(argc, (const char **) argv) != 0) + return 1; + + /* load the Mupen64Plus core library */ + if (AttachCoreLib(l_CoreLibPath) != M64ERR_SUCCESS) + return 2; + + /* start the Mupen64Plus core library, load the configuration file */ + #ifdef PAULSCODE + m64p_error rval = (*CoreStartup)( CORE_API_VERSION, l_ConfigDirPath, l_DataDirPath, "Core", DebugCallback, NULL, StateCallback ); + #else + m64p_error rval = (*CoreStartup)(CORE_API_VERSION, l_ConfigDirPath, l_DataDirPath, "Core", DebugCallback, NULL, NULL); + #endif + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "couldn't start Mupen64Plus core library."); + DetachCoreLib(); + return 3; + } + + /* Open configuration sections */ + rval = OpenConfigurationHandles(); + if (rval != M64ERR_SUCCESS) + { + (*CoreShutdown)(); + DetachCoreLib(); + return 4; + } + + /* parse command-line options */ + rval = ParseCommandLineFinal(argc, (const char **) argv); + if (rval != M64ERR_SUCCESS) + { + (*CoreShutdown)(); + DetachCoreLib(); + return 5; + } + + /* Handle the core comparison feature */ + if (l_CoreCompareMode != 0 && !(g_CoreCapabilities & M64CAPS_CORE_COMPARE)) + { + DebugMessage(M64MSG_ERROR, "can't use --core-compare feature with this Mupen64Plus core library."); + DetachCoreLib(); + return 6; + } + compare_core_init(l_CoreCompareMode); + + /* save the given command-line options in configuration file if requested */ + if (l_SaveOptions) + SaveConfigurationOptions(); + + /* load ROM image */ + FILE *fPtr = fopen(l_ROMFilepath, "rb"); + if (fPtr == NULL) + { + DebugMessage(M64MSG_ERROR, "couldn't open ROM file '%s' for reading.", l_ROMFilepath); + (*CoreShutdown)(); + DetachCoreLib(); + return 7; + } + + /* get the length of the ROM, allocate memory buffer, load it from disk */ + long romlength = 0; + fseek(fPtr, 0L, SEEK_END); + romlength = ftell(fPtr); + fseek(fPtr, 0L, SEEK_SET); + unsigned char *ROM_buffer = (unsigned char *) malloc(romlength); + if (ROM_buffer == NULL) + { + DebugMessage(M64MSG_ERROR, "couldn't allocate %li-byte buffer for ROM image file '%s'.", romlength, l_ROMFilepath); + fclose(fPtr); + (*CoreShutdown)(); + DetachCoreLib(); + return 8; + } + else if (fread(ROM_buffer, 1, romlength, fPtr) != romlength) + { + DebugMessage(M64MSG_ERROR, "couldn't read %li bytes from ROM image file '%s'.", romlength, l_ROMFilepath); + free(ROM_buffer); + fclose(fPtr); + (*CoreShutdown)(); + DetachCoreLib(); + return 9; + } + fclose(fPtr); + + /* Try to load the ROM image into the core */ + if ((*CoreDoCommand)(M64CMD_ROM_OPEN, (int) romlength, ROM_buffer) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "core failed to open ROM image file '%s'.", l_ROMFilepath); + free(ROM_buffer); + (*CoreShutdown)(); + DetachCoreLib(); + return 10; + } + free(ROM_buffer); /* the core copies the ROM image, so we can release this buffer immediately */ + + /* handle the cheat codes */ + CheatStart(l_CheatMode, l_CheatNumList); + if (l_CheatMode == CHEAT_SHOW_LIST) + { + (*CoreDoCommand)(M64CMD_ROM_CLOSE, 0, NULL); + (*CoreShutdown)(); + DetachCoreLib(); + return 11; + } + + /* search for and load plugins */ + rval = PluginSearchLoad(l_ConfigUI); + if (rval != M64ERR_SUCCESS) + { + (*CoreDoCommand)(M64CMD_ROM_CLOSE, 0, NULL); + (*CoreShutdown)(); + DetachCoreLib(); + return 12; + } + + /* attach plugins to core */ + for (i = 0; i < 4; i++) + { + if ((*CoreAttachPlugin)(g_PluginMap[i].type, g_PluginMap[i].handle) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "core error while attaching %s plugin.", g_PluginMap[i].name); + (*CoreDoCommand)(M64CMD_ROM_CLOSE, 0, NULL); + (*CoreShutdown)(); + DetachCoreLib(); + return 13; + } + } + + /* set up Frame Callback if --testshots is enabled */ + if (l_TestShotList != NULL) + { + if ((*CoreDoCommand)(M64CMD_SET_FRAME_CALLBACK, 0, FrameCallback) != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_WARNING, "couldn't set frame callback, so --testshots won't work."); + } + } + + /* run the game */ + #ifdef PAULSCODE + // paulscode: workaround for broken M64CMD_RESET. Set do_Start = 1 before M64CMD_STOP to reset the emulator. + while( do_Start ) + { + do_Start = 0; + (*CoreDoCommand)(M64CMD_EXECUTE, 0, NULL); + } + #else + (*CoreDoCommand)(M64CMD_EXECUTE, 0, NULL); + #endif + + /* detach plugins from core and unload them */ + for (i = 0; i < 4; i++) + (*CoreDetachPlugin)(g_PluginMap[i].type); + PluginUnload(); + + /* close the ROM image */ + (*CoreDoCommand)(M64CMD_ROM_CLOSE, 0, NULL); + + /* save the configuration file again if --nosaveoptions was not specified, to keep any updated parameters from the core/plugins */ + if (l_SaveOptions) + SaveConfigurationOptions(); + + /* Shut down and release the Core library */ + (*CoreShutdown)(); + DetachCoreLib(); + + /* free allocated memory */ + if (l_TestShotList != NULL) + free(l_TestShotList); + + return 0; +} + diff --git a/source/front-end/src/main.h b/source/front-end/src/main.h new file mode 100644 index 0000000..5ab3752 --- /dev/null +++ b/source/front-end/src/main.h @@ -0,0 +1,31 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - main.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef __MAIN_H__ +#define __MAIN_H__ + +extern void DebugMessage(int level, const char *message, ...); +extern void DebugCallback(void *Context, int level, const char *message); + +extern int g_Verbose; + +#endif /* __MAIN_H__ */ + diff --git a/source/front-end/src/osal_dynamiclib.h b/source/front-end/src/osal_dynamiclib.h new file mode 100644 index 0000000..15b45d3 --- /dev/null +++ b/source/front-end/src/osal_dynamiclib.h @@ -0,0 +1,34 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - 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" + +m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath); + +void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName); + +m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle); + +#endif /* #define OSAL_DYNAMICLIB_H */ + diff --git a/source/front-end/src/osal_dynamiclib_unix.c b/source/front-end/src/osal_dynamiclib_unix.c new file mode 100644 index 0000000..870db48 --- /dev/null +++ b/source/front-end/src/osal_dynamiclib_unix.c @@ -0,0 +1,71 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - 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 +#include +#include +#include + +#include "main.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 = dlopen(pccLibraryPath, RTLD_NOW); + + if (*pLibHandle == NULL) + { + /* only print an error message if there is a directory separator (/) in the pathname */ + /* this prevents us from throwing an error for the use case where Mupen64Plus is not installed */ + if (strchr(pccLibraryPath, '/') != NULL) + DebugMessage(M64MSG_ERROR, "dlopen('%s') failed: %s", pccLibraryPath, dlerror()); + 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 dlsym(LibHandle, pccProcedureName); +} + +m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle) +{ + int rval = dlclose(LibHandle); + + if (rval != 0) + { + DebugMessage(M64MSG_ERROR, "dlclose() failed: %s", dlerror()); + return M64ERR_INTERNAL; + } + + return M64ERR_SUCCESS; +} + + diff --git a/source/front-end/src/osal_dynamiclib_win32.c b/source/front-end/src/osal_dynamiclib_win32.c new file mode 100644 index 0000000..36d40c8 --- /dev/null +++ b/source/front-end/src/osal_dynamiclib_win32.c @@ -0,0 +1,75 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 +#include +#include + +#include "main.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); + DebugMessage(M64MSG_ERROR, "LoadLibrary('%s') error: %s", 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); + DebugMessage(M64MSG_ERROR, "FreeLibrary() error: %s", pchErrMsg); + LocalFree(pchErrMsg); + return M64ERR_INTERNAL; + } + + return M64ERR_SUCCESS; +} diff --git a/source/front-end/src/osal_files.h b/source/front-end/src/osal_files.h new file mode 100644 index 0000000..31ef4a6 --- /dev/null +++ b/source/front-end/src/osal_files.h @@ -0,0 +1,49 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_files.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 is for all kinds of system-dependent file handling + * + */ + +#if !defined(OSAL_FILES_H) +#define OSAL_FILES_H + +#include "m64p_types.h" +#include "osal_preproc.h" + +/* data structure for linked list of shared libraries found in a directory */ +typedef struct _osal_lib_search { + char filepath[PATH_MAX]; + char *filename; + m64p_plugin_type plugin_type; + struct _osal_lib_search *next; + } osal_lib_search; + +/* const definitions for system directories to search when looking for mupen64plus plugins */ +extern const int osal_libsearchdirs; +extern const char *osal_libsearchpath[]; + +/* functions for searching for shared libraries in a given directory */ +extern osal_lib_search *osal_library_search(const char *searchpath); +extern void osal_free_lib_list(osal_lib_search *head); + +#endif /* #define OSAL_FILES_H */ + diff --git a/source/front-end/src/osal_files_unix.c b/source/front-end/src/osal_files_unix.c new file mode 100644 index 0000000..2199271 --- /dev/null +++ b/source/front-end/src/osal_files_unix.c @@ -0,0 +1,113 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_files_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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* This implements all kinds of system-dependent file handling + * + */ + +#include +#include +#include +#include +#include // for opendir(), readdir(), closedir() + +#include "main.h" +#include "m64p_types.h" +#include "osal_preproc.h" +#include "osal_files.h" + +/* definitions for system directories to search when looking for mupen64plus plugins */ +#if defined(PLUGINDIR) + const int osal_libsearchdirs = 4; + const char *osal_libsearchpath[4] = { PLUGINDIR, "/usr/local/lib/mupen64plus", "/usr/lib/mupen64plus", "./" }; +#else + const int osal_libsearchdirs = 3; + const char *osal_libsearchpath[3] = { "/usr/local/lib/mupen64plus", "/usr/lib/mupen64plus", "./" }; +#endif + +osal_lib_search *osal_library_search(const char *searchpath) +{ + osal_lib_search *head = NULL, *curr = NULL; + DIR *dir; + struct dirent *entry; + +#ifdef __APPLE__ + const char* suffix = ".dylib"; +#else + const char* suffix = ".so"; +#endif + + dir = opendir(searchpath); + if (dir == NULL) + return NULL; + + /* look for any shared libraries in this folder */ + while ((entry = readdir(dir)) != NULL) + { + osal_lib_search *newlib = NULL; + if (strcmp(entry->d_name + strlen(entry->d_name) - strlen(suffix), suffix) != 0) + continue; + /* this is a .so file, so add it to the list */ + newlib = malloc(sizeof(osal_lib_search)); + if (newlib == NULL) + { + DebugMessage(M64MSG_ERROR, "Memory allocation error in osal_library_search()!"); + osal_free_lib_list(head); + closedir(dir); + return NULL; + } + if (head == NULL) + { + head = curr = newlib; + } + else + { + curr->next = newlib; + curr = newlib; + } + /* set up the filepath and filename members */ + strncpy(curr->filepath, searchpath, PATH_MAX-2); + curr->filepath[PATH_MAX-2] = 0; + if (curr->filepath[strlen(curr->filepath)-1] != '/') + strcat(curr->filepath, "/"); + int pathlen = strlen(curr->filepath); + curr->filename = curr->filepath + pathlen; + strncat(curr->filepath, entry->d_name, PATH_MAX - pathlen - 1); + curr->filepath[PATH_MAX-1] = 0; + /* set plugin_type and next pointer */ + curr->plugin_type = 0; + curr->next = NULL; + } + + closedir(dir); + return head; +} + +void osal_free_lib_list(osal_lib_search *head) +{ + while (head != NULL) + { + osal_lib_search *next = head->next; + free(head); + head = next; + } +} + diff --git a/source/front-end/src/osal_files_win32.c b/source/front-end/src/osal_files_win32.c new file mode 100644 index 0000000..69c12c6 --- /dev/null +++ b/source/front-end/src/osal_files_win32.c @@ -0,0 +1,106 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_files_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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* This implements all kinds of system-dependent file handling + * + */ + +#include +#include +#include +#include + +#include "main.h" +#include "m64p_types.h" +#include "osal_preproc.h" +#include "osal_files.h" + +/* definitions for system directories to search when looking for mupen64plus plugins */ +const int osal_libsearchdirs = 1; +const char *osal_libsearchpath[1] = { ".\\" }; + +osal_lib_search *osal_library_search(const char *searchpath) +{ + osal_lib_search *head = NULL, *curr = NULL; + WIN32_FIND_DATA entry; + HANDLE hDir; + + char *pchSearchPath = (char *) malloc(strlen(searchpath) + 16); + if (pchSearchPath == NULL) + { + DebugMessage(M64MSG_ERROR, "Couldn't allocate memory for file search path in osal_library_search()!"); + return NULL; + } + sprintf(pchSearchPath, "%s\\*.dll", searchpath); + hDir = FindFirstFile(pchSearchPath, &entry); + free(pchSearchPath); + if (hDir == INVALID_HANDLE_VALUE) + return NULL; + + /* look for any shared libraries in this folder */ + do + { + osal_lib_search *newlib = NULL; + /* this is a .dll file, so add it to the list */ + newlib = (osal_lib_search *) malloc(sizeof(osal_lib_search)); + if (newlib == NULL) + { + DebugMessage(M64MSG_ERROR, "Memory allocation error in osal_library_search()!"); + osal_free_lib_list(head); + FindClose(hDir); + return NULL; + } + if (head == NULL) + { + head = curr = newlib; + } + else + { + curr->next = newlib; + curr = newlib; + } + /* set up the filepath and filename members */ + strncpy(curr->filepath, searchpath, PATH_MAX-2); + curr->filepath[PATH_MAX-2] = 0; + if (curr->filepath[strlen(curr->filepath)-1] != '\\') + strcat(curr->filepath, "\\"); + int pathlen = (int) strlen(curr->filepath); + curr->filename = curr->filepath + pathlen; + strncat(curr->filepath, entry.cFileName, PATH_MAX - pathlen - 1); + curr->filepath[PATH_MAX-1] = 0; + /* set plugin_type and next pointer */ + curr->plugin_type = (m64p_plugin_type) 0; + curr->next = NULL; + } while (FindNextFile(hDir, &entry)); + + FindClose(hDir); + return head; +} + +void osal_free_lib_list(osal_lib_search *head) +{ + while (head != NULL) + { + osal_lib_search *next = head->next; + free(head); + head = next; + } +} diff --git a/source/front-end/src/osal_preproc.h b/source/front-end/src/osal_preproc.h new file mode 100755 index 0000000..d9596af --- /dev/null +++ b/source/front-end/src/osal_preproc.h @@ -0,0 +1,70 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_preproc.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 is for OS-specific #includes and #defines + * + */ + +#if !defined(OSAL_PREPROC_H) +#define OSAL_PREPROC_H + +#if defined(WIN32) + + #include + #define PATH_MAX 2048 + #define OSAL_DEFAULT_DYNLIB_FILENAME "mupen64plus.dll" + #define OSAL_DIR_SEPARATOR '\\' + #define OSAL_CURRENT_DIR ".\\" + #define OSAL_DLL_EXTENSION ".dll" + #define osal_insensitive_strcmp(x, y) _stricmp(x, y) + +#elif defined(__APPLE__) + + #include // for PATH_MAX + #define OSAL_DEFAULT_DYNLIB_FILENAME "libmupen64plus.dylib" + #define OSAL_DIR_SEPARATOR '/' + #define OSAL_CURRENT_DIR "./" + #define OSAL_DLL_EXTENSION ".dylib" + #define osal_insensitive_strcmp(x, y) strcasecmp(x, y) + +#else /* Linux-like UNIX */ + + #if defined(ANDROID) +// #include +// #define printf(...) __android_log_print(ANDROID_LOG_VERBOSE, "UI-Console", __VA_ARGS__) + #endif + + #include // for PATH_MAX + #define OSAL_DEFAULT_DYNLIB_FILENAME "libmupen64plus.so.2" + #define OSAL_DIR_SEPARATOR '/' + #define OSAL_CURRENT_DIR "./" + #define OSAL_DLL_EXTENSION ".so" + #define osal_insensitive_strcmp(x, y) strcasecmp(x, y) + + /* PATH_MAX only may be defined by limits.h */ + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif + +#endif + +#endif /* #define OSAL_PREPROC_H */ + diff --git a/source/front-end/src/plugin.c b/source/front-end/src/plugin.c new file mode 100644 index 0000000..a8edb78 --- /dev/null +++ b/source/front-end/src/plugin.c @@ -0,0 +1,261 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - plugin.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +#include "m64p_types.h" +#include "m64p_common.h" +#include "core_interface.h" +#include "osal_dynamiclib.h" +#include "osal_files.h" +#include "plugin.h" +#include "main.h" /* for the debug callback function */ +#include "version.h" + +/* global variables */ +const char *g_PluginDir = NULL; +const char *g_GfxPlugin = NULL; // pointer to graphics plugin specified at commandline (if any) +const char *g_AudioPlugin = NULL; // pointer to audio plugin specified at commandline (if any) +const char *g_InputPlugin = NULL; // pointer to input plugin specified at commandline (if any) +const char *g_RspPlugin = NULL; // pointer to rsp plugin specified at commandline (if any) + +plugin_map_node g_PluginMap[] = {{M64PLUGIN_GFX, "Video", NULL, "", NULL, 0 }, + {M64PLUGIN_AUDIO, "Audio", NULL, "", NULL, 0 }, + {M64PLUGIN_INPUT, "Input", NULL, "", NULL, 0 }, + {M64PLUGIN_RSP, "RSP", NULL, "", NULL, 0 } }; + +/* local functions */ +static m64p_error PluginLoadTry(const char *filepath, int MapIndex) +{ + /* try to open a shared library at the given filepath */ + m64p_dynlib_handle handle; + m64p_error rval = osal_dynlib_open(&handle, filepath); + if (rval != M64ERR_SUCCESS) + return rval; + + /* call the GetVersion function for the plugin and check compatibility */ + ptr_PluginGetVersion PluginGetVersion = (ptr_PluginGetVersion) osal_dynlib_getproc(handle, "PluginGetVersion"); + if (PluginGetVersion == NULL) + { + if (g_Verbose) + DebugMessage(M64MSG_ERROR, "library '%s' is not a Mupen64Plus library.", filepath); + osal_dynlib_close(handle); + return M64ERR_INCOMPATIBLE; + } + m64p_plugin_type PluginType = (m64p_plugin_type) 0; + int PluginVersion = 0; + const char *PluginName = NULL; + (*PluginGetVersion)(&PluginType, &PluginVersion, NULL, &PluginName, NULL); + if (PluginType != g_PluginMap[MapIndex].type) + { + /* the type of this plugin doesn't match with the type that was requested by the caller */ + osal_dynlib_close(handle); + return M64ERR_INCOMPATIBLE; + } + /* the front-end doesn't talk to the plugins, so we don't care about the plugin version or api version */ + + /* call the plugin's initialization function and make sure it starts okay */ + ptr_PluginStartup PluginStartup = (ptr_PluginStartup) osal_dynlib_getproc(handle, "PluginStartup"); + if (PluginStartup == NULL) + { + DebugMessage(M64MSG_ERROR, "library '%s' broken. No PluginStartup() function found.", filepath); + osal_dynlib_close(handle); + return M64ERR_INCOMPATIBLE; + } + rval = (*PluginStartup)(CoreHandle, g_PluginMap[MapIndex].name, DebugCallback); /* DebugCallback is in main.c */ + if (rval != M64ERR_SUCCESS) + { + DebugMessage(M64MSG_ERROR, "Error: %s plugin library '%s' failed to start.", g_PluginMap[MapIndex].name, filepath); + osal_dynlib_close(handle); + return rval; + } + + /* plugin loaded successfully, so set the plugin map's members */ + g_PluginMap[MapIndex].handle = handle; + strcpy(g_PluginMap[MapIndex].filename, filepath); + g_PluginMap[MapIndex].libname = PluginName; + g_PluginMap[MapIndex].libversion = PluginVersion; + + return M64ERR_SUCCESS; +} + +/* global functions */ +m64p_error PluginSearchLoad(m64p_handle ConfigUI) +{ + osal_lib_search *lib_filelist = NULL; + int i; + + /* start by checking the directory given on the command line */ + if (g_PluginDir != NULL) + { + lib_filelist = osal_library_search(g_PluginDir); + if (lib_filelist == NULL) + { + DebugMessage(M64MSG_ERROR, "No plugins found in --plugindir path: %s", g_PluginDir); + return M64ERR_INPUT_NOT_FOUND; + } + } + + /* if no plugins found, search the PluginDir in the UI-console section of the config file */ + if (lib_filelist == NULL) + { + const char *plugindir = (*ConfigGetParamString)(ConfigUI, "PluginDir"); + lib_filelist = osal_library_search(plugindir); + } + + /* if still no plugins found, search some common system folders */ + if (lib_filelist == NULL) + { + for (i = 0; i < osal_libsearchdirs; i++) + { + lib_filelist = osal_library_search(osal_libsearchpath[i]); + if (lib_filelist != NULL) + break; + } + } + + /* try to load one of each type of plugin */ + for (i = 0; i < 4; i++) + { + m64p_plugin_type type = g_PluginMap[i].type; + const char *cmdline_path = NULL; + const char *config_var = NULL; + int use_dummy = 0; + switch (type) + { + case M64PLUGIN_RSP: cmdline_path = g_RspPlugin; config_var = "RspPlugin"; break; + case M64PLUGIN_GFX: cmdline_path = g_GfxPlugin; config_var = "VideoPlugin"; break; + case M64PLUGIN_AUDIO: cmdline_path = g_AudioPlugin; config_var = "AudioPlugin"; break; + case M64PLUGIN_INPUT: cmdline_path = g_InputPlugin; config_var = "InputPlugin"; break; + default: cmdline_path = NULL; config_var = ""; + } + /* first search for a plugin matching what was given on the command line */ + if (cmdline_path != NULL) + { + /* if full path was given, try loading exactly this file */ + if (strchr(cmdline_path, OSAL_DIR_SEPARATOR) != NULL) + { + PluginLoadTry(cmdline_path, i); + } + else if (strcmp(cmdline_path, "dummy") == 0) + { + use_dummy = 1; + } + else /* otherwise search through the plugin directory to find a match with this name */ + { + osal_lib_search *curr = lib_filelist; + while (curr != NULL && g_PluginMap[i].handle == NULL) + { + if (strncmp(curr->filename, cmdline_path, strlen(cmdline_path)) == 0) + PluginLoadTry(curr->filepath, i); + curr = curr->next; + } + } + /* exit with error if we couldn't find the specified plugin */ + if (!use_dummy && g_PluginMap[i].handle == NULL) + { + DebugMessage(M64MSG_ERROR, "Specified %s plugin not found: %s", g_PluginMap[i].name, cmdline_path); + osal_free_lib_list(lib_filelist); + return M64ERR_INPUT_NOT_FOUND; + } + } + else /* otherwise search for a plugin specified in the config file */ + { + const char *config_path = (*ConfigGetParamString)(ConfigUI, config_var); + if (config_path != NULL && strlen(config_path) > 0) + { + /* if full path was given, try loading exactly this file */ + if (strchr(config_path, OSAL_DIR_SEPARATOR) != NULL) + { + PluginLoadTry(config_path, i); + } + else if (strcmp(config_path, "dummy") == 0) + { + use_dummy = 1; + } + else /* otherwise search through the plugin directory to find a match with this name */ + { + osal_lib_search *curr = lib_filelist; + while (curr != NULL && g_PluginMap[i].handle == NULL) + { + if (strncmp(curr->filename, config_path, strlen(config_path)) == 0) + PluginLoadTry(curr->filepath, i); + curr = curr->next; + } + } + } + } + /* As a last resort, search for any appropriate plugin in search directory */ + if (!use_dummy && g_PluginMap[i].handle == NULL) + { + osal_lib_search *curr = lib_filelist; + while (curr != NULL && g_PluginMap[i].handle == NULL) + { + PluginLoadTry(curr->filepath, i); + curr = curr->next; + } + } + /* print out the particular plugin used */ + if (g_PluginMap[i].handle == NULL) + { + DebugMessage(M64MSG_INFO, "using %s plugin: ", g_PluginMap[i].name); + } + else + { + DebugMessage(M64MSG_INFO, "using %s plugin: '%s' v%i.%i.%i", g_PluginMap[i].name, + g_PluginMap[i].libname, VERSION_PRINTF_SPLIT(g_PluginMap[i].libversion)); + DebugMessage(M64MSG_VERBOSE, "%s plugin library: %s", g_PluginMap[i].name, g_PluginMap[i].filename); + } + } + + /* free up the list of library files in the plugin search directory */ + osal_free_lib_list(lib_filelist); + return M64ERR_SUCCESS; +} + +m64p_error PluginUnload(void) +{ + typedef m64p_error (*ptr_PluginShutdown)(void); + ptr_PluginShutdown PluginShutdown; + int i; + + /* shutdown each type of plugin */ + for (i = 0; i < 4; i++) + { + if (g_PluginMap[i].handle == NULL) + continue; + /* call the destructor function for the plugin and release the library */ + PluginShutdown = (ptr_PluginShutdown) osal_dynlib_getproc(g_PluginMap[i].handle, "PluginShutdown"); + if (PluginShutdown != NULL) + (*PluginShutdown)(); + osal_dynlib_close(g_PluginMap[i].handle); + /* clear out the plugin map's members */ + g_PluginMap[i].handle = NULL; + g_PluginMap[i].filename[0] = 0; + g_PluginMap[i].libname = NULL; + g_PluginMap[i].libversion = 0; + } + + return M64ERR_SUCCESS; +} + diff --git a/source/front-end/src/plugin.h b/source/front-end/src/plugin.h new file mode 100644 index 0000000..3d9a1f3 --- /dev/null +++ b/source/front-end/src/plugin.h @@ -0,0 +1,50 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - plugin.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#if !defined(PLUGIN_H) +#define PLUGIN_H + +#include "m64p_types.h" +#include "osal_preproc.h" + +extern m64p_error PluginSearchLoad(m64p_handle ConfigUI); +extern m64p_error PluginUnload(void); + +extern const char *g_PluginDir; // directory to search for plugins +extern const char *g_GfxPlugin; // graphics plugin specified at commandline (if any) +extern const char *g_AudioPlugin; // audio plugin specified at commandline (if any) +extern const char *g_InputPlugin; // input plugin specified at commandline (if any) +extern const char *g_RspPlugin; // rsp plugin specified at commandline (if any) + +typedef struct { + m64p_plugin_type type; + char name[8]; + m64p_dynlib_handle handle; + char filename[PATH_MAX]; + const char *libname; + int libversion; + } plugin_map_node; + +extern plugin_map_node g_PluginMap[4]; + +#endif /* #define PLUGIN_H */ + + diff --git a/source/front-end/src/version.h b/source/front-end/src/version.h new file mode 100644 index 0000000..7344653 --- /dev/null +++ b/source/front-end/src/version.h @@ -0,0 +1,39 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - version.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 is for versioning information + * + */ + +#if !defined(VERSION_H) +#define VERSION_H + +#define CONSOLE_UI_NAME "Mupen64Plus Console User-Interface" +#define CONSOLE_UI_VERSION 0x020000 +#define CORE_API_VERSION 0x020001 +#define CONFIG_API_VERSION 0x020000 + +#define MINIMUM_CORE_VERSION 0x016300 + +#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff) + +#endif /* #define VERSION_H */ +