various improvements to the new LCDs settings.

- you can select "main screen first" to automatically put the main GPU screen on top. combining this with the "one LCD" setting lets games like NSMB and Sonic Rush be playable on a single screen (it auto-switches to the screen that has the character on it).
- fully exclude screen gap from calculations when in single screen or side-by-side mode
- make OSD elements stay consistently located when flipping the LCDs around
- possibly improved the stylus-dragged-offscreen behavior for the alternate layouts
This commit is contained in:
nitsuja 2009-11-03 17:51:28 +00:00
parent 2c8473e761
commit 71022e6920
8 changed files with 147 additions and 52 deletions

View File

@ -56,6 +56,26 @@ static bool IsHudDummy (HudCoordinates *hud)
return (hud->x == 666 && hud->y == 666);
}
template<typename T>
static T calcY(T y) // alters a GUI element y coordinate as necessary to obey swapScreens and singleScreen settings
{
if(osd->singleScreen)
{
if(y >= 192)
y -= 192;
if(osd->swapScreens)
y += 192;
}
else if(osd->swapScreens)
{
if(y >= 192)
y -= 192;
else
y += 192;
}
return y;
}
void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
u32 i = 0;
@ -70,7 +90,7 @@ void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
}
if((x >= hud.x && x <= hud.x + hud.xsize) &&
(y >= hud.y && y <= hud.y + hud.ysize) && !hudstruct->clicked ) {
(calcY(y) >= calcY(hud.y) && calcY(y) <= calcY(hud.y) + hud.ysize) && !hudstruct->clicked ) {
hud.clicked=1;
hud.storedx = x - hud.x;
@ -200,7 +220,7 @@ static void drawPad(double x, double y, double ratio) {
// aligning to odd half-pixel boundaries prevents agg2d from blurring thin straight lines
x = floor(x) + 0.5;
y = floor(y) + 0.5;
y = floor(calcY(y)) + 0.5;
double xc = 41 - 0.5;
double yc = 20 - 0.5;
@ -346,7 +366,7 @@ static void TextualInputDisplay() {
std::string str(buttonChars+i, 2);
str[1] = '\0';
aggDraw.hud->renderTextDropshadowed(x, Hud.InputDisplay.y, str);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
}
// touch pad
@ -362,7 +382,7 @@ static void TextualInputDisplay() {
{
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,255,255,255);
aggDraw.hud->renderTextDropshadowed(x, Hud.InputDisplay.y, str);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
}
else
{
@ -370,19 +390,20 @@ static void TextualInputDisplay() {
{
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,48,48,255);
aggDraw.hud->renderTextDropshadowed(x, Hud.InputDisplay.y-(physicalTouchOn?8:0), str);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)-(physicalTouchOn?8:0), str);
}
if(physicalTouchOn)
{
sprintf(str, "%d,%d", physicalTouchX, physicalTouchY);
aggDraw.hud->lineColor(0,255,0,255);
aggDraw.hud->renderTextDropshadowed(x, Hud.InputDisplay.y+(gameTouchOn?8:0), str);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)+(gameTouchOn?8:0), str);
}
}
}
}
static void TouchDisplay() {
// note: calcY should not be used in this function.
aggDraw.hud->lineWidth(1.0);
temptouch.X = NDS_getRawUserInput().touch.touchX >> 4;
@ -400,7 +421,7 @@ static void TouchDisplay() {
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
aggDraw.hud->fillColor(0, 0, 0, touchalpha[i]);
aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y-1 + 192, temptouch.X+1, temptouch.Y+1 + 192);
aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y + 192-1, temptouch.X+1, temptouch.Y + 192+1);
}
}
}
@ -427,7 +448,7 @@ static s64 slotTimer=0;
static void DrawStateSlots(){
const int yloc = Hud.SavestateSlots.y; //160
const int yloc = calcY(Hud.SavestateSlots.y); //160
const int xloc = Hud.SavestateSlots.x; //8
s64 fadecounter = 512 - (hudTimer-slotTimer)/4; //change constant to alter fade speed
@ -476,10 +497,10 @@ static void DrawEditableElementIndicators()
aggDraw.hud->fillColor(0,0,0,0);
aggDraw.hud->lineColor(0,0,0,64);
aggDraw.hud->lineWidth(2.0);
aggDraw.hud->rectangle(hud.x,hud.y,hud.x+hud.xsize+1.0,hud.y+hud.ysize+1.0);
aggDraw.hud->rectangle(hud.x,calcY(hud.y),hud.x+hud.xsize+1.0,calcY(hud.y)+hud.ysize+1.0);
aggDraw.hud->lineColor(255,hud.clicked?127:255,0,255);
aggDraw.hud->lineWidth(1.0);
aggDraw.hud->rectangle(hud.x-0.5,hud.y-0.5,hud.x+hud.xsize+0.5,hud.y+hud.ysize+0.5);
aggDraw.hud->rectangle(hud.x-0.5,calcY(hud.y)-0.5,hud.x+hud.xsize+0.5,calcY(hud.y)+hud.ysize+0.5);
i++;
}
}
@ -562,6 +583,9 @@ OSDCLASS::OSDCLASS(u8 core)
rotAngle = 0;
singleScreen = false;
swapScreens = false;
needUpdate = false;
if (core==0)
@ -705,7 +729,7 @@ void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...)
va_end(list);
aggDraw.hud->lineColor(255,255,255);
aggDraw.hud->renderTextDropshadowed(x,y,msg);
aggDraw.hud->renderTextDropshadowed(x,calcY(y),msg);
needUpdate = true;
}

View File

@ -104,8 +104,12 @@ private:
bool needUpdate;
bool checkTimers();
public:
char name[7]; // for debuging
bool singleScreen;
bool swapScreens;
OSDCLASS(u8 core);
~OSDCLASS();

View File

@ -3631,7 +3631,7 @@ DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "")
// mouse position in game screen pixel coordinates
{
void UnscaleScreenCoords(s32& x, s32& y);
void ToDSScreenRelativeCoords(s32& x, s32& y, bool bottomScreen);
void ToDSScreenRelativeCoords(s32& x, s32& y, int bottomScreen);
POINT point;
GetCursorPos(&point);
@ -3640,7 +3640,7 @@ DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "")
s32 y (point.y);
UnscaleScreenCoords(x,y);
ToDSScreenRelativeCoords(x,y,true);
ToDSScreenRelativeCoords(x,y,1);
lua_pushinteger(L, x);
lua_setfield(L, -2, "xmouse");

View File

@ -727,8 +727,6 @@ void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, s
assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY);
assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY);
currMovieData.truncateAt(currFrameCounter);
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr);
@ -912,6 +910,7 @@ bool mov_loadstate(EMUFILE* fp, int size)
// #endif
currMovieData.rerecordCount = currRerecordCount;
currMovieData.truncateAt(currFrameCounter);
openRecordingMovie(curMovieFilename);
if(!osRecordingMovie)

View File

@ -216,10 +216,10 @@ void HK_LCDsMode(int)
doLCDsLayout();
}
extern void LCDsSwap();
extern void LCDsSwap(int);
void HK_LCDsSwap(int)
{
LCDsSwap();
LCDsSwap(-1);
}
void HK_Reset(int, bool justPressed) {ResetGame();}

View File

@ -504,8 +504,9 @@ void UnscaleScreenCoords(s32& x, s32& y)
// input x,y should be windows client-space coords already at 1x scaling.
// output is in pixels relative to the top-left of the chosen screen.
// (-1 == top screen, 1 == bottom screen, 0 == absolute vertically aligned)
// the gap between screens (if any) is subtracted away from the output y.
void ToDSScreenRelativeCoords(s32& x, s32& y, bool bottomScreen)
void ToDSScreenRelativeCoords(s32& x, s32& y, int whichScreen)
{
s32 tx=x, ty=y;
@ -536,26 +537,46 @@ void ToDSScreenRelativeCoords(s32& x, s32& y, bool bottomScreen)
y = 192;
else if(y > 191)
y = 191;
// finally, make it relative to the correct screen
if((bottomScreen) && (video.swap == 0))
y -= 192;
}
else
if (video.layout == 1)
// finally, make it relative to the correct screen
if (video.layout == 0 || video.layout == 2)
{
if(whichScreen)
{
if (video.swap == 0)
x = tx - 255;
bool topOnTop = (video.swap == 0) || (video.swap == 2 && !MainScreen.offset) || (video.swap == 3 && MainScreen.offset);
bool bottom = (whichScreen > 0);
if(topOnTop)
y += bottom ? -192 : 0;
else
x = tx;
//INFO("X=%i, Y=%i (tx = %i, ty = %i)\n", x, y, tx, ty);
y += (y < 192) ? (bottom ? 0 : 192) : (bottom ? 0 : -192);
}
}
else if (video.layout == 1) // side-by-side
{
if(whichScreen)
{
bool topOnTop = (video.swap == 0) || (video.swap == 2 && !MainScreen.offset) || (video.swap == 3 && MainScreen.offset);
bool bottom = (whichScreen > 0);
if(topOnTop)
x += bottom ? -256 : 0;
else
x += (x < 256) ? (bottom ? 0 : 256) : (bottom ? 0 : -256);
}
else
if (video.layout == 2)
{
if(x >= 256)
{
x = tx;
//INFO("X=%i, Y=%i (tx = %i, ty = %i)\n", x, y, tx, ty);
x -= 256;
y += 192;
}
else if(x < 0)
{
x += 256;
y -= 192;
}
}
}
}
// END Rotation definitions
@ -953,16 +974,21 @@ template<typename T, int bpp> static void doRotate(void* dst)
}
void UpdateWndRects(HWND hwnd);
void FixAspectRatio();
void LCDsSwap()
void LCDsSwap(int swapVal)
{
video.swap = !video.swap;
MainWindow->checkMenu(ID_LCDS_SWAP, !video.swap);
if(swapVal == -1) swapVal = video.swap ^ 1; // -1 means to flip the existing setting
if(swapVal < 0 || swapVal > 3) swapVal = 0;
if(osd && !(swapVal & video.swap & 1)) osd->swapScreens = !osd->swapScreens; // 1-frame fixup
video.swap = swapVal;
WritePrivateProfileInt("Video", "LCDsSwap", video.swap, IniName);
}
void doLCDsLayout()
{
osd->singleScreen = (video.layout == 2);
RECT rc = { 0 };
int oldheight, oldwidth;
int newheight, newwidth;
@ -1078,6 +1104,7 @@ void doLCDsLayout()
WritePrivateProfileInt("Video", "LCDsLayout", video.layout, IniName);
SetMinWindowSize();
MainWindow->setClientSize(newwidth, newheight);
FixAspectRatio();
UpdateWndRects(MainWindow->getHWnd());
}
@ -1116,10 +1143,40 @@ static void DD_DoDisplay()
lpBackSurface->Unlock((LPRECT)ddsd.lpSurface);
if (video.layout != 2)
RECT* dstRects [2] = {&MainScreenRect, &SubScreenRect};
RECT* srcRects [2];
if(video.swap == 0)
{
// Main screen
if(lpPrimarySurface->Blt(&MainScreenRect, lpBackSurface, (video.swap == 0)?&MainScreenSrcRect:&SubScreenSrcRect, DDBLT_WAIT, 0) == DDERR_SURFACELOST)
srcRects[0] = &MainScreenSrcRect;
srcRects[1] = &SubScreenSrcRect;
if(osd) osd->swapScreens = false;
}
else if(video.swap == 1)
{
srcRects[0] = &SubScreenSrcRect;
srcRects[1] = &MainScreenSrcRect;
if(osd) osd->swapScreens = true;
}
else if(video.swap == 2)
{
srcRects[0] = (MainScreen.offset) ? &SubScreenSrcRect : &MainScreenSrcRect;
srcRects[1] = (MainScreen.offset) ? &MainScreenSrcRect : &SubScreenSrcRect;
if(osd) osd->swapScreens = (MainScreen.offset != 0);
}
else if(video.swap == 3)
{
srcRects[0] = (MainScreen.offset) ? &MainScreenSrcRect : &SubScreenSrcRect;
srcRects[1] = (MainScreen.offset) ? &SubScreenSrcRect : &MainScreenSrcRect;
if(osd) osd->swapScreens = (SubScreen.offset != 0);
}
for(int i = 0; i < 2; i++)
{
if(i && video.layout == 2)
break;
if(lpPrimarySurface->Blt(dstRects[i], lpBackSurface, srcRects[i], DDBLT_WAIT, 0) == DDERR_SURFACELOST)
{
LOG("DirectDraw buffers is lost\n");
if(IDirectDrawSurface7_Restore(lpPrimarySurface) == DD_OK)
@ -1127,14 +1184,6 @@ static void DD_DoDisplay()
}
}
// Sub screen
if(lpPrimarySurface->Blt(video.layout == 2?&MainScreenRect:&SubScreenRect, lpBackSurface, (video.swap == 0)?&SubScreenSrcRect:&MainScreenSrcRect, DDBLT_WAIT, 0) == DDERR_SURFACELOST)
{
LOG("DirectDraw buffers is lost\n");
if(IDirectDrawSurface7_Restore(lpPrimarySurface) == DD_OK)
IDirectDrawSurface7_Restore(lpBackSurface);
}
if (video.layout == 1) return;
if (video.layout == 2) return;
@ -2104,7 +2153,6 @@ int _main()
video.layout = video.layout_old = 0;
}
video.swap = GetPrivateProfileInt("Video", "LCDsSwap", 0, IniName);
if (video.swap > 1) video.swap = 1;
CommonSettings.hud.FpsDisplay = GetPrivateProfileBool("Display","Display Fps", false, IniName);
CommonSettings.hud.FrameCounterDisplay = GetPrivateProfileBool("Display","FrameCounter", false, IniName);
@ -2287,6 +2335,8 @@ int _main()
NDS_Init ();
#endif
osd->singleScreen = (video.layout == 2);
/*
* Activate the GDB stubs
* This has to come after the NDS_Init where the cpus are set up.
@ -2517,7 +2567,9 @@ void UpdateWndRects(HWND hwnd)
RECT rc;
int wndWidth, wndHeight;
int defHeight = (video.height + video.screengap);
int defHeight = video.height;
if(video.layout == 0)
defHeight += video.screengap;
float ratio;
int oneScreenHeight, gapHeight;
@ -3365,7 +3417,11 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
MainWindow->checkMenu(ID_LCDS_VERTICAL, ((video.layout==0)));
MainWindow->checkMenu(ID_LCDS_HORIZONTAL, ((video.layout==1)));
MainWindow->checkMenu(ID_LCDS_ONE, ((video.layout==2)));
MainWindow->checkMenu(ID_LCDS_SWAP, video.swap);
// LCDs swap
MainWindow->checkMenu(ID_LCDS_NOSWAP, video.swap == 0);
MainWindow->checkMenu(ID_LCDS_SWAP, video.swap == 1);
MainWindow->checkMenu(ID_LCDS_MAINGPU, video.swap == 2);
MainWindow->checkMenu(ID_LCDS_SUBGPU, video.swap == 3);
//Force Maintain Ratio
MainWindow->checkMenu(IDC_FORCERATIO, ((ForceRatio)));
//Screen rotation
@ -3833,13 +3889,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
if(HudEditorMode)
{
ToDSScreenRelativeCoords(x,y,false);
ToDSScreenRelativeCoords(x,y,0);
EditHud(x,y, &Hud);
}
else
{
if ((video.layout == 2) && (video.swap == 1)) return 0;
ToDSScreenRelativeCoords(x,y,true);
if ((video.layout == 2) && ((video.swap == 0) || (video.swap == 2 && !MainScreen.offset) || (video.swap == 3 && MainScreen.offset))) return 0;
ToDSScreenRelativeCoords(x,y,1);
if(x<0) x = 0; else if(x>255) x = 255;
if(y<0) y = 0; else if(y>192) y = 192;
NDS_setTouchPos(x, y);
@ -4456,8 +4512,17 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
doLCDsLayout();
return 0;
case ID_LCDS_NOSWAP:
LCDsSwap(0);
return 0;
case ID_LCDS_SWAP:
LCDsSwap();
LCDsSwap(1);
return 0;
case ID_LCDS_MAINGPU:
LCDsSwap(2);
return 0;
case ID_LCDS_SUBGPU:
LCDsSwap(3);
return 0;
case ID_VIEW_FRAMECOUNTER:

View File

@ -708,6 +708,9 @@
#define ID_LCDS_HORIZONTAL 40056
#define ID_LCDS_ONE 40057
#define ID_LCDS_SWAP 40058
#define ID_LCDS_NOSWAP 40059
#define ID_LCDS_MAINGPU 40060
#define ID_LCDS_SUBGPU 40061
#define IDC_LABEL_UP 50000
#define IDC_LABEL_RIGHT 50001
#define IDC_LABEL_LEFT 50002

Binary file not shown.