more screen modes
- add support for different aspect ratios - add support for displaying only one screen at once
This commit is contained in:
parent
536902d610
commit
b9a56bc4e4
|
@ -121,21 +121,36 @@ void EnableCheats(bool enable);
|
||||||
// 0 = even (both screens get same size)
|
// 0 = even (both screens get same size)
|
||||||
// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
|
// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
|
||||||
// 2 = emphasize bottom screen
|
// 2 = emphasize bottom screen
|
||||||
|
// 4 = top only
|
||||||
|
// 5 = bottom only
|
||||||
// * screenGap: size of the gap between the two screens
|
// * screenGap: size of the gap between the two screens
|
||||||
// * integerScale: force screens to be scaled up at integer scaling factors
|
// * integerScale: force screens to be scaled up at integer scaling factors
|
||||||
// * screenSwap: whether to swap the position of both screens
|
// * screenSwap: whether to swap the position of both screens
|
||||||
void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale, int swapScreens);
|
// * 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);
|
||||||
|
|
||||||
// get a 2x3 transform matrix for each screen
|
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,
|
// note: the transform assumes an origin point at the top left of the display,
|
||||||
// X going left and Y going down
|
// X going left and Y going down
|
||||||
// for each screen the source coordinates should be (0,0) and (256,192)
|
// for each screen the source coordinates should be (0,0) and (256,192)
|
||||||
// 'top' and 'bot' should point each to an array of 6 floats
|
// 'out' should point to an array of 6*MaxScreenTransforms floats
|
||||||
void GetScreenTransforms(float* top, float* bot);
|
// '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
|
// de-transform the provided host display coordinates to get coordinates
|
||||||
// on the bottom screen
|
// on the bottom screen
|
||||||
void GetTouchCoords(int& x, int& y);
|
bool GetTouchCoords(int& x, int& y);
|
||||||
|
|
||||||
|
|
||||||
// initialize the audio utility
|
// initialize the audio utility
|
||||||
|
|
|
@ -31,7 +31,8 @@ namespace Frontend
|
||||||
float TopScreenMtx[6];
|
float TopScreenMtx[6];
|
||||||
float BotScreenMtx[6];
|
float BotScreenMtx[6];
|
||||||
float TouchMtx[6];
|
float TouchMtx[6];
|
||||||
|
bool TopEnable;
|
||||||
|
bool BotEnable;
|
||||||
|
|
||||||
void M23_Identity(float* m)
|
void M23_Identity(float* m)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +48,13 @@ void M23_Scale(float* m, float s)
|
||||||
m[4] *= s; m[5] *= 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)
|
void M23_RotateFast(float* m, int angle)
|
||||||
{
|
{
|
||||||
if (angle == 0) return;
|
if (angle == 0) return;
|
||||||
|
@ -109,7 +117,14 @@ void M23_Transform(float* m, float& x, float& y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale, int swapScreens)
|
void SetupScreenLayout(int screenWidth, int screenHeight,
|
||||||
|
int screenLayout,
|
||||||
|
int rotation,
|
||||||
|
int sizing,
|
||||||
|
int screenGap,
|
||||||
|
bool integerScale,
|
||||||
|
bool swapScreens,
|
||||||
|
float topAspect, float botAspect)
|
||||||
{
|
{
|
||||||
float refpoints[4][2] =
|
float refpoints[4][2] =
|
||||||
{
|
{
|
||||||
|
@ -130,6 +145,9 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||||
M23_Translate(TopScreenMtx, -256/2, -192/2);
|
M23_Translate(TopScreenMtx, -256/2, -192/2);
|
||||||
M23_Translate(BotScreenMtx, -256/2, -192/2);
|
M23_Translate(BotScreenMtx, -256/2, -192/2);
|
||||||
|
|
||||||
|
M23_Scale(TopScreenMtx, topAspect, 1);
|
||||||
|
M23_Scale(BotScreenMtx, botAspect, 1);
|
||||||
|
|
||||||
// rotation
|
// rotation
|
||||||
{
|
{
|
||||||
float rotmtx[6];
|
float rotmtx[6];
|
||||||
|
@ -145,136 +163,174 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||||
M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
|
M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move screens apart
|
int posRefPointOffset = 0;
|
||||||
|
int posRefPointCount = 4;
|
||||||
|
|
||||||
|
if (sizing == 4 || sizing == 5)
|
||||||
{
|
{
|
||||||
int idx = layout == 0 ? 1 : 0;
|
float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
|
||||||
float offset =
|
int primOffset = sizing == 4 ? 0 : 2;
|
||||||
(((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1))
|
int secOffset = sizing == 5 ? 2 : 0;
|
||||||
? 192.f : 256.f)
|
|
||||||
+ screenGap) / 2.f;
|
|
||||||
if ((rotation == 1 || rotation == 2) ^ swapScreens)
|
|
||||||
offset *= -1.f;
|
|
||||||
|
|
||||||
M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0);
|
float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
|
||||||
M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0);
|
float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
|
||||||
|
|
||||||
refpoints[0][idx] -= offset;
|
float scale = std::min(screenWidth / hSize, screenHeight / vSize);
|
||||||
refpoints[1][idx] -= offset;
|
if (integerScale)
|
||||||
refpoints[2][idx] += offset;
|
scale = floorf(scale);
|
||||||
refpoints[3][idx] += offset;
|
|
||||||
|
|
||||||
botTrans[idx] = offset;
|
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
|
||||||
// scale
|
|
||||||
{
|
{
|
||||||
if (sizing == 0)
|
TopEnable = BotEnable = true;
|
||||||
|
// move screens apart
|
||||||
{
|
{
|
||||||
float minX = refpoints[0][0], maxX = minX;
|
int idx = layout == 0 ? 1 : 0;
|
||||||
float minY = refpoints[0][1], maxY = minY;
|
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++)
|
bool moveV = rotation % 2 == layout;
|
||||||
|
|
||||||
|
float offsetTop = (moveV ? 192 : 256 * topAspect) / 2 + screenGap / 2;
|
||||||
|
float offsetBot = (moveV ? 192 : 256 * botAspect) / 2 + screenGap / 2;
|
||||||
|
|
||||||
|
if ((rotation == 1 || rotation == 2) ^ swapScreens)
|
||||||
{
|
{
|
||||||
minX = std::min(minX, refpoints[i][0]);
|
offsetTop *= -1;
|
||||||
minY = std::min(minY, refpoints[i][1]);
|
offsetBot *= -1;
|
||||||
maxX = std::max(maxX, refpoints[i][0]);
|
|
||||||
maxY = std::max(maxY, refpoints[i][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float hSize = maxX - minX;
|
M23_Translate(TopScreenMtx, (idx==0)?-offsetTop:0, (idx==1)?-offsetTop:0);
|
||||||
float vSize = maxY - minY;
|
M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
|
||||||
|
|
||||||
// scale evenly
|
refpoints[0][idx] -= offsetTop;
|
||||||
float scale = std::min(screenWidth / hSize, screenHeight / vSize);
|
refpoints[1][idx] -= offsetTop;
|
||||||
|
refpoints[2][idx] += offsetBot;
|
||||||
|
refpoints[3][idx] += offsetBot;
|
||||||
|
|
||||||
if (integerScale)
|
botTrans[idx] = offsetBot;
|
||||||
scale = floor(scale);
|
|
||||||
|
|
||||||
M23_Scale(TopScreenMtx, scale);
|
|
||||||
M23_Scale(BotScreenMtx, scale);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
refpoints[i][0] *= scale;
|
|
||||||
refpoints[i][1] *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
botScale = scale;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// scale
|
||||||
{
|
{
|
||||||
int primOffset = (sizing == 1) ? 0 : 2;
|
if (sizing == 0)
|
||||||
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 (layout == 0)
|
|
||||||
{
|
{
|
||||||
if (screenHeight - primVSize * primScale < secVSize)
|
float minX = refpoints[0][0], maxX = minX;
|
||||||
primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
|
float minY = refpoints[0][1], maxY = minY;
|
||||||
else
|
|
||||||
secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
|
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;
|
||||||
|
|
||||||
|
// scale evenly
|
||||||
|
float scale = std::min(screenWidth / hSize, screenHeight / vSize);
|
||||||
|
|
||||||
|
if (integerScale)
|
||||||
|
scale = floor(scale);
|
||||||
|
|
||||||
|
M23_Scale(TopScreenMtx, scale);
|
||||||
|
M23_Scale(BotScreenMtx, scale);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
refpoints[i][0] *= scale;
|
||||||
|
refpoints[i][1] *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
botScale = scale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (screenWidth - primHSize * primScale < secHSize)
|
int primOffset = (sizing == 1) ? 0 : 2;
|
||||||
primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
|
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 (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
|
else
|
||||||
secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
|
{
|
||||||
|
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 = floor(primScale);
|
||||||
|
secScale = floor(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (integerScale)
|
|
||||||
{
|
|
||||||
primScale = floor(primScale);
|
|
||||||
secScale = floor(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
|
// position
|
||||||
{
|
{
|
||||||
float minX = refpoints[0][0], maxX = minX;
|
float minX = refpoints[posRefPointOffset][0], maxX = minX;
|
||||||
float minY = refpoints[0][1], maxY = minY;
|
float minY = refpoints[posRefPointOffset][1], maxY = minY;
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++)
|
for (int i = posRefPointOffset + 1; i < posRefPointOffset + posRefPointCount; i++)
|
||||||
{
|
{
|
||||||
minX = std::min(minX, refpoints[i][0]);
|
minX = std::min(minX, refpoints[i][0]);
|
||||||
minY = std::min(minY, refpoints[i][1]);
|
minY = std::min(minY, refpoints[i][1]);
|
||||||
|
@ -297,6 +353,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||||
// prepare a 'reverse' matrix for the touchscreen
|
// prepare a 'reverse' matrix for the touchscreen
|
||||||
// this matrix undoes the transforms applied to the bottom screen
|
// this matrix undoes the transforms applied to the bottom screen
|
||||||
// and can be used to calculate touchscreen coords from host screen coords
|
// and can be used to calculate touchscreen coords from host screen coords
|
||||||
|
if (BotEnable)
|
||||||
{
|
{
|
||||||
M23_Identity(TouchMtx);
|
M23_Identity(TouchMtx);
|
||||||
|
|
||||||
|
@ -309,25 +366,45 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||||
M23_RotateFast(rotmtx, (4-rotation) & 3);
|
M23_RotateFast(rotmtx, (4-rotation) & 3);
|
||||||
M23_Multiply(TouchMtx, rotmtx, TouchMtx);
|
M23_Multiply(TouchMtx, rotmtx, TouchMtx);
|
||||||
|
|
||||||
|
M23_Scale(TouchMtx, 1.f/botAspect, 1);
|
||||||
M23_Translate(TouchMtx, 256/2, 192/2);
|
M23_Translate(TouchMtx, 256/2, 192/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetScreenTransforms(float* top, float* bot)
|
int GetScreenTransforms(float* out, int* kind)
|
||||||
{
|
{
|
||||||
memcpy(top, TopScreenMtx, 6*sizeof(float));
|
int num = 0;
|
||||||
memcpy(bot, BotScreenMtx, 6*sizeof(float));
|
if (TopEnable)
|
||||||
|
{
|
||||||
|
memcpy(out + 6*num, TopScreenMtx, sizeof(TopScreenMtx));
|
||||||
|
kind[num] = 0;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
if (BotEnable)
|
||||||
|
{
|
||||||
|
memcpy(out + 6*num, BotScreenMtx, sizeof(BotScreenMtx));
|
||||||
|
kind[num] = 1;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetTouchCoords(int& x, int& y)
|
bool GetTouchCoords(int& x, int& y)
|
||||||
{
|
{
|
||||||
float vx = x;
|
if (BotEnable)
|
||||||
float vy = y;
|
{
|
||||||
|
float vx = x;
|
||||||
|
float vy = y;
|
||||||
|
|
||||||
M23_Transform(TouchMtx, vx, vy);
|
M23_Transform(TouchMtx, vx, vy);
|
||||||
|
|
||||||
x = (int)vx;
|
x = (int)vx;
|
||||||
y = (int)vy;
|
y = (int)vy;
|
||||||
|
|
||||||
|
if (x >= 0 && x < 256 && y >= 0 && y < 192)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ int ScreenLayout;
|
||||||
int ScreenSwap;
|
int ScreenSwap;
|
||||||
int ScreenSizing;
|
int ScreenSizing;
|
||||||
int IntegerScaling;
|
int IntegerScaling;
|
||||||
|
int ScreenAspectTop;
|
||||||
|
int ScreenAspectBot;
|
||||||
int ScreenFilter;
|
int ScreenFilter;
|
||||||
|
|
||||||
int ScreenUseGL;
|
int ScreenUseGL;
|
||||||
|
@ -146,6 +148,8 @@ ConfigEntry PlatformConfigFile[] =
|
||||||
{"ScreenSwap", 0, &ScreenSwap, 0, NULL, 0},
|
{"ScreenSwap", 0, &ScreenSwap, 0, NULL, 0},
|
||||||
{"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0},
|
{"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0},
|
||||||
{"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},
|
{"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},
|
||||||
|
{"ScreenAspectTop",0, &ScreenAspectTop,0, NULL, 0},
|
||||||
|
{"ScreenAspectBot",0, &ScreenAspectBot,0, NULL, 0},
|
||||||
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
||||||
|
|
||||||
{"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0},
|
{"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0},
|
||||||
|
|
|
@ -56,6 +56,8 @@ extern int ScreenGap;
|
||||||
extern int ScreenLayout;
|
extern int ScreenLayout;
|
||||||
extern int ScreenSwap;
|
extern int ScreenSwap;
|
||||||
extern int ScreenSizing;
|
extern int ScreenSizing;
|
||||||
|
extern int ScreenAspectTop;
|
||||||
|
extern int ScreenAspectBot;
|
||||||
extern int IntegerScaling;
|
extern int IntegerScaling;
|
||||||
extern int ScreenFilter;
|
extern int ScreenFilter;
|
||||||
|
|
||||||
|
|
|
@ -646,15 +646,25 @@ void ScreenHandler::screenSetupLayout(int w, int h)
|
||||||
int sizing = Config::ScreenSizing;
|
int sizing = Config::ScreenSizing;
|
||||||
if (sizing == 3) sizing = autoScreenSizing;
|
if (sizing == 3) sizing = autoScreenSizing;
|
||||||
|
|
||||||
|
float aspectRatios[] =
|
||||||
|
{
|
||||||
|
1.f,
|
||||||
|
(16.f/9)/(4.f/3),
|
||||||
|
(21.f/9)/(4.f/3),
|
||||||
|
((float)w/h)/(4.f/3)
|
||||||
|
};
|
||||||
|
|
||||||
Frontend::SetupScreenLayout(w, h,
|
Frontend::SetupScreenLayout(w, h,
|
||||||
Config::ScreenLayout,
|
Config::ScreenLayout,
|
||||||
Config::ScreenRotation,
|
Config::ScreenRotation,
|
||||||
sizing,
|
sizing,
|
||||||
Config::ScreenGap,
|
Config::ScreenGap,
|
||||||
Config::IntegerScaling != 0,
|
Config::IntegerScaling != 0,
|
||||||
Config::ScreenSwap != 0);
|
Config::ScreenSwap != 0,
|
||||||
|
aspectRatios[Config::ScreenAspectTop],
|
||||||
|
aspectRatios[Config::ScreenAspectBot]);
|
||||||
|
|
||||||
Frontend::GetScreenTransforms(screenMatrix[0], screenMatrix[1]);
|
numScreens = Frontend::GetScreenTransforms(screenMatrix[0], screenKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize ScreenHandler::screenGetMinSize()
|
QSize ScreenHandler::screenGetMinSize()
|
||||||
|
@ -779,19 +789,16 @@ void ScreenPanelNative::setupScreenLayout()
|
||||||
{
|
{
|
||||||
int w = width();
|
int w = width();
|
||||||
int h = height();
|
int h = height();
|
||||||
float* mtx;
|
|
||||||
|
|
||||||
screenSetupLayout(w, h);
|
screenSetupLayout(w, h);
|
||||||
|
|
||||||
mtx = screenMatrix[0];
|
for (int i = 0; i < numScreens; i++)
|
||||||
screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f,
|
{
|
||||||
mtx[2], mtx[3], 0.f,
|
float* mtx = screenMatrix[i];
|
||||||
mtx[4], mtx[5], 1.f);
|
screenTrans[i].setMatrix(mtx[0], mtx[1], 0.f,
|
||||||
|
mtx[2], mtx[3], 0.f,
|
||||||
mtx = screenMatrix[1];
|
mtx[4], mtx[5], 1.f);
|
||||||
screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f,
|
}
|
||||||
mtx[2], mtx[3], 0.f,
|
|
||||||
mtx[4], mtx[5], 1.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
||||||
|
@ -811,11 +818,11 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
||||||
|
|
||||||
QRect screenrc(0, 0, 256, 192);
|
QRect screenrc(0, 0, 256, 192);
|
||||||
|
|
||||||
painter.setTransform(screenTrans[0]);
|
for (int i = 0; i < numScreens; i++)
|
||||||
painter.drawImage(screenrc, screen[0]);
|
{
|
||||||
|
painter.setTransform(screenTrans[i]);
|
||||||
painter.setTransform(screenTrans[1]);
|
painter.drawImage(screenrc, screen[screenKind[i]]);
|
||||||
painter.drawImage(screenrc, screen[1]);
|
}
|
||||||
|
|
||||||
OSD::Update(nullptr);
|
OSD::Update(nullptr);
|
||||||
OSD::DrawNative(painter);
|
OSD::DrawNative(painter);
|
||||||
|
@ -1002,11 +1009,11 @@ void ScreenPanelGL::paintGL()
|
||||||
|
|
||||||
GLint transloc = screenShader->uniformLocation("uTransform");
|
GLint transloc = screenShader->uniformLocation("uTransform");
|
||||||
|
|
||||||
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[0]);
|
for (int i = 0; i < numScreens; i++)
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 2*3);
|
{
|
||||||
|
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[i]);
|
||||||
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[1]);
|
glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3);
|
||||||
glDrawArrays(GL_TRIANGLES, 2*3, 2*3);
|
}
|
||||||
|
|
||||||
screenShader->release();
|
screenShader->release();
|
||||||
|
|
||||||
|
@ -1272,9 +1279,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
QMenu* submenu = menu->addMenu("Screen sizing");
|
QMenu* submenu = menu->addMenu("Screen sizing");
|
||||||
grpScreenSizing = new QActionGroup(submenu);
|
grpScreenSizing = new QActionGroup(submenu);
|
||||||
|
|
||||||
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto"};
|
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
|
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
|
||||||
actScreenSizing[i]->setActionGroup(grpScreenSizing);
|
actScreenSizing[i]->setActionGroup(grpScreenSizing);
|
||||||
|
@ -1290,6 +1297,38 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
actIntegerScaling->setCheckable(true);
|
actIntegerScaling->setCheckable(true);
|
||||||
connect(actIntegerScaling, &QAction::triggered, this, &MainWindow::onChangeIntegerScaling);
|
connect(actIntegerScaling, &QAction::triggered, this, &MainWindow::onChangeIntegerScaling);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
QMenu* submenu = menu->addMenu("Aspect ratio");
|
||||||
|
grpScreenAspectTop = new QActionGroup(submenu);
|
||||||
|
|
||||||
|
const char* aspectRatiosTop[] = {"Top 4:3 (native)", "Top 16:9", "Top 21:9", "Top window"};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
actScreenAspectTop[i] = submenu->addAction(QString(aspectRatiosTop[i]));
|
||||||
|
actScreenAspectTop[i]->setActionGroup(grpScreenAspectTop);
|
||||||
|
actScreenAspectTop[i]->setData(QVariant(i));
|
||||||
|
actScreenAspectTop[i]->setCheckable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(grpScreenAspectTop, &QActionGroup::triggered, this, &MainWindow::onChangeScreenAspectTop);
|
||||||
|
|
||||||
|
submenu->addSeparator();
|
||||||
|
|
||||||
|
grpScreenAspectBot = new QActionGroup(submenu);
|
||||||
|
|
||||||
|
const char* aspectRatiosBot[] = {"Bottom 4:3 (native)", "Bottom 16:9", "Bottom 21:9", "Bottom window"};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
actScreenAspectBot[i] = submenu->addAction(QString(aspectRatiosBot[i]));
|
||||||
|
actScreenAspectBot[i]->setActionGroup(grpScreenAspectBot);
|
||||||
|
actScreenAspectBot[i]->setData(QVariant(i));
|
||||||
|
actScreenAspectBot[i]->setCheckable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(grpScreenAspectBot, &QActionGroup::triggered, this, &MainWindow::onChangeScreenAspectBot);
|
||||||
|
}
|
||||||
|
|
||||||
actScreenFiltering = menu->addAction("Screen filtering");
|
actScreenFiltering = menu->addAction("Screen filtering");
|
||||||
actScreenFiltering->setCheckable(true);
|
actScreenFiltering->setCheckable(true);
|
||||||
|
@ -1352,6 +1391,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
actScreenSwap->setChecked(Config::ScreenSwap != 0);
|
actScreenSwap->setChecked(Config::ScreenSwap != 0);
|
||||||
|
|
||||||
|
actScreenAspectTop[Config::ScreenAspectTop]->setChecked(true);
|
||||||
|
actScreenAspectBot[Config::ScreenAspectBot]->setChecked(true);
|
||||||
|
|
||||||
actScreenFiltering->setChecked(Config::ScreenFilter != 0);
|
actScreenFiltering->setChecked(Config::ScreenFilter != 0);
|
||||||
actShowOSD->setChecked(Config::ShowOSD != 0);
|
actShowOSD->setChecked(Config::ShowOSD != 0);
|
||||||
|
|
||||||
|
@ -2264,6 +2306,22 @@ void MainWindow::onChangeScreenSizing(QAction* act)
|
||||||
emit screenLayoutChange();
|
emit screenLayoutChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onChangeScreenAspectTop(QAction* act)
|
||||||
|
{
|
||||||
|
int aspect = act->data().toInt();
|
||||||
|
Config::ScreenAspectTop = aspect;
|
||||||
|
|
||||||
|
emit screenLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onChangeScreenAspectBot(QAction* act)
|
||||||
|
{
|
||||||
|
int aspect = act->data().toInt();
|
||||||
|
Config::ScreenAspectBot = aspect;
|
||||||
|
|
||||||
|
emit screenLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onChangeIntegerScaling(bool checked)
|
void MainWindow::onChangeIntegerScaling(bool checked)
|
||||||
{
|
{
|
||||||
Config::IntegerScaling = checked?1:0;
|
Config::IntegerScaling = checked?1:0;
|
||||||
|
@ -2444,7 +2502,9 @@ int main(int argc, char** argv)
|
||||||
SANITIZE(Config::ScreenRotation, 0, 3);
|
SANITIZE(Config::ScreenRotation, 0, 3);
|
||||||
SANITIZE(Config::ScreenGap, 0, 500);
|
SANITIZE(Config::ScreenGap, 0, 500);
|
||||||
SANITIZE(Config::ScreenLayout, 0, 2);
|
SANITIZE(Config::ScreenLayout, 0, 2);
|
||||||
SANITIZE(Config::ScreenSizing, 0, 3);
|
SANITIZE(Config::ScreenSizing, 0, 5);
|
||||||
|
SANITIZE(Config::ScreenAspectTop, 0, 4);
|
||||||
|
SANITIZE(Config::ScreenAspectBot, 0, 4);
|
||||||
#undef SANITIZE
|
#undef SANITIZE
|
||||||
|
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <QOpenGLFunctions_3_2_Core>
|
#include <QOpenGLFunctions_3_2_Core>
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
|
|
||||||
|
#include "FrontendUtil.h"
|
||||||
|
|
||||||
class EmuThread : public QThread
|
class EmuThread : public QThread
|
||||||
{
|
{
|
||||||
|
@ -105,7 +106,9 @@ protected:
|
||||||
void screenOnMouseRelease(QMouseEvent* event);
|
void screenOnMouseRelease(QMouseEvent* event);
|
||||||
void screenOnMouseMove(QMouseEvent* event);
|
void screenOnMouseMove(QMouseEvent* event);
|
||||||
|
|
||||||
float screenMatrix[2][6];
|
float screenMatrix[Frontend::MaxScreenTransforms][6];
|
||||||
|
int screenKind[Frontend::MaxScreenTransforms];
|
||||||
|
int numScreens;
|
||||||
|
|
||||||
bool touching;
|
bool touching;
|
||||||
|
|
||||||
|
@ -137,7 +140,7 @@ private:
|
||||||
void setupScreenLayout();
|
void setupScreenLayout();
|
||||||
|
|
||||||
QImage screen[2];
|
QImage screen[2];
|
||||||
QTransform screenTrans[2];
|
QTransform screenTrans[Frontend::MaxScreenTransforms];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,6 +240,8 @@ private slots:
|
||||||
void onChangeScreenLayout(QAction* act);
|
void onChangeScreenLayout(QAction* act);
|
||||||
void onChangeScreenSwap(bool checked);
|
void onChangeScreenSwap(bool checked);
|
||||||
void onChangeScreenSizing(QAction* act);
|
void onChangeScreenSizing(QAction* act);
|
||||||
|
void onChangeScreenAspectTop(QAction* act);
|
||||||
|
void onChangeScreenAspectBot(QAction* act);
|
||||||
void onChangeIntegerScaling(bool checked);
|
void onChangeIntegerScaling(bool checked);
|
||||||
void onChangeScreenFiltering(bool checked);
|
void onChangeScreenFiltering(bool checked);
|
||||||
void onChangeShowOSD(bool checked);
|
void onChangeShowOSD(bool checked);
|
||||||
|
@ -303,8 +308,12 @@ public:
|
||||||
QAction* actScreenLayout[3];
|
QAction* actScreenLayout[3];
|
||||||
QAction* actScreenSwap;
|
QAction* actScreenSwap;
|
||||||
QActionGroup* grpScreenSizing;
|
QActionGroup* grpScreenSizing;
|
||||||
QAction* actScreenSizing[4];
|
QAction* actScreenSizing[6];
|
||||||
QAction* actIntegerScaling;
|
QAction* actIntegerScaling;
|
||||||
|
QActionGroup* grpScreenAspectTop;
|
||||||
|
QAction* actScreenAspectTop[4];
|
||||||
|
QActionGroup* grpScreenAspectBot;
|
||||||
|
QAction* actScreenAspectBot[4];
|
||||||
QAction* actScreenFiltering;
|
QAction* actScreenFiltering;
|
||||||
QAction* actShowOSD;
|
QAction* actShowOSD;
|
||||||
QAction* actLimitFramerate;
|
QAction* actLimitFramerate;
|
||||||
|
|
Loading…
Reference in New Issue