aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRSDuck <RSDuck@users.noreply.github.com>2023-07-29 21:27:28 +0200
committerRSDuck <RSDuck@users.noreply.github.com>2023-07-29 21:27:28 +0200
commit3efbf1b813e40c02e3e12488712f33bb0b63f468 (patch)
tree3b5cbca73ca0e7ba20361594ab62a2fa869b601b /src
parent8fd46e5f8ccc4fe152bef2059114f6373030d63c (diff)
a bit of frontend refactoring
Diffstat (limited to 'src')
-rw-r--r--src/frontend/FrontendUtil.h218
-rw-r--r--src/frontend/Util_Video.cpp1106
-rw-r--r--src/frontend/qt_sdl/Config.h11
-rw-r--r--src/frontend/qt_sdl/main.cpp135
-rw-r--r--src/frontend/qt_sdl/main.h35
5 files changed, 767 insertions, 738 deletions
diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h
index 91f5d88..51f8f61 100644
--- a/src/frontend/FrontendUtil.h
+++ b/src/frontend/FrontendUtil.h
@@ -1,99 +1,119 @@
-/*
- Copyright 2016-2022 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 FRONTENDUTIL_H
-#define FRONTENDUTIL_H
-
-#include "types.h"
-
-#include <string>
-#include <vector>
-
-namespace Frontend
-{
-
-// setup the display layout based on the provided display size and parameters
-// * screenWidth/screenHeight: size of the host display
-// * screenLayout: how the DS screens are laid out
-// 0 = natural (top screen above bottom screen always)
-// 1 = vertical
-// 2 = horizontal
-// 3 = hybrid
-// * 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)
-// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
-// 2 = emphasize bottom screen
-// 4 = top only
-// 5 = bottom only
-// * screenGap: size of the gap between the two screens
-// * integerScale: force screens to be scaled up at integer scaling factors
-// * 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,
- int screenLayout,
- int rotation,
- int sizing,
- int screenGap,
- bool integerScale,
- bool swapScreens,
- float topAspect, float botAspect);
-
-const int MaxScreenTransforms = 3;
-
-// 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,
-// X going right and Y going down
-// for each screen the source coordinates should be (0,0) and (256,192)
-// 'out' should point to an array of 6*MaxScreenTransforms floats
-// 'kind' should point to an array of MaxScreenTransforms ints
-// (0 = indicates top screen, 1 = bottom screen)
-// returns the amount of screens
-int GetScreenTransforms(float* out, int* kind);
-
-// de-transform the provided host display coordinates to get coordinates
-// on the bottom screen
-bool GetTouchCoords(int& x, int& y, bool clamp);
-
-
-// initialize the audio utility
-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)
-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
+/*
+ Copyright 2016-2022 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 FRONTENDUTIL_H
+#define FRONTENDUTIL_H
+
+#include "types.h"
+
+#include <string>
+#include <vector>
+
+namespace Frontend
+{
+
+enum ScreenLayout
+{
+ screenLayout_Natural, // top screen above bottom screen always
+ screenLayout_Horizontal,
+ screenLayout_Vertical,
+ screenLayout_Hybrid,
+ screenLayout_MAX,
+};
+
+enum ScreenRotation
+{
+ screenRot_0Deg,
+ screenRot_90Deg,
+ screenRot_180Deg,
+ screenRot_270Deg,
+ screenRot_MAX,
+};
+
+enum ScreenSizing
+{
+ screenSizing_Even, // both screens get same size
+ screenSizing_EmphTop, // make top screen as big as possible, fit bottom screen in remaining space
+ screenSizing_EmphBot,
+ screenSizing_Auto, // not applied in SetupScreenLayout
+ screenSizing_TopOnly,
+ screenSizing_BotOnly,
+ screenSizing_MAX,
+};
+
+// setup the display layout based on the provided display size and parameters
+// * screenWidth/screenHeight: size of the host display
+// * screenLayout: how the DS screens are laid out
+// * rotation: angle at which the DS screens are presented
+// * sizing: how the display size is shared between the two screens
+// * screenGap: size of the gap between the two screens in pixels
+// * integerScale: force screens to be scaled up at integer scaling factors
+// * 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,
+ ScreenLayout screenLayout,
+ ScreenRotation rotation,
+ ScreenSizing sizing,
+ int screenGap,
+ bool integerScale,
+ bool swapScreens,
+ float topAspect, float botAspect);
+
+const int MaxScreenTransforms = 3;
+
+// 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,
+// X going right and Y going down
+// for each screen the source coordinates should be (0,0) and (256,192)
+// 'out' should point to an array of 6*MaxScreenTransforms floats
+// 'kind' should point to an array of MaxScreenTransforms ints
+// (0 = indicates top screen, 1 = bottom screen)
+// returns the amount of screens
+int GetScreenTransforms(float* out, int* kind);
+
+// de-transform the provided host display coordinates to get coordinates
+// on the bottom screen
+bool GetTouchCoords(int& x, int& y, bool clamp);
+
+
+// initialize the audio utility
+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)
+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
diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp
index 778c299..e4c49e9 100644
--- a/src/frontend/Util_Video.cpp
+++ b/src/frontend/Util_Video.cpp
@@ -1,553 +1,553 @@
-/*
- Copyright 2016-2022 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <cmath>
-#include <algorithm>
-
-#include "FrontendUtil.h"
-
-
-namespace Frontend
-{
-
-float TopScreenMtx[6];
-float BotScreenMtx[6];
-float HybScreenMtx[6];
-float TouchMtx[6];
-float HybTouchMtx[6];
-bool TopEnable;
-bool BotEnable;
-bool HybEnable;
-int HybScreen;
-int HybPrevTouchScreen; // 0:unknown, 1:buttom screen, 2:hybrid screen
-
-void M23_Identity(float* m)
-{
- m[0] = 1; m[1] = 0;
- m[2] = 0; m[3] = 1;
- m[4] = 0; m[5] = 0;
-}
-
-void M23_Scale(float* m, float s)
-{
- m[0] *= s; m[1] *= s;
- m[2] *= s; m[3] *= s;
- m[4] *= s; m[5] *= s;
-}
-
-void M23_Scale(float* m, float x, float y)
-{
- m[0] *= x; m[1] *= y;
- m[2] *= x; m[3] *= y;
- m[4] *= x; m[5] *= y;
-}
-
-void M23_RotateFast(float* m, int angle)
-{
- if (angle == 0) return;
-
- float temp[4]; memcpy(temp, m, sizeof(float)*4);
-
- switch (angle)
- {
- case 1: // 90
- m[0] = temp[2];
- m[1] = temp[3];
- m[2] = -temp[0];
- m[3] = -temp[1];
- break;
-
- case 2: // 180
- m[0] = -temp[0];
- m[1] = -temp[1];
- m[2] = -temp[2];
- m[3] = -temp[3];
- break;
-
- case 3: // 270
- m[0] = -temp[2];
- m[1] = -temp[3];
- m[2] = temp[0];
- m[3] = temp[1];
- break;
- }
-}
-
-void M23_Translate(float* m, float tx, float ty)
-{
- m[4] += tx;
- m[5] += ty;
-}
-
-void M23_Multiply(float* m, float* _a, float* _b)
-{
- float a[6]; memcpy(a, _a, 6*sizeof(float));
- float b[6]; memcpy(b, _b, 6*sizeof(float));
-
- m[0] = (a[0] * b[0]) + (a[2] * b[1]);
- m[1] = (a[1] * b[0]) + (a[3] * b[1]);
-
- m[2] = (a[0] * b[2]) + (a[2] * b[3]);
- m[3] = (a[1] * b[2]) + (a[3] * b[3]);
-
- m[4] = (a[0] * b[4]) + (a[2] * b[5]) + a[4];
- m[5] = (a[1] * b[4]) + (a[3] * b[5]) + a[5];
-}
-
-void M23_Transform(float* m, float& x, float& y)
-{
- float vx = x;
- float vy = y;
-
- x = (vx * m[0]) + (vy * m[2]) + m[4];
- y = (vx * m[1]) + (vy * m[3]) + m[5];
-}
-
-
-void SetupScreenLayout(int screenWidth, int screenHeight,
- int screenLayout,
- int rotation,
- int sizing,
- int screenGap,
- bool integerScale,
- bool swapScreens,
- float topAspect, float botAspect)
-{
- HybEnable = screenLayout == 3;
- if (HybEnable)
- {
- screenLayout = 0;
- sizing = 0;
- HybScreen = swapScreens ? 1 : 0;
- swapScreens = false;
- topAspect = botAspect = 1;
- HybPrevTouchScreen = 0;
- }
-
- float refpoints[6][2] =
- {
- {0, 0}, {256, 192},
- {0, 0}, {256, 192},
- {0, 0}, {256, 192}
- };
-
- int layout = screenLayout == 0
- ? rotation % 2
- : screenLayout - 1;
-
- float botScale = 1;
- float hybScale = 1;
- float botTrans[4] = {0};
- float hybTrans[2] = {0};
-
- M23_Identity(TopScreenMtx);
- M23_Identity(BotScreenMtx);
- M23_Identity(HybScreenMtx);
-
- M23_Translate(TopScreenMtx, -256/2, -192/2);
- M23_Translate(BotScreenMtx, -256/2, -192/2);
-
- M23_Scale(TopScreenMtx, topAspect, 1);
- M23_Scale(BotScreenMtx, botAspect, 1);
-
- // rotation
- {
- float rotmtx[6];
- M23_Identity(rotmtx);
-
- M23_RotateFast(rotmtx, rotation);
- M23_Multiply(TopScreenMtx, rotmtx, TopScreenMtx);
- M23_Multiply(BotScreenMtx, rotmtx, BotScreenMtx);
- M23_Multiply(HybScreenMtx, rotmtx, HybScreenMtx);
-
- M23_Transform(TopScreenMtx, refpoints[0][0], refpoints[0][1]);
- M23_Transform(TopScreenMtx, refpoints[1][0], refpoints[1][1]);
- M23_Transform(BotScreenMtx, refpoints[2][0], refpoints[2][1]);
- M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
- }
-
- int posRefPointOffset = 0;
- int posRefPointCount = HybEnable ? 6 : 4;
-
- if (sizing == 4 || sizing == 5)
- {
- float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
- int primOffset = sizing == 4 ? 0 : 2;
- int secOffset = sizing == 5 ? 2 : 0;
-
- float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
- float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
-
- float scale = std::min(screenWidth / hSize, screenHeight / vSize);
- if (integerScale)
- scale = floorf(scale);
-
- TopEnable = sizing == 4;
- BotEnable = sizing == 5;
- botScale = scale;
-
- M23_Scale(mtx, scale);
- refpoints[primOffset][0] *= scale;
- refpoints[primOffset][1] *= scale;
- refpoints[primOffset+1][0] *= scale;
- refpoints[primOffset+1][1] *= scale;
-
- posRefPointOffset = primOffset;
- posRefPointCount = 2;
- }
- else
- {
- TopEnable = BotEnable = true;
-
- // move screens apart
- {
- int idx = layout == 0 ? 1 : 0;
-
- bool moveV = rotation % 2 == layout;
-
- float offsetBot = (moveV ? 192.0 : 256.0 * botAspect) / 2.0 + screenGap / 2.0;
- float offsetTop = -((moveV ? 192.0 : 256.0 * topAspect) / 2.0 + screenGap / 2.0);
-
- if ((rotation == 1 || rotation == 2) ^ swapScreens)
- {
- offsetTop *= -1;
- offsetBot *= -1;
- }
-
- M23_Translate(TopScreenMtx, (idx==0)?offsetTop:0, (idx==1)?offsetTop:0);
- M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
-
- refpoints[0][idx] += offsetTop;
- refpoints[1][idx] += offsetTop;
- refpoints[2][idx] += offsetBot;
- refpoints[3][idx] += offsetBot;
-
- botTrans[idx] = offsetBot;
- }
-
- // scale
- {
- if (sizing == 0)
- {
- float minX = refpoints[0][0], maxX = minX;
- float minY = refpoints[0][1], maxY = minY;
-
- for (int i = 1; i < 4; i++)
- {
- minX = std::min(minX, refpoints[i][0]);
- minY = std::min(minY, refpoints[i][1]);
- maxX = std::max(maxX, refpoints[i][0]);
- maxY = std::max(maxY, refpoints[i][1]);
- }
-
- float hSize = maxX - minX;
- float vSize = maxY - minY;
-
- if (HybEnable)
- {
- hybScale = layout == 0
- ? (4 * vSize) / (3 * hSize)
- : (4 * hSize) / (3 * vSize);
- if (layout == 0)
- hSize += (vSize * 4) / 3;
- else
- vSize += (hSize * 4) / 3;
- }
-
- // scale evenly
- float scale = std::min(screenWidth / hSize, screenHeight / vSize);
-
- if (integerScale)
- scale = floor(scale);
-
- hybScale *= scale;
-
- M23_Scale(TopScreenMtx, scale);
- M23_Scale(BotScreenMtx, scale);
- M23_Scale(HybScreenMtx, hybScale);
-
- for (int i = 0; i < 4; i++)
- {
- refpoints[i][0] *= scale;
- refpoints[i][1] *= scale;
- }
-
- botScale = scale;
-
- // move screens aside
- if (HybEnable)
- {
- float hybWidth = layout == 0
- ? (scale * vSize * 4) / 3
- : (scale * hSize * 4) / 3;
-
- if (rotation > 1)
- hybWidth *= -1;
-
- M23_Translate(TopScreenMtx, (layout==0)?hybWidth:0, (layout==1)?hybWidth:0);
- M23_Translate(BotScreenMtx, (layout==0)?hybWidth:0, (layout==1)?hybWidth:0);
- refpoints[0][layout] += hybWidth;
- refpoints[1][layout] += hybWidth;
- refpoints[2][layout] += hybWidth;
- refpoints[3][layout] += hybWidth;
-
- botTrans[2+layout] += hybWidth;
-
- hybTrans[0] = scale * (rotation == 0 || rotation == 3 ? minX : maxX);
- hybTrans[1] = scale * (rotation == 0 || rotation == 1 ? minY : maxY);
- M23_Translate(HybScreenMtx, hybTrans[0], hybTrans[1]);
-
- M23_Transform(HybScreenMtx, refpoints[4][0], refpoints[4][1]);
- M23_Transform(HybScreenMtx, refpoints[5][0], refpoints[5][1]);
- }
- }
- else
- {
- int primOffset = (sizing == 1) ? 0 : 2;
- int secOffset = (sizing == 1) ? 2 : 0;
- float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx;
- float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx;
-
- float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
- float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
- float secMinX = refpoints[secOffset][0], secMaxX = secMinX;
- float secMinY = refpoints[secOffset][1], secMaxY = secMinY;
-
- primMinX = std::min(primMinX, refpoints[primOffset+1][0]);
- primMinY = std::min(primMinY, refpoints[primOffset+1][1]);
- primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]);
- primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]);
-
- secMinX = std::min(secMinX, refpoints[secOffset+1][0]);
- secMinY = std::min(secMinY, refpoints[secOffset+1][1]);
- secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]);
- secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]);
-
- float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX;
- float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY;
-
- float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX;
- float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY;
-
- float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize);
- float secScale = 1.f;
-
- if (integerScale)
- primScale = floorf(primScale);
-
- if (layout == 0)
- {
- if (screenHeight - primVSize * primScale < secVSize)
- primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
- else
- secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
- }
- else
- {
- if (screenWidth - primHSize * primScale < secHSize)
- primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
- else
- secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
- }
-
- if (integerScale)
- {
- primScale = floorf(primScale);
- secScale = floorf(secScale);
- }
-
- M23_Scale(primMtx, primScale);
- M23_Scale(secMtx, secScale);
-
- refpoints[primOffset+0][0] *= primScale;
- refpoints[primOffset+0][1] *= primScale;
- refpoints[primOffset+1][0] *= primScale;
- refpoints[primOffset+1][1] *= primScale;
- refpoints[secOffset+0][0] *= secScale;
- refpoints[secOffset+0][1] *= secScale;
- refpoints[secOffset+1][0] *= secScale;
- refpoints[secOffset+1][1] *= secScale;
-
- botScale = (sizing == 1) ? secScale : primScale;
- }
- }
- }
-
- // position
- {
- float minX = refpoints[posRefPointOffset][0], maxX = minX;
- float minY = refpoints[posRefPointOffset][1], maxY = minY;
-
- for (int i = posRefPointOffset + 1; i < posRefPointOffset + posRefPointCount; i++)
- {
- minX = std::min(minX, refpoints[i][0]);
- minY = std::min(minY, refpoints[i][1]);
- maxX = std::max(maxX, refpoints[i][0]);
- maxY = std::max(maxY, refpoints[i][1]);
- }
-
- float width = maxX - minX;
- float height = maxY - minY;
-
- float tx = (screenWidth/2) - (width/2) - minX;
- float ty = (screenHeight/2) - (height/2) - minY;
-
- M23_Translate(TopScreenMtx, tx, ty);
- M23_Translate(BotScreenMtx, tx, ty);
- M23_Translate(HybScreenMtx, tx, ty);
-
- botTrans[2] += tx; botTrans[3] += ty;
- hybTrans[0] += tx; hybTrans[1] += ty;
- }
-
- // prepare a 'reverse' matrix for the touchscreen
- // this matrix undoes the transforms applied to the bottom screen
- // and can be used to calculate touchscreen coords from host screen coords
- if (BotEnable)
- {
- M23_Identity(TouchMtx);
-
- M23_Translate(TouchMtx, -botTrans[2], -botTrans[3]);
- M23_Scale(TouchMtx, 1.f / botScale);
- M23_Translate(TouchMtx, -botTrans[0], -botTrans[1]);
-
- float rotmtx[6];
- M23_Identity(rotmtx);
- M23_RotateFast(rotmtx, (4-rotation) & 3);
- M23_Multiply(TouchMtx, rotmtx, TouchMtx);
-
- M23_Scale(TouchMtx, 1.f/botAspect, 1);
- M23_Translate(TouchMtx, 256/2, 192/2);
-
- if (HybEnable && HybScreen == 1)
- {
- M23_Identity(HybTouchMtx);
-
- M23_Translate(HybTouchMtx, -hybTrans[0], -hybTrans[1]);
- M23_Scale(HybTouchMtx, 1.f/hybScale);
- M23_Multiply(HybTouchMtx, rotmtx, HybTouchMtx);
- }
- }
-}
-
-int GetScreenTransforms(float* out, int* kind)
-{
- int num = 0;
- if (TopEnable)
- {
- memcpy(out + 6*num, TopScreenMtx, sizeof(TopScreenMtx));
- kind[num++] = 0;
- }
- if (BotEnable)
- {
- memcpy(out + 6*num, BotScreenMtx, sizeof(BotScreenMtx));
- kind[num++] = 1;
- }
- if (HybEnable)
- {
- memcpy(out + 6*num, HybScreenMtx, sizeof(HybScreenMtx));
- kind[num++] = HybScreen;
- }
- return num;
-}
-
-bool GetTouchCoords(int& x, int& y, bool clamp)
-{
- if (HybEnable && HybScreen == 1)
- {
- float vx = x;
- float vy = y;
- float hvx = x;
- float hvy = y;
-
- M23_Transform(TouchMtx, vx, vy);
- M23_Transform(HybTouchMtx, hvx, hvy);
-
- if (clamp)
- {
- if (HybPrevTouchScreen == 1)
- {
- x = std::clamp((int)vx, 0, 255);
- y = std::clamp((int)vy, 0, 191);
-
- return true;
- }
- if (HybPrevTouchScreen == 2)
- {
- x = std::clamp((int)hvx, 0, 255);
- y = std::clamp((int)hvy, 0, 191);
-
- return true;
- }
- }
- else
- {
- if (vx >= 0 && vx < 256 && vy >= 0 && vy < 192)
- {
- HybPrevTouchScreen = 1;
-
- x = (int)vx;
- y = (int)vy;
-
- return true;
- }
- if (hvx >= 0 && hvx < 256 && hvy >= 0 && hvy < 192)
- {
- HybPrevTouchScreen = 2;
-
- x = (int)hvx;
- y = (int)hvy;
-
- return true;
- }
- }
- }
- else if (BotEnable)
- {
- float vx = x;
- float vy = y;
-
- M23_Transform(TouchMtx, vx, vy);
-
- if (clamp)
- {
- x = std::clamp((int)vx, 0, 255);
- y = std::clamp((int)vy, 0, 191);
-
- return true;
- }
- else
- {
- if (vx >= 0 && vx < 256 && vy >= 0 && vy < 192)
- {
- x = (int)vx;
- y = (int)vy;
-
- return true;
- }
- }
- }
-
- return false;
-}
-
-}
-
+/*
+ Copyright 2016-2022 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cmath>
+#include <algorithm>
+
+#include "FrontendUtil.h"
+
+
+namespace Frontend
+{
+
+float TopScreenMtx[6];
+float BotScreenMtx[6];
+float HybScreenMtx[6];
+float TouchMtx[6];
+float HybTouchMtx[6];
+bool TopEnable;
+bool BotEnable;
+bool HybEnable;
+int HybScreen;
+int HybPrevTouchScreen; // 0:unknown, 1:buttom screen, 2:hybrid screen
+
+void M23_Identity(float* m)
+{
+ m[0] = 1; m[1] = 0;
+ m[2] = 0; m[3] = 1;
+ m[4] = 0; m[5] = 0;
+}
+
+void M23_Scale(float* m, float s)
+{
+ m[0] *= s; m[1] *= s;
+ m[2] *= s; m[3] *= s;
+ m[4] *= s; m[5] *= s;
+}
+
+void M23_Scale(float* m, float x, float y)
+{
+ m[0] *= x; m[1] *= y;
+ m[2] *= x; m[3] *= y;
+ m[4] *= x; m[5] *= y;
+}
+
+void M23_RotateFast(float* m, int angle)
+{
+ if (angle == 0) return;
+
+ float temp[4]; memcpy(temp, m, sizeof(float)*4);
+
+ switch (angle)
+ {
+ case 1: // 90
+ m[0] = temp[2];
+ m[1] = temp[3];
+ m[2] = -temp[0];
+ m[3] = -temp[1];
+ break;
+
+ case 2: // 180
+ m[0] = -temp[0];
+ m[1] = -temp[1];
+ m[2] = -temp[2];
+ m[3] = -temp[3];
+ break;
+
+ case 3: // 270
+ m[0] = -temp[2];
+ m[1] = -temp[3];
+ m[2] = temp[0];
+ m[3] = temp[1];
+ break;
+ }
+}
+
+void M23_Translate(float* m, float tx, float ty)
+{
+ m[4] += tx;
+ m[5] += ty;
+}
+
+void M23_Multiply(float* m, float* _a, float* _b)
+{
+ float a[6]; memcpy(a, _a, 6*sizeof(float));
+ float b[6]; memcpy(b, _b, 6*sizeof(float));
+
+ m[0] = (a[0] * b[0]) + (a[2] * b[1]);
+ m[1] = (a[1] * b[0]) + (a[3] * b[1]);
+
+ m[2] = (a[0] * b[2]) + (a[2] * b[3]);
+ m[3] = (a[1] * b[2]) + (a[3] * b[3]);
+
+ m[4] = (a[0] * b[4]) + (a[2] * b[5]) + a[4];
+ m[5] = (a[1] * b[4]) + (a[3] * b[5]) + a[5];
+}
+
+void M23_Transform(float* m, float& x, float& y)
+{
+ float vx = x;
+ float vy = y;
+
+ x = (vx * m[0]) + (vy * m[2]) + m[4];
+ y = (vx * m[1]) + (vy * m[3]) + m[5];
+}
+
+
+void SetupScreenLayout(int screenWidth, int screenHeight,
+ ScreenLayout screenLayout,
+ ScreenRotation rotation,
+ ScreenSizing sizing,
+ int screenGap,
+ bool integerScale,
+ bool swapScreens,
+ float topAspect, float botAspect)
+{
+ HybEnable = screenLayout == 3;
+ if (HybEnable)
+ {
+ screenLayout = screenLayout_Natural;
+ sizing = screenSizing_Even;
+ HybScreen = swapScreens ? 1 : 0;
+ swapScreens = false;
+ topAspect = botAspect = 1;
+ HybPrevTouchScreen = 0;
+ }
+
+ float refpoints[6][2] =
+ {
+ {0, 0}, {256, 192},
+ {0, 0}, {256, 192},
+ {0, 0}, {256, 192}
+ };
+
+ int layout = screenLayout == screenLayout_Natural
+ ? rotation % 2
+ : screenLayout - 1;
+
+ float botScale = 1;
+ float hybScale = 1;
+ float botTrans[4] = {0};
+ float hybTrans[2] = {0};
+
+ M23_Identity(TopScreenMtx);
+ M23_Identity(BotScreenMtx);
+ M23_Identity(HybScreenMtx);
+
+ M23_Translate(TopScreenMtx, -256/2, -192/2);
+ M23_Translate(BotScreenMtx, -256/2, -192/2);
+
+ M23_Scale(TopScreenMtx, topAspect, 1);
+ M23_Scale(BotScreenMtx, botAspect, 1);
+
+ // rotation
+ {
+ float rotmtx[6];
+ M23_Identity(rotmtx);
+
+ M23_RotateFast(rotmtx, rotation);
+ M23_Multiply(TopScreenMtx, rotmtx, TopScreenMtx);
+ M23_Multiply(BotScreenMtx, rotmtx, BotScreenMtx);
+ M23_Multiply(HybScreenMtx, rotmtx, HybScreenMtx);
+
+ M23_Transform(TopScreenMtx, refpoints[0][0], refpoints[0][1]);
+ M23_Transform(TopScreenMtx, refpoints[1][0], refpoints[1][1]);
+ M23_Transform(BotScreenMtx, refpoints[2][0], refpoints[2][1]);
+ M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
+ }
+
+ int posRefPointOffset = 0;
+ int posRefPointCount = HybEnable ? 6 : 4;
+
+ if (sizing == screenSizing_TopOnly || sizing == screenSizing_BotOnly)
+ {
+ float* mtx = sizing == screenSizing_TopOnly ? TopScreenMtx : BotScreenMtx;
+ int primOffset = sizing == screenSizing_TopOnly ? 0 : 2;
+ int secOffset = sizing == screenSizing_BotOnly ? 2 : 0;
+
+ float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
+ float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
+
+ float scale = std::min(screenWidth / hSize, screenHeight / vSize);
+ if (integerScale)
+ scale = floorf(scale);
+
+ TopEnable = sizing == screenSizing_TopOnly;
+ BotEnable = sizing == screenSizing_BotOnly;
+ botScale = scale;
+
+ M23_Scale(mtx, scale);
+ refpoints[primOffset][0] *= scale;
+ refpoints[primOffset][1] *= scale;
+ refpoints[primOffset+1][0] *= scale;
+ refpoints[primOffset+1][1] *= scale;
+
+ posRefPointOffset = primOffset;
+ posRefPointCount = 2;
+ }
+ else
+ {
+ TopEnable = BotEnable = true;
+
+ // move screens apart
+ {
+ int idx = layout == 0 ? 1 : 0;
+
+ bool moveV = rotation % 2 == layout;
+
+ float offsetBot = (moveV ? 192.0 : 256.0 * botAspect) / 2.0 + screenGap / 2.0;
+ float offsetTop = -((moveV ? 192.0 : 256.0 * topAspect) / 2.0 + screenGap / 2.0);
+
+ if ((rotation == 1 || rotation == 2) ^ swapScreens)
+ {
+ offsetTop *= -1;
+ offsetBot *= -1;
+ }
+
+ M23_Translate(TopScreenMtx, (idx==0)?offsetTop:0, (idx==1)?offsetTop:0);
+ M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
+
+ refpoints[0][idx] += offsetTop;
+ refpoints[1][idx] += offsetTop;
+ refpoints[2][idx] += offsetBot;
+ refpoints[3][idx] += offsetBot;
+
+ botTrans[idx] = offsetBot;
+ }
+
+ // scale
+ {
+ if (sizing == screenSizing_Even)
+ {
+ float minX = refpoints[0][0], maxX = minX;
+ float minY = refpoints[0][1], maxY = minY;
+
+ for (int i = 1; i < 4; i++)
+ {
+ minX = std::min(minX, refpoints[i][0]);
+ minY = std::min(minY, refpoints[i][1]);
+ maxX = std::max(maxX, refpoints[i][0]);
+ maxY = std::max(maxY, refpoints[i][1]);
+ }
+
+ float hSize = maxX - minX;
+ float vSize = maxY - minY;
+
+ if (HybEnable)
+ {
+ hybScale = layout == 0
+ ? (4 * vSize) / (3 * hSize)
+ : (4 * hSize) / (3 * vSize);
+ if (layout == 0)
+ hSize += (vSize * 4) / 3;
+ else
+ vSize += (hSize * 4) / 3;
+ }
+
+ // scale evenly
+ float scale = std::min(screenWidth / hSize, screenHeight / vSize);
+
+ if (integerScale)
+ scale = floor(scale);
+
+ hybScale *= scale;
+
+ M23_Scale(TopScreenMtx, scale);
+ M23_Scale(BotScreenMtx, scale);
+ M23_Scale(HybScreenMtx, hybScale);
+
+ for (int i = 0; i < 4; i++)
+ {
+ refpoints[i][0] *= scale;
+ refpoints[i][1] *= scale;
+ }
+
+ botScale = scale;
+
+ // move screens aside
+ if (HybEnable)
+ {
+ float hybWidth = layout == 0
+ ? (scale * vSize * 4) / 3
+ : (scale * hSize * 4) / 3;
+
+ if (rotation > screenRot_90Deg)
+ hybWidth *= -1;
+
+ M23_Translate(TopScreenMtx, (layout==0)?hybWidth:0, (layout==1)?hybWidth:0);
+ M23_Translate(BotScreenMtx, (layout==0)?hybWidth:0, (layout==1)?hybWidth:0);
+ refpoints[0][layout] += hybWidth;
+ refpoints[1][layout] += hybWidth;
+ refpoints[2][layout] += hybWidth;
+ refpoints[3][layout] += hybWidth;
+
+ botTrans[2+layout] += hybWidth;
+
+ hybTrans[0] = scale * (rotation == screenRot_0Deg || rotation == screenRot_270Deg ? minX : maxX);
+ hybTrans[1] = scale * (rotation == screenRot_0Deg || rotation == screenRot_90Deg ? minY : maxY);
+ M23_Translate(HybScreenMtx, hybTrans[0], hybTrans[1]);
+
+ M23_Transform(HybScreenMtx, refpoints[4][0], refpoints[4][1]);
+ M23_Transform(HybScreenMtx, refpoints[5][0], refpoints[5][1]);
+ }
+ }
+ else
+ {
+ int primOffset = (sizing == screenSizing_EmphTop) ? 0 : 2;
+ int secOffset = (sizing == screenSizing_EmphTop) ? 2 : 0;
+ float* primMtx = (sizing == screenSizing_EmphTop) ? TopScreenMtx : BotScreenMtx;
+ float* secMtx = (sizing == screenSizing_EmphTop) ? BotScreenMtx : TopScreenMtx;
+
+ float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
+ float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
+ float secMinX = refpoints[secOffset][0], secMaxX = secMinX;
+ float secMinY = refpoints[secOffset][1], secMaxY = secMinY;
+
+ primMinX = std::min(primMinX, refpoints[primOffset+1][0]);
+ primMinY = std::min(primMinY, refpoints[primOffset+1][1]);
+ primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]);
+ primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]);
+
+ secMinX = std::min(secMinX, refpoints[secOffset+1][0]);
+ secMinY = std::min(secMinY, refpoints[secOffset+1][1]);
+ secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]);
+ secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]);
+
+ float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX;
+ float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY;
+
+ float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX;
+ float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY;
+
+ float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize);
+ float secScale = 1.f;
+
+ if (integerScale)
+ primScale = floorf(primScale);
+
+ if (layout == 0)
+ {
+ if (screenHeight - primVSize * primScale < secVSize)
+ primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
+ else
+ secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
+ }
+ else
+ {
+ if (screenWidth - primHSize * primScale < secHSize)
+ primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
+ else
+ secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
+ }
+
+ if (integerScale)
+ {
+ primScale = floorf(primScale);
+ secScale = floorf(secScale);
+ }
+
+ M23_Scale(primMtx, primScale);
+ M23_Scale(secMtx, secScale);
+
+ refpoints[primOffset+0][0] *= primScale;
+ refpoints[primOffset+0][1] *= primScale;
+ refpoints[primOffset+1][0] *= primScale;
+ refpoints[primOffset+1][1] *= primScale;
+ refpoints[secOffset+0][0] *= secScale;
+ refpoints[secOffset+0][1] *= secScale;
+ refpoints[secOffset+1][0] *= secScale;
+ refpoints[secOffset+1][1] *= secScale;
+
+ botScale = (sizing == screenSizing_EmphTop) ? secScale : primScale;
+ }
+ }
+ }
+
+ // position
+ {
+ float minX = refpoints[posRefPointOffset][0], maxX = minX;
+ float minY = refpoints[posRefPointOffset][1], maxY = minY;
+
+ for (int i = posRefPointOffset + 1; i < posRefPointOffset + posRefPointCount; i++)
+ {
+ minX = std::min(minX, refpoints[i][0]);
+ minY = std::min(minY, refpoints[i][1]);
+ maxX = std::max(maxX, refpoints[i][0]);
+ maxY = std::max(maxY, refpoints[i][1]);
+ }
+
+ float width = maxX - minX;
+ float height = maxY - minY;
+
+ float tx = (screenWidth/2) - (width/2) - minX;
+ float ty = (screenHeight/2) - (height/2) - minY;
+
+ M23_Translate(TopScreenMtx, tx, ty);
+ M23_Translate(BotScreenMtx, tx, ty);
+ M23_Translate(HybScreenMtx, tx, ty);
+
+ botTrans[2] += tx; botTrans[3] += ty;
+ hybTrans[0] += tx; hybTrans[1] += ty;
+ }
+
+ // prepare a 'reverse' matrix for the touchscreen
+ // this matrix undoes the transforms applied to the bottom screen
+ // and can be used to calculate touchscreen coords from host screen coords
+ if (BotEnable)
+ {
+ M23_Identity(TouchMtx);
+
+ M23_Translate(TouchMtx, -botTrans[2], -botTrans[3]);
+ M23_Scale(TouchMtx, 1.f / botScale);
+ M23_Translate(TouchMtx, -botTrans[0], -botTrans[1]);
+
+ float rotmtx[6];
+ M23_Identity(rotmtx);
+ M23_RotateFast(rotmtx, (4-rotation) & 3);
+ M23_Multiply(TouchMtx, rotmtx, TouchMtx);
+
+ M23_Scale(TouchMtx, 1.f/botAspect, 1);
+ M23_Translate(TouchMtx, 256/2, 192/2);
+
+ if (HybEnable && HybScreen == 1)
+ {
+ M23_Identity(HybTouchMtx);
+
+ M23_Translate(HybTouchMtx, -hybTrans[0], -hybTrans[1]);
+ M23_Scale(HybTouchMtx, 1.f/hybScale);
+ M23_Multiply(HybTouchMtx, rotmtx, HybTouchMtx);
+ }
+ }
+}
+
+int GetScreenTransforms(float* out, int* kind)
+{
+ int num = 0;
+ if (TopEnable)
+ {
+ memcpy(out + 6*num, TopScreenMtx, sizeof(TopScreenMtx));
+ kind[num++] = 0;
+ }
+ if (BotEnable)
+ {
+ memcpy(out + 6*num, BotScreenMtx, sizeof(BotScreenMtx));
+ kind[num++] = 1;
+ }
+ if (HybEnable)
+ {
+ memcpy(out + 6*num, HybScreenMtx, sizeof(HybScreenMtx));
+ kind[num++] = HybScreen;
+ }
+ return num;
+}
+
+bool GetTouchCoords(int& x, int& y, bool clamp)
+{
+ if (HybEnable && HybScreen == 1)
+ {
+ float vx = x;
+ float vy = y;
+ float hvx = x;
+ float hvy = y;
+
+ M23_Transform(TouchMtx, vx, vy);
+ M23_Transform(HybTouchMtx, hvx, hvy);
+
+ if (clamp)
+ {
+ if (HybPrevTouchScreen == 1)
+ {
+ x = std::clamp((int)vx, 0, 255);
+ y = std::clamp((int)vy, 0, 191);
+
+ return true;
+ }
+ if (HybPrevTouchScreen == 2)
+ {
+ x = std::clamp((int)hvx, 0, 255);
+ y = std::clamp((int)hvy, 0, 191);
+
+ return true;
+ }
+ }
+ else
+ {
+ if (vx >= 0 && vx < 256 && vy >= 0 && vy < 192)
+ {
+ HybPrevTouchScreen = 1;
+
+ x = (int)vx;
+ y = (int)vy;
+
+ return true;
+ }
+ if (hvx >= 0 && hvx < 256 && hvy >= 0 && hvy < 192)
+ {
+ HybPrevTouchScreen = 2;
+
+ x = (int)hvx;
+ y = (int)hvy;
+
+ return true;
+ }
+ }
+ }
+ else if (BotEnable)
+ {
+ float vx = x;
+ float vy = y;
+
+ M23_Transform(TouchMtx, vx, vy);
+
+ if (clamp)
+ {
+ x = std::clamp((int)vx, 0, 255);
+ y = std::clamp((int)vy, 0, 191);
+
+ return true;
+ }
+ else
+ {
+ if (vx >= 0 && vx < 256 && vy >= 0 && vy < 192)
+ {
+ x = (int)vx;
+ y = (int)vy;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+}
+
diff --git a/src/frontend/qt_sdl/Config.h b/src/frontend/qt_sdl/Config.h
index b2b56f2..1cd0e56 100644
--- a/src/frontend/qt_sdl/Config.h
+++ b/src/frontend/qt_sdl/Config.h
@@ -44,17 +44,6 @@ enum
enum
{
- screenSizing_Even,
- screenSizing_EmphTop,
- screenSizing_EmphBot,
- screenSizing_Auto,
- screenSizing_TopOnly,
- screenSizing_BotOnly,
- screenSizing_MAX,
-};
-
-enum
-{
micInputType_Silence,
micInputType_External,
micInputType_Noise,
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index a7a1b96..e5e1977 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -174,13 +174,14 @@ const struct { int id; float ratio; const char* label; } aspectRatios[] =
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
{ 3, 0, "window" }
};
+constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);
EmuThread::EmuThread(QObject* parent) : QThread(parent)
{
- EmuStatus = 0;
- EmuRunning = 2;
- EmuPause = 0;
+ EmuStatus = emuStatus_Exit;
+ EmuRunning = emuStatus_Paused;
+ EmuPauseStack = EmuPauseStackRunning;
RunningSomething = false;
connect(this, SIGNAL(windowUpdate()), mainWindow->panelWidget, SLOT(repaint()));
@@ -353,7 +354,7 @@ void EmuThread::run()
char melontitle[100];
- while (EmuRunning != 0)
+ while (EmuRunning != emuStatus_Exit)
{
Input::Process();
@@ -425,10 +426,10 @@ void EmuThread::run()
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
}
- if (EmuRunning == 1 || EmuRunning == 3)
+ if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
{
- EmuStatus = 1;
- if (EmuRunning == 3) EmuRunning = 2;
+ EmuStatus = emuStatus_Running;
+ if (EmuRunning == emuStatus_FrameStep) EmuRunning = emuStatus_Paused;
// update render settings if needed
// HACK:
@@ -473,7 +474,7 @@ void EmuThread::run()
AudioInOut::MicProcess();
// auto screen layout
- if (Config::ScreenSizing == screenSizing_Auto)
+ if (Config::ScreenSizing == Frontend::screenSizing_Auto)
{
mainScreenPos[2] = mainScreenPos[1];
mainScreenPos[1] = mainScreenPos[0];
@@ -485,14 +486,14 @@ void EmuThread::run()
{
// constant flickering, likely displaying 3D on both screens
// TODO: when both screens are used for 2D only...???
- guess = screenSizing_Even;
+ guess = Frontend::screenSizing_Even;
}
else
{
if (mainScreenPos[0] == 1)
- guess = screenSizing_EmphTop;
+ guess = Frontend::screenSizing_EmphTop;
else
- guess = screenSizing_EmphBot;
+ guess = Frontend::screenSizing_EmphBot;
}
if (guess != autoScreenSizing)
@@ -528,7 +529,7 @@ void EmuThread::run()
MelonCap::Update();
#endif // MELONCAP
- if (EmuRunning == 0) break;
+ if (EmuRunning == emuStatus_Exit) break;
winUpdateCount++;
if (winUpdateCount >= winUpdateFreq && !oglContext)
@@ -632,21 +633,21 @@ void EmuThread::run()
if (oglContext)
drawScreenGL();
- int contextRequest = ContextRequest;
- if (contextRequest == 1)
+ ContextRequestKind contextRequest = ContextRequest;
+ if (contextRequest == contextRequest_InitGL)
{
initOpenGL();
- ContextRequest = 0;
+ ContextRequest = contextRequest_None;
}
- else if (contextRequest == 2)
+ else if (contextRequest == contextRequest_DeInitGL)
{
deinitOpenGL();
- ContextRequest = 0;
+ ContextRequest = contextRequest_None;
}
}
}
- EmuStatus = 0;
+ EmuStatus = emuStatus_Exit;
GPU::DeInitRenderer();
NDS::DeInit();
@@ -660,8 +661,8 @@ void EmuThread::changeWindowTitle(char* title)
void EmuThread::emuRun()
{
- EmuRunning = 1;
- EmuPause = 0;
+ EmuRunning = emuStatus_Running;
+ EmuPauseStack = EmuPauseStackRunning;
RunningSomething = true;
// checkme
@@ -671,34 +672,34 @@ void EmuThread::emuRun()
void EmuThread::initContext()
{
- ContextRequest = 1;
- while (ContextRequest != 0);
+ ContextRequest = contextRequest_InitGL;
+ while (ContextRequest != contextRequest_None);
}
void EmuThread::deinitContext()
{
- ContextRequest = 2;
- while (ContextRequest != 0);
+ ContextRequest = contextRequest_DeInitGL;
+ while (ContextRequest != contextRequest_None);
}
void EmuThread::emuPause()
{
- EmuPause++;
- if (EmuPause > 1) return;
+ EmuPauseStack++;
+ if (EmuPauseStack > EmuPauseStackPauseThreshold) return;
PrevEmuStatus = EmuRunning;
- EmuRunning = 2;
- while (EmuStatus != 2);
+ EmuRunning = emuStatus_Paused;
+ while (EmuStatus != emuStatus_Paused);
AudioInOut::Disable();
}
void EmuThread::emuUnpause()
{
- if (EmuPause < 1) return;
+ if (EmuPauseStack < EmuPauseStackPauseThreshold) return;
- EmuPause--;
- if (EmuPause > 0) return;
+ EmuPauseStack--;
+ if (EmuPauseStack >= EmuPauseStackPauseThreshold) return;
EmuRunning = PrevEmuStatus;
@@ -707,21 +708,21 @@ void EmuThread::emuUnpause()
void EmuThread::emuStop()
{
- EmuRunning = 0;
- EmuPause = 0;
+ EmuRunning = emuStatus_Exit;
+ EmuPauseStack = EmuPauseStackRunning;
AudioInOut::Disable();
}
void EmuThread::emuFrameStep()
{
- if (EmuPause < 1) emit windowEmuPause();
- EmuRunning = 3;
+ if (EmuPauseStack < EmuPauseStackPauseThreshold) emit windowEmuPause();
+ EmuRunning = emuStatus_FrameStep;
}
bool EmuThread::emuIsRunning()
{
- return (EmuRunning == 1);
+ return EmuRunning == emuStatus_Running;
}
bool EmuThread::emuIsActive()
@@ -830,9 +831,9 @@ void ScreenHandler::screenSetupLayout(int w, int h)
aspectBot = ((float) w / h) / (4.f / 3.f);
Frontend::SetupScreenLayout(w, h,
- Config::ScreenLayout,
- Config::ScreenRotation,
- sizing,
+ 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,
@@ -844,32 +845,34 @@ void ScreenHandler::screenSetupLayout(int w, int h)
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 w = 256 * 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);
}
- if (Config::ScreenLayout == 0) // natural
+ 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 == 1) // vertical
+ 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 == 2) // horizontal
+ else if (Config::ScreenLayout == Frontend::screenLayout_Horizontal)
{
if (isHori)
return QSize(h+gap+h, w);
@@ -1610,7 +1613,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Screen rotation");
grpScreenRotation = new QActionGroup(submenu);
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < Frontend::screenRot_MAX; i++)
{
int data = i*90;
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"};
- 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]->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"};
- 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]->setActionGroup(grpScreenSizing);
@@ -1686,8 +1689,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Aspect ratio");
grpScreenAspectTop = new QActionGroup(submenu);
grpScreenAspectBot = new QActionGroup(submenu);
- actScreenAspectTop = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
- actScreenAspectBot = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
+ actScreenAspectTop = new QAction*[AspectRatiosNum];
+ actScreenAspectBot = new QAction*[AspectRatiosNum];
for (int i = 0; i < 2; i++)
{
@@ -1701,7 +1704,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actions = actScreenAspectBot;
}
- for (int j = 0; j < sizeof(aspectRatios) / sizeof(aspectRatios[0]); j++)
+ for (int j = 0; j < AspectRatiosNum; j++)
{
auto ratio = aspectRatios[j];
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);
- for (int i = 0; i < sizeof(aspectRatios) / sizeof(aspectRatios[0]); i++)
+ for (int i = 0; i < AspectRatiosNum; i++)
{
if (Config::ScreenAspectTop == aspectRatios[i].id)
actScreenAspectTop[i]->setChecked(true);
@@ -3011,18 +3014,18 @@ void MainWindow::onChangeScreenSwap(bool checked)
Config::ScreenSwap = checked?1:0;
// Swap between top and bottom screen when displaying one screen.
- if (Config::ScreenSizing == screenSizing_TopOnly)
+ if (Config::ScreenSizing == Frontend::screenSizing_TopOnly)
{
// Bottom Screen.
- Config::ScreenSizing = screenSizing_BotOnly;
- actScreenSizing[screenSizing_TopOnly]->setChecked(false);
+ Config::ScreenSizing = Frontend::screenSizing_BotOnly;
+ actScreenSizing[Frontend::screenSizing_TopOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
}
- else if (Config::ScreenSizing == screenSizing_BotOnly)
+ else if (Config::ScreenSizing == Frontend::screenSizing_BotOnly)
{
// Top Screen.
- Config::ScreenSizing = screenSizing_TopOnly;
- actScreenSizing[screenSizing_BotOnly]->setChecked(false);
+ Config::ScreenSizing = Frontend::screenSizing_TopOnly;
+ actScreenSizing[Frontend::screenSizing_BotOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
}
@@ -3111,13 +3114,13 @@ void MainWindow::onFullscreenToggled()
void MainWindow::onScreenEmphasisToggled()
{
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();
@@ -3279,12 +3282,12 @@ int main(int argc, char** argv)
SANITIZE(Config::AudioInterp, 0, 3);
SANITIZE(Config::AudioVolume, 0, 256);
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::ScreenLayout, 0, 3);
- SANITIZE(Config::ScreenSizing, 0, (int)screenSizing_MAX);
- SANITIZE(Config::ScreenAspectTop, 0, 4);
- SANITIZE(Config::ScreenAspectBot, 0, 4);
+ SANITIZE(Config::ScreenLayout, 0, (int)Frontend::screenLayout_MAX);
+ SANITIZE(Config::ScreenSizing, 0, (int)Frontend::screenSizing_MAX);
+ SANITIZE(Config::ScreenAspectTop, 0, AspectRatiosNum);
+ SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum);
#undef SANITIZE
AudioInOut::Init();
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index 8a902ee..44283a9 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -94,12 +94,29 @@ private:
void initOpenGL();
void deinitOpenGL();
- std::atomic<int> EmuStatus;
- int PrevEmuStatus;
- int EmuRunning;
- int EmuPause;
-
- std::atomic<int> ContextRequest = 0;
+ enum EmuStatusKind
+ {
+ emuStatus_Exit,
+ emuStatus_Running,
+ emuStatus_Paused,
+ emuStatus_FrameStep,
+ };
+ std::atomic<EmuStatusKind> EmuStatus;
+
+ 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;
GLuint screenVertexBuffer, screenVertexArray;
@@ -404,14 +421,14 @@ public:
QAction* actSavestateSRAMReloc;
QAction* actScreenSize[4];
QActionGroup* grpScreenRotation;
- QAction* actScreenRotation[4];
+ QAction* actScreenRotation[Frontend::screenRot_MAX];
QActionGroup* grpScreenGap;
QAction* actScreenGap[6];
QActionGroup* grpScreenLayout;
- QAction* actScreenLayout[4];
+ QAction* actScreenLayout[Frontend::screenLayout_MAX];
QAction* actScreenSwap;
QActionGroup* grpScreenSizing;
- QAction* actScreenSizing[6];
+ QAction* actScreenSizing[Frontend::screenSizing_MAX];
QAction* actIntegerScaling;
QActionGroup* grpScreenAspectTop;
QAction** actScreenAspectTop;