mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
Merge remote-tracking branch 'upstream/master' into RDLines
This commit is contained in:
commit
ab90b0aa83
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
cmake_policy(VERSION 3.15)
|
cmake_policy(VERSION 3.15)
|
||||||
if (POLICY CMP0076)
|
if (POLICY CMP0076)
|
||||||
@ -9,6 +9,11 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
|||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
|
option(USE_VCPKG "Use vcpkg for dependency packages" OFF)
|
||||||
|
if (USE_VCPKG)
|
||||||
|
include(ConfigureVcpkg)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(melonDS
|
project(melonDS
|
||||||
VERSION 0.9.5
|
VERSION 0.9.5
|
||||||
DESCRIPTION "DS emulator, sorta"
|
DESCRIPTION "DS emulator, sorta"
|
||||||
|
90
cmake/ConfigureVcpkg.cmake
Normal file
90
cmake/ConfigureVcpkg.cmake
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
set(_DEFAULT_VCPKG_ROOT "${CMAKE_SOURCE_DIR}/vcpkg")
|
||||||
|
set(VCPKG_ROOT "${_DEFAULT_VCPKG_ROOT}" CACHE STRING "The path to the vcpkg repository")
|
||||||
|
|
||||||
|
if (VCPKG_ROOT STREQUAL "${_DEFAULT_VCPKG_ROOT}")
|
||||||
|
FetchContent_Declare(vcpkg
|
||||||
|
GIT_REPOSITORY "https://github.com/Microsoft/vcpkg.git"
|
||||||
|
GIT_TAG 2023.10.19
|
||||||
|
SOURCE_DIR "${CMAKE_SOURCE_DIR}/vcpkg")
|
||||||
|
FetchContent_MakeAvailable(vcpkg)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(VCPKG_OVERLAY_TRIPLETS "${CMAKE_SOURCE_DIR}/cmake/overlay-triplets")
|
||||||
|
|
||||||
|
option(USE_RECOMMENDED_TRIPLETS "Use the recommended triplets that are used for official builds" ON)
|
||||||
|
|
||||||
|
if (CMAKE_OSX_ARCHITECTURES MATCHES ";")
|
||||||
|
message(FATAL_ERROR "macOS universal builds are not supported. Build them individually and combine afterwards instead.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (USE_RECOMMENDED_TRIPLETS)
|
||||||
|
execute_process(
|
||||||
|
COMMAND uname -m
|
||||||
|
OUTPUT_VARIABLE _HOST_PROCESSOR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
set(_CAN_TARGET_AS_HOST OFF)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
if (NOT CMAKE_OSX_ARCHITECTURES)
|
||||||
|
if (_HOST_PROCESSOR STREQUAL arm64)
|
||||||
|
set(CMAKE_OSX_ARCHITECTURES arm64)
|
||||||
|
else()
|
||||||
|
set(CMAKE_OSX_ARCHITECTURES x86_64)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_OSX_ARCHITECTURES STREQUAL arm64)
|
||||||
|
set(_WANTED_TRIPLET arm64-osx-11-release)
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0)
|
||||||
|
else()
|
||||||
|
set(_WANTED_TRIPLET x64-osx-1015-release)
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
# TODO Windows arm64 if possible
|
||||||
|
set(_CAN_TARGET_AS_HOST ON)
|
||||||
|
set(_WANTED_TRIPLET x64-mingw-static)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Don't override it if the user set something else
|
||||||
|
if (NOT VCPKG_TARGET_TRIPLET)
|
||||||
|
set(VCPKG_TARGET_TRIPLET "${_WANTED_TRIPLET}")
|
||||||
|
else()
|
||||||
|
set(_WANTED_TRIPLET "${VCPKG_TARGET_TRIPLET}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
if (_HOST_PROCESSOR MATCHES arm64)
|
||||||
|
if (_WANTED_TRIPLET MATCHES "^arm64-osx-")
|
||||||
|
set(_CAN_TARGET_AS_HOST ON)
|
||||||
|
elseif (_WANTED_TRIPLET STREQUAL "x64-osx-1015-release")
|
||||||
|
# Use the default triplet for when building for arm64
|
||||||
|
# because we're probably making a universal build
|
||||||
|
set(VCPKG_HOST_TRIPLET arm64-osx-11-release)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (_WANTED_TRIPLET MATCHES "^x64-osx-")
|
||||||
|
set(_CAN_TARGET_AS_HOST ON)
|
||||||
|
elseif (_WANTED_TRIPLET STREQUAL "arm64-osx-11-release")
|
||||||
|
set(VCPKG_HOST_TRIPLET x64-osx-1015-release)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# If host and target triplet differ, vcpkg seems to always assume that the host can't run the target's binaries.
|
||||||
|
# In cases like cross compiling from ARM -> Intel macOS, or target being an older version of the host OS, we *can* do that so the packages built targeting the host are redundant.
|
||||||
|
if (_CAN_TARGET_AS_HOST AND NOT VCPKG_HOST_TRIPLET)
|
||||||
|
option(VCPKG_TARGET_AS_HOST "Use the target as host triplet to speed up builds" ON)
|
||||||
|
else()
|
||||||
|
option(VCPKG_TARGET_AS_HOST "Use the target as host triplet to speed up builds" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (VCPKG_TARGET_AS_HOST)
|
||||||
|
set(VCPKG_HOST_TRIPLET "${VCPKG_TARGET_TRIPLET}" CACHE STRING "Host triplet to use for vcpkg")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
|
12
cmake/overlay-triplets/arm64-osx-11-release.cmake
Normal file
12
cmake/overlay-triplets/arm64-osx-11-release.cmake
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
set(VCPKG_TARGET_ARCHITECTURE arm64)
|
||||||
|
set(VCPKG_CRT_LINKAGE dynamic)
|
||||||
|
set(VCPKG_LIBRARY_LINKAGE static)
|
||||||
|
|
||||||
|
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
|
||||||
|
set(VCPKG_CMAKE_SYSTEM_VERSION 11.0)
|
||||||
|
set(VCPKG_OSX_ARCHITECTURES arm64)
|
||||||
|
set(VCPKG_BUILD_TYPE release)
|
||||||
|
set(VCPKG_OSX_DEPLOYMENT_TARGET 11.0)
|
||||||
|
|
||||||
|
set(VCPKG_C_FLAGS -mmacosx-version-min=11.0)
|
||||||
|
set(VCPKG_CXX_FLAGS -mmacosx-version-min=11.0)
|
12
cmake/overlay-triplets/x64-osx-1015-release.cmake
Normal file
12
cmake/overlay-triplets/x64-osx-1015-release.cmake
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
set(VCPKG_TARGET_ARCHITECTURE x64)
|
||||||
|
set(VCPKG_CRT_LINKAGE dynamic)
|
||||||
|
set(VCPKG_LIBRARY_LINKAGE static)
|
||||||
|
|
||||||
|
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
|
||||||
|
set(VCPKG_CMAKE_SYSTEM_VERSION 10.15)
|
||||||
|
set(VCPKG_OSX_ARCHITECTURES x86_64)
|
||||||
|
set(VCPKG_BUILD_TYPE release)
|
||||||
|
set(VCPKG_OSX_DEPLOYMENT_TARGET 10.15)
|
||||||
|
|
||||||
|
set(VCPKG_C_FLAGS -mmacosx-version-min=10.15)
|
||||||
|
set(VCPKG_CXX_FLAGS -mmacosx-version-min=10.15)
|
@ -193,6 +193,7 @@ void CartGame::SetupSave(u32 type)
|
|||||||
SRAMType = S_FLASH512K;
|
SRAMType = S_FLASH512K;
|
||||||
break;
|
break;
|
||||||
case 128*1024:
|
case 128*1024:
|
||||||
|
case (128*1024 + 0x10): // .sav file with appended real time clock data (ex: emulator mGBA)
|
||||||
SRAMType = S_FLASH1M;
|
SRAMType = S_FLASH1M;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -5,6 +5,8 @@ include(FixInterfaceIncludes)
|
|||||||
set(SOURCES_QT_SDL
|
set(SOURCES_QT_SDL
|
||||||
main.cpp
|
main.cpp
|
||||||
main_shaders.h
|
main_shaders.h
|
||||||
|
Screen.cpp
|
||||||
|
Window.cpp
|
||||||
CheatsDialog.cpp
|
CheatsDialog.cpp
|
||||||
Config.cpp
|
Config.cpp
|
||||||
DateTimeDialog.cpp
|
DateTimeDialog.cpp
|
||||||
@ -38,7 +40,7 @@ set(SOURCES_QT_SDL
|
|||||||
SaveManager.cpp
|
SaveManager.cpp
|
||||||
CameraManager.cpp
|
CameraManager.cpp
|
||||||
AudioInOut.cpp
|
AudioInOut.cpp
|
||||||
|
|
||||||
ArchiveUtil.h
|
ArchiveUtil.h
|
||||||
ArchiveUtil.cpp
|
ArchiveUtil.cpp
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#ifndef INPUT_H
|
#ifndef INPUT_H
|
||||||
#define INPUT_H
|
#define INPUT_H
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace Input
|
namespace Input
|
||||||
|
@ -248,7 +248,9 @@ bool Init()
|
|||||||
Log(LogLevel::Info, "MP sharedmem doesn't exist. creating\n");
|
Log(LogLevel::Info, "MP sharedmem doesn't exist. creating\n");
|
||||||
if (!MPQueue->create(kQueueSize))
|
if (!MPQueue->create(kQueueSize))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, "MP sharedmem create failed :(\n");
|
Log(LogLevel::Error, "MP sharedmem create failed :( (%d)\n", MPQueue->error());
|
||||||
|
delete MPQueue;
|
||||||
|
MPQueue = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +330,7 @@ void SetRecvTimeout(int timeout)
|
|||||||
|
|
||||||
void Begin()
|
void Begin()
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return;
|
||||||
MPQueue->lock();
|
MPQueue->lock();
|
||||||
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
||||||
PacketReadOffset = header->PacketWriteOffset;
|
PacketReadOffset = header->PacketWriteOffset;
|
||||||
@ -340,6 +343,7 @@ void Begin()
|
|||||||
|
|
||||||
void End()
|
void End()
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return;
|
||||||
MPQueue->lock();
|
MPQueue->lock();
|
||||||
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
||||||
//SemReset(InstanceID);
|
//SemReset(InstanceID);
|
||||||
@ -421,6 +425,7 @@ void FIFOWrite(int fifo, void* buf, int len)
|
|||||||
|
|
||||||
int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return 0;
|
||||||
MPQueue->lock();
|
MPQueue->lock();
|
||||||
u8* data = (u8*)MPQueue->data();
|
u8* data = (u8*)MPQueue->data();
|
||||||
MPQueueHeader* header = (MPQueueHeader*)&data[0];
|
MPQueueHeader* header = (MPQueueHeader*)&data[0];
|
||||||
@ -476,6 +481,7 @@ int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
|||||||
|
|
||||||
int RecvPacketGeneric(u8* packet, bool block, u64* timestamp)
|
int RecvPacketGeneric(u8* packet, bool block, u64* timestamp)
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!SemWait(InstanceID, block ? RecvTimeout : 0))
|
if (!SemWait(InstanceID, block ? RecvTimeout : 0))
|
||||||
@ -552,6 +558,8 @@ int SendAck(u8* packet, int len, u64 timestamp)
|
|||||||
|
|
||||||
int RecvHostPacket(u8* packet, u64* timestamp)
|
int RecvHostPacket(u8* packet, u64* timestamp)
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return -1;
|
||||||
|
|
||||||
if (LastHostID != -1)
|
if (LastHostID != -1)
|
||||||
{
|
{
|
||||||
// check if the host is still connected
|
// check if the host is still connected
|
||||||
@ -571,6 +579,8 @@ int RecvHostPacket(u8* packet, u64* timestamp)
|
|||||||
|
|
||||||
u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
|
u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
|
||||||
{
|
{
|
||||||
|
if (!MPQueue) return 0;
|
||||||
|
|
||||||
u16 ret = 0;
|
u16 ret = 0;
|
||||||
u16 myinstmask = (1 << InstanceID);
|
u16 myinstmask = (1 << InstanceID);
|
||||||
u16 curinstmask;
|
u16 curinstmask;
|
||||||
|
@ -66,12 +66,25 @@ void IPCInit()
|
|||||||
|
|
||||||
IPCBuffer = new QSharedMemory("melonIPC");
|
IPCBuffer = new QSharedMemory("melonIPC");
|
||||||
|
|
||||||
|
#if !defined(Q_OS_WINDOWS)
|
||||||
|
// QSharedMemory instances can be left over from crashed processes on UNIX platforms.
|
||||||
|
// To prevent melonDS thinking there's another instance, we attach and then immediately detach from the
|
||||||
|
// shared memory. If no other process was actually using it, it'll be destroyed and we'll have a clean
|
||||||
|
// shared memory buffer after creating it again below.
|
||||||
|
if (IPCBuffer->attach())
|
||||||
|
{
|
||||||
|
IPCBuffer->detach();
|
||||||
|
delete IPCBuffer;
|
||||||
|
IPCBuffer = new QSharedMemory("melonIPC");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!IPCBuffer->attach())
|
if (!IPCBuffer->attach())
|
||||||
{
|
{
|
||||||
Log(LogLevel::Info, "IPC sharedmem doesn't exist. creating\n");
|
Log(LogLevel::Info, "IPC sharedmem doesn't exist. creating\n");
|
||||||
if (!IPCBuffer->create(1024))
|
if (!IPCBuffer->create(1024))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, "IPC sharedmem create failed :(\n");
|
Log(LogLevel::Error, "IPC sharedmem create failed: %s\n", IPCBuffer->errorString().toStdString().c_str());
|
||||||
delete IPCBuffer;
|
delete IPCBuffer;
|
||||||
IPCBuffer = nullptr;
|
IPCBuffer = nullptr;
|
||||||
return;
|
return;
|
||||||
|
566
src/frontend/qt_sdl/Screen.cpp
Normal file
566
src/frontend/qt_sdl/Screen.cpp
Normal file
@ -0,0 +1,566 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016-2023 melonDS team
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QDebug>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#ifndef APPLE
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include "NDS.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
//#include "main_shaders.h"
|
||||||
|
|
||||||
|
#include "OSD.h"
|
||||||
|
|
||||||
|
using namespace melonDS;
|
||||||
|
|
||||||
|
|
||||||
|
/*const struct { int id; float ratio; const char* label; } aspectRatios[] =
|
||||||
|
{
|
||||||
|
{ 0, 1, "4:3 (native)" },
|
||||||
|
{ 4, (5.f / 3) / (4.f / 3), "5:3 (3DS)"},
|
||||||
|
{ 1, (16.f / 9) / (4.f / 3), "16:9" },
|
||||||
|
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
|
||||||
|
{ 3, 0, "window" }
|
||||||
|
};
|
||||||
|
int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);*/
|
||||||
|
|
||||||
|
// TEMP
|
||||||
|
extern MainWindow* mainWindow;
|
||||||
|
extern EmuThread* emuThread;
|
||||||
|
extern bool RunningSomething;
|
||||||
|
extern int autoScreenSizing;
|
||||||
|
|
||||||
|
extern int videoRenderer;
|
||||||
|
extern bool videoSettingsDirty;
|
||||||
|
|
||||||
|
|
||||||
|
ScreenHandler::ScreenHandler(QWidget* widget)
|
||||||
|
{
|
||||||
|
widget->setMouseTracking(true);
|
||||||
|
widget->setAttribute(Qt::WA_AcceptTouchEvents);
|
||||||
|
QTimer* mouseTimer = setupMouseTimer();
|
||||||
|
widget->connect(mouseTimer, &QTimer::timeout, [=] { if (Config::MouseHide) widget->setCursor(Qt::BlankCursor);});
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenHandler::~ScreenHandler()
|
||||||
|
{
|
||||||
|
mouseTimer->stop();
|
||||||
|
delete mouseTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenSetupLayout(int w, int h)
|
||||||
|
{
|
||||||
|
int sizing = Config::ScreenSizing;
|
||||||
|
if (sizing == 3) sizing = autoScreenSizing;
|
||||||
|
|
||||||
|
float aspectTop, aspectBot;
|
||||||
|
|
||||||
|
for (auto ratio : aspectRatios)
|
||||||
|
{
|
||||||
|
if (ratio.id == Config::ScreenAspectTop)
|
||||||
|
aspectTop = ratio.ratio;
|
||||||
|
if (ratio.id == Config::ScreenAspectBot)
|
||||||
|
aspectBot = ratio.ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aspectTop == 0)
|
||||||
|
aspectTop = ((float) w / h) / (4.f / 3.f);
|
||||||
|
|
||||||
|
if (aspectBot == 0)
|
||||||
|
aspectBot = ((float) w / h) / (4.f / 3.f);
|
||||||
|
|
||||||
|
Frontend::SetupScreenLayout(w, h,
|
||||||
|
static_cast<Frontend::ScreenLayout>(Config::ScreenLayout),
|
||||||
|
static_cast<Frontend::ScreenRotation>(Config::ScreenRotation),
|
||||||
|
static_cast<Frontend::ScreenSizing>(sizing),
|
||||||
|
Config::ScreenGap,
|
||||||
|
Config::IntegerScaling != 0,
|
||||||
|
Config::ScreenSwap != 0,
|
||||||
|
aspectTop,
|
||||||
|
aspectBot);
|
||||||
|
|
||||||
|
numScreens = Frontend::GetScreenTransforms(screenMatrix[0], screenKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ScreenHandler::screenGetMinSize(int factor = 1)
|
||||||
|
{
|
||||||
|
bool isHori = (Config::ScreenRotation == Frontend::screenRot_90Deg
|
||||||
|
|| Config::ScreenRotation == Frontend::screenRot_270Deg);
|
||||||
|
int gap = Config::ScreenGap * factor;
|
||||||
|
|
||||||
|
int w = 256 * factor;
|
||||||
|
int h = 192 * factor;
|
||||||
|
|
||||||
|
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly
|
||||||
|
|| Config::ScreenSizing == Frontend::screenSizing_BotOnly)
|
||||||
|
{
|
||||||
|
return QSize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config::ScreenLayout == Frontend::screenLayout_Natural)
|
||||||
|
{
|
||||||
|
if (isHori)
|
||||||
|
return QSize(h+gap+h, w);
|
||||||
|
else
|
||||||
|
return QSize(w, h+gap+h);
|
||||||
|
}
|
||||||
|
else if (Config::ScreenLayout == Frontend::screenLayout_Vertical)
|
||||||
|
{
|
||||||
|
if (isHori)
|
||||||
|
return QSize(h, w+gap+w);
|
||||||
|
else
|
||||||
|
return QSize(w, h+gap+h);
|
||||||
|
}
|
||||||
|
else if (Config::ScreenLayout == Frontend::screenLayout_Horizontal)
|
||||||
|
{
|
||||||
|
if (isHori)
|
||||||
|
return QSize(h+gap+h, w);
|
||||||
|
else
|
||||||
|
return QSize(w+gap+w, h);
|
||||||
|
}
|
||||||
|
else // hybrid
|
||||||
|
{
|
||||||
|
if (isHori)
|
||||||
|
return QSize(h+gap+h, 3*w + (int)ceil((4*gap) / 3.0));
|
||||||
|
else
|
||||||
|
return QSize(3*w + (int)ceil((4*gap) / 3.0), h+gap+h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenOnMousePress(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
if (event->button() != Qt::LeftButton) return;
|
||||||
|
|
||||||
|
int x = event->pos().x();
|
||||||
|
int y = event->pos().y();
|
||||||
|
|
||||||
|
if (Frontend::GetTouchCoords(x, y, false))
|
||||||
|
{
|
||||||
|
touching = true;
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->TouchScreen(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenOnMouseRelease(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
if (event->button() != Qt::LeftButton) return;
|
||||||
|
|
||||||
|
if (touching)
|
||||||
|
{
|
||||||
|
touching = false;
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->ReleaseScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenOnMouseMove(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
showCursor();
|
||||||
|
|
||||||
|
if (!(event->buttons() & Qt::LeftButton)) return;
|
||||||
|
if (!touching) return;
|
||||||
|
|
||||||
|
int x = event->pos().x();
|
||||||
|
int y = event->pos().y();
|
||||||
|
|
||||||
|
if (Frontend::GetTouchCoords(x, y, true))
|
||||||
|
{
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->TouchScreen(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenHandleTablet(QTabletEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
switch(event->type())
|
||||||
|
{
|
||||||
|
case QEvent::TabletPress:
|
||||||
|
case QEvent::TabletMove:
|
||||||
|
{
|
||||||
|
int x = event->x();
|
||||||
|
int y = event->y();
|
||||||
|
|
||||||
|
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TabletMove))
|
||||||
|
{
|
||||||
|
touching = true;
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->TouchScreen(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QEvent::TabletRelease:
|
||||||
|
if (touching)
|
||||||
|
{
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->ReleaseScreen();
|
||||||
|
touching = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::screenHandleTouch(QTouchEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
switch(event->type())
|
||||||
|
{
|
||||||
|
case QEvent::TouchBegin:
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
|
if (event->touchPoints().length() > 0)
|
||||||
|
{
|
||||||
|
QPointF lastPosition = event->touchPoints().first().lastPos();
|
||||||
|
int x = (int)lastPosition.x();
|
||||||
|
int y = (int)lastPosition.y();
|
||||||
|
|
||||||
|
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TouchUpdate))
|
||||||
|
{
|
||||||
|
touching = true;
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->TouchScreen(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QEvent::TouchEnd:
|
||||||
|
if (touching)
|
||||||
|
{
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->NDS->ReleaseScreen();
|
||||||
|
touching = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenHandler::showCursor()
|
||||||
|
{
|
||||||
|
mainWindow->panelWidget->setCursor(Qt::ArrowCursor);
|
||||||
|
mouseTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimer* ScreenHandler::setupMouseTimer()
|
||||||
|
{
|
||||||
|
mouseTimer = new QTimer();
|
||||||
|
mouseTimer->setSingleShot(true);
|
||||||
|
mouseTimer->setInterval(Config::MouseHideSeconds*1000);
|
||||||
|
mouseTimer->start();
|
||||||
|
|
||||||
|
return mouseTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent), ScreenHandler(this)
|
||||||
|
{
|
||||||
|
screen[0] = QImage(256, 192, QImage::Format_RGB32);
|
||||||
|
screen[1] = QImage(256, 192, QImage::Format_RGB32);
|
||||||
|
|
||||||
|
screenTrans[0].reset();
|
||||||
|
screenTrans[1].reset();
|
||||||
|
|
||||||
|
OSD::Init(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenPanelNative::~ScreenPanelNative()
|
||||||
|
{
|
||||||
|
OSD::DeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::setupScreenLayout()
|
||||||
|
{
|
||||||
|
int w = width();
|
||||||
|
int h = height();
|
||||||
|
|
||||||
|
screenSetupLayout(w, h);
|
||||||
|
|
||||||
|
for (int i = 0; i < numScreens; i++)
|
||||||
|
{
|
||||||
|
float* mtx = screenMatrix[i];
|
||||||
|
screenTrans[i].setMatrix(mtx[0], mtx[1], 0.f,
|
||||||
|
mtx[2], mtx[3], 0.f,
|
||||||
|
mtx[4], mtx[5], 1.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
|
||||||
|
// fill background
|
||||||
|
painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0));
|
||||||
|
|
||||||
|
if (emuThread->emuIsActive())
|
||||||
|
{
|
||||||
|
assert(emuThread->NDS != nullptr);
|
||||||
|
emuThread->FrontBufferLock.lock();
|
||||||
|
int frontbuf = emuThread->FrontBuffer;
|
||||||
|
if (!emuThread->NDS->GPU.Framebuffer[frontbuf][0] || !emuThread->NDS->GPU.Framebuffer[frontbuf][1])
|
||||||
|
{
|
||||||
|
emuThread->FrontBufferLock.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(screen[0].scanLine(0), emuThread->NDS->GPU.Framebuffer[frontbuf][0].get(), 256 * 192 * 4);
|
||||||
|
memcpy(screen[1].scanLine(0), emuThread->NDS->GPU.Framebuffer[frontbuf][1].get(), 256 * 192 * 4);
|
||||||
|
emuThread->FrontBufferLock.unlock();
|
||||||
|
|
||||||
|
QRect screenrc(0, 0, 256, 192);
|
||||||
|
|
||||||
|
for (int i = 0; i < numScreens; i++)
|
||||||
|
{
|
||||||
|
painter.setTransform(screenTrans[i]);
|
||||||
|
painter.drawImage(screenrc, screen[screenKind[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSD::Update();
|
||||||
|
OSD::DrawNative(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
setupScreenLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::mousePressEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMousePress(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::mouseReleaseEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMouseRelease(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::mouseMoveEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMouseMove(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::tabletEvent(QTabletEvent* event)
|
||||||
|
{
|
||||||
|
screenHandleTablet(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenPanelNative::event(QEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::TouchBegin
|
||||||
|
|| event->type() == QEvent::TouchEnd
|
||||||
|
|| event->type() == QEvent::TouchUpdate)
|
||||||
|
{
|
||||||
|
screenHandleTouch((QTouchEvent*)event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelNative::onScreenLayoutChanged()
|
||||||
|
{
|
||||||
|
setMinimumSize(screenGetMinSize());
|
||||||
|
setupScreenLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QWidget(parent), ScreenHandler(this)
|
||||||
|
{
|
||||||
|
setAutoFillBackground(false);
|
||||||
|
setAttribute(Qt::WA_NativeWindow, true);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||||
|
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||||
|
setAttribute(Qt::WA_KeyCompression, false);
|
||||||
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
setMinimumSize(screenGetMinSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenPanelGL::~ScreenPanelGL()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool ScreenPanelGL::createContext()
|
||||||
|
{
|
||||||
|
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
||||||
|
std::array<GL::Context::Version, 2> versionsToTry = {
|
||||||
|
GL::Context::Version{GL::Context::Profile::Core, 4, 3},
|
||||||
|
GL::Context::Version{GL::Context::Profile::Core, 3, 2}};
|
||||||
|
if (windowInfo.has_value())
|
||||||
|
{
|
||||||
|
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
|
||||||
|
glContext->DoneCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return glContext != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ScreenPanelGL::devicePixelRatioFromScreen() const
|
||||||
|
{
|
||||||
|
const QScreen* screen_for_ratio = window()->windowHandle()->screen();
|
||||||
|
if (!screen_for_ratio)
|
||||||
|
screen_for_ratio = QGuiApplication::primaryScreen();
|
||||||
|
|
||||||
|
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScreenPanelGL::scaledWindowWidth() const
|
||||||
|
{
|
||||||
|
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen())), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScreenPanelGL::scaledWindowHeight() const
|
||||||
|
{
|
||||||
|
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen())), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<WindowInfo> ScreenPanelGL::getWindowInfo()
|
||||||
|
{
|
||||||
|
WindowInfo wi;
|
||||||
|
|
||||||
|
// Windows and Apple are easy here since there's no display connection.
|
||||||
|
#if defined(_WIN32)
|
||||||
|
wi.type = WindowInfo::Type::Win32;
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
wi.type = WindowInfo::Type::MacOS;
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
#else
|
||||||
|
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||||
|
const QString platform_name = QGuiApplication::platformName();
|
||||||
|
if (platform_name == QStringLiteral("xcb"))
|
||||||
|
{
|
||||||
|
wi.type = WindowInfo::Type::X11;
|
||||||
|
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
}
|
||||||
|
else if (platform_name == QStringLiteral("wayland"))
|
||||||
|
{
|
||||||
|
wi.type = WindowInfo::Type::Wayland;
|
||||||
|
QWindow* handle = windowHandle();
|
||||||
|
if (handle == nullptr)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
wi.display_connection = pni->nativeResourceForWindow("display", handle);
|
||||||
|
wi.window_handle = pni->nativeResourceForWindow("surface", handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qCritical() << "Unknown PNI platform " << platform_name;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wi.surface_width = static_cast<u32>(scaledWindowWidth());
|
||||||
|
wi.surface_height = static_cast<u32>(scaledWindowHeight());
|
||||||
|
wi.surface_scale = static_cast<float>(devicePixelRatioFromScreen());
|
||||||
|
|
||||||
|
return wi;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QPaintEngine* ScreenPanelGL::paintEngine() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::setupScreenLayout()
|
||||||
|
{
|
||||||
|
int w = width();
|
||||||
|
int h = height();
|
||||||
|
|
||||||
|
screenSetupLayout(w, h);
|
||||||
|
if (emuThread)
|
||||||
|
transferLayout(emuThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
setupScreenLayout();
|
||||||
|
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::mousePressEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMousePress(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::mouseReleaseEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMouseRelease(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::mouseMoveEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
screenOnMouseMove(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::tabletEvent(QTabletEvent* event)
|
||||||
|
{
|
||||||
|
screenHandleTablet(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenPanelGL::event(QEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::TouchBegin
|
||||||
|
|| event->type() == QEvent::TouchEnd
|
||||||
|
|| event->type() == QEvent::TouchUpdate)
|
||||||
|
{
|
||||||
|
screenHandleTouch((QTouchEvent*)event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::transferLayout(EmuThread* thread)
|
||||||
|
{
|
||||||
|
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
||||||
|
if (windowInfo.has_value())
|
||||||
|
thread->updateScreenSettings(Config::ScreenFilter, *windowInfo, numScreens, screenKind, &screenMatrix[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenPanelGL::onScreenLayoutChanged()
|
||||||
|
{
|
||||||
|
setMinimumSize(screenGetMinSize());
|
||||||
|
setupScreenLayout();
|
||||||
|
}
|
155
src/frontend/qt_sdl/Screen.h
Normal file
155
src/frontend/qt_sdl/Screen.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016-2023 melonDS team
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCREEN_H
|
||||||
|
#define SCREEN_H
|
||||||
|
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "FrontendUtil.h"
|
||||||
|
#include "duckstation/gl/context.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QWindow>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QActionGroup>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
|
||||||
|
|
||||||
|
class EmuThread;
|
||||||
|
|
||||||
|
|
||||||
|
const struct { int id; float ratio; const char* label; } aspectRatios[] =
|
||||||
|
{
|
||||||
|
{ 0, 1, "4:3 (native)" },
|
||||||
|
{ 4, (5.f / 3) / (4.f / 3), "5:3 (3DS)"},
|
||||||
|
{ 1, (16.f / 9) / (4.f / 3), "16:9" },
|
||||||
|
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
|
||||||
|
{ 3, 0, "window" }
|
||||||
|
};
|
||||||
|
constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenHandler
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScreenHandler(QWidget* widget);
|
||||||
|
virtual ~ScreenHandler();
|
||||||
|
QTimer* setupMouseTimer();
|
||||||
|
void updateMouseTimer();
|
||||||
|
QTimer* mouseTimer;
|
||||||
|
QSize screenGetMinSize(int factor);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void screenSetupLayout(int w, int h);
|
||||||
|
|
||||||
|
void screenOnMousePress(QMouseEvent* event);
|
||||||
|
void screenOnMouseRelease(QMouseEvent* event);
|
||||||
|
void screenOnMouseMove(QMouseEvent* event);
|
||||||
|
|
||||||
|
void screenHandleTablet(QTabletEvent* event);
|
||||||
|
void screenHandleTouch(QTouchEvent* event);
|
||||||
|
|
||||||
|
float screenMatrix[Frontend::MaxScreenTransforms][6];
|
||||||
|
int screenKind[Frontend::MaxScreenTransforms];
|
||||||
|
int numScreens;
|
||||||
|
|
||||||
|
bool touching = false;
|
||||||
|
|
||||||
|
void showCursor();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenPanelNative : public QWidget, public ScreenHandler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScreenPanelNative(QWidget* parent);
|
||||||
|
virtual ~ScreenPanelNative();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
|
void tabletEvent(QTabletEvent* event) override;
|
||||||
|
bool event(QEvent* event) override;
|
||||||
|
private slots:
|
||||||
|
void onScreenLayoutChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupScreenLayout();
|
||||||
|
|
||||||
|
QImage screen[2];
|
||||||
|
QTransform screenTrans[Frontend::MaxScreenTransforms];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenPanelGL : public QWidget, public ScreenHandler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScreenPanelGL(QWidget* parent);
|
||||||
|
virtual ~ScreenPanelGL();
|
||||||
|
|
||||||
|
std::optional<WindowInfo> getWindowInfo();
|
||||||
|
|
||||||
|
bool createContext();
|
||||||
|
|
||||||
|
GL::Context* getContext() { return glContext.get(); }
|
||||||
|
|
||||||
|
void transferLayout(EmuThread* thread);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
qreal devicePixelRatioFromScreen() const;
|
||||||
|
int scaledWindowWidth() const;
|
||||||
|
int scaledWindowHeight() const;
|
||||||
|
|
||||||
|
QPaintEngine* paintEngine() const override;
|
||||||
|
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
|
void tabletEvent(QTabletEvent* event) override;
|
||||||
|
bool event(QEvent* event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onScreenLayoutChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupScreenLayout();
|
||||||
|
|
||||||
|
std::unique_ptr<GL::Context> glContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCREEN_H
|
||||||
|
|
2055
src/frontend/qt_sdl/Window.cpp
Normal file
2055
src/frontend/qt_sdl/Window.cpp
Normal file
File diff suppressed because it is too large
Load Diff
298
src/frontend/qt_sdl/Window.h
Normal file
298
src/frontend/qt_sdl/Window.h
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016-2023 melonDS team
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINDOW_H
|
||||||
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include "glad/glad.h"
|
||||||
|
#include "FrontendUtil.h"
|
||||||
|
#include "duckstation/gl/context.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QWindow>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QActionGroup>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
|
||||||
|
#include "Screen.h"
|
||||||
|
|
||||||
|
|
||||||
|
class EmuThread;
|
||||||
|
|
||||||
|
/*
|
||||||
|
class WindowBase : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WindowBase(QWidget* parent = nullptr);
|
||||||
|
~WindowBase();
|
||||||
|
|
||||||
|
bool hasOGL;
|
||||||
|
GL::Context* getOGLContext();
|
||||||
|
|
||||||
|
//void onAppStateChanged(Qt::ApplicationState state);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
void changeEvent(QEvent* event) override;
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
|
|
||||||
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
|
void dropEvent(QDropEvent* event) override;
|
||||||
|
|
||||||
|
void focusInEvent(QFocusEvent* event) override;
|
||||||
|
void focusOutEvent(QFocusEvent* event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void screenLayoutChange();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
//void onQuit();
|
||||||
|
|
||||||
|
//void onTitleUpdate(QString title);
|
||||||
|
|
||||||
|
//void onEmuStart();
|
||||||
|
//void onEmuStop();
|
||||||
|
|
||||||
|
//void onUpdateVideoSettings(bool glchange);
|
||||||
|
|
||||||
|
void onFullscreenToggled();
|
||||||
|
void onScreenEmphasisToggled();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void closeEvent(QCloseEvent* event) override;
|
||||||
|
|
||||||
|
void createScreenPanel();
|
||||||
|
|
||||||
|
//bool pausedManually = false;
|
||||||
|
|
||||||
|
int oldW, oldH;
|
||||||
|
bool oldMax;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScreenHandler* panel;
|
||||||
|
QWidget* panelWidget;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget* parent = nullptr);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
bool hasOGL;
|
||||||
|
GL::Context* getOGLContext();
|
||||||
|
|
||||||
|
bool preloadROMs(QStringList file, QStringList gbafile, bool boot);
|
||||||
|
QStringList splitArchivePath(const QString& filename, bool useMemberSyntax);
|
||||||
|
|
||||||
|
void onAppStateChanged(Qt::ApplicationState state);
|
||||||
|
|
||||||
|
void osdAddMessage(unsigned int color, const char* fmt, ...);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
void changeEvent(QEvent* event) override;
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
|
|
||||||
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
|
void dropEvent(QDropEvent* event) override;
|
||||||
|
|
||||||
|
void focusInEvent(QFocusEvent* event) override;
|
||||||
|
void focusOutEvent(QFocusEvent* event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void screenLayoutChange();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onOpenFile();
|
||||||
|
void onClickRecentFile();
|
||||||
|
void onClearRecentFiles();
|
||||||
|
void onBootFirmware();
|
||||||
|
void onInsertCart();
|
||||||
|
void onEjectCart();
|
||||||
|
void onInsertGBACart();
|
||||||
|
void onInsertGBAAddon();
|
||||||
|
void onEjectGBACart();
|
||||||
|
void onSaveState();
|
||||||
|
void onLoadState();
|
||||||
|
void onUndoStateLoad();
|
||||||
|
void onImportSavefile();
|
||||||
|
void onQuit();
|
||||||
|
|
||||||
|
void onPause(bool checked);
|
||||||
|
void onReset();
|
||||||
|
void onStop();
|
||||||
|
void onFrameStep();
|
||||||
|
void onOpenPowerManagement();
|
||||||
|
void onOpenDateTime();
|
||||||
|
void onEnableCheats(bool checked);
|
||||||
|
void onSetupCheats();
|
||||||
|
void onCheatsDialogFinished(int res);
|
||||||
|
void onROMInfo();
|
||||||
|
void onRAMInfo();
|
||||||
|
void onOpenTitleManager();
|
||||||
|
void onMPNewInstance();
|
||||||
|
|
||||||
|
void onOpenEmuSettings();
|
||||||
|
void onEmuSettingsDialogFinished(int res);
|
||||||
|
void onOpenInputConfig();
|
||||||
|
void onInputConfigFinished(int res);
|
||||||
|
void onOpenVideoSettings();
|
||||||
|
void onOpenCameraSettings();
|
||||||
|
void onCameraSettingsFinished(int res);
|
||||||
|
void onOpenAudioSettings();
|
||||||
|
void onUpdateAudioSettings();
|
||||||
|
void onAudioSettingsFinished(int res);
|
||||||
|
void onOpenMPSettings();
|
||||||
|
void onMPSettingsFinished(int res);
|
||||||
|
void onOpenWifiSettings();
|
||||||
|
void onWifiSettingsFinished(int res);
|
||||||
|
void onOpenFirmwareSettings();
|
||||||
|
void onFirmwareSettingsFinished(int res);
|
||||||
|
void onOpenPathSettings();
|
||||||
|
void onPathSettingsFinished(int res);
|
||||||
|
void onOpenInterfaceSettings();
|
||||||
|
void onInterfaceSettingsFinished(int res);
|
||||||
|
void onUpdateMouseTimer();
|
||||||
|
void onChangeSavestateSRAMReloc(bool checked);
|
||||||
|
void onChangeScreenSize();
|
||||||
|
void onChangeScreenRotation(QAction* act);
|
||||||
|
void onChangeScreenGap(QAction* act);
|
||||||
|
void onChangeScreenLayout(QAction* act);
|
||||||
|
void onChangeScreenSwap(bool checked);
|
||||||
|
void onChangeScreenSizing(QAction* act);
|
||||||
|
void onChangeScreenAspect(QAction* act);
|
||||||
|
void onChangeIntegerScaling(bool checked);
|
||||||
|
void onChangeScreenFiltering(bool checked);
|
||||||
|
void onChangeShowOSD(bool checked);
|
||||||
|
void onChangeLimitFramerate(bool checked);
|
||||||
|
void onChangeAudioSync(bool checked);
|
||||||
|
|
||||||
|
void onTitleUpdate(QString title);
|
||||||
|
|
||||||
|
void onEmuStart();
|
||||||
|
void onEmuStop();
|
||||||
|
|
||||||
|
void onUpdateVideoSettings(bool glchange);
|
||||||
|
|
||||||
|
void onFullscreenToggled();
|
||||||
|
void onScreenEmphasisToggled();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void closeEvent(QCloseEvent* event) override;
|
||||||
|
|
||||||
|
QStringList currentROM;
|
||||||
|
QStringList currentGBAROM;
|
||||||
|
QList<QString> recentFileList;
|
||||||
|
QMenu *recentMenu;
|
||||||
|
void updateRecentFilesMenu();
|
||||||
|
|
||||||
|
bool verifySetup();
|
||||||
|
QString pickFileFromArchive(QString archiveFileName);
|
||||||
|
QStringList pickROM(bool gba);
|
||||||
|
void updateCartInserted(bool gba);
|
||||||
|
|
||||||
|
void createScreenPanel();
|
||||||
|
|
||||||
|
bool pausedManually = false;
|
||||||
|
|
||||||
|
int oldW, oldH;
|
||||||
|
bool oldMax;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScreenHandler* panel;
|
||||||
|
QWidget* panelWidget;
|
||||||
|
|
||||||
|
QAction* actOpenROM;
|
||||||
|
QAction* actBootFirmware;
|
||||||
|
QAction* actCurrentCart;
|
||||||
|
QAction* actInsertCart;
|
||||||
|
QAction* actEjectCart;
|
||||||
|
QAction* actCurrentGBACart;
|
||||||
|
QAction* actInsertGBACart;
|
||||||
|
QAction* actInsertGBAAddon[1];
|
||||||
|
QAction* actEjectGBACart;
|
||||||
|
QAction* actImportSavefile;
|
||||||
|
QAction* actSaveState[9];
|
||||||
|
QAction* actLoadState[9];
|
||||||
|
QAction* actUndoStateLoad;
|
||||||
|
QAction* actQuit;
|
||||||
|
|
||||||
|
QAction* actPause;
|
||||||
|
QAction* actReset;
|
||||||
|
QAction* actStop;
|
||||||
|
QAction* actFrameStep;
|
||||||
|
QAction* actPowerManagement;
|
||||||
|
QAction* actDateTime;
|
||||||
|
QAction* actEnableCheats;
|
||||||
|
QAction* actSetupCheats;
|
||||||
|
QAction* actROMInfo;
|
||||||
|
QAction* actRAMInfo;
|
||||||
|
QAction* actTitleManager;
|
||||||
|
QAction* actMPNewInstance;
|
||||||
|
|
||||||
|
QAction* actEmuSettings;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
QAction* actPreferences;
|
||||||
|
#endif
|
||||||
|
QAction* actInputConfig;
|
||||||
|
QAction* actVideoSettings;
|
||||||
|
QAction* actCameraSettings;
|
||||||
|
QAction* actAudioSettings;
|
||||||
|
QAction* actMPSettings;
|
||||||
|
QAction* actWifiSettings;
|
||||||
|
QAction* actFirmwareSettings;
|
||||||
|
QAction* actPathSettings;
|
||||||
|
QAction* actInterfaceSettings;
|
||||||
|
QAction* actSavestateSRAMReloc;
|
||||||
|
QAction* actScreenSize[4];
|
||||||
|
QActionGroup* grpScreenRotation;
|
||||||
|
QAction* actScreenRotation[Frontend::screenRot_MAX];
|
||||||
|
QActionGroup* grpScreenGap;
|
||||||
|
QAction* actScreenGap[6];
|
||||||
|
QActionGroup* grpScreenLayout;
|
||||||
|
QAction* actScreenLayout[Frontend::screenLayout_MAX];
|
||||||
|
QAction* actScreenSwap;
|
||||||
|
QActionGroup* grpScreenSizing;
|
||||||
|
QAction* actScreenSizing[Frontend::screenSizing_MAX];
|
||||||
|
QAction* actIntegerScaling;
|
||||||
|
QActionGroup* grpScreenAspectTop;
|
||||||
|
QAction** actScreenAspectTop;
|
||||||
|
QActionGroup* grpScreenAspectBot;
|
||||||
|
QAction** actScreenAspectBot;
|
||||||
|
QAction* actScreenFiltering;
|
||||||
|
QAction* actShowOSD;
|
||||||
|
QAction* actLimitFramerate;
|
||||||
|
QAction* actAudioSync;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ToggleFullscreen(MainWindow* mainWindow);
|
||||||
|
|
||||||
|
#endif // WINDOW_H
|
File diff suppressed because it is too large
Load Diff
@ -37,6 +37,7 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
#include "FrontendUtil.h"
|
#include "FrontendUtil.h"
|
||||||
#include "duckstation/gl/context.h"
|
#include "duckstation/gl/context.h"
|
||||||
|
|
||||||
@ -156,110 +157,6 @@ private:
|
|||||||
int lastScreenWidth = -1, lastScreenHeight = -1;
|
int lastScreenWidth = -1, lastScreenHeight = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ScreenHandler
|
|
||||||
{
|
|
||||||
Q_GADGET
|
|
||||||
|
|
||||||
public:
|
|
||||||
ScreenHandler(QWidget* widget);
|
|
||||||
virtual ~ScreenHandler();
|
|
||||||
QTimer* setupMouseTimer();
|
|
||||||
void updateMouseTimer();
|
|
||||||
QTimer* mouseTimer;
|
|
||||||
QSize screenGetMinSize(int factor);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void screenSetupLayout(int w, int h);
|
|
||||||
|
|
||||||
void screenOnMousePress(QMouseEvent* event);
|
|
||||||
void screenOnMouseRelease(QMouseEvent* event);
|
|
||||||
void screenOnMouseMove(QMouseEvent* event);
|
|
||||||
|
|
||||||
void screenHandleTablet(QTabletEvent* event);
|
|
||||||
void screenHandleTouch(QTouchEvent* event);
|
|
||||||
|
|
||||||
float screenMatrix[Frontend::MaxScreenTransforms][6];
|
|
||||||
int screenKind[Frontend::MaxScreenTransforms];
|
|
||||||
int numScreens;
|
|
||||||
|
|
||||||
bool touching = false;
|
|
||||||
|
|
||||||
void showCursor();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ScreenPanelNative : public QWidget, public ScreenHandler
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ScreenPanelNative(QWidget* parent);
|
|
||||||
virtual ~ScreenPanelNative();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent* event) override;
|
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent* event) override;
|
|
||||||
|
|
||||||
void tabletEvent(QTabletEvent* event) override;
|
|
||||||
bool event(QEvent* event) override;
|
|
||||||
private slots:
|
|
||||||
void onScreenLayoutChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setupScreenLayout();
|
|
||||||
|
|
||||||
QImage screen[2];
|
|
||||||
QTransform screenTrans[Frontend::MaxScreenTransforms];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ScreenPanelGL : public QWidget, public ScreenHandler
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ScreenPanelGL(QWidget* parent);
|
|
||||||
virtual ~ScreenPanelGL();
|
|
||||||
|
|
||||||
std::optional<WindowInfo> getWindowInfo();
|
|
||||||
|
|
||||||
bool createContext();
|
|
||||||
|
|
||||||
GL::Context* getContext() { return glContext.get(); }
|
|
||||||
|
|
||||||
void transferLayout(EmuThread* thread);
|
|
||||||
protected:
|
|
||||||
|
|
||||||
qreal devicePixelRatioFromScreen() const;
|
|
||||||
int scaledWindowWidth() const;
|
|
||||||
int scaledWindowHeight() const;
|
|
||||||
|
|
||||||
QPaintEngine* paintEngine() const override;
|
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent* event) override;
|
|
||||||
|
|
||||||
void tabletEvent(QTabletEvent* event) override;
|
|
||||||
bool event(QEvent* event) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onScreenLayoutChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setupScreenLayout();
|
|
||||||
|
|
||||||
std::unique_ptr<GL::Context> glContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MelonApplication : public QApplication
|
class MelonApplication : public QApplication
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -269,199 +166,4 @@ public:
|
|||||||
bool event(QEvent* event) override;
|
bool event(QEvent* event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MainWindow(QWidget* parent = nullptr);
|
|
||||||
~MainWindow();
|
|
||||||
|
|
||||||
bool hasOGL;
|
|
||||||
GL::Context* getOGLContext();
|
|
||||||
|
|
||||||
bool preloadROMs(QStringList file, QStringList gbafile, bool boot);
|
|
||||||
QStringList splitArchivePath(const QString& filename, bool useMemberSyntax);
|
|
||||||
|
|
||||||
void onAppStateChanged(Qt::ApplicationState state);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
|
||||||
void changeEvent(QEvent* event) override;
|
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent* event) override;
|
|
||||||
void keyReleaseEvent(QKeyEvent* event) override;
|
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
|
||||||
void dropEvent(QDropEvent* event) override;
|
|
||||||
|
|
||||||
void focusInEvent(QFocusEvent* event) override;
|
|
||||||
void focusOutEvent(QFocusEvent* event) override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void screenLayoutChange();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onOpenFile();
|
|
||||||
void onClickRecentFile();
|
|
||||||
void onClearRecentFiles();
|
|
||||||
void onBootFirmware();
|
|
||||||
void onInsertCart();
|
|
||||||
void onEjectCart();
|
|
||||||
void onInsertGBACart();
|
|
||||||
void onInsertGBAAddon();
|
|
||||||
void onEjectGBACart();
|
|
||||||
void onSaveState();
|
|
||||||
void onLoadState();
|
|
||||||
void onUndoStateLoad();
|
|
||||||
void onImportSavefile();
|
|
||||||
void onQuit();
|
|
||||||
|
|
||||||
void onPause(bool checked);
|
|
||||||
void onReset();
|
|
||||||
void onStop();
|
|
||||||
void onFrameStep();
|
|
||||||
void onOpenPowerManagement();
|
|
||||||
void onOpenDateTime();
|
|
||||||
void onEnableCheats(bool checked);
|
|
||||||
void onSetupCheats();
|
|
||||||
void onCheatsDialogFinished(int res);
|
|
||||||
void onROMInfo();
|
|
||||||
void onRAMInfo();
|
|
||||||
void onOpenTitleManager();
|
|
||||||
void onMPNewInstance();
|
|
||||||
|
|
||||||
void onOpenEmuSettings();
|
|
||||||
void onEmuSettingsDialogFinished(int res);
|
|
||||||
void onOpenInputConfig();
|
|
||||||
void onInputConfigFinished(int res);
|
|
||||||
void onOpenVideoSettings();
|
|
||||||
void onOpenCameraSettings();
|
|
||||||
void onCameraSettingsFinished(int res);
|
|
||||||
void onOpenAudioSettings();
|
|
||||||
void onUpdateAudioSettings();
|
|
||||||
void onAudioSettingsFinished(int res);
|
|
||||||
void onOpenMPSettings();
|
|
||||||
void onMPSettingsFinished(int res);
|
|
||||||
void onOpenWifiSettings();
|
|
||||||
void onWifiSettingsFinished(int res);
|
|
||||||
void onOpenFirmwareSettings();
|
|
||||||
void onFirmwareSettingsFinished(int res);
|
|
||||||
void onOpenPathSettings();
|
|
||||||
void onPathSettingsFinished(int res);
|
|
||||||
void onOpenInterfaceSettings();
|
|
||||||
void onInterfaceSettingsFinished(int res);
|
|
||||||
void onUpdateMouseTimer();
|
|
||||||
void onChangeSavestateSRAMReloc(bool checked);
|
|
||||||
void onChangeScreenSize();
|
|
||||||
void onChangeScreenRotation(QAction* act);
|
|
||||||
void onChangeScreenGap(QAction* act);
|
|
||||||
void onChangeScreenLayout(QAction* act);
|
|
||||||
void onChangeScreenSwap(bool checked);
|
|
||||||
void onChangeScreenSizing(QAction* act);
|
|
||||||
void onChangeScreenAspect(QAction* act);
|
|
||||||
void onChangeIntegerScaling(bool checked);
|
|
||||||
void onChangeScreenFiltering(bool checked);
|
|
||||||
void onChangeShowOSD(bool checked);
|
|
||||||
void onChangeLimitFramerate(bool checked);
|
|
||||||
void onChangeAudioSync(bool checked);
|
|
||||||
|
|
||||||
void onTitleUpdate(QString title);
|
|
||||||
|
|
||||||
void onEmuStart();
|
|
||||||
void onEmuStop();
|
|
||||||
|
|
||||||
void onUpdateVideoSettings(bool glchange);
|
|
||||||
|
|
||||||
void onFullscreenToggled();
|
|
||||||
void onScreenEmphasisToggled();
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void closeEvent(QCloseEvent* event) override;
|
|
||||||
|
|
||||||
QStringList currentROM;
|
|
||||||
QStringList currentGBAROM;
|
|
||||||
QList<QString> recentFileList;
|
|
||||||
QMenu *recentMenu;
|
|
||||||
void updateRecentFilesMenu();
|
|
||||||
|
|
||||||
bool verifySetup();
|
|
||||||
QString pickFileFromArchive(QString archiveFileName);
|
|
||||||
QStringList pickROM(bool gba);
|
|
||||||
void updateCartInserted(bool gba);
|
|
||||||
|
|
||||||
void createScreenPanel();
|
|
||||||
|
|
||||||
bool pausedManually = false;
|
|
||||||
|
|
||||||
int oldW, oldH;
|
|
||||||
bool oldMax;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ScreenHandler* panel;
|
|
||||||
QWidget* panelWidget;
|
|
||||||
|
|
||||||
QAction* actOpenROM;
|
|
||||||
QAction* actBootFirmware;
|
|
||||||
QAction* actCurrentCart;
|
|
||||||
QAction* actInsertCart;
|
|
||||||
QAction* actEjectCart;
|
|
||||||
QAction* actCurrentGBACart;
|
|
||||||
QAction* actInsertGBACart;
|
|
||||||
QAction* actInsertGBAAddon[1];
|
|
||||||
QAction* actEjectGBACart;
|
|
||||||
QAction* actImportSavefile;
|
|
||||||
QAction* actSaveState[9];
|
|
||||||
QAction* actLoadState[9];
|
|
||||||
QAction* actUndoStateLoad;
|
|
||||||
QAction* actQuit;
|
|
||||||
|
|
||||||
QAction* actPause;
|
|
||||||
QAction* actReset;
|
|
||||||
QAction* actStop;
|
|
||||||
QAction* actFrameStep;
|
|
||||||
QAction* actPowerManagement;
|
|
||||||
QAction* actDateTime;
|
|
||||||
QAction* actEnableCheats;
|
|
||||||
QAction* actSetupCheats;
|
|
||||||
QAction* actROMInfo;
|
|
||||||
QAction* actRAMInfo;
|
|
||||||
QAction* actTitleManager;
|
|
||||||
QAction* actMPNewInstance;
|
|
||||||
|
|
||||||
QAction* actEmuSettings;
|
|
||||||
#ifdef __APPLE__
|
|
||||||
QAction* actPreferences;
|
|
||||||
#endif
|
|
||||||
QAction* actInputConfig;
|
|
||||||
QAction* actVideoSettings;
|
|
||||||
QAction* actCameraSettings;
|
|
||||||
QAction* actAudioSettings;
|
|
||||||
QAction* actMPSettings;
|
|
||||||
QAction* actWifiSettings;
|
|
||||||
QAction* actFirmwareSettings;
|
|
||||||
QAction* actPathSettings;
|
|
||||||
QAction* actInterfaceSettings;
|
|
||||||
QAction* actSavestateSRAMReloc;
|
|
||||||
QAction* actScreenSize[4];
|
|
||||||
QActionGroup* grpScreenRotation;
|
|
||||||
QAction* actScreenRotation[Frontend::screenRot_MAX];
|
|
||||||
QActionGroup* grpScreenGap;
|
|
||||||
QAction* actScreenGap[6];
|
|
||||||
QActionGroup* grpScreenLayout;
|
|
||||||
QAction* actScreenLayout[Frontend::screenLayout_MAX];
|
|
||||||
QAction* actScreenSwap;
|
|
||||||
QActionGroup* grpScreenSizing;
|
|
||||||
QAction* actScreenSizing[Frontend::screenSizing_MAX];
|
|
||||||
QAction* actIntegerScaling;
|
|
||||||
QActionGroup* grpScreenAspectTop;
|
|
||||||
QAction** actScreenAspectTop;
|
|
||||||
QActionGroup* grpScreenAspectBot;
|
|
||||||
QAction** actScreenAspectBot;
|
|
||||||
QAction* actScreenFiltering;
|
|
||||||
QAction* actShowOSD;
|
|
||||||
QAction* actLimitFramerate;
|
|
||||||
QAction* actAudioSync;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MAIN_H
|
#endif // MAIN_H
|
||||||
|
18
vcpkg.json
Normal file
18
vcpkg.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"dependencies": [
|
||||||
|
"sdl2",
|
||||||
|
"libarchive",
|
||||||
|
"libslirp",
|
||||||
|
"zstd",
|
||||||
|
{
|
||||||
|
"name": "qtbase",
|
||||||
|
"default-features": false,
|
||||||
|
"features": ["gui", "png", "thread", "widgets", "opengl", "zstd"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtmultimedia",
|
||||||
|
"default-features": false
|
||||||
|
},
|
||||||
|
"qtsvg"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user