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 5ce4577e8..8a3f9d083 100644 Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ