a bit of frontend refactoring
This commit is contained in:
parent
8fd46e5f8c
commit
3efbf1b813
|
@ -1,99 +1,119 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2022 melonDS team
|
Copyright 2016-2022 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
melonDS is free software: you can redistribute it and/or modify it under
|
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
|
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)
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
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
|
You should have received a copy of the GNU General Public License along
|
||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FRONTENDUTIL_H
|
#ifndef FRONTENDUTIL_H
|
||||||
#define FRONTENDUTIL_H
|
#define FRONTENDUTIL_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Frontend
|
namespace Frontend
|
||||||
{
|
{
|
||||||
|
|
||||||
// setup the display layout based on the provided display size and parameters
|
enum ScreenLayout
|
||||||
// * screenWidth/screenHeight: size of the host display
|
{
|
||||||
// * screenLayout: how the DS screens are laid out
|
screenLayout_Natural, // top screen above bottom screen always
|
||||||
// 0 = natural (top screen above bottom screen always)
|
screenLayout_Horizontal,
|
||||||
// 1 = vertical
|
screenLayout_Vertical,
|
||||||
// 2 = horizontal
|
screenLayout_Hybrid,
|
||||||
// 3 = hybrid
|
screenLayout_MAX,
|
||||||
// * rotation: angle at which the DS screens are presented: 0/1/2/3 = 0/90/180/270
|
};
|
||||||
// * sizing: how the display size is shared between the two screens
|
|
||||||
// 0 = even (both screens get same size)
|
enum ScreenRotation
|
||||||
// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
|
{
|
||||||
// 2 = emphasize bottom screen
|
screenRot_0Deg,
|
||||||
// 4 = top only
|
screenRot_90Deg,
|
||||||
// 5 = bottom only
|
screenRot_180Deg,
|
||||||
// * screenGap: size of the gap between the two screens
|
screenRot_270Deg,
|
||||||
// * integerScale: force screens to be scaled up at integer scaling factors
|
screenRot_MAX,
|
||||||
// * screenSwap: whether to swap the position of both screens
|
};
|
||||||
// * topAspect/botAspect: ratio by which to scale the top and bottom screen respectively
|
|
||||||
void SetupScreenLayout(int screenWidth, int screenHeight,
|
enum ScreenSizing
|
||||||
int screenLayout,
|
{
|
||||||
int rotation,
|
screenSizing_Even, // both screens get same size
|
||||||
int sizing,
|
screenSizing_EmphTop, // make top screen as big as possible, fit bottom screen in remaining space
|
||||||
int screenGap,
|
screenSizing_EmphBot,
|
||||||
bool integerScale,
|
screenSizing_Auto, // not applied in SetupScreenLayout
|
||||||
bool swapScreens,
|
screenSizing_TopOnly,
|
||||||
float topAspect, float botAspect);
|
screenSizing_BotOnly,
|
||||||
|
screenSizing_MAX,
|
||||||
const int MaxScreenTransforms = 3;
|
};
|
||||||
|
|
||||||
// get a 2x3 transform matrix for each screen and whether it's a top or bottom screen
|
// setup the display layout based on the provided display size and parameters
|
||||||
// note: the transform assumes an origin point at the top left of the display,
|
// * screenWidth/screenHeight: size of the host display
|
||||||
// X going right and Y going down
|
// * screenLayout: how the DS screens are laid out
|
||||||
// for each screen the source coordinates should be (0,0) and (256,192)
|
// * rotation: angle at which the DS screens are presented
|
||||||
// 'out' should point to an array of 6*MaxScreenTransforms floats
|
// * sizing: how the display size is shared between the two screens
|
||||||
// 'kind' should point to an array of MaxScreenTransforms ints
|
// * screenGap: size of the gap between the two screens in pixels
|
||||||
// (0 = indicates top screen, 1 = bottom screen)
|
// * integerScale: force screens to be scaled up at integer scaling factors
|
||||||
// returns the amount of screens
|
// * screenSwap: whether to swap the position of both screens
|
||||||
int GetScreenTransforms(float* out, int* kind);
|
// * topAspect/botAspect: ratio by which to scale the top and bottom screen respectively
|
||||||
|
void SetupScreenLayout(int screenWidth, int screenHeight,
|
||||||
// de-transform the provided host display coordinates to get coordinates
|
ScreenLayout screenLayout,
|
||||||
// on the bottom screen
|
ScreenRotation rotation,
|
||||||
bool GetTouchCoords(int& x, int& y, bool clamp);
|
ScreenSizing sizing,
|
||||||
|
int screenGap,
|
||||||
|
bool integerScale,
|
||||||
// initialize the audio utility
|
bool swapScreens,
|
||||||
void Init_Audio(int outputfreq);
|
float topAspect, float botAspect);
|
||||||
|
|
||||||
// get how many samples to read from the core audio output
|
const int MaxScreenTransforms = 3;
|
||||||
// based on how many are needed by the frontend (outlen in samples)
|
|
||||||
int AudioOut_GetNumSamples(int outlen);
|
// get a 2x3 transform matrix for each screen and whether it's a top or bottom screen
|
||||||
|
// note: the transform assumes an origin point at the top left of the display,
|
||||||
// resample audio from the core audio output to match the frontend's
|
// X going right and Y going down
|
||||||
// output frequency, and apply specified volume
|
// for each screen the source coordinates should be (0,0) and (256,192)
|
||||||
// note: this assumes the output buffer is interleaved stereo
|
// 'out' should point to an array of 6*MaxScreenTransforms floats
|
||||||
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume);
|
// 'kind' should point to an array of MaxScreenTransforms ints
|
||||||
|
// (0 = indicates top screen, 1 = bottom screen)
|
||||||
// feed silence to the microphone input
|
// returns the amount of screens
|
||||||
void Mic_FeedSilence();
|
int GetScreenTransforms(float* out, int* kind);
|
||||||
|
|
||||||
// feed random noise to the microphone input
|
// de-transform the provided host display coordinates to get coordinates
|
||||||
void Mic_FeedNoise();
|
// on the bottom screen
|
||||||
|
bool GetTouchCoords(int& x, int& y, bool clamp);
|
||||||
// feed an external buffer to the microphone input
|
|
||||||
// buffer should be mono
|
|
||||||
void Mic_FeedExternalBuffer();
|
// initialize the audio utility
|
||||||
void Mic_SetExternalBuffer(s16* buffer, u32 len);
|
void Init_Audio(int outputfreq);
|
||||||
|
|
||||||
}
|
// get how many samples to read from the core audio output
|
||||||
|
// based on how many are needed by the frontend (outlen in samples)
|
||||||
#endif // FRONTENDUTIL_H
|
int AudioOut_GetNumSamples(int outlen);
|
||||||
|
|
||||||
|
// resample audio from the core audio output to match the frontend's
|
||||||
|
// output frequency, and apply specified volume
|
||||||
|
// note: this assumes the output buffer is interleaved stereo
|
||||||
|
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume);
|
||||||
|
|
||||||
|
// feed silence to the microphone input
|
||||||
|
void Mic_FeedSilence();
|
||||||
|
|
||||||
|
// feed random noise to the microphone input
|
||||||
|
void Mic_FeedNoise();
|
||||||
|
|
||||||
|
// feed an external buffer to the microphone input
|
||||||
|
// buffer should be mono
|
||||||
|
void Mic_FeedExternalBuffer();
|
||||||
|
void Mic_SetExternalBuffer(s16* buffer, u32 len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FRONTENDUTIL_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,17 +42,6 @@ enum
|
||||||
HK_MAX
|
HK_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
screenSizing_Even,
|
|
||||||
screenSizing_EmphTop,
|
|
||||||
screenSizing_EmphBot,
|
|
||||||
screenSizing_Auto,
|
|
||||||
screenSizing_TopOnly,
|
|
||||||
screenSizing_BotOnly,
|
|
||||||
screenSizing_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
micInputType_Silence,
|
micInputType_Silence,
|
||||||
|
|
|
@ -174,13 +174,14 @@ const struct { int id; float ratio; const char* label; } aspectRatios[] =
|
||||||
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
|
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
|
||||||
{ 3, 0, "window" }
|
{ 3, 0, "window" }
|
||||||
};
|
};
|
||||||
|
constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);
|
||||||
|
|
||||||
|
|
||||||
EmuThread::EmuThread(QObject* parent) : QThread(parent)
|
EmuThread::EmuThread(QObject* parent) : QThread(parent)
|
||||||
{
|
{
|
||||||
EmuStatus = 0;
|
EmuStatus = emuStatus_Exit;
|
||||||
EmuRunning = 2;
|
EmuRunning = emuStatus_Paused;
|
||||||
EmuPause = 0;
|
EmuPauseStack = EmuPauseStackRunning;
|
||||||
RunningSomething = false;
|
RunningSomething = false;
|
||||||
|
|
||||||
connect(this, SIGNAL(windowUpdate()), mainWindow->panelWidget, SLOT(repaint()));
|
connect(this, SIGNAL(windowUpdate()), mainWindow->panelWidget, SLOT(repaint()));
|
||||||
|
@ -353,7 +354,7 @@ void EmuThread::run()
|
||||||
|
|
||||||
char melontitle[100];
|
char melontitle[100];
|
||||||
|
|
||||||
while (EmuRunning != 0)
|
while (EmuRunning != emuStatus_Exit)
|
||||||
{
|
{
|
||||||
Input::Process();
|
Input::Process();
|
||||||
|
|
||||||
|
@ -425,10 +426,10 @@ void EmuThread::run()
|
||||||
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
|
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EmuRunning == 1 || EmuRunning == 3)
|
if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
|
||||||
{
|
{
|
||||||
EmuStatus = 1;
|
EmuStatus = emuStatus_Running;
|
||||||
if (EmuRunning == 3) EmuRunning = 2;
|
if (EmuRunning == emuStatus_FrameStep) EmuRunning = emuStatus_Paused;
|
||||||
|
|
||||||
// update render settings if needed
|
// update render settings if needed
|
||||||
// HACK:
|
// HACK:
|
||||||
|
@ -473,7 +474,7 @@ void EmuThread::run()
|
||||||
AudioInOut::MicProcess();
|
AudioInOut::MicProcess();
|
||||||
|
|
||||||
// auto screen layout
|
// auto screen layout
|
||||||
if (Config::ScreenSizing == screenSizing_Auto)
|
if (Config::ScreenSizing == Frontend::screenSizing_Auto)
|
||||||
{
|
{
|
||||||
mainScreenPos[2] = mainScreenPos[1];
|
mainScreenPos[2] = mainScreenPos[1];
|
||||||
mainScreenPos[1] = mainScreenPos[0];
|
mainScreenPos[1] = mainScreenPos[0];
|
||||||
|
@ -485,14 +486,14 @@ void EmuThread::run()
|
||||||
{
|
{
|
||||||
// constant flickering, likely displaying 3D on both screens
|
// constant flickering, likely displaying 3D on both screens
|
||||||
// TODO: when both screens are used for 2D only...???
|
// TODO: when both screens are used for 2D only...???
|
||||||
guess = screenSizing_Even;
|
guess = Frontend::screenSizing_Even;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mainScreenPos[0] == 1)
|
if (mainScreenPos[0] == 1)
|
||||||
guess = screenSizing_EmphTop;
|
guess = Frontend::screenSizing_EmphTop;
|
||||||
else
|
else
|
||||||
guess = screenSizing_EmphBot;
|
guess = Frontend::screenSizing_EmphBot;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guess != autoScreenSizing)
|
if (guess != autoScreenSizing)
|
||||||
|
@ -528,7 +529,7 @@ void EmuThread::run()
|
||||||
MelonCap::Update();
|
MelonCap::Update();
|
||||||
#endif // MELONCAP
|
#endif // MELONCAP
|
||||||
|
|
||||||
if (EmuRunning == 0) break;
|
if (EmuRunning == emuStatus_Exit) break;
|
||||||
|
|
||||||
winUpdateCount++;
|
winUpdateCount++;
|
||||||
if (winUpdateCount >= winUpdateFreq && !oglContext)
|
if (winUpdateCount >= winUpdateFreq && !oglContext)
|
||||||
|
@ -632,21 +633,21 @@ void EmuThread::run()
|
||||||
if (oglContext)
|
if (oglContext)
|
||||||
drawScreenGL();
|
drawScreenGL();
|
||||||
|
|
||||||
int contextRequest = ContextRequest;
|
ContextRequestKind contextRequest = ContextRequest;
|
||||||
if (contextRequest == 1)
|
if (contextRequest == contextRequest_InitGL)
|
||||||
{
|
{
|
||||||
initOpenGL();
|
initOpenGL();
|
||||||
ContextRequest = 0;
|
ContextRequest = contextRequest_None;
|
||||||
}
|
}
|
||||||
else if (contextRequest == 2)
|
else if (contextRequest == contextRequest_DeInitGL)
|
||||||
{
|
{
|
||||||
deinitOpenGL();
|
deinitOpenGL();
|
||||||
ContextRequest = 0;
|
ContextRequest = contextRequest_None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuStatus = 0;
|
EmuStatus = emuStatus_Exit;
|
||||||
|
|
||||||
GPU::DeInitRenderer();
|
GPU::DeInitRenderer();
|
||||||
NDS::DeInit();
|
NDS::DeInit();
|
||||||
|
@ -660,8 +661,8 @@ void EmuThread::changeWindowTitle(char* title)
|
||||||
|
|
||||||
void EmuThread::emuRun()
|
void EmuThread::emuRun()
|
||||||
{
|
{
|
||||||
EmuRunning = 1;
|
EmuRunning = emuStatus_Running;
|
||||||
EmuPause = 0;
|
EmuPauseStack = EmuPauseStackRunning;
|
||||||
RunningSomething = true;
|
RunningSomething = true;
|
||||||
|
|
||||||
// checkme
|
// checkme
|
||||||
|
@ -671,34 +672,34 @@ void EmuThread::emuRun()
|
||||||
|
|
||||||
void EmuThread::initContext()
|
void EmuThread::initContext()
|
||||||
{
|
{
|
||||||
ContextRequest = 1;
|
ContextRequest = contextRequest_InitGL;
|
||||||
while (ContextRequest != 0);
|
while (ContextRequest != contextRequest_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::deinitContext()
|
void EmuThread::deinitContext()
|
||||||
{
|
{
|
||||||
ContextRequest = 2;
|
ContextRequest = contextRequest_DeInitGL;
|
||||||
while (ContextRequest != 0);
|
while (ContextRequest != contextRequest_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::emuPause()
|
void EmuThread::emuPause()
|
||||||
{
|
{
|
||||||
EmuPause++;
|
EmuPauseStack++;
|
||||||
if (EmuPause > 1) return;
|
if (EmuPauseStack > EmuPauseStackPauseThreshold) return;
|
||||||
|
|
||||||
PrevEmuStatus = EmuRunning;
|
PrevEmuStatus = EmuRunning;
|
||||||
EmuRunning = 2;
|
EmuRunning = emuStatus_Paused;
|
||||||
while (EmuStatus != 2);
|
while (EmuStatus != emuStatus_Paused);
|
||||||
|
|
||||||
AudioInOut::Disable();
|
AudioInOut::Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::emuUnpause()
|
void EmuThread::emuUnpause()
|
||||||
{
|
{
|
||||||
if (EmuPause < 1) return;
|
if (EmuPauseStack < EmuPauseStackPauseThreshold) return;
|
||||||
|
|
||||||
EmuPause--;
|
EmuPauseStack--;
|
||||||
if (EmuPause > 0) return;
|
if (EmuPauseStack >= EmuPauseStackPauseThreshold) return;
|
||||||
|
|
||||||
EmuRunning = PrevEmuStatus;
|
EmuRunning = PrevEmuStatus;
|
||||||
|
|
||||||
|
@ -707,21 +708,21 @@ void EmuThread::emuUnpause()
|
||||||
|
|
||||||
void EmuThread::emuStop()
|
void EmuThread::emuStop()
|
||||||
{
|
{
|
||||||
EmuRunning = 0;
|
EmuRunning = emuStatus_Exit;
|
||||||
EmuPause = 0;
|
EmuPauseStack = EmuPauseStackRunning;
|
||||||
|
|
||||||
AudioInOut::Disable();
|
AudioInOut::Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::emuFrameStep()
|
void EmuThread::emuFrameStep()
|
||||||
{
|
{
|
||||||
if (EmuPause < 1) emit windowEmuPause();
|
if (EmuPauseStack < EmuPauseStackPauseThreshold) emit windowEmuPause();
|
||||||
EmuRunning = 3;
|
EmuRunning = emuStatus_FrameStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuThread::emuIsRunning()
|
bool EmuThread::emuIsRunning()
|
||||||
{
|
{
|
||||||
return (EmuRunning == 1);
|
return EmuRunning == emuStatus_Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuThread::emuIsActive()
|
bool EmuThread::emuIsActive()
|
||||||
|
@ -830,9 +831,9 @@ void ScreenHandler::screenSetupLayout(int w, int h)
|
||||||
aspectBot = ((float) w / h) / (4.f / 3.f);
|
aspectBot = ((float) w / h) / (4.f / 3.f);
|
||||||
|
|
||||||
Frontend::SetupScreenLayout(w, h,
|
Frontend::SetupScreenLayout(w, h,
|
||||||
Config::ScreenLayout,
|
static_cast<Frontend::ScreenLayout>(Config::ScreenLayout),
|
||||||
Config::ScreenRotation,
|
static_cast<Frontend::ScreenRotation>(Config::ScreenRotation),
|
||||||
sizing,
|
static_cast<Frontend::ScreenSizing>(sizing),
|
||||||
Config::ScreenGap,
|
Config::ScreenGap,
|
||||||
Config::IntegerScaling != 0,
|
Config::IntegerScaling != 0,
|
||||||
Config::ScreenSwap != 0,
|
Config::ScreenSwap != 0,
|
||||||
|
@ -844,32 +845,34 @@ void ScreenHandler::screenSetupLayout(int w, int h)
|
||||||
|
|
||||||
QSize ScreenHandler::screenGetMinSize(int factor = 1)
|
QSize ScreenHandler::screenGetMinSize(int factor = 1)
|
||||||
{
|
{
|
||||||
bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3);
|
bool isHori = (Config::ScreenRotation == Frontend::screenRot_90Deg
|
||||||
|
|| Config::ScreenRotation == Frontend::screenRot_270Deg);
|
||||||
int gap = Config::ScreenGap * factor;
|
int gap = Config::ScreenGap * factor;
|
||||||
|
|
||||||
int w = 256 * factor;
|
int w = 256 * factor;
|
||||||
int h = 192 * factor;
|
int h = 192 * factor;
|
||||||
|
|
||||||
if (Config::ScreenSizing == 4 || Config::ScreenSizing == 5)
|
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly
|
||||||
|
|| Config::ScreenSizing == Frontend::screenSizing_BotOnly)
|
||||||
{
|
{
|
||||||
return QSize(w, h);
|
return QSize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config::ScreenLayout == 0) // natural
|
if (Config::ScreenLayout == Frontend::screenLayout_Natural)
|
||||||
{
|
{
|
||||||
if (isHori)
|
if (isHori)
|
||||||
return QSize(h+gap+h, w);
|
return QSize(h+gap+h, w);
|
||||||
else
|
else
|
||||||
return QSize(w, h+gap+h);
|
return QSize(w, h+gap+h);
|
||||||
}
|
}
|
||||||
else if (Config::ScreenLayout == 1) // vertical
|
else if (Config::ScreenLayout == Frontend::screenLayout_Vertical)
|
||||||
{
|
{
|
||||||
if (isHori)
|
if (isHori)
|
||||||
return QSize(h, w+gap+w);
|
return QSize(h, w+gap+w);
|
||||||
else
|
else
|
||||||
return QSize(w, h+gap+h);
|
return QSize(w, h+gap+h);
|
||||||
}
|
}
|
||||||
else if (Config::ScreenLayout == 2) // horizontal
|
else if (Config::ScreenLayout == Frontend::screenLayout_Horizontal)
|
||||||
{
|
{
|
||||||
if (isHori)
|
if (isHori)
|
||||||
return QSize(h+gap+h, w);
|
return QSize(h+gap+h, w);
|
||||||
|
@ -1610,7 +1613,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
QMenu* submenu = menu->addMenu("Screen rotation");
|
QMenu* submenu = menu->addMenu("Screen rotation");
|
||||||
grpScreenRotation = new QActionGroup(submenu);
|
grpScreenRotation = new QActionGroup(submenu);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < Frontend::screenRot_MAX; i++)
|
||||||
{
|
{
|
||||||
int data = i*90;
|
int data = i*90;
|
||||||
actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data));
|
actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data));
|
||||||
|
@ -1644,7 +1647,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
const char* screenlayout[] = {"Natural", "Vertical", "Horizontal", "Hybrid"};
|
const char* screenlayout[] = {"Natural", "Vertical", "Horizontal", "Hybrid"};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < Frontend::screenLayout_MAX; i++)
|
||||||
{
|
{
|
||||||
actScreenLayout[i] = submenu->addAction(QString(screenlayout[i]));
|
actScreenLayout[i] = submenu->addAction(QString(screenlayout[i]));
|
||||||
actScreenLayout[i]->setActionGroup(grpScreenLayout);
|
actScreenLayout[i]->setActionGroup(grpScreenLayout);
|
||||||
|
@ -1666,7 +1669,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
|
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
|
||||||
|
|
||||||
for (int i = 0; i < screenSizing_MAX; i++)
|
for (int i = 0; i < Frontend::screenSizing_MAX; i++)
|
||||||
{
|
{
|
||||||
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
|
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
|
||||||
actScreenSizing[i]->setActionGroup(grpScreenSizing);
|
actScreenSizing[i]->setActionGroup(grpScreenSizing);
|
||||||
|
@ -1686,8 +1689,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
QMenu* submenu = menu->addMenu("Aspect ratio");
|
QMenu* submenu = menu->addMenu("Aspect ratio");
|
||||||
grpScreenAspectTop = new QActionGroup(submenu);
|
grpScreenAspectTop = new QActionGroup(submenu);
|
||||||
grpScreenAspectBot = new QActionGroup(submenu);
|
grpScreenAspectBot = new QActionGroup(submenu);
|
||||||
actScreenAspectTop = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
|
actScreenAspectTop = new QAction*[AspectRatiosNum];
|
||||||
actScreenAspectBot = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
|
actScreenAspectBot = new QAction*[AspectRatiosNum];
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
@ -1701,7 +1704,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
actions = actScreenAspectBot;
|
actions = actScreenAspectBot;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < sizeof(aspectRatios) / sizeof(aspectRatios[0]); j++)
|
for (int j = 0; j < AspectRatiosNum; j++)
|
||||||
{
|
{
|
||||||
auto ratio = aspectRatios[j];
|
auto ratio = aspectRatios[j];
|
||||||
QString label = QString("%1 %2").arg(i ? "Bottom" : "Top", ratio.label);
|
QString label = QString("%1 %2").arg(i ? "Bottom" : "Top", ratio.label);
|
||||||
|
@ -1806,7 +1809,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
actScreenSwap->setChecked(Config::ScreenSwap);
|
actScreenSwap->setChecked(Config::ScreenSwap);
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(aspectRatios) / sizeof(aspectRatios[0]); i++)
|
for (int i = 0; i < AspectRatiosNum; i++)
|
||||||
{
|
{
|
||||||
if (Config::ScreenAspectTop == aspectRatios[i].id)
|
if (Config::ScreenAspectTop == aspectRatios[i].id)
|
||||||
actScreenAspectTop[i]->setChecked(true);
|
actScreenAspectTop[i]->setChecked(true);
|
||||||
|
@ -3011,18 +3014,18 @@ void MainWindow::onChangeScreenSwap(bool checked)
|
||||||
Config::ScreenSwap = checked?1:0;
|
Config::ScreenSwap = checked?1:0;
|
||||||
|
|
||||||
// Swap between top and bottom screen when displaying one screen.
|
// Swap between top and bottom screen when displaying one screen.
|
||||||
if (Config::ScreenSizing == screenSizing_TopOnly)
|
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly)
|
||||||
{
|
{
|
||||||
// Bottom Screen.
|
// Bottom Screen.
|
||||||
Config::ScreenSizing = screenSizing_BotOnly;
|
Config::ScreenSizing = Frontend::screenSizing_BotOnly;
|
||||||
actScreenSizing[screenSizing_TopOnly]->setChecked(false);
|
actScreenSizing[Frontend::screenSizing_TopOnly]->setChecked(false);
|
||||||
actScreenSizing[Config::ScreenSizing]->setChecked(true);
|
actScreenSizing[Config::ScreenSizing]->setChecked(true);
|
||||||
}
|
}
|
||||||
else if (Config::ScreenSizing == screenSizing_BotOnly)
|
else if (Config::ScreenSizing == Frontend::screenSizing_BotOnly)
|
||||||
{
|
{
|
||||||
// Top Screen.
|
// Top Screen.
|
||||||
Config::ScreenSizing = screenSizing_TopOnly;
|
Config::ScreenSizing = Frontend::screenSizing_TopOnly;
|
||||||
actScreenSizing[screenSizing_BotOnly]->setChecked(false);
|
actScreenSizing[Frontend::screenSizing_BotOnly]->setChecked(false);
|
||||||
actScreenSizing[Config::ScreenSizing]->setChecked(true);
|
actScreenSizing[Config::ScreenSizing]->setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3111,13 +3114,13 @@ void MainWindow::onFullscreenToggled()
|
||||||
void MainWindow::onScreenEmphasisToggled()
|
void MainWindow::onScreenEmphasisToggled()
|
||||||
{
|
{
|
||||||
int currentSizing = Config::ScreenSizing;
|
int currentSizing = Config::ScreenSizing;
|
||||||
if (currentSizing == screenSizing_EmphTop)
|
if (currentSizing == Frontend::screenSizing_EmphTop)
|
||||||
{
|
{
|
||||||
Config::ScreenSizing = screenSizing_EmphBot;
|
Config::ScreenSizing = Frontend::screenSizing_EmphBot;
|
||||||
}
|
}
|
||||||
else if (currentSizing == screenSizing_EmphBot)
|
else if (currentSizing == Frontend::screenSizing_EmphBot)
|
||||||
{
|
{
|
||||||
Config::ScreenSizing = screenSizing_EmphTop;
|
Config::ScreenSizing = Frontend::screenSizing_EmphTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit screenLayoutChange();
|
emit screenLayoutChange();
|
||||||
|
@ -3279,12 +3282,12 @@ int main(int argc, char** argv)
|
||||||
SANITIZE(Config::AudioInterp, 0, 3);
|
SANITIZE(Config::AudioInterp, 0, 3);
|
||||||
SANITIZE(Config::AudioVolume, 0, 256);
|
SANITIZE(Config::AudioVolume, 0, 256);
|
||||||
SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX);
|
SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX);
|
||||||
SANITIZE(Config::ScreenRotation, 0, 3);
|
SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX);
|
||||||
SANITIZE(Config::ScreenGap, 0, 500);
|
SANITIZE(Config::ScreenGap, 0, 500);
|
||||||
SANITIZE(Config::ScreenLayout, 0, 3);
|
SANITIZE(Config::ScreenLayout, 0, (int)Frontend::screenLayout_MAX);
|
||||||
SANITIZE(Config::ScreenSizing, 0, (int)screenSizing_MAX);
|
SANITIZE(Config::ScreenSizing, 0, (int)Frontend::screenSizing_MAX);
|
||||||
SANITIZE(Config::ScreenAspectTop, 0, 4);
|
SANITIZE(Config::ScreenAspectTop, 0, AspectRatiosNum);
|
||||||
SANITIZE(Config::ScreenAspectBot, 0, 4);
|
SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum);
|
||||||
#undef SANITIZE
|
#undef SANITIZE
|
||||||
|
|
||||||
AudioInOut::Init();
|
AudioInOut::Init();
|
||||||
|
|
|
@ -94,12 +94,29 @@ private:
|
||||||
void initOpenGL();
|
void initOpenGL();
|
||||||
void deinitOpenGL();
|
void deinitOpenGL();
|
||||||
|
|
||||||
std::atomic<int> EmuStatus;
|
enum EmuStatusKind
|
||||||
int PrevEmuStatus;
|
{
|
||||||
int EmuRunning;
|
emuStatus_Exit,
|
||||||
int EmuPause;
|
emuStatus_Running,
|
||||||
|
emuStatus_Paused,
|
||||||
|
emuStatus_FrameStep,
|
||||||
|
};
|
||||||
|
std::atomic<EmuStatusKind> EmuStatus;
|
||||||
|
|
||||||
std::atomic<int> ContextRequest = 0;
|
EmuStatusKind PrevEmuStatus;
|
||||||
|
EmuStatusKind EmuRunning;
|
||||||
|
|
||||||
|
constexpr static int EmuPauseStackRunning = 0;
|
||||||
|
constexpr static int EmuPauseStackPauseThreshold = 1;
|
||||||
|
int EmuPauseStack;
|
||||||
|
|
||||||
|
enum ContextRequestKind
|
||||||
|
{
|
||||||
|
contextRequest_None = 0,
|
||||||
|
contextRequest_InitGL,
|
||||||
|
contextRequest_DeInitGL
|
||||||
|
};
|
||||||
|
std::atomic<ContextRequestKind> ContextRequest = contextRequest_None;
|
||||||
|
|
||||||
GL::Context* oglContext = nullptr;
|
GL::Context* oglContext = nullptr;
|
||||||
GLuint screenVertexBuffer, screenVertexArray;
|
GLuint screenVertexBuffer, screenVertexArray;
|
||||||
|
@ -404,14 +421,14 @@ public:
|
||||||
QAction* actSavestateSRAMReloc;
|
QAction* actSavestateSRAMReloc;
|
||||||
QAction* actScreenSize[4];
|
QAction* actScreenSize[4];
|
||||||
QActionGroup* grpScreenRotation;
|
QActionGroup* grpScreenRotation;
|
||||||
QAction* actScreenRotation[4];
|
QAction* actScreenRotation[Frontend::screenRot_MAX];
|
||||||
QActionGroup* grpScreenGap;
|
QActionGroup* grpScreenGap;
|
||||||
QAction* actScreenGap[6];
|
QAction* actScreenGap[6];
|
||||||
QActionGroup* grpScreenLayout;
|
QActionGroup* grpScreenLayout;
|
||||||
QAction* actScreenLayout[4];
|
QAction* actScreenLayout[Frontend::screenLayout_MAX];
|
||||||
QAction* actScreenSwap;
|
QAction* actScreenSwap;
|
||||||
QActionGroup* grpScreenSizing;
|
QActionGroup* grpScreenSizing;
|
||||||
QAction* actScreenSizing[6];
|
QAction* actScreenSizing[Frontend::screenSizing_MAX];
|
||||||
QAction* actIntegerScaling;
|
QAction* actIntegerScaling;
|
||||||
QActionGroup* grpScreenAspectTop;
|
QActionGroup* grpScreenAspectTop;
|
||||||
QAction** actScreenAspectTop;
|
QAction** actScreenAspectTop;
|
||||||
|
|
Loading…
Reference in New Issue