mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 14:19:55 -06:00
more screen modes
- add support for different aspect ratios - add support for displaying only one screen at once
This commit is contained in:
@ -31,7 +31,8 @@ namespace Frontend
|
||||
float TopScreenMtx[6];
|
||||
float BotScreenMtx[6];
|
||||
float TouchMtx[6];
|
||||
|
||||
bool TopEnable;
|
||||
bool BotEnable;
|
||||
|
||||
void M23_Identity(float* m)
|
||||
{
|
||||
@ -47,6 +48,13 @@ void M23_Scale(float* m, float 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;
|
||||
@ -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] =
|
||||
{
|
||||
@ -130,6 +145,9 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||
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];
|
||||
@ -145,136 +163,174 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||
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 offset =
|
||||
(((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1))
|
||||
? 192.f : 256.f)
|
||||
+ screenGap) / 2.f;
|
||||
if ((rotation == 1 || rotation == 2) ^ swapScreens)
|
||||
offset *= -1.f;
|
||||
float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
|
||||
int primOffset = sizing == 4 ? 0 : 2;
|
||||
int secOffset = sizing == 5 ? 2 : 0;
|
||||
|
||||
M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0);
|
||||
M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0);
|
||||
float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
|
||||
float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
|
||||
|
||||
refpoints[0][idx] -= offset;
|
||||
refpoints[1][idx] -= offset;
|
||||
refpoints[2][idx] += offset;
|
||||
refpoints[3][idx] += offset;
|
||||
float scale = std::min(screenWidth / hSize, screenHeight / vSize);
|
||||
if (integerScale)
|
||||
scale = floorf(scale);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// scale
|
||||
else
|
||||
{
|
||||
if (sizing == 0)
|
||||
TopEnable = BotEnable = true;
|
||||
// move screens apart
|
||||
{
|
||||
float minX = refpoints[0][0], maxX = minX;
|
||||
float minY = refpoints[0][1], maxY = minY;
|
||||
int idx = layout == 0 ? 1 : 0;
|
||||
|
||||
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]);
|
||||
minY = std::min(minY, refpoints[i][1]);
|
||||
maxX = std::max(maxX, refpoints[i][0]);
|
||||
maxY = std::max(maxY, refpoints[i][1]);
|
||||
offsetTop *= -1;
|
||||
offsetBot *= -1;
|
||||
}
|
||||
|
||||
float hSize = maxX - minX;
|
||||
float vSize = maxY - minY;
|
||||
M23_Translate(TopScreenMtx, (idx==0)?-offsetTop:0, (idx==1)?-offsetTop:0);
|
||||
M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
|
||||
|
||||
// scale evenly
|
||||
float scale = std::min(screenWidth / hSize, screenHeight / vSize);
|
||||
refpoints[0][idx] -= offsetTop;
|
||||
refpoints[1][idx] -= offsetTop;
|
||||
refpoints[2][idx] += offsetBot;
|
||||
refpoints[3][idx] += offsetBot;
|
||||
|
||||
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;
|
||||
botTrans[idx] = offsetBot;
|
||||
}
|
||||
else
|
||||
|
||||
// scale
|
||||
{
|
||||
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 (layout == 0)
|
||||
if (sizing == 0)
|
||||
{
|
||||
if (screenHeight - primVSize * primScale < secVSize)
|
||||
primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
|
||||
else
|
||||
secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
|
||||
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;
|
||||
|
||||
// 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
|
||||
{
|
||||
if (screenWidth - primHSize * primScale < secHSize)
|
||||
primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
|
||||
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 (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
|
||||
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
|
||||
{
|
||||
float minX = refpoints[0][0], maxX = minX;
|
||||
float minY = refpoints[0][1], maxY = minY;
|
||||
float minX = refpoints[posRefPointOffset][0], maxX = minX;
|
||||
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]);
|
||||
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
|
||||
// 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);
|
||||
|
||||
@ -309,25 +366,45 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void GetScreenTransforms(float* top, float* bot)
|
||||
int GetScreenTransforms(float* out, int* kind)
|
||||
{
|
||||
memcpy(top, TopScreenMtx, 6*sizeof(float));
|
||||
memcpy(bot, BotScreenMtx, 6*sizeof(float));
|
||||
int num = 0;
|
||||
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;
|
||||
float vy = y;
|
||||
if (BotEnable)
|
||||
{
|
||||
float vx = x;
|
||||
float vy = y;
|
||||
|
||||
M23_Transform(TouchMtx, vx, vy);
|
||||
M23_Transform(TouchMtx, vx, vy);
|
||||
|
||||
x = (int)vx;
|
||||
y = (int)vy;
|
||||
x = (int)vx;
|
||||
y = (int)vy;
|
||||
|
||||
if (x >= 0 && x < 256 && y >= 0 && y < 192)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user