From 71022e6920924b3483b551566003251db451aba9 Mon Sep 17 00:00:00 2001 From: nitsuja Date: Tue, 3 Nov 2009 17:51:28 +0000 Subject: [PATCH] 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 --- desmume/src/GPU_osd.cpp | 46 ++++++++--- desmume/src/GPU_osd.h | 4 + desmume/src/lua-engine.cpp | 4 +- desmume/src/movie.cpp | 3 +- desmume/src/windows/hotkey.cpp | 4 +- desmume/src/windows/main.cpp | 135 +++++++++++++++++++++++-------- desmume/src/windows/resource.h | 3 + desmume/src/windows/resources.rc | Bin 441870 -> 443510 bytes 8 files changed, 147 insertions(+), 52 deletions(-) diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index 79698ab83..c05272ef3 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -56,6 +56,26 @@ static bool IsHudDummy (HudCoordinates *hud) return (hud->x == 666 && hud->y == 666); } +template +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; } diff --git a/desmume/src/GPU_osd.h b/desmume/src/GPU_osd.h index c479d6c98..a95885e86 100644 --- a/desmume/src/GPU_osd.h +++ b/desmume/src/GPU_osd.h @@ -104,8 +104,12 @@ private: bool needUpdate; bool checkTimers(); + public: char name[7]; // for debuging + bool singleScreen; + bool swapScreens; + OSDCLASS(u8 core); ~OSDCLASS(); diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index 2db6c6a7b..d9146d895 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -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"); diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp index 1360c91d8..2f2f663f0 100644 --- a/desmume/src/movie.cpp +++ b/desmume/src/movie.cpp @@ -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) diff --git a/desmume/src/windows/hotkey.cpp b/desmume/src/windows/hotkey.cpp index f2f6c7589..bdb401510 100644 --- a/desmume/src/windows/hotkey.cpp +++ b/desmume/src/windows/hotkey.cpp @@ -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();} diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 0be8bb118..8a5cdee30 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -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 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: diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index 38d0f8265..5005e7cbc 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -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 diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 5ce4577e891f2ad55d0f07d9f1d3c9a8d2e33e06..8a3f9d08339a8aea9a3ff10118631eb032a443c1 100644 GIT binary patch delta 824 zcmeDCBlWFAdc!_l6)2L(P|A?QP%`$L^BHmx222)o(w?lK!!ups9IFgSotkJdLo(3l zR3OYlsGGj=Hmf2?A+IlkBZDV{AA>tX07K~H!e~qE8h{4NgIpoR8Oq=UQQR!3*Dk2X zxLr_>X|3jv_Q`g^2&Tk4L)r_|fnHd+d5xY7Q+ty+GZ3?EZ!%{Mnl?;4wf)HjR;{-H DD}m11 delta 143 zcmey?A>H>!YQsKV_F#r`hD3&f>4hH5meUoYm^7LX=(iuxXWV{3pJ|3Bru5_k`Wn+O qSTd(Zb3`&?($dJ6yo