diff options
author | RSDuck <RSDuck@users.noreply.github.com> | 2023-07-29 21:27:28 +0200 |
---|---|---|
committer | RSDuck <RSDuck@users.noreply.github.com> | 2023-07-29 21:27:28 +0200 |
commit | 3efbf1b813e40c02e3e12488712f33bb0b63f468 (patch) | |
tree | 3b5cbca73ca0e7ba20361594ab62a2fa869b601b /src/frontend | |
parent | 8fd46e5f8ccc4fe152bef2059114f6373030d63c (diff) |
a bit of frontend refactoring
Diffstat (limited to 'src/frontend')
-rw-r--r-- | src/frontend/FrontendUtil.h | 218 | ||||
-rw-r--r-- | src/frontend/Util_Video.cpp | 1106 | ||||
-rw-r--r-- | src/frontend/qt_sdl/Config.h | 11 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.cpp | 135 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.h | 35 |
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; |