diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index d30ce3735..600a01f3f 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -552,7 +552,7 @@ void DrawHUD() drawPad(Hud.GraphicalInputDisplay.x, Hud.GraphicalInputDisplay.y, 2.5); } - #if defined(WIN32) + #if defined(WIN32) && !defined(DESMUME_QT) if (CommonSettings.hud.ShowMicrophone) { osd->addFixed(Hud.Microphone.x, Hud.Microphone.y, "%03d [%07d]",MicDisplay, Hud.cpuloopIterationCount); diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 1304d0926..48b01d207 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -34,7 +34,7 @@ #include -#if defined(HOST_WINDOWS) +#if defined(HOST_WINDOWS) && !defined(DESMUME_QT) #include "pathsettings.h" #endif diff --git a/desmume/src/filter/videofilter.h b/desmume/src/filter/videofilter.h index 37fd63701..8f383e3b6 100644 --- a/desmume/src/filter/videofilter.h +++ b/desmume/src/filter/videofilter.h @@ -28,6 +28,7 @@ #ifdef HOST_WINDOWS typedef unsigned __int32 uint32_t; + #include #include typedef CRITICAL_SECTION ThreadLock; typedef HANDLE ThreadCond; diff --git a/desmume/src/metaspu/metaspu.cpp b/desmume/src/metaspu/metaspu.cpp index 67ec6286b..cc1182cc5 100644 --- a/desmume/src/metaspu/metaspu.cpp +++ b/desmume/src/metaspu/metaspu.cpp @@ -24,7 +24,7 @@ #include //for pcsx2 method -#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) || defined(DESMUME_QT) #include "SndOut.h" #endif @@ -465,7 +465,7 @@ private: }; //NitsujaSynchronizer -#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) || defined(DESMUME_QT) class PCSX2Synchronizer : public ISynchronizingAudioBuffer { public: @@ -512,7 +512,7 @@ ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method) { case ESynchMethod_N: return new NitsujaSynchronizer(); case ESynchMethod_Z: return new ZeromusSynchronizer(); -#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) || defined(DESMUME_QT) case ESynchMethod_P: return new PCSX2Synchronizer(); #endif default: return NULL; diff --git a/desmume/src/mic.cpp b/desmume/src/mic.cpp index ac9368e0a..3dc3a4b43 100644 --- a/desmume/src/mic.cpp +++ b/desmume/src/mic.cpp @@ -18,7 +18,7 @@ * Boston, MA 02111-1307, USA. */ -#ifndef WIN32 +#if !defined(WIN32) || defined(DESMUME_QT) #include #include "mic.h" diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 7c8c82fcb..6cd0d38c1 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -952,7 +952,7 @@ bool mov_loadstate(EMUFILE* fp, int size) if(tempMovieData.guid != currMovieData.guid) { //mbg 8/18/08 - this code can be used to turn the error message into an OK/CANCEL - #if defined(WIN32) + #if defined(WIN32) && !defined(DESMUME_QT) std::string msg = "There is a mismatch between savestate's movie and current movie.\ncurrent: " + currMovieData.guid.toString() + "\nsavestate: " + tempMovieData.guid.toString() + "\n\nThis means that you have loaded a savestate belonging to a different movie than the one you are playing now.\n\nContinue loading this savestate anyway?"; int result = MessageBox(MainWindow->getHWnd(),msg.c_str(),"Error loading savestate",MB_OKCANCEL); if(result == IDCANCEL) diff --git a/desmume/src/path.h b/desmume/src/path.h index 21df28364..3a233628f 100644 --- a/desmume/src/path.h +++ b/desmume/src/path.h @@ -25,9 +25,11 @@ #include #include #include -#include "winutil.h" #include "common.h" +#ifndef DESMUME_QT +#include "winutil.h" #include "resource.h" +#endif #elif !defined(DESMUME_COCOA) #include #endif /* HOST_WINDOWS */ @@ -144,11 +146,13 @@ public: while (p >= pathToModule && *p != DIRECTORY_DELIMITER_CHAR) p--; if (++p >= pathToModule) *p = 0; +#ifndef DESMUME_QT extern char* _hack_alternateModulePath; if(_hack_alternateModulePath) { strcpy(pathToModule,_hack_alternateModulePath); } +#endif #elif defined(DESMUME_COCOA) std::string pathStr = Path::GetFileDirectoryPath(path); diff --git a/desmume/src/qt/project/DeSmuME.pro b/desmume/src/qt/project/DeSmuME.pro new file mode 100644 index 000000000..2039ac6c2 --- /dev/null +++ b/desmume/src/qt/project/DeSmuME.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + core \ + frontend diff --git a/desmume/src/qt/project/core/core.pro b/desmume/src/qt/project/core/core.pro new file mode 100644 index 000000000..d3771c602 --- /dev/null +++ b/desmume/src/qt/project/core/core.pro @@ -0,0 +1,423 @@ +QT -= core gui +TEMPLATE = lib + +CONFIG += staticlib +CONFIG -= app_bundle +CONFIG -= qt + +TARGET = desmume + +DEFINES += DESMUME_QT + +win32 { + !win32-g++: DEFINES += NOMINMAX \ + _CRT_SECURE_NO_DEPRECATE \ + WIN32 \ + HAVE_LIBZ + + DEFINES -= UNICODE + + INCLUDEPATH += $$PWD/../../../windows + + SOURCES += \ + ../../../fs-windows.cpp \ + ../../../metaspu/SoundTouch/3dnow_win.cpp \ + ../../../metaspu/SoundTouch/cpu_detect_x86_win.cpp + + # Windows glib + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/.libs/ -lglib-vc8-x64 + } else { + LIBS += -L$$PWD/../../../windows/.libs/ -lglib-vc8-Win32 + } + LIBS += -lole32 -lshell32 -ladvapi32 + INCLUDEPATH += $$PWD/../../../windows/glib-2.20.1/build/glib $$PWD/../../../windows/glib-2.20.1/build + DEPENDPATH += $$PWD/../../../windows/glib-2.20.1/build/glib + + # Windows zlib + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/zlib123/ -lzlib-vc8-x64 + } else { + LIBS += -L$$PWD/../../../windows/zlib123/ -lzlib-vc8-Win32 + } + INCLUDEPATH += $$PWD/../../../windows/zlib123 + DEPENDPATH += $$PWD/../../../windows/zlib123 + + # Windows libagg + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/agg/ -lagg-2.5-x64 + } else { + LIBS += -L$$PWD/../../../windows/agg/ -lagg-2.5 + } + INCLUDEPATH += $$PWD/../../../windows/agg/include + DEPENDPATH += $$PWD/../../../windows/agg/include + + svnrev.target = userconfig/svnrev.h + svnrev.commands = cd $$PWD & svnrev.cmd + QMAKE_EXTRA_TARGETS += svnrev + PRE_TARGETDEPS += userconfig/svnrev.h +} else:unix:!macx { + DESMUME_ARCH = $$QMAKE_HOST.arch + linux-*-64: DESMUME_ARCH = x86_64 + linux-*-32: DESMUME_ARCH = x86 + + DEFINES += \ + HOST_LINUX=1 \ + PACKAGE_NAME=\\\"desmume\\\" \ + PACKAGE_TARNAME=\\\"desmume\\\" \ + PACKAGE_VERSION=\\\"svn\\\" \ + PACKAGE_STRING=\\\"desmume\ svn\\\" \ + PACKAGE_BUGREPORT=\\\"\\\" \ + PACKAGE_URL=\\\"\\\" \ + PACKAGE=\\\"desmume\\\" \ + VERSION=\\\"svn\\\" \ + STDC_HEADERS=1 \ + HAVE_SYS_TYPES_H=1 \ + HAVE_SYS_STAT_H=1 \ + HAVE_STDLIB_H=1 \ + HAVE_STRING_H=1 \ + HAVE_MEMORY_H=1 \ + HAVE_STRINGS_H=1 \ + HAVE_INTTYPES_H=1 \ + HAVE_STDINT_H=1 \ + HAVE_UNISTD_H=1 \ + HAVE_LIBZ=1 \ + HAVE_GL_GL_H=1 \ + HAVE_GL_GLU_H=1 \ + HAVE_LIBDL=1 \ + HAVE_LIBGL=1 \ + HAVE_GL_GLX_H=1 \ + HAVE_GL_GLX=1 \ + GLADEUI_UNINSTALLED_DIR=\\\"/home/alvin/src/desmume-svn-code/src/gtk-glade/glade/\\\" \ + GTKGLEXT_AVAILABLE=1 \ + HAVE_LIBAGG=1 \ + GETTEXT_PACKAGE=\\\"desmume\\\" \ + HAVE_LOCALE_H=1 \ + HAVE_LC_MESSAGES=1 \ + HAVE_BIND_TEXTDOMAIN_CODESET=1 \ + HAVE_GETTEXT=1 \ + HAVE_DCGETTEXT=1 \ + ENABLE_NLS=1 \ + HAVE_JIT=1 \ + _GNU_SOURCE=1 \ + _REENTRANT + + SOURCES += \ + ../../../fs-linux.cpp \ + ../../../metaspu/SoundTouch/cpu_detect_x86_gcc.cpp + + QMAKE_CXXFLAGS += -pthread + + # Note: If you plan to distribute the binary, remove -march=native + QMAKE_CXXFLAGS_RELEASE += -O3 -flto=4 -fuse-linker-plugin -funroll-loops -march=native -minline-all-stringops + QMAKE_LFLAGS_RELEASE += -O3 -flto=4 -fuse-linker-plugin -funroll-loops -march=native -minline-all-stringops + + contains(DESMUME_ARCH, x86_64) { + message("Build target decided as x86_64") + DEFINES += HOST_64=1 + } else { + message("Build target decided as x86") + DEFINES += HOST_32=1 + } + + CONFIG += link_pkgconfig + PKGCONFIG += glib-2.0 libagg zlib + + svnrev.target = userconfig/svnrev.h + svnrev.commands = cd $$PWD; sh svnrev.sh + QMAKE_EXTRA_TARGETS += svnrev + PRE_TARGETDEPS += userconfig/svnrev.h +} else:macx { + error("Mac OS X not supported") +} + +INCLUDEPATH += userconfig/ defaultconfig/ ../../../../src + +SOURCES += \ + ../../../armcpu.cpp \ + ../../../arm_instructions.cpp \ + ../../../agg2d.inl \ + ../../../bios.cpp \ + ../../../commandline.cpp \ + ../../../common.cpp \ + ../../../cp15.cpp \ + ../../../debug.cpp \ + ../../../Disassembler.cpp \ + ../../../emufile.cpp \ + ../../../encrypt.cpp \ + ../../../FIFO.cpp \ + ../../../firmware.cpp \ + ../../../GPU.cpp \ + ../../../GPU_osd.cpp \ + ../../../matrix.cpp \ + ../../../mc.cpp \ + ../../../MMU.cpp \ + ../../../NDSSystem.cpp \ + ../../../ROMReader.cpp \ + ../../../render3D.cpp \ + ../../../rtc.cpp \ + ../../../saves.cpp \ + ../../../slot1.cpp \ + ../../../slot2.cpp \ + ../../../SPU.cpp \ + ../../../gfx3d.cpp \ + ../../../thumb_instructions.cpp \ + ../../../movie.cpp \ + ../../../utils/advanscene.cpp \ + ../../../utils/datetime.cpp \ + ../../../utils/guid.cpp \ + ../../../utils/emufat.cpp \ + ../../../utils/fsnitro.cpp \ + ../../../utils/md5.cpp \ + ../../../utils/xstring.cpp \ + ../../../utils/vfat.cpp \ + ../../../utils/task.cpp \ + ../../../utils/dlditool.cpp \ + ../../../utils/ConvertUTF.c \ + ../../../utils/decrypt/crc.cpp \ + ../../../utils/decrypt/decrypt.cpp \ + ../../../utils/decrypt/header.cpp \ + ../../../utils/libfat/cache.cpp \ + ../../../utils/libfat/directory.cpp \ + ../../../utils/libfat/disc.cpp \ + ../../../utils/libfat/fatdir.cpp \ + ../../../utils/libfat/fatfile.cpp \ + ../../../utils/libfat/file_allocation_table.cpp \ + ../../../utils/libfat/filetime.cpp \ + ../../../utils/libfat/libfat_public_api.cpp \ + ../../../utils/libfat/libfat.cpp \ + ../../../utils/libfat/lock.cpp \ + ../../../utils/libfat/partition.cpp \ + ../../../utils/tinyxml/tinystr.cpp \ + ../../../utils/tinyxml/tinyxml.cpp \ + ../../../utils/tinyxml/tinyxmlerror.cpp \ + ../../../utils/tinyxml/tinyxmlparser.cpp \ + ../../../addons/slot1_none.cpp \ + ../../../addons/slot1_r4.cpp \ + ../../../addons/slot1_retail_auto.cpp \ + ../../../addons/slot1_retail_mcrom_debug.cpp \ + ../../../addons/slot1_retail_mcrom.cpp \ + ../../../addons/slot1_retail_nand.cpp \ + ../../../addons/slot1comp_mc.cpp \ + ../../../addons/slot1comp_protocol.cpp \ + ../../../addons/slot1comp_rom.cpp \ + ../../../addons/slot2_auto.cpp \ + ../../../addons/slot2_expMemory.cpp \ + ../../../addons/slot2_gbagame.cpp \ + ../../../addons/slot2_guitarGrip.cpp \ + ../../../addons/slot2_mpcf.cpp \ + ../../../addons/slot2_none.cpp \ + ../../../addons/slot2_paddle.cpp \ + ../../../addons/slot2_passme.cpp \ + ../../../addons/slot2_piano.cpp \ + ../../../addons/slot2_rumblepak.cpp \ + ../../../cheatSystem.cpp \ + ../../../texcache.cpp \ + ../../../rasterize.cpp \ + ../../../metaspu/metaspu.cpp \ + ../../../filter/2xsai.cpp \ + ../../../filter/bilinear.cpp \ + ../../../filter/epx.cpp \ + ../../../filter/hq2x.cpp \ + ../../../filter/hq4x.cpp \ + ../../../filter/lq2x.cpp \ + ../../../filter/scanline.cpp \ + ../../../filter/videofilter.cpp \ + ../../../filter/xbrz.cpp \ + ../../../version.cpp \ + ../../../utils/AsmJit/core/assembler.cpp \ + ../../../utils/AsmJit/core/assert.cpp \ + ../../../utils/AsmJit/core/buffer.cpp \ + ../../../utils/AsmJit/core/compiler.cpp \ + ../../../utils/AsmJit/core/compilercontext.cpp \ + ../../../utils/AsmJit/core/compilerfunc.cpp \ + ../../../utils/AsmJit/core/compileritem.cpp \ + ../../../utils/AsmJit/core/context.cpp \ + ../../../utils/AsmJit/core/cpuinfo.cpp \ + ../../../utils/AsmJit/core/defs.cpp \ + ../../../utils/AsmJit/core/func.cpp \ + ../../../utils/AsmJit/core/logger.cpp \ + ../../../utils/AsmJit/core/memorymanager.cpp \ + ../../../utils/AsmJit/core/memorymarker.cpp \ + ../../../utils/AsmJit/core/operand.cpp \ + ../../../utils/AsmJit/core/stringbuilder.cpp \ + ../../../utils/AsmJit/core/stringutil.cpp \ + ../../../utils/AsmJit/core/virtualmemory.cpp \ + ../../../utils/AsmJit/core/zonememory.cpp \ + ../../../utils/AsmJit/x86/x86assembler.cpp \ + ../../../utils/AsmJit/x86/x86compiler.cpp \ + ../../../utils/AsmJit/x86/x86compilercontext.cpp \ + ../../../utils/AsmJit/x86/x86compilerfunc.cpp \ + ../../../utils/AsmJit/x86/x86compileritem.cpp \ + ../../../utils/AsmJit/x86/x86cpuinfo.cpp \ + ../../../utils/AsmJit/x86/x86defs.cpp \ + ../../../utils/AsmJit/x86/x86func.cpp \ + ../../../utils/AsmJit/x86/x86operand.cpp \ + ../../../utils/AsmJit/x86/x86util.cpp \ + ../../../mic.cpp \ + ../../../aggdraw.cpp \ + ../../../wifi.cpp \ + ../../../arm_jit.cpp \ + ../../../readwrite.cpp \ + ../../../driver.cpp \ + ../../../path.cpp \ + ../../../OGLRender.cpp \ + ../../../metaspu/SoundTouch/AAFilter.cpp \ + ../../../metaspu/SoundTouch/FIFOSampleBuffer.cpp \ + ../../../metaspu/SoundTouch/FIRFilter.cpp \ + ../../../metaspu/SoundTouch/mmx_optimized.cpp \ + ../../../metaspu/SoundTouch/RateTransposer.cpp \ + ../../../metaspu/SoundTouch/SoundTouch.cpp \ + ../../../metaspu/SoundTouch/sse_optimized.cpp \ + ../../../metaspu/SoundTouch/TDStretch.cpp \ + ../../../metaspu/SoundTouch/WavFile.cpp \ + ../../../metaspu/SndOut.cpp \ + ../../../metaspu/Timestretcher.cpp + +HEADERS += \ + ../../../armcpu.h \ + ../../../agg2d.h \ + ../../../bios.h \ + ../../../bits.h \ + ../../../commandline.h \ + ../../../common.h \ + ../../../cp15.h \ + ../../../debug.h \ + ../../../Disassembler.h \ + ../../../emufile.h \ + ../../../emufile_types.h \ + ../../../encrypt.h \ + ../../../FIFO.h \ + ../../../firmware.h \ + ../../../fs.h \ + ../../../GPU.h \ + ../../../GPU_osd.h \ + ../../../instructions.h \ + ../../../matrix.h \ + ../../../mem.h \ + ../../../mc.h \ + ../../../mic.h \ + ../../../MMU_timing.h \ + ../../../MMU.h \ + ../../../NDSSystem.h \ + ../../../OGLRender.h \ + ../../../ROMReader.h \ + ../../../render3D.h \ + ../../../rtc.h \ + ../../../saves.h \ + ../../../slot1.h \ + ../../../slot2.h \ + ../../../SPU.h \ + ../../../gfx3d.h \ + ../../../types.h \ + ../../../shaders.h \ + ../../../movie.h \ + ../../../PACKED.h \ + ../../../PACKED_END.h \ + ../../../utils/advanscene.h \ + ../../../utils/datetime.h \ + ../../../utils/ConvertUTF.h \ + ../../../utils/guid.h \ + ../../../utils/emufat.h \ + ../../../utils/emufat_types.h \ + ../../../utils/fsnitro.h \ + ../../../utils/md5.h \ + ../../../utils/valuearray.h \ + ../../../utils/xstring.h \ + ../../../utils/vfat.h \ + ../../../utils/task.h \ + ../../../utils/decrypt/crc.h \ + ../../../utils/decrypt/decrypt.h \ + ../../../utils/decrypt/header.h \ + ../../../utils/libfat/bit_ops.h \ + ../../../utils/libfat/cache.h \ + ../../../utils/libfat/common.h \ + ../../../utils/libfat/directory.h \ + ../../../utils/libfat/disc_io.h \ + ../../../utils/libfat/disc.h \ + ../../../utils/libfat/fat.h \ + ../../../utils/libfat/fatdir.h \ + ../../../utils/libfat/fatfile.h \ + ../../../utils/libfat/file_allocation_table.h \ + ../../../utils/libfat/filetime.h \ + ../../../utils/libfat/libfat_pc.h \ + ../../../utils/libfat/libfat_public_api.h \ + ../../../utils/libfat/lock.h \ + ../../../utils/libfat/mem_allocate.h \ + ../../../utils/libfat/partition.h \ + ../../../utils/tinyxml/tinystr.h \ + ../../../utils/tinyxml/tinyxml.h \ + ../../../addons/slot1comp_mc.h \ + ../../../addons/slot1comp_protocol.h \ + ../../../addons/slot1comp_rom.h \ + ../../../cheatSystem.h \ + ../../../texcache.h \ + ../../../rasterize.h \ + ../../../metaspu/metaspu.h \ + ../../../filter/filter.h \ + ../../../filter/hq2x.h \ + ../../../filter/hq4x.h \ + ../../../filter/interp.h \ + ../../../filter/lq2x.h \ + ../../../filter/videofilter.h \ + ../../../filter/xbrz.h \ + ../../../version.h \ + ../../../utils/AsmJit/AsmJit.h \ + ../../../utils/AsmJit/Config.h \ + ../../../utils/AsmJit/core.h \ + ../../../utils/AsmJit/x86.h \ + ../../../utils/AsmJit/core/apibegin.h \ + ../../../utils/AsmJit/core/apiend.h \ + ../../../utils/AsmJit/core/assembler.h \ + ../../../utils/AsmJit/core/assert.h \ + ../../../utils/AsmJit/core/buffer.h \ + ../../../utils/AsmJit/core/build.h \ + ../../../utils/AsmJit/core/compiler.h \ + ../../../utils/AsmJit/core/compilercontext.h \ + ../../../utils/AsmJit/core/compilerfunc.h \ + ../../../utils/AsmJit/core/compileritem.h \ + ../../../utils/AsmJit/core/context.h \ + ../../../utils/AsmJit/core/cpuinfo.h \ + ../../../utils/AsmJit/core/defs.h \ + ../../../utils/AsmJit/core/func.h \ + ../../../utils/AsmJit/core/intutil.h \ + ../../../utils/AsmJit/core/lock.h \ + ../../../utils/AsmJit/core/logger.h \ + ../../../utils/AsmJit/core/memorymanager.h \ + ../../../utils/AsmJit/core/memorymarker.h \ + ../../../utils/AsmJit/core/operand.h \ + ../../../utils/AsmJit/core/podvector.h \ + ../../../utils/AsmJit/core/stringbuilder.h \ + ../../../utils/AsmJit/core/stringutil.h \ + ../../../utils/AsmJit/core/virtualmemory.h \ + ../../../utils/AsmJit/core/zonememory.h \ + ../../../utils/AsmJit/x86/x86assembler.h \ + ../../../utils/AsmJit/x86/x86compiler.h \ + ../../../utils/AsmJit/x86/x86compilercontext.h \ + ../../../utils/AsmJit/x86/x86compilerfunc.h \ + ../../../utils/AsmJit/x86/x86compileritem.h \ + ../../../utils/AsmJit/x86/x86cpuinfo.h \ + ../../../utils/AsmJit/x86/x86defs.h \ + ../../../utils/AsmJit/x86/x86func.h \ + ../../../utils/AsmJit/x86/x86operand.h \ + ../../../utils/AsmJit/x86/x86util.h \ + ../../../aggdraw.h \ + ../../../wifi.h \ + ../../../arm_jit.h \ + ../../../instruction_attributes.h \ + ../../../readwrite.h \ + ../../../driver.h \ + ../../../path.h \ + ../../../metaspu/SoundTouch/AAFilter.h \ + ../../../metaspu/SoundTouch/BPMDetect.h \ + ../../../metaspu/SoundTouch/cpu_detect.h \ + ../../../metaspu/SoundTouch/FIFOSampleBuffer.h \ + ../../../metaspu/SoundTouch/FIFOSamplePipe.h \ + ../../../metaspu/SoundTouch/FIRFilter.h \ + ../../../metaspu/SoundTouch/RateTransposer.h \ + ../../../metaspu/SoundTouch/SoundTouch.h \ + ../../../metaspu/SoundTouch/STTypes.h \ + ../../../metaspu/SoundTouch/TDStretch.h \ + ../../../metaspu/SoundTouch/WavFile.h \ + ../../../metaspu/SndOut.h \ + defaultconfig/svnrev.h diff --git a/desmume/src/qt/project/core/defaultconfig/svnrev.h b/desmume/src/qt/project/core/defaultconfig/svnrev.h new file mode 100644 index 000000000..4443f66c8 --- /dev/null +++ b/desmume/src/qt/project/core/defaultconfig/svnrev.h @@ -0,0 +1,7 @@ +// REVISION TRACKING +// userconfig/svnrev.h should be auto-generated and used, +// but this one is here just to prevent build errors. + +#define SVN_REV 0 +#define SVN_REV_STR "0" + diff --git a/desmume/src/qt/project/core/defaultconfig/svnrev_template.h b/desmume/src/qt/project/core/defaultconfig/svnrev_template.h new file mode 100644 index 000000000..3127cbc0e --- /dev/null +++ b/desmume/src/qt/project/core/defaultconfig/svnrev_template.h @@ -0,0 +1,7 @@ +// REVISION TRACKING +// This file is auto-generated. +// Do not commit this file to the code repository! + +#define SVN_REV $WCREV$ +#define SVN_REV_STR "$WCREV$" + diff --git a/desmume/src/qt/project/core/svnrev.cmd b/desmume/src/qt/project/core/svnrev.cmd new file mode 100644 index 000000000..44c199631 --- /dev/null +++ b/desmume/src/qt/project/core/svnrev.cmd @@ -0,0 +1,19 @@ +@echo off +rem Copyright (C) 2013-2014 DeSmuME team +rem +rem This file is free software: you can redistribute it and/or modify +rem it under the terms of the GNU General Public License as published by +rem the Free Software Foundation, either version 2 of the License, or +rem (at your option) any later version. +rem +rem This file is distributed in the hope that it will be useful +rem but WITHOUT ANY WARRANTY; without even the implied warranty of +rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +rem GNU General Public License for more details. +rem +rem You should have received a copy of the GNU General Public License +rem along with the this software. If not, see . + +echo Generating svnrev.h... +..\..\..\windows\defaultconfig\SubWCRev.exe ..\..\..\.. ".\defaultconfig\svnrev_template.h" ".\userconfig\svnrev.h" +exit 0 diff --git a/desmume/src/qt/project/core/svnrev.sh b/desmume/src/qt/project/core/svnrev.sh new file mode 100644 index 000000000..17742b382 --- /dev/null +++ b/desmume/src/qt/project/core/svnrev.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# Copyright (C) 2013-2014 DeSmuME team +# +# This file 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 file 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 the this software. If not, see . + +echo "Obtaining svn revision..." + +if which svnversion > /dev/null; then + WC_PATH="" + if [ -d "../../../../.svn" ]; then + WC_PATH="../../../../" + elif [ -d "../../../../../.svn" ]; then + WC_PATH="../../../../../" + fi + REV=$(svnversion -n $WC_PATH | sed -e 's/[[:alpha:]]//g' -e 's/^[[:digit:]]*://') +fi +if [ "$REV" = "" ]; then + echo "Cannot obtain svn revision." + REV="0" +else + echo "Obtained svn revision is $REV." +fi + +sed 's/\$WCREV\$/'$REV'/' defaultconfig/svnrev_template.h > userconfig/svnrev_gen.h + +if which diff > /dev/null && diff -q userconfig/svnrev_gen.h userconfig/svnrev.h > /dev/null 2>&1; then + # Hopefully don't trigger a rebuild + echo "Generated svnrev.h is the same as the existing one. Keeping original." + rm userconfig/svnrev_gen.h +else + echo "Updating svnrev.h..." + rm userconfig/svnrev.h + mv userconfig/svnrev_gen.h userconfig/svnrev.h +fi + diff --git a/desmume/src/qt/project/core/userconfig/readme.txt b/desmume/src/qt/project/core/userconfig/readme.txt new file mode 100644 index 000000000..8811bb662 --- /dev/null +++ b/desmume/src/qt/project/core/userconfig/readme.txt @@ -0,0 +1 @@ +This directory places the autogenerated svnrev.h diff --git a/desmume/src/qt/project/frontend/ds.cpp b/desmume/src/qt/project/frontend/ds.cpp new file mode 100644 index 000000000..821e30a64 --- /dev/null +++ b/desmume/src/qt/project/frontend/ds.cpp @@ -0,0 +1,149 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" + +#include "NDSSystem.h" +#include "render3D.h" +#include "rasterize.h" +#include "SPU.h" +#include "slot2.h" +#include "GPU_osd.h" + +#include "commandline.h" + +//#include "filter/videofilter.h" + +#include "video.h" +#include "sndqt.h" + +// TODO: Handle pausing correctly +volatile bool execute = false; +// TODO: Create a subclass of BaseDriver for Qt frontend + +GPU3DInterface *core3DList[] = { + &gpu3DNull, + &gpu3DRasterize, +#if 0 + &gpu3Dgl, +#endif + NULL +}; + +SoundInterface_struct *SNDCoreList[] = { + &SNDDummy, + &SNDQt, + NULL +}; + +namespace desmume { +namespace qt { +namespace ds { + +Video *video; +Input input; + +namespace { + +bool romLoaded = false; +bool unpaused = true; + +} /* namespace */ + +void init() { + video = new Video(4); + //video_buffer = video->GetDstBufferPtr(); + /*video->SetFilterParameteri(VF_PARAM_SCANLINE_A, _scanline_filter_a); + video->SetFilterParameteri(VF_PARAM_SCANLINE_B, _scanline_filter_b); + video->SetFilterParameteri(VF_PARAM_SCANLINE_C, _scanline_filter_c); + video->SetFilterParameteri(VF_PARAM_SCANLINE_D, _scanline_filter_d);*/ + + ::CommonSettings.use_jit = true; + ::CommonSettings.jit_max_block_size = 100; + + struct ::NDS_fw_config_data fw_config; + ::NDS_FillDefaultFirmwareConfigData(&fw_config); + + ::slot2_Init(); + ::slot2_Change(NDS_SLOT2_AUTO); + + ::NDS_Init(); + + ::SPU_ChangeSoundCore(SNDCORE_QT, 1024 * 4); + ::SPU_SetSynchMode(1, 0); // Sync N + //::SPU_SetSynchMode(1, 2); // Sync P + + ::Desmume_InitOnce(); + //Hud.reset(); + + ::NDS_CreateDummyFirmware(&fw_config); + + ::backup_setManualBackupType(0); + + ::NDS_3D_ChangeCore(1); +} + +void deinit() { + romLoaded = false; + unpaused = false; + ::NDS_DeInit(); +} + + +bool loadROM(const char* path) { + bool shouldUnpause = unpaused; + pause(); + if (::NDS_LoadROM(path) < 0) { + return false; + } else { + romLoaded = true; + if (shouldUnpause) { + unpause(); + } + return true; + } +} + +bool isRunning() { + return romLoaded && unpaused; +} + +void pause() { + unpaused = false; + ::execute = false; + ::SPU_Pause(1); +} + +void unpause() { + unpaused = true; + if (romLoaded) { + ::execute = true; + ::SPU_Pause(0); + } +} + +void execFrame() { + if (romLoaded && unpaused) { + ::NDS_exec(); + ::SPU_Emulate_user(); + } +} + +} /* namespace ds */ +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/ds.h b/desmume/src/qt/project/frontend/ds.h new file mode 100644 index 000000000..6ebcf83b2 --- /dev/null +++ b/desmume/src/qt/project/frontend/ds.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_DS_H +#define DESMUME_QT_DS_H + +#include "video.h" +#include "ds_input.h" + +namespace desmume { +namespace qt { +namespace ds { + +extern Video *video; +extern Input input; + +void init(); +void deinit(); +bool loadROM(const char* path); +bool isRunning(); +void pause(); +void unpause(); +void execFrame(); + +} /* namespace ds */ +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_DS_H */ diff --git a/desmume/src/qt/project/frontend/ds_input.cpp b/desmume/src/qt/project/frontend/ds_input.cpp new file mode 100644 index 000000000..f8a0fa557 --- /dev/null +++ b/desmume/src/qt/project/frontend/ds_input.cpp @@ -0,0 +1,83 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" +#include "ds_input.h" + +#include "NDSSystem.h" + +namespace desmume { +namespace qt { +namespace ds { + +Input::Input() { + for (int i = 0; i < KEY_COUNT; i++) { + mKeyStates[i] = false; + } +} + +void Input::updateDSInputRaw() { + ::NDS_setPad( + mKeyStates[KEY_RIGHT], + mKeyStates[KEY_LEFT], + mKeyStates[KEY_DOWN], + mKeyStates[KEY_UP], + mKeyStates[KEY_SELECT], + mKeyStates[KEY_START], + mKeyStates[KEY_B], + mKeyStates[KEY_A], + mKeyStates[KEY_Y], + mKeyStates[KEY_X], + mKeyStates[KEY_L], + mKeyStates[KEY_R], + mKeyStates[KEY_DEBUG], + mKeyStates[KEY_LID] + ); + //RunAntipodalRestriction(::NDS_getRawUserInput().buttons); +} + +void Input::updateDSInputActual() { + ::NDS_beginProcessingInput(); + { + //UserButtons& input = NDS_getProcessingUserInput().buttons; + //ApplyAntipodalRestriction(input); + } + ::NDS_endProcessingInput(); +} + +void Input::keyPress(KeysEnum key) { + mKeyStates[key] = true; + updateDSInputRaw(); +} + +void Input::keyRelease(KeysEnum key) { + mKeyStates[key] = false; + updateDSInputRaw(); +} + +void Input::touchMove(int x, int y) { + ::NDS_setTouchPos(x, y); +} + +void Input::touchUp() { + ::NDS_releaseTouch(); +} + +} /* namespace ds */ +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/ds_input.h b/desmume/src/qt/project/frontend/ds_input.h new file mode 100644 index 000000000..024b62977 --- /dev/null +++ b/desmume/src/qt/project/frontend/ds_input.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_DS_INPUT_H +#define DESMUME_QT_DS_INPUT_H + +namespace desmume { +namespace qt { +namespace ds { + +enum KeysEnum { + KEY_A = 0, + KEY_B, + KEY_SELECT, + KEY_START, + KEY_RIGHT, + KEY_LEFT, + KEY_UP, + KEY_DOWN, + KEY_R, + KEY_L, + KEY_X, + KEY_Y, + KEY_DEBUG, + KEY_LID, + KEY_COUNT +}; + +class Input { + bool mKeyStates[KEY_COUNT]; +public: + Input(); + void updateDSInputRaw(); + void updateDSInputActual(); + void keyPress(KeysEnum key); + void keyRelease(KeysEnum key); + void touchMove(int x, int y); + void touchUp(); +}; + +} /* namespace ds */ +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_DS_INPUT_H */ diff --git a/desmume/src/qt/project/frontend/frontend.pro b/desmume/src/qt/project/frontend/frontend.pro new file mode 100644 index 000000000..98d259f5b --- /dev/null +++ b/desmume/src/qt/project/frontend/frontend.pro @@ -0,0 +1,110 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-03-08T21:04:19 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +QT += multimedia + +TARGET = desmume-qt +TEMPLATE = app + +DEFINES += DESMUME_QT + +win32 { + !win32-g++: DEFINES += NOMINMAX \ + _CRT_SECURE_NO_DEPRECATE \ + WIN32 \ + HAVE_LIBZ + + DEFINES -= UNICODE + + RC_ICONS = resources/DeSmuME.ico + + # Windows glib + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/.libs/ -lglib-vc8-x64 + } else { + LIBS += -L$$PWD/../../../windows/.libs/ -lglib-vc8-Win32 + } + LIBS += -lole32 -lshell32 -ladvapi32 + INCLUDEPATH += $$PWD/../../../windows/glib-2.20.1/build/glib $$PWD/../../../windows/glib-2.20.1/build + DEPENDPATH += $$PWD/../../../windows/glib-2.20.1/build/glib + + # Windows zlib + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/zlib123/ -lzlib-vc8-x64 + } else { + LIBS += -L$$PWD/../../../windows/zlib123/ -lzlib-vc8-Win32 + } + INCLUDEPATH += $$PWD/../../../windows/zlib123 + DEPENDPATH += $$PWD/../../../windows/zlib123 + + # Windows libagg + contains(QMAKE_TARGET.arch, x86_64) { + LIBS += -L$$PWD/../../../windows/agg/ -lagg-2.5-x64 + } else { + LIBS += -L$$PWD/../../../windows/agg/ -lagg-2.5 + } + INCLUDEPATH += $$PWD/../../../windows/agg/include + DEPENDPATH += $$PWD/../../../windows/agg/include +} else:unix:!macx { + DESMUME_ARCH = $$QMAKE_HOST.arch + linux-*-64: DESMUME_ARCH = x86_64 + linux-*-32: DESMUME_ARCH = x86 + + # Note: If you plan to distribute the binary, remove -march=native + QMAKE_CXXFLAGS_RELEASE += -O3 -flto=4 -fuse-linker-plugin -funroll-loops -march=native -minline-all-stringops + QMAKE_LFLAGS_RELEASE += -O3 -flto=4 -fuse-linker-plugin -funroll-loops -march=native -minline-all-stringops +} else:macx { + error("Mac OS X not supported") +} + +INCLUDEPATH += ./ + +SOURCES += main.cpp\ + ui/mainwindow.cpp \ + ui/screenwidget.cpp \ + mainloop.cpp \ + sndqt.cpp \ + ds.cpp \ + video.cpp \ + ui/controlconfigdialog.cpp \ + ds_input.cpp \ + keyboardinput.cpp + +HEADERS += ui/mainwindow.h \ + ui/screenwidget.h \ + mainloop.h \ + sndqt.h \ + ds.h \ + video.h \ + ui/controlconfigdialog.h \ + keyboardinput.h \ + ds_input.h + +RESOURCES += \ + resources/resources.qrc + +FORMS += ui/mainwindow.ui \ + ui/controlconfigdialog.ui + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -ldesmume +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -ldesmume +else:unix: LIBS += -L$$OUT_PWD/../core/ -ldesmume + +INCLUDEPATH += $$PWD/../../.. +DEPENDPATH += $$PWD/../../.. + +win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libdesmume.a +else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libdesmume.a +else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/desmume.lib +else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/desmume.lib +else:unix: PRE_TARGETDEPS += $$OUT_PWD/../core/libdesmume.a + +unix: CONFIG += link_pkgconfig +unix: PKGCONFIG += glib-2.0 libagg zlib diff --git a/desmume/src/qt/project/frontend/keyboardinput.cpp b/desmume/src/qt/project/frontend/keyboardinput.cpp new file mode 100644 index 000000000..ffcf09f27 --- /dev/null +++ b/desmume/src/qt/project/frontend/keyboardinput.cpp @@ -0,0 +1,67 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" +#include "keyboardinput.h" + +#include + +namespace desmume { +namespace qt { + +KeyboardInput keyboard; + +KeyboardInput::KeyboardInput() { + mKeyAssignment[ds::KEY_A] = Qt::Key_X; + mKeyAssignment[ds::KEY_B] = Qt::Key_Z; + mKeyAssignment[ds::KEY_SELECT] = Qt::Key_Shift; + mKeyAssignment[ds::KEY_START] = Qt::Key_Enter; + mKeyAssignment[ds::KEY_RIGHT] = Qt::Key_Right; + mKeyAssignment[ds::KEY_LEFT] = Qt::Key_Left; + mKeyAssignment[ds::KEY_UP] = Qt::Key_Up; + mKeyAssignment[ds::KEY_DOWN] = Qt::Key_Down; + mKeyAssignment[ds::KEY_R] = Qt::Key_W; + mKeyAssignment[ds::KEY_L] = Qt::Key_Q; + mKeyAssignment[ds::KEY_X] = Qt::Key_S; + mKeyAssignment[ds::KEY_Y] = Qt::Key_A; + mKeyAssignment[ds::KEY_DEBUG] = 0; + mKeyAssignment[ds::KEY_LID] = Qt::Key_Backspace; +} + +bool KeyboardInput::keyPress(int key) { + for (int i = 0; i < ds::KEY_COUNT; i++) { + if (mKeyAssignment[i] == key) { + ds::input.keyPress((ds::KeysEnum)i); + return true; + } + } + return false; +} + +bool KeyboardInput::keyRelease(int key) { + for (int i = 0; i < ds::KEY_COUNT; i++) { + if (mKeyAssignment[i] == key) { + ds::input.keyRelease((ds::KeysEnum)i); + return true; + } + } + return false; +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/keyboardinput.h b/desmume/src/qt/project/frontend/keyboardinput.h new file mode 100644 index 000000000..863702487 --- /dev/null +++ b/desmume/src/qt/project/frontend/keyboardinput.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_KEYBOARDINPUT_H +#define DESMUME_QT_KEYBOARDINPUT_H + +#include "ds_input.h" + +namespace desmume { +namespace qt { + +class KeyboardInput { + int mKeyAssignment[ds::KEY_COUNT]; +public: + KeyboardInput(); + bool keyPress(int key); + bool keyRelease(int key); +}; + +extern KeyboardInput keyboard; + +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_KEYBOARDINPUT_H */ diff --git a/desmume/src/qt/project/frontend/main.cpp b/desmume/src/qt/project/frontend/main.cpp new file mode 100644 index 000000000..55da8b5c2 --- /dev/null +++ b/desmume/src/qt/project/frontend/main.cpp @@ -0,0 +1,46 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "mainloop.h" +#include "ds.h" + +#include "ui/mainwindow.h" +#include +#include + +int main(int argc, char *argv[]) { + QApplication a(argc, argv); + QIcon icon; + icon.addFile(QStringLiteral(":/images/DeSmuME-icon-16")); + icon.addFile(QStringLiteral(":/images/DeSmuME-icon-32")); + icon.addFile(QStringLiteral(":/images/DeSmuME-icon")); + a.setWindowIcon(icon); + + desmume::qt::MainWindow w; + w.show(); + + desmume::qt::ds::init(); + + desmume::qt::MainLoop mainLoop; + mainLoop.kickStart(); + + QObject::connect(desmume::qt::ds::video, &desmume::qt::Video::screenBufferUpdated, &w, &desmume::qt::MainWindow::screenBufferUpdate); + QObject::connect(&mainLoop, &desmume::qt::MainLoop::screenRedrawRequested, &w, &desmume::qt::MainWindow::screenRedraw); + + return a.exec(); +} diff --git a/desmume/src/qt/project/frontend/mainloop.cpp b/desmume/src/qt/project/frontend/mainloop.cpp new file mode 100644 index 000000000..b5cafdbe8 --- /dev/null +++ b/desmume/src/qt/project/frontend/mainloop.cpp @@ -0,0 +1,108 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" + +#include "mainloop.h" +#include +#include +#include + +namespace desmume { +namespace qt { + +MainLoop::MainLoop(QObject *parent) + : QObject(parent) + , mBasicTimer(new QBasicTimer) + , mTime(new QElapsedTimer) + , mLoopInitialized(false) + , mFrameMod3(0) + , mNextFrameTimeNs(0) +{ +} + +void MainLoop::kickStart() { + mBasicTimer->start(100, this); +} + +void MainLoop::timerEvent(QTimerEvent* event) { + loop(); +} + +void MainLoop::loop() { + if (mLoopInitialized) { + // I wanted to put some code here but... + } else { + mLoopInitialized = true; + mTime->start(); + mNextFrameTimeNs = 0; + mFrameMod3 = 0; + } + + // ---- Time keeping ---- + // TODO: Add frameskip option + + mFrameMod3 = (mFrameMod3 + 1) % 3; + int timerInterval = 16; + + // Adjust the time drift + qint64 timeDriftNs = mTime->nsecsElapsed() - mNextFrameTimeNs; + if (timeDriftNs > 0) { + //qDebug("Drift! %lld", timeDriftNs); + if (timeDriftNs < (10 * 1000 * 1000)) { + // If the drift is tolerable, try to catch up the next frame + // It's fine if the drift is less than 1ms + // Hopefully the compiler will generate mul + shr + timerInterval -= timeDriftNs / (1000 * 1000); + } else { + // Otherwise don't, delay the next frame instead. + mNextFrameTimeNs += timeDriftNs; + } + } else { + while (mTime->nsecsElapsed() < mNextFrameTimeNs); + } + + // Schedule next frame + if (/* fpsLimiterEnabled */ true) { + mBasicTimer->start(timerInterval, Qt::PreciseTimer, this); + const int frameIntervalNs = (mFrameMod3 == 0) ? 16666666 : 16666667; + mNextFrameTimeNs += frameIntervalNs; + } else { + mBasicTimer->start(0, this); + } + + //qDebug("Accumulative: %lld", mTime->elapsed()); + + // ---- Real action ---- + + // Redraw last frame + this->screenRedrawRequested(true); + + // Update input and emulate! + ds::input.updateDSInputActual(); + ds::execFrame(); + + // Run the video filter + ds::video->runFilter(); + + // Don't redraw yet... + //this->screenRedrawRequested(false); +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/mainloop.h b/desmume/src/qt/project/frontend/mainloop.h new file mode 100644 index 000000000..84f9689c7 --- /dev/null +++ b/desmume/src/qt/project/frontend/mainloop.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_MAINLOOP_H +#define DESMUME_QT_MAINLOOP_H + +#include +#include +#include +#include + +namespace desmume { +namespace qt { + +class MainLoop : public QObject { + Q_OBJECT + QBasicTimer* mBasicTimer; + QElapsedTimer* mTime; + bool mLoopInitialized; + int mFrameMod3; + qint64 mNextFrameTimeNs; + void loop(); +protected: + void timerEvent(QTimerEvent* event); +public: + explicit MainLoop(QObject* parent = 0); + void kickStart(); + +signals: + void screenRedrawRequested(bool immediate); + +private slots: + +}; + +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_MAINLOOP_H */ diff --git a/desmume/src/qt/project/frontend/resources/DeSmuME-16.png b/desmume/src/qt/project/frontend/resources/DeSmuME-16.png new file mode 100644 index 000000000..f62b628b9 Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/DeSmuME-16.png differ diff --git a/desmume/src/qt/project/frontend/resources/DeSmuME-32.png b/desmume/src/qt/project/frontend/resources/DeSmuME-32.png new file mode 100644 index 000000000..90039be71 Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/DeSmuME-32.png differ diff --git a/desmume/src/qt/project/frontend/resources/DeSmuME.ico b/desmume/src/qt/project/frontend/resources/DeSmuME.ico new file mode 100644 index 000000000..fe691527c Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/DeSmuME.ico differ diff --git a/desmume/src/qt/project/frontend/resources/DeSmuME.png b/desmume/src/qt/project/frontend/resources/DeSmuME.png new file mode 100644 index 000000000..b1e8ed30d Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/DeSmuME.png differ diff --git a/desmume/src/qt/project/frontend/resources/images/open.png b/desmume/src/qt/project/frontend/resources/images/open.png new file mode 100644 index 000000000..d95dace6e Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/images/open.png differ diff --git a/desmume/src/qt/project/frontend/resources/images/pause.png b/desmume/src/qt/project/frontend/resources/images/pause.png new file mode 100644 index 000000000..b07ed5b3e Binary files /dev/null and b/desmume/src/qt/project/frontend/resources/images/pause.png differ diff --git a/desmume/src/qt/project/frontend/resources/resources.qrc b/desmume/src/qt/project/frontend/resources/resources.qrc new file mode 100644 index 000000000..3227205b9 --- /dev/null +++ b/desmume/src/qt/project/frontend/resources/resources.qrc @@ -0,0 +1,9 @@ + + + images/open.png + images/pause.png + DeSmuME.png + DeSmuME-16.png + DeSmuME-32.png + + diff --git a/desmume/src/qt/project/frontend/sndqt.cpp b/desmume/src/qt/project/frontend/sndqt.cpp new file mode 100644 index 000000000..422fc080c --- /dev/null +++ b/desmume/src/qt/project/frontend/sndqt.cpp @@ -0,0 +1,117 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "SPU.h" +#include "sndqt.h" + +#include +#include +#include +#include +#include + +int SNDQTInit(int buffersize); +void SNDQTDeInit(); +void SNDQTUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDQTGetAudioSpace(); +void SNDQTMuteAudio(); +void SNDQTUnMuteAudio(); +void SNDQTSetVolume(int volume); + +SoundInterface_struct SNDQt = { +SNDCORE_QT, +"Qt QAudioOutput Sound Interface", +SNDQTInit, +SNDQTDeInit, +SNDQTUpdateAudio, +SNDQTGetAudioSpace, +SNDQTMuteAudio, +SNDQTUnMuteAudio, +SNDQTSetVolume +}; + +namespace { + +QAudioOutput *audio = NULL; +QIODevice *aio = NULL; + +} /* namespace */ + +int SNDQTInit(int buffersize) { + QAudioFormat fmt; + fmt.setSampleRate(DESMUME_SAMPLE_RATE); + fmt.setSampleType(QAudioFormat::SignedInt); + fmt.setSampleSize(16); + fmt.setChannelCount(2); + fmt.setCodec("audio/pcm"); + fmt.setByteOrder(QAudioFormat::LittleEndian); + + QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); + if (!info.isFormatSupported(fmt)) { + qWarning() << "Raw audio format not supported by backend, cannot play audio."; + return -1; + } + + audio = new QAudioOutput(fmt); + + audio->setBufferSize(buffersize * 2 * 2); + + aio = audio->start(); + return 0; +} + +void SNDQTDeInit() { + audio->stop(); + aio = NULL; + delete audio; + audio = NULL; +} + +void SNDQTUpdateAudio(s16 *buffer, u32 num_samples) { + if (aio == NULL) { + qDebug("%s is called at the wrong time!\n", __FUNCTION__); + return; + } + qint64 written = 0, writtenTotal = 0; + const u32 count = num_samples * 2 * 2; + do { + written = aio->write((char *) buffer, count - writtenTotal); + } while (written >= 0 && (writtenTotal += written) < count); +} + +u32 SNDQTGetAudioSpace() { + if (aio == NULL) { + qDebug("%s is called at the wrong time!\n", __FUNCTION__); + return 0; + } + return audio->bytesFree() / 2 / 2; +} + +void SNDQTMuteAudio() { + audio->suspend(); + //audio->setVolume(0.0); +} + +void SNDQTUnMuteAudio() { + audio->resume(); + //audio->setVolume(1.0); +} + +void SNDQTSetVolume(int volume) { + audio->setVolume(volume / 1.0); +} diff --git a/desmume/src/qt/project/frontend/sndqt.h b/desmume/src/qt/project/frontend/sndqt.h new file mode 100644 index 000000000..8da379e71 --- /dev/null +++ b/desmume/src/qt/project/frontend/sndqt.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef SNDQT_H +#define SNDQT_H + +#include "SPU.h" + +#define SNDCORE_QT 778 + +extern SoundInterface_struct SNDQt; + +#endif /* SNDQT_H */ diff --git a/desmume/src/qt/project/frontend/ui/controlconfigdialog.cpp b/desmume/src/qt/project/frontend/ui/controlconfigdialog.cpp new file mode 100644 index 000000000..f4a50237d --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/controlconfigdialog.cpp @@ -0,0 +1,38 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "controlconfigdialog.h" +#include "ui_controlconfigdialog.h" +#include + +namespace desmume { +namespace qt { + +ControlConfigDialog::ControlConfigDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ControlConfigDialog) +{ + ui->setupUi(this); +} + +ControlConfigDialog::~ControlConfigDialog() { + delete ui; +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/ui/controlconfigdialog.h b/desmume/src/qt/project/frontend/ui/controlconfigdialog.h new file mode 100644 index 000000000..0e3e66b2b --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/controlconfigdialog.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_CONTROLCONFIGDIALOG_H +#define DESMUME_QT_CONTROLCONFIGDIALOG_H + +#include + +namespace desmume { +namespace qt { + +namespace Ui { +class ControlConfigDialog; +} /* namespace Ui */ + +class ControlConfigDialog : public QDialog { + Q_OBJECT + +public: + explicit ControlConfigDialog(QWidget *parent = 0); + ~ControlConfigDialog(); + +private: + Ui::ControlConfigDialog *ui; + +private slots: +}; + + +} /* namespace qt */ +} /* namespace desmume */ +#endif /* DESMUME_QT_CONTROLCONFIGDIALOG_H */ diff --git a/desmume/src/qt/project/frontend/ui/controlconfigdialog.ui b/desmume/src/qt/project/frontend/ui/controlconfigdialog.ui new file mode 100644 index 000000000..d3376c0c0 --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/controlconfigdialog.ui @@ -0,0 +1,68 @@ + + + desmume::qt::ControlConfigDialog + + + + 0 + 0 + 400 + 300 + + + + Configure Controls + + + + + 290 + 20 + 81 + 241 + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + desmume::qt::ControlConfigDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + desmume::qt::ControlConfigDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/desmume/src/qt/project/frontend/ui/mainwindow.cpp b/desmume/src/qt/project/frontend/ui/mainwindow.cpp new file mode 100644 index 000000000..cdac5d71f --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/mainwindow.cpp @@ -0,0 +1,158 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" +#include "keyboardinput.h" +#include "version.h" + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "controlconfigdialog.h" +#include +#include +#include +#include +#include +#include + +namespace desmume { +namespace qt { + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + this->populateVideoFilterMenu(); + this->setWindowTitle(EMU_DESMUME_NAME_AND_VERSION()); + ui->statusBar->showMessage(EMU_DESMUME_NAME_AND_VERSION()); + this->ui->screen->setFocus(); +} + +MainWindow::~MainWindow() { + delete ui; +} + +void MainWindow::populateVideoFilterMenu() { + videoFilterActionGroup = new QActionGroup(this); + for (int i = 0; i < VideoFilterTypeIDCount; i++) { + const VideoFilterAttributes& filter = VideoFilterAttributesList[i]; + QAction *act = new QAction(this); + act->setObjectName(QStringLiteral("actionVideoFilter") + filter.typeString); + act->setCheckable(true); + act->setData(i); + if (i == VideoFilterTypeID_None) { + act->setText("&None"); + act->setChecked(true); + } else { + act->setText(filter.typeString); + } + videoFilterActionGroup->addAction(act); + ui->menuVideoFilter->addAction(act); + } + connect(videoFilterActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(videoFilterActionGroup_triggered(QAction*))); +} + +void MainWindow::videoFilterActionGroup_triggered(QAction *action) { + VideoFilterTypeID filterID = (VideoFilterTypeID)action->data().toInt(); + ds::video->setFilter(filterID); +} + +void MainWindow::screenBufferUpdate(unsigned int *buf, const QSize &size, qreal scale) { + ui->screen->setScreenBuffer(buf, size, scale); +} + +void MainWindow::screenRedraw(bool immediate) { + if (immediate) { + ui->screen->repaint(); + } else { + ui->screen->update(); + } +} + +void MainWindow::keyPressEvent(QKeyEvent *event) { + if (!keyboard.keyPress(event->key())) { + QMainWindow::keyPressEvent(event); + } +} + +void MainWindow::keyReleaseEvent(QKeyEvent *event) { + if (!keyboard.keyRelease(event->key())) { + QMainWindow::keyPressEvent(event); + } +} + +void MainWindow::on_actionOpenROM_triggered() { + QString fileName = QFileDialog::getOpenFileName(this, "Open NDS ROM", "", "NDS ROM Files (*.nds)"); + if (fileName.length() > 0) { + if (ds::loadROM(fileName.toLocal8Bit())) { + ui->statusBar->showMessage(QStringLiteral("Loaded ROM ") + fileName); + ui->actionPause->setEnabled(true); + } else { + ui->actionPause->setEnabled(false); + QMessageBox::warning(this, QStringLiteral("DeSmuME"), QStringLiteral("Cannot open ROM ") + fileName); + } + } +} + +void MainWindow::on_actionPause_toggled(bool checked) { + if (checked) { + ds::pause(); + } else { + ds::unpause(); + } +} + +void MainWindow::on_actionConfigureControls_triggered() { + ControlConfigDialog dlg(this); + dlg.exec(); +} + +void MainWindow::on_actionAboutQt_triggered() { + QMessageBox::aboutQt(this); +} + +void desmume::qt::MainWindow::on_action_AboutDeSmuME_triggered() { + // TODO: Make a better About dialog + QMessageBox::about( + this, + "About DeSmuME", + QStringLiteral("Version: \n\t") + + EMU_DESMUME_NAME_AND_VERSION() + "\n" + "\n" + "This file is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 2 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "This file is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with the this software. If not, see ." + ); +} + +void MainWindow::on_actionQuit_triggered() { + this->close(); +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/ui/mainwindow.h b/desmume/src/qt/project/frontend/ui/mainwindow.h new file mode 100644 index 000000000..f1502718f --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/mainwindow.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_MAINWINDOW_H +#define DESMUME_QT_MAINWINDOW_H + +#include + +#include +#include +#include +#include + +namespace desmume { +namespace qt { + +namespace Ui { +class MainWindow; +} /* namespace Ui */ + +class MainWindow : public QMainWindow +{ + Q_OBJECT + QActionGroup* videoFilterActionGroup; + void populateVideoFilterMenu(); +protected: + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void screenBufferUpdate(unsigned int *buf, const QSize &size, qreal scale); + void screenRedraw(bool immediate); + +private slots: + void on_actionQuit_triggered(); + void videoFilterActionGroup_triggered(QAction* action); + void on_actionConfigureControls_triggered(); + void on_actionPause_toggled(bool checked); + + void on_actionOpenROM_triggered(); + + void on_actionAboutQt_triggered(); + + void on_action_AboutDeSmuME_triggered(); + +private: + Ui::MainWindow *ui; +}; + +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_MAINWINDOW_H */ diff --git a/desmume/src/qt/project/frontend/ui/mainwindow.ui b/desmume/src/qt/project/frontend/ui/mainwindow.ui new file mode 100644 index 000000000..f6e947c4a --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/mainwindow.ui @@ -0,0 +1,199 @@ + + + desmume::qt::MainWindow + + + DeSmuME + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 256 + 384 + + + + + + + + + + &File + + + + + + + + + + &View + + + + Video &Filter + + + + + false + + + LCDs &Layout + + + + + false + + + Screen &Rotation + + + + + + + + + false + + + &Config + + + + + + false + + + &Tools + + + + + &Help + + + + + + + + + + + + + + 16 + 16 + + + + TopToolBarArea + + + false + + + + + + + + false + + + + + + :/images/open:/images/open + + + Open ROM + + + Open an NDS ROM file + + + Ctrl+O + + + + + &Quit + + + + + Configure &Controls + + + Configure input controls + + + + + true + + + false + + + + :/images/pause:/images/pause + + + &Pause + + + Pause the emulation + + + Pause + + + + + About &Qt + + + + + &About DeSmuME + + + + + + + desmume::qt::ScreenWidget + QWidget +
ui/screenwidget.h
+ 1 +
+
+ + + + +
diff --git a/desmume/src/qt/project/frontend/ui/screenwidget.cpp b/desmume/src/qt/project/frontend/ui/screenwidget.cpp new file mode 100644 index 000000000..04930c7dc --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/screenwidget.cpp @@ -0,0 +1,171 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ds.h" + +#include "screenwidget.h" +#include +#include +#include +#include +#include +#include +#include + +namespace desmume { +namespace qt { + +ScreenWidget::ScreenWidget(QWidget* parent) + : QWidget(parent) + , mScreenBuf(NULL) +{ +} + +void ScreenWidget::calcTransform() { + if (mScreenBuf != NULL) { + QTransform transform; + int daW = this->width(), daH = this->height(); + int imgW, imgH; + switch (/* layout */ 0) { + case /* vertical */ 0: + imgW = mScreenSize.width(); + imgH = mScreenSize.height() /* + gapSize * mScale */; + break; + case /* horizontal */ 1: + imgW = mScreenSize.width() * 2; + imgH = mScreenSize.height() / 2; + break; + case /* singleScreen */ 2: + imgW = mScreenSize.width(); + imgH = mScreenSize.height() / 2; + break; + } + if (/* rotateHorizontal */ false) { + qSwap(imgW, imgH); + } + qreal hRatio = (qreal)daW / (qreal)imgW; + qreal vRatio = (qreal)daH / (qreal)imgH; + if (/* keepAspectRatio */ true) { + hRatio = qMin(hRatio, vRatio); + vRatio = hRatio; + } + + // Scale to fit drawing area + transform.translate(daW / 2, daH / 2); + transform.scale(hRatio, vRatio); + transform.rotate(/* rotationAngle */ 0.0); + transform.translate(-mScreenSize.width() / 2, -mScreenSize.height() / 2); + + // Transform each screen + if (/* hasMainScreen */ true) { + mMainScreenTransform = transform; + if (/* swapped */ false) { + switch (/* layout */ 0) { + case /* vertical */ 0: + mMainScreenTransform.translate(0, mScreenSize.height() / 2 /* + gapSize * mScale */); + break; + case /* horizontal */ 1: + mMainScreenTransform.translate(mScreenSize.width(), 0); + break; + case /* singleScreen */ 2: + break; + } + } + mMainScreenTransformInv = mMainScreenTransform; + mMainScreenTransformInv.scale(mScale, mScale); + mMainScreenTransformInv = mMainScreenTransformInv.inverted(); + } + if (/* hasTouchScreen */ true) { + mTouchScreenTransform = transform; + if (/* !swapped */ true) { + switch (/* layout */ 0) { + case /* vertical */ 0: + mTouchScreenTransform.translate(0, mScreenSize.height() / 2 /* + gapSize * mScale */); + break; + case /* horizontal */ 1: + mTouchScreenTransform.translate(mScreenSize.width(), 0); + break; + case /* singleScreen */ 2: + break; + } + } + mTouchScreenTransformInv = mTouchScreenTransform; + mTouchScreenTransformInv.scale(mScale, mScale); + mTouchScreenTransformInv = mTouchScreenTransformInv.inverted(); + } + } +} + +void ScreenWidget::resizeEvent(QResizeEvent* event) { + calcTransform(); +} + +void ScreenWidget::mousePressEvent(QMouseEvent* event) { + this->setFocus(); + mAcceptTouchDS = false; + if (ds::isRunning() && event->button() == Qt::LeftButton) { + const QPoint touchScreenPt = mTouchScreenTransformInv.map(event->pos()); + const QRect r(0, 0, 255, 191); + if (r.contains(touchScreenPt)) { + mAcceptTouchDS = true; + ds::input.touchMove(touchScreenPt.x(), touchScreenPt.y()); + } + } +} + +void ScreenWidget::mouseMoveEvent(QMouseEvent* event) { + if (ds::isRunning() && event->buttons() == Qt::LeftButton && mAcceptTouchDS) { + const QPoint touchScreenPt = mTouchScreenTransformInv.map(event->pos()); + ds::input.touchMove(touchScreenPt.x(), touchScreenPt.y()); + } +} + +void ScreenWidget::mouseReleaseEvent(QMouseEvent* event) { + if (mAcceptTouchDS) { + ds::input.touchUp(); + } + mAcceptTouchDS = false; +} + +void ScreenWidget::setScreenBuffer(unsigned int* buf, const QSize& size, qreal scale) { + this->mScreenBuf = buf; + this->mScreenSize = size; + this->mScale = scale; + calcTransform(); +} + +void ScreenWidget::paintEvent(QPaintEvent* event) { + QPainter painter(this); + // Fill background with magenta for debugging purpose + painter.fillRect(0, 0, this->width(), this->height(), QColor::fromRgb(255, 0, 255)); + if (this->mScreenBuf != NULL) { + QImage img( + (unsigned char*)this->mScreenBuf, + this->mScreenSize.width(), + this->mScreenSize.height(), + QImage::Format_RGBX8888 + ); + painter.setTransform(mMainScreenTransform); + painter.drawImage(0, 0, img, 0, 0, -1, mScreenSize.height() / 2); + painter.setTransform(mTouchScreenTransform); + painter.drawImage(0, 0, img, 0, mScreenSize.height() / 2); + } +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/ui/screenwidget.h b/desmume/src/qt/project/frontend/ui/screenwidget.h new file mode 100644 index 000000000..40caa9876 --- /dev/null +++ b/desmume/src/qt/project/frontend/ui/screenwidget.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_SCREENWIDGET_H +#define DESMUME_QT_SCREENWIDGET_H + +#include +#include +#include + +namespace desmume { +namespace qt { + +class ScreenWidget : public QWidget +{ + Q_OBJECT + unsigned int* mScreenBuf; + QSize mScreenSize; + qreal mScale; + QTransform mMainScreenTransform; + QTransform mTouchScreenTransform; + QTransform mMainScreenTransformInv; + QTransform mTouchScreenTransformInv; + bool mAcceptTouchDS; + void calcTransform(); +protected: + void resizeEvent(QResizeEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + void paintEvent(QPaintEvent* event); +public: + explicit ScreenWidget(QWidget* parent = 0); + void setScreenBuffer(unsigned int* buf, const QSize& size, qreal scale); +signals: + +public slots: + +}; + +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_SCREENWIDGET_H */ diff --git a/desmume/src/qt/project/frontend/video.cpp b/desmume/src/qt/project/frontend/video.cpp new file mode 100644 index 000000000..ed7112a79 --- /dev/null +++ b/desmume/src/qt/project/frontend/video.cpp @@ -0,0 +1,137 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#include "video.h" +#include "GPU.h" +#include "GPU_osd.h" + +#include + +#ifdef HOST_WINDOWS + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; +# ifdef _MSC_VER +# define __restrict__ __restrict +# endif +#endif + +namespace desmume { +namespace qt { + +namespace { + +// These conevrsion functions are adapted from Cocoa port. +static const uint8_t bits5to8[] = { + 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3A, + 0x42, 0x4A, 0x52, 0x5A, 0x63, 0x6B, 0x73, 0x7B, + 0x84, 0x8C, 0x94, 0x9C, 0xA5, 0xAD, 0xB5, 0xBD, + 0xC5, 0xCE, 0xD6, 0xDE, 0xE6, 0xEF, 0xF7, 0xFF +}; + +static inline uint32_t RGB555ToRGBA8888(const uint16_t color16) +{ + return (bits5to8[((color16 >> 0) & 0x001F)] << 0) | + (bits5to8[((color16 >> 5) & 0x001F)] << 8) | + (bits5to8[((color16 >> 10) & 0x001F)] << 16) | + 0xFF000000; +} + +static inline uint32_t RGB555ToBGRA8888(const uint16_t color16) +{ + return (bits5to8[((color16 >> 10) & 0x001F)] << 0) | + (bits5to8[((color16 >> 5) & 0x001F)] << 8) | + (bits5to8[((color16 >> 0) & 0x001F)] << 16) | + 0xFF000000; +} + +static inline void RGB555ToRGBA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount) +{ + const uint32_t *__restrict__ destBufferEnd = destBuffer + pixelCount; + + while (destBuffer < destBufferEnd) + { + *destBuffer++ = RGB555ToRGBA8888(*srcBuffer++); + } +} + +static inline void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount) +{ + const uint32_t *__restrict__ destBufferEnd = destBuffer + pixelCount; + + while (destBuffer < destBufferEnd) + { + *destBuffer++ = RGB555ToBGRA8888(*srcBuffer++); + } +} + +} /* namespace */ + +Video::Video(int numThreads, QObject* parent) + : QObject(parent) + , mFilter(256, 384, VideoFilterTypeID_None, numThreads) +{ +} + +bool Video::setFilter(VideoFilterTypeID filterID) { + const VideoFilterAttributes& attrib = VideoFilterAttributesList[filterID]; + if (attrib.scaleDivide == 1 || attrib.scaleDivide == 2) { + bool res = this->mFilter.ChangeFilterByID(filterID); + runFilter(); + return res; + } else { + qWarning( + "Filter %s has a `scaleDivide` of %d." + "The code currently can't handle this well," + "so this filter will not be enabled.\n", + attrib.typeString, + (int)attrib.scaleDivide + ); + return false; + } +} + +unsigned int* Video::runFilter() { + RGB555ToRGBA8888Buffer((u16*)GPU_screen, this->mFilter.GetSrcBufferPtr(), 256 * 384); + unsigned int* buf = this->mFilter.RunFilter(); + this->screenBufferUpdated(buf, this->getDstSize(), this->getDstScale()); + return buf; +} + +unsigned int* Video::getDstBufferPtr() { + return this->mFilter.GetDstBufferPtr(); +} + +int Video::getDstWidth() { + return this->mFilter.GetDstWidth(); +} + +int Video::getDstHeight() { + return this->mFilter.GetDstHeight(); +} + +QSize Video::getDstSize() { + return QSize(this->mFilter.GetDstWidth(), this->mFilter.GetDstHeight()); +} + +qreal Video::getDstScale() { + const VideoFilterAttributes& attrib = this->mFilter.GetAttributes(); + return (qreal)attrib.scaleMultiply / (qreal)attrib.scaleDivide; +} + +} /* namespace qt */ +} /* namespace desmume */ diff --git a/desmume/src/qt/project/frontend/video.h b/desmume/src/qt/project/frontend/video.h new file mode 100644 index 000000000..1ddf4d80d --- /dev/null +++ b/desmume/src/qt/project/frontend/video.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2014 DeSmuME team + Copyright (C) 2014 Alvin Wong + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DESMUME_QT_VIDEO_H +#define DESMUME_QT_VIDEO_H + +#include "filter/videofilter.h" +#include +#include + +namespace desmume { +namespace qt { + +class Video : public QObject { + Q_OBJECT + VideoFilter mFilter; +public: + Video(int numThreads, QObject* parent = 0); + bool setFilter(VideoFilterTypeID filterID); + unsigned int* runFilter(); + unsigned int* getDstBufferPtr(); + int getDstWidth(); + int getDstHeight(); + QSize getDstSize(); + qreal getDstScale(); +signals: + void screenBufferUpdated(unsigned int *buf, const QSize &size, qreal scale); +}; + +} /* namespace qt */ +} /* namespace desmume */ + +#endif /* DESMUME_QT_VIDEO_H */ diff --git a/desmume/src/types.h b/desmume/src/types.h index 6942c6f8d..c715ee9d1 100644 --- a/desmume/src/types.h +++ b/desmume/src/types.h @@ -24,7 +24,9 @@ #define HOST_WINDOWS //todo - everyone will want to support this eventually, i suppose - #include "config.h" + #ifndef DESMUME_QT + #include "config.h" + #endif #endif //_MSC_VER diff --git a/desmume/src/version.cpp b/desmume/src/version.cpp index d8ddb5a67..b754699c4 100644 --- a/desmume/src/version.cpp +++ b/desmume/src/version.cpp @@ -32,7 +32,7 @@ #endif //todo - everyone will want to support this eventually, i suppose -#if defined(HOST_WINDOWS) || defined(DESMUME_COCOA) +#if defined(HOST_WINDOWS) || defined(DESMUME_COCOA) || defined(DESMUME_QT) #include "svnrev.h" #else #ifndef SVN_REV