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); 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) { void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
u32 i = 0; u32 i = 0;
@ -70,7 +90,7 @@ void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
} }
if((x >= hud.x && x <= hud.x + hud.xsize) && 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.clicked=1;
hud.storedx = x - hud.x; 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 // aligning to odd half-pixel boundaries prevents agg2d from blurring thin straight lines
x = floor(x) + 0.5; x = floor(x) + 0.5;
y = floor(y) + 0.5; y = floor(calcY(y)) + 0.5;
double xc = 41 - 0.5; double xc = 41 - 0.5;
double yc = 20 - 0.5; double yc = 20 - 0.5;
@ -346,7 +366,7 @@ static void TextualInputDisplay() {
std::string str(buttonChars+i, 2); std::string str(buttonChars+i, 2);
str[1] = '\0'; str[1] = '\0';
aggDraw.hud->renderTextDropshadowed(x, Hud.InputDisplay.y, str); aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
} }
// touch pad // touch pad
@ -362,7 +382,7 @@ static void TextualInputDisplay() {
{ {
sprintf(str, "%d,%d", gameTouchX, gameTouchY); sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,255,255,255); 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 else
{ {
@ -370,19 +390,20 @@ static void TextualInputDisplay() {
{ {
sprintf(str, "%d,%d", gameTouchX, gameTouchY); sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,48,48,255); 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) if(physicalTouchOn)
{ {
sprintf(str, "%d,%d", physicalTouchX, physicalTouchY); sprintf(str, "%d,%d", physicalTouchX, physicalTouchY);
aggDraw.hud->lineColor(0,255,0,255); 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() { static void TouchDisplay() {
// note: calcY should not be used in this function.
aggDraw.hud->lineWidth(1.0); aggDraw.hud->lineWidth(1.0);
temptouch.X = NDS_getRawUserInput().touch.touchX >> 4; 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 - 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->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
aggDraw.hud->fillColor(0, 0, 0, touchalpha[i]); 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(){ 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 const int xloc = Hud.SavestateSlots.x; //8
s64 fadecounter = 512 - (hudTimer-slotTimer)/4; //change constant to alter fade speed 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->fillColor(0,0,0,0);
aggDraw.hud->lineColor(0,0,0,64); aggDraw.hud->lineColor(0,0,0,64);
aggDraw.hud->lineWidth(2.0); 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->lineColor(255,hud.clicked?127:255,0,255);
aggDraw.hud->lineWidth(1.0); 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++; i++;
} }
} }
@ -562,6 +583,9 @@ OSDCLASS::OSDCLASS(u8 core)
rotAngle = 0; rotAngle = 0;
singleScreen = false;
swapScreens = false;
needUpdate = false; needUpdate = false;
if (core==0) if (core==0)
@ -705,7 +729,7 @@ void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...)
va_end(list); va_end(list);
aggDraw.hud->lineColor(255,255,255); aggDraw.hud->lineColor(255,255,255);
aggDraw.hud->renderTextDropshadowed(x,y,msg); aggDraw.hud->renderTextDropshadowed(x,calcY(y),msg);
needUpdate = true; needUpdate = true;
} }

View File

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

View File

@ -3631,7 +3631,7 @@ DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "")
// mouse position in game screen pixel coordinates // mouse position in game screen pixel coordinates
{ {
void UnscaleScreenCoords(s32& x, s32& y); void UnscaleScreenCoords(s32& x, s32& y);
void ToDSScreenRelativeCoords(s32& x, s32& y, bool bottomScreen); void ToDSScreenRelativeCoords(s32& x, s32& y, int bottomScreen);
POINT point; POINT point;
GetCursorPos(&point); GetCursorPos(&point);
@ -3640,7 +3640,7 @@ DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "")
s32 y (point.y); s32 y (point.y);
UnscaleScreenCoords(x,y); UnscaleScreenCoords(x,y);
ToDSScreenRelativeCoords(x,y,true); ToDSScreenRelativeCoords(x,y,1);
lua_pushinteger(L, x); lua_pushinteger(L, x);
lua_setfield(L, -2, "xmouse"); 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(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY);
assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY); assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY);
currMovieData.truncateAt(currFrameCounter);
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr); currMovieData.records.push_back(mr);
@ -912,6 +910,7 @@ bool mov_loadstate(EMUFILE* fp, int size)
// #endif // #endif
currMovieData.rerecordCount = currRerecordCount; currMovieData.rerecordCount = currRerecordCount;
currMovieData.truncateAt(currFrameCounter);
openRecordingMovie(curMovieFilename); openRecordingMovie(curMovieFilename);
if(!osRecordingMovie) if(!osRecordingMovie)

View File

@ -216,10 +216,10 @@ void HK_LCDsMode(int)
doLCDsLayout(); doLCDsLayout();
} }
extern void LCDsSwap(); extern void LCDsSwap(int);
void HK_LCDsSwap(int) void HK_LCDsSwap(int)
{ {
LCDsSwap(); LCDsSwap(-1);
} }
void HK_Reset(int, bool justPressed) {ResetGame();} 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. // 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. // 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. // 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; s32 tx=x, ty=y;
@ -536,26 +537,46 @@ void ToDSScreenRelativeCoords(s32& x, s32& y, bool bottomScreen)
y = 192; y = 192;
else if(y > 191) else if(y > 191)
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) bool topOnTop = (video.swap == 0) || (video.swap == 2 && !MainScreen.offset) || (video.swap == 3 && MainScreen.offset);
x = tx - 255; bool bottom = (whichScreen > 0);
if(topOnTop)
y += bottom ? -192 : 0;
else else
x = tx; y += (y < 192) ? (bottom ? 0 : 192) : (bottom ? 0 : -192);
//INFO("X=%i, Y=%i (tx = %i, ty = %i)\n", x, y, tx, ty); }
}
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 else
if (video.layout == 2) {
if(x >= 256)
{ {
x = tx; x -= 256;
//INFO("X=%i, Y=%i (tx = %i, ty = %i)\n", x, y, tx, ty); y += 192;
} }
else if(x < 0)
{
x += 256;
y -= 192;
}
}
}
} }
// END Rotation definitions // END Rotation definitions
@ -953,16 +974,21 @@ template<typename T, int bpp> static void doRotate(void* dst)
} }
void UpdateWndRects(HWND hwnd); void UpdateWndRects(HWND hwnd);
void FixAspectRatio();
void LCDsSwap() void LCDsSwap(int swapVal)
{ {
video.swap = !video.swap; if(swapVal == -1) swapVal = video.swap ^ 1; // -1 means to flip the existing setting
MainWindow->checkMenu(ID_LCDS_SWAP, !video.swap); 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); WritePrivateProfileInt("Video", "LCDsSwap", video.swap, IniName);
} }
void doLCDsLayout() void doLCDsLayout()
{ {
osd->singleScreen = (video.layout == 2);
RECT rc = { 0 }; RECT rc = { 0 };
int oldheight, oldwidth; int oldheight, oldwidth;
int newheight, newwidth; int newheight, newwidth;
@ -1078,6 +1104,7 @@ void doLCDsLayout()
WritePrivateProfileInt("Video", "LCDsLayout", video.layout, IniName); WritePrivateProfileInt("Video", "LCDsLayout", video.layout, IniName);
SetMinWindowSize(); SetMinWindowSize();
MainWindow->setClientSize(newwidth, newheight); MainWindow->setClientSize(newwidth, newheight);
FixAspectRatio();
UpdateWndRects(MainWindow->getHWnd()); UpdateWndRects(MainWindow->getHWnd());
} }
@ -1116,10 +1143,40 @@ static void DD_DoDisplay()
lpBackSurface->Unlock((LPRECT)ddsd.lpSurface); lpBackSurface->Unlock((LPRECT)ddsd.lpSurface);
if (video.layout != 2) RECT* dstRects [2] = {&MainScreenRect, &SubScreenRect};
RECT* srcRects [2];
if(video.swap == 0)
{ {
// Main screen srcRects[0] = &MainScreenSrcRect;
if(lpPrimarySurface->Blt(&MainScreenRect, lpBackSurface, (video.swap == 0)?&MainScreenSrcRect:&SubScreenSrcRect, DDBLT_WAIT, 0) == DDERR_SURFACELOST) 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"); LOG("DirectDraw buffers is lost\n");
if(IDirectDrawSurface7_Restore(lpPrimarySurface) == DD_OK) 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 == 1) return;
if (video.layout == 2) return; if (video.layout == 2) return;
@ -2104,7 +2153,6 @@ int _main()
video.layout = video.layout_old = 0; video.layout = video.layout_old = 0;
} }
video.swap = GetPrivateProfileInt("Video", "LCDsSwap", 0, IniName); 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.FpsDisplay = GetPrivateProfileBool("Display","Display Fps", false, IniName);
CommonSettings.hud.FrameCounterDisplay = GetPrivateProfileBool("Display","FrameCounter", false, IniName); CommonSettings.hud.FrameCounterDisplay = GetPrivateProfileBool("Display","FrameCounter", false, IniName);
@ -2287,6 +2335,8 @@ int _main()
NDS_Init (); NDS_Init ();
#endif #endif
osd->singleScreen = (video.layout == 2);
/* /*
* Activate the GDB stubs * Activate the GDB stubs
* This has to come after the NDS_Init where the cpus are set up. * This has to come after the NDS_Init where the cpus are set up.
@ -2517,7 +2567,9 @@ void UpdateWndRects(HWND hwnd)
RECT rc; RECT rc;
int wndWidth, wndHeight; int wndWidth, wndHeight;
int defHeight = (video.height + video.screengap); int defHeight = video.height;
if(video.layout == 0)
defHeight += video.screengap;
float ratio; float ratio;
int oneScreenHeight, gapHeight; 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_VERTICAL, ((video.layout==0)));
MainWindow->checkMenu(ID_LCDS_HORIZONTAL, ((video.layout==1))); MainWindow->checkMenu(ID_LCDS_HORIZONTAL, ((video.layout==1)));
MainWindow->checkMenu(ID_LCDS_ONE, ((video.layout==2))); 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 //Force Maintain Ratio
MainWindow->checkMenu(IDC_FORCERATIO, ((ForceRatio))); MainWindow->checkMenu(IDC_FORCERATIO, ((ForceRatio)));
//Screen rotation //Screen rotation
@ -3833,13 +3889,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
if(HudEditorMode) if(HudEditorMode)
{ {
ToDSScreenRelativeCoords(x,y,false); ToDSScreenRelativeCoords(x,y,0);
EditHud(x,y, &Hud); EditHud(x,y, &Hud);
} }
else else
{ {
if ((video.layout == 2) && (video.swap == 1)) return 0; if ((video.layout == 2) && ((video.swap == 0) || (video.swap == 2 && !MainScreen.offset) || (video.swap == 3 && MainScreen.offset))) return 0;
ToDSScreenRelativeCoords(x,y,true); ToDSScreenRelativeCoords(x,y,1);
if(x<0) x = 0; else if(x>255) x = 255; if(x<0) x = 0; else if(x>255) x = 255;
if(y<0) y = 0; else if(y>192) y = 192; if(y<0) y = 0; else if(y>192) y = 192;
NDS_setTouchPos(x, y); NDS_setTouchPos(x, y);
@ -4456,8 +4512,17 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
doLCDsLayout(); doLCDsLayout();
return 0; return 0;
case ID_LCDS_NOSWAP:
LCDsSwap(0);
return 0;
case ID_LCDS_SWAP: 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; return 0;
case ID_VIEW_FRAMECOUNTER: case ID_VIEW_FRAMECOUNTER:

View File

@ -708,6 +708,9 @@
#define ID_LCDS_HORIZONTAL 40056 #define ID_LCDS_HORIZONTAL 40056
#define ID_LCDS_ONE 40057 #define ID_LCDS_ONE 40057
#define ID_LCDS_SWAP 40058 #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_UP 50000
#define IDC_LABEL_RIGHT 50001 #define IDC_LABEL_RIGHT 50001
#define IDC_LABEL_LEFT 50002 #define IDC_LABEL_LEFT 50002

Binary file not shown.