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 | |
| parent | 8fd46e5f8ccc4fe152bef2059114f6373030d63c (diff) | |
a bit of frontend refactoring
Diffstat (limited to 'src')
| -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;  |