diff --git a/ChangeLog b/ChangeLog index c47604e..b6f1f92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +v0.2.4 Jan 19, 2017: + + * Dropped support for SDL1 + * PySDL2 is unbundled, not distributed with source anymore + * Input bug fixes + v0.2.3 May 04, 2015: * Migrated to Qt5 diff --git a/README.md b/README.md index 678e39d..e5900d1 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ provides a user-friendly interface over Mupen64Plus shared library. Features -------- +* Changeable emulation plugins for audio, core, input, rsp, video +* Selection of emulation core +* Configuration dialogs for core, plugin and input settings * ROMs list with preview images * Input bindings configuration * Cheats support @@ -27,8 +30,8 @@ Features Dependencies ------------ -* PyQt5 -* PySDL2 +* [PyQt5](https://www.riverbankcomputing.com/software/pyqt/download5) (QtCore, QtGui, QtWidgets, QtOpenGL) +* [PySDL2](https://pysdl2.readthedocs.io) Install ------- diff --git a/dist/debian/copyright b/dist/debian/copyright index edad72a..97833d6 100644 --- a/dist/debian/copyright +++ b/dist/debian/copyright @@ -47,55 +47,6 @@ License: BSD-3-clause OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Files: src/m64p/SDL/* -Copyright: 2006, Alex Holkner -License: LGPL-2.1+ - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - . - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - . - On Debian systems the full text of the GNU Library General Public License, - version 2 or later, can be found in the `/usr/share/common-licenses/LGPL-2.1' - file. - -Files: src/m64p/SDL2/* -Copyright: 2012-2014, Marcus von Appen - 2012-2014, Steven Johnson - 2012-2014, Marcel Rodrigues - 2012-2014, Dan Gillett -Comment: - This software is distributed under the Public Domain (CC0 Public Domain - Dedication). - . - In cases, where the law prohibits the recognition of Public Domain - software, this software can be licensed under the zlib license -License: CC0 or Zlib - -Files: examples/resources/tuffy.ttf sdl2/test/resources/tuffy*.ttf -Copyright: 2004-2011, Thatcher Ulrich, Karoly Barta and Michael Everson -License: public-domain - We, the copyright holders of this work, hereby release it into the - public domain. This applies worldwide. - . - In case this is not legally possible, - . - We grant any entity the right to use this work for any purpose, without - any conditions, unless such conditions are required by law. - . - Thatcher Ulrich http://tulrich.com - Karoly Barta - Michael Evans http://www.evertype.com - Files: src/m64py/ui/icons/* Copyright: 2005-2009, Ulisse Perusin 2005-2009, Steven Garrity diff --git a/dist/macosx/m64py.spec b/dist/macosx/m64py.spec index b986c44..ee7bef5 100644 --- a/dist/macosx/m64py.spec +++ b/dist/macosx/m64py.spec @@ -9,9 +9,6 @@ a = Analysis([join(BASE_DIR, 'm64py')], pathex=[join(BASE_DIR, 'src')], hookspath=None, runtime_hooks=None) -a.binaries + [('libQtCLucene.4.dylib', - '/usr/local/lib/libQtCLucene.4.dylib', 'BINARY')] - pyz = PYZ(a.pure) exe = EXE(pyz, diff --git a/dist/redhat/m64py.spec.in b/dist/redhat/m64py.spec.in index ab6bb16..ecb159d 100644 --- a/dist/redhat/m64py.spec.in +++ b/dist/redhat/m64py.spec.in @@ -15,7 +15,7 @@ Prefix: %{_prefix} BuildArch: noarch Vendor: Milan Nikolic Url: http://m64py.sourceforge.net -Requires: PyQt5 SDL +Requires: PyQt5 PySDL2 %description M64Py is a Qt5 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator. diff --git a/dist/windows/hooks/libdir.py b/dist/windows/hooks/libdir.py new file mode 100644 index 0000000..20514e7 --- /dev/null +++ b/dist/windows/hooks/libdir.py @@ -0,0 +1,13 @@ +import os +import sys + +def extend_system_path(paths): + old = os.environ.get('PATH', '') + paths.append(old) + new = os.pathsep.join(paths) + os.environ['PATH'] = new + +d = os.path.abspath(os.path.join(sys._MEIPASS, "lib")) + +sys.path.append(d) +extend_system_path([d]) diff --git a/dist/windows/m64py.iss.in b/dist/windows/m64py.iss.in index e345168..30a5f54 100644 --- a/dist/windows/m64py.iss.in +++ b/dist/windows/m64py.iss.in @@ -26,19 +26,20 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ Source: "m64py\*.ttf"; DestDir: "{app}"; Source: "m64py\*.ini"; DestDir: "{app}"; Source: "m64py\*.txt"; DestDir: "{app}"; -Source: "m64py\*.pyd"; DestDir: "{app}"; Source: "m64py\*.exe"; DestDir: "{app}"; Source: "m64py\*.dll"; DestDir: "{app}"; Source: "m64py\*.zip"; DestDir: "{app}"; +Source: "m64py\*.v64"; DestDir: "{app}"; +Source: "m64py\*.pyd"; DestDir: "{app}"; +Source: "m64py\lib\*"; DestDir: "{app}\lib"; +Source: "m64py\doc\*"; DestDir: "{app}\doc"; Source: "m64py\AUTHORS"; DestDir: "{app}"; Source: "m64py\COPYING"; DestDir: "{app}"; Source: "m64py\README.md"; DestDir: "{app}"; Source: "m64py\ChangeLog"; DestDir: "{app}"; -Source: "m64py\*.v64"; DestDir: "{app}"; -Source: "m64py\qt5_plugins\platforms\qwindows.dll"; DestDir: "{app}\qt5_plugins\platforms"; -Source: "m64py\qt5_plugins\imageformats\qjpeg.dll"; DestDir: "{app}\qt5_plugins\imageformats"; -Source: "m64py\qt5_plugins\imageformats\qsvg.dll"; DestDir: "{app}\qt5_plugins\imageformats"; -Source: "m64py\doc\*"; DestDir: "{app}\doc"; +Source: "m64py\lib\qt5_plugins\platforms\qwindows.dll"; DestDir: "{app}\lib\qt5_plugins\platforms"; +Source: "m64py\lib\qt5_plugins\imageformats\qjpeg.dll"; DestDir: "{app}\lib\qt5_plugins\imageformats"; +Source: "m64py\lib\qt5_plugins\imageformats\qsvg.dll"; DestDir: "{app}\lib\qt5_plugins\imageformats"; [Icons] Name: {group}\M64Py; Filename: {app}\m64py.exe; Tasks: desktopicon; diff --git a/dist/windows/m64py.spec b/dist/windows/m64py.spec index e801784..8dac738 100644 --- a/dist/windows/m64py.spec +++ b/dist/windows/m64py.spec @@ -4,7 +4,7 @@ from os.path import join DIST_DIR = os.environ["DIST_DIR"] BASE_DIR = os.environ["BASE_DIR"] -a = Analysis([join(BASE_DIR, 'm64py')], hiddenimports=['pickle', 'PyQt5.Qt'], pathex=[join(BASE_DIR, 'src')]) +a = Analysis([join(BASE_DIR, 'm64py')], hiddenimports=['pickle', 'PyQt5.Qt'], pathex=[join(BASE_DIR, 'src')], hookspath=[join(DIST_DIR, 'hooks')], runtime_hooks=[join(DIST_DIR, 'hooks', 'libdir.py')]) pyz = PYZ(a.pure) diff --git a/setup.py b/setup.py index c32f153..531c8f6 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,7 @@ class build_qt(Command): class build_exe(Command): """Needs PyQt5, rarfile, PyLZMA, PyWin32, PyInstaller, Inno Setup 5""" user_options = [] - arch = "i686-w64-mingw32" + arch = "i686-w64-mingw32.static" url = "https://bitbucket.org/ecsv/mupen64plus-mxe-daily/get/master.zip" dist_dir = join(BASE_DIR, "dist", "windows") @@ -101,6 +101,24 @@ class build_exe(Command): zf.close() shutil.rmtree(tempdir) + def move_files(self): + dest_path = join(self.dist_dir, "m64py", "lib") + plugins_path = join(self.dist_dir, "m64py", "qt5_plugins") + shutil.copytree(plugins_path, join(dest_path, "qt5_plugins")) + shutil.rmtree(plugins_path) + + for file_name in glob.glob(join(self.dist_dir, "m64py", "*.pyd")): + if "PyQt5" not in file_name: + shutil.move(file_name, dest_path) + + for file_name in glob.glob(join(self.dist_dir, "m64py", "api*.dll")): + shutil.move(file_name, dest_path) + + for file_name in glob.glob(join(self.dist_dir, "m64py", "*.dll")): + print(file_name) + if "python3" not in file_name and "mupen64plus" not in basename(file_name): + shutil.move(file_name, dest_path) + def copy_files(self): dest_path = join(self.dist_dir, "m64py") rar_dir = join(os.environ["ProgramFiles(x86)"], "Unrar") @@ -116,17 +134,17 @@ class build_exe(Command): import PyQt5 qt5_dir = dirname(PyQt5.__file__) - qwindows = join(qt5_dir, "plugins", "platforms", "qwindows.dll") - qwindows_dest = join(dest_path, "qt5_plugins", "platforms") + qwindows = join(qt5_dir, "Qt", "plugins", "platforms", "qwindows.dll") + qwindows_dest = join(dest_path, "lib", "qt5_plugins", "platforms") if not os.path.exists(qwindows_dest): os.makedirs(qwindows_dest) shutil.copy(qwindows, qwindows_dest) def remove_files(self): dest_path = join(self.dist_dir, "m64py") - for dir_name in ["api", "include", "man6", "applications", "apps"]: - shutil.rmtree(join(dest_path, dir_name)) - for file_name in glob.glob(join(dest_path, "icu*.dll")): + for dir_name in ["api", "man6", "applications", "apps"]: + shutil.rmtree(join(dest_path, dir_name), True) + for file_name in glob.glob(join(dest_path, "glide*.exe")): os.remove(file_name) def run_build_installer(self): @@ -144,19 +162,20 @@ class build_exe(Command): subprocess.call([iscc, iss_out]) def run_build(self): - import PyInstaller.build + import PyInstaller.building.build_main work_path = join(self.dist_dir, "build") spec_file = join(self.dist_dir, "m64py.spec") os.environ["BASE_DIR"] = BASE_DIR os.environ["DIST_DIR"] = self.dist_dir opts = {"distpath": self.dist_dir, "workpath": work_path, "clean_build": True, "upx_dir": None, "debug": False} - PyInstaller.build.main(None, spec_file, True, **opts) + PyInstaller.building.build_main.main(None, spec_file, True, **opts) def run(self): self.run_command("build_qt") set_rthook() self.run_build() self.copy_emulator() + self.move_files() self.copy_files() self.remove_files() self.run_build_installer() @@ -197,6 +216,7 @@ class build_zip(build_exe): self.set_config_path() self.run_build() self.copy_emulator() + self.move_files() self.copy_files() self.remove_files() self.run_build_zip() @@ -248,7 +268,7 @@ class build_dmg(Command): def remove_files(self): dest_path = join(self.dist_dir, "dmg", "M64Py.app", "Contents", "MacOS") for dir_name in ["include", "lib"]: - shutil.rmtree(join(dest_path, dir_name)) + shutil.rmtree(join(dest_path, dir_name), True) os.remove(join(self.dist_dir, "dmg", "M64Py.app", "Contents", "Resources", "icon-windowed.icns")) def run_build_dmg(self): @@ -257,17 +277,16 @@ class build_dmg(Command): subprocess.call(["hdiutil", "create", dst_path, "-srcfolder", src_path]) def run_build(self): - import PyInstaller.build + import PyInstaller.building.build_main work_path = join(self.dist_dir, "build") spec_file = join(self.dist_dir, "m64py.spec") os.environ["BASE_DIR"] = BASE_DIR os.environ["DIST_DIR"] = self.dist_dir opts = {"distpath": self.dist_dir, "workpath": work_path, "clean_build": True, "upx_dir": None, "debug": False} - PyInstaller.build.main(None, spec_file, True, **opts) + PyInstaller.building.build_main.main(None, spec_file, True, **opts) def run(self): self.run_command("build_qt") - set_rthook() self.run_build() self.copy_files() self.copy_emulator() @@ -282,12 +301,13 @@ def set_rthook(): module_dir = dirname(PyInstaller.__file__) rthook = join(module_dir, "loader", "rthooks", "pyi_rth_qt5plugins.py") with open(rthook, "r") as hook: data = hook.read() - if "import sip" not in data: + if 'sys._MEIPASS, "lib"' not in data: lines = data.split("\n") for line in lines: - hook_file += line + "\n" if "MEIPASS" in line: - hook_file += "\nimport sip\n" + hook_file += "d = os.path.join(sys._MEIPASS, \"lib\", d)\n" + else: + hook_file += line + "\n" with open(rthook, "w") as hook: hook.write(hook_file) @@ -357,7 +377,7 @@ setup( packages = ["m64py", "m64py.core", "m64py.frontend", "m64py.ui"], package_dir = {"": "src"}, scripts = ["m64py"], - requires = ["PyQt5"], + requires = ["PyQt5", "PySDL2"], platforms = ["Linux", "Windows", "Darwin"], cmdclass = cmdclass, data_files = [ diff --git a/src/m64py/core/defs.py b/src/m64py/core/defs.py index a28eea9..4e44693 100644 --- a/src/m64py/core/defs.py +++ b/src/m64py/core/defs.py @@ -22,7 +22,7 @@ CORE_NAME = "mupen64plus" CORE_API_VERSION = 0x20001 CONFIG_API_VERSION = 0x20000 MINIMUM_CORE_VERSION = 0x016300 -FRONTEND_VERSION = "0.2.3" +FRONTEND_VERSION = "0.2.4" SIZE_1X = (320, 240) SIZE_2X = (640, 480) diff --git a/src/m64py/core/vidext.py b/src/m64py/core/vidext.py index c75203e..a593ca4 100644 --- a/src/m64py/core/vidext.py +++ b/src/m64py/core/vidext.py @@ -20,7 +20,7 @@ try: # nvidia hack from OpenGL import GL glimport = True -except ImportError: +except: glimport = False from PyQt5.QtOpenGL import QGLFormat