mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 05:17:40 -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)
|
||||
if (POLICY CMP0076)
|
||||
@ -9,6 +9,11 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||
|
||||
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
|
||||
VERSION 0.9.5
|
||||
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;
|
||||
break;
|
||||
case 128*1024:
|
||||
case (128*1024 + 0x10): // .sav file with appended real time clock data (ex: emulator mGBA)
|
||||
SRAMType = S_FLASH1M;
|
||||
break;
|
||||
case 0:
|
||||
|
@ -5,6 +5,8 @@ include(FixInterfaceIncludes)
|
||||
set(SOURCES_QT_SDL
|
||||
main.cpp
|
||||
main_shaders.h
|
||||
Screen.cpp
|
||||
Window.cpp
|
||||
CheatsDialog.cpp
|
||||
Config.cpp
|
||||
DateTimeDialog.cpp
|
||||
@ -38,7 +40,7 @@ set(SOURCES_QT_SDL
|
||||
SaveManager.cpp
|
||||
CameraManager.cpp
|
||||
AudioInOut.cpp
|
||||
|
||||
|
||||
ArchiveUtil.h
|
||||
ArchiveUtil.cpp
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Input
|
||||
|
@ -248,7 +248,9 @@ bool Init()
|
||||
Log(LogLevel::Info, "MP sharedmem doesn't exist. creating\n");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -328,6 +330,7 @@ void SetRecvTimeout(int timeout)
|
||||
|
||||
void Begin()
|
||||
{
|
||||
if (!MPQueue) return;
|
||||
MPQueue->lock();
|
||||
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
||||
PacketReadOffset = header->PacketWriteOffset;
|
||||
@ -340,6 +343,7 @@ void Begin()
|
||||
|
||||
void End()
|
||||
{
|
||||
if (!MPQueue) return;
|
||||
MPQueue->lock();
|
||||
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
||||
//SemReset(InstanceID);
|
||||
@ -421,6 +425,7 @@ void FIFOWrite(int fifo, void* buf, int len)
|
||||
|
||||
int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
||||
{
|
||||
if (!MPQueue) return 0;
|
||||
MPQueue->lock();
|
||||
u8* data = (u8*)MPQueue->data();
|
||||
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)
|
||||
{
|
||||
if (!MPQueue) return 0;
|
||||
for (;;)
|
||||
{
|
||||
if (!SemWait(InstanceID, block ? RecvTimeout : 0))
|
||||
@ -552,6 +558,8 @@ int SendAck(u8* packet, int len, u64 timestamp)
|
||||
|
||||
int RecvHostPacket(u8* packet, u64* timestamp)
|
||||
{
|
||||
if (!MPQueue) return -1;
|
||||
|
||||
if (LastHostID != -1)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (!MPQueue) return 0;
|
||||
|
||||
u16 ret = 0;
|
||||
u16 myinstmask = (1 << InstanceID);
|
||||
u16 curinstmask;
|
||||
|
@ -66,12 +66,25 @@ void IPCInit()
|
||||
|
||||
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())
|
||||
{
|
||||
Log(LogLevel::Info, "IPC sharedmem doesn't exist. creating\n");
|
||||
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;
|
||||
IPCBuffer = nullptr;
|
||||
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 <optional>
|
||||
|
||||
#include "Window.h"
|
||||
#include "FrontendUtil.h"
|
||||
#include "duckstation/gl/context.h"
|
||||
|
||||
@ -156,110 +157,6 @@ private:
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -269,199 +166,4 @@ public:
|
||||
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
|
||||
|
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