diff --git a/source/ngc/fceuconfig.cpp b/source/ngc/fceuconfig.cpp index 6b6bbb4..f51b088 100644 --- a/source/ngc/fceuconfig.cpp +++ b/source/ngc/fceuconfig.cpp @@ -44,6 +44,8 @@ void FixInvalidSettings() GCSettings.render = 2; if(GCSettings.timing != 0 && GCSettings.timing != 1) GCSettings.timing = 0; + if(!(GCSettings.videomode >= 0 && GCSettings.videomode < 5)) + GCSettings.videomode = 0; } /**************************************************************************** @@ -58,6 +60,7 @@ DefaultSettings () GCSettings.currpal = 0; // color palette GCSettings.timing = 0; // 0 - NTSC, 1 - PAL + GCSettings.videomode = 0; // automatic video mode detection GCSettings.Controller = CTRL_PAD2; // NES pad, Four Score, Zapper GCSettings.crosshair = 1; // show zapper crosshair GCSettings.spritelimit = 1; // enforce 8 sprite limit diff --git a/source/ngc/fceugx.h b/source/ngc/fceugx.h index 5bc9de8..a4a405f 100644 --- a/source/ngc/fceugx.h +++ b/source/ngc/fceugx.h @@ -69,6 +69,7 @@ struct SGCSettings{ float ZoomLevel; // zoom amount int VerifySaves; int render; // 0 - original, 1 - filtered, 2 - unfiltered + int videomode; // 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz) int widescreen; int hideoverscan; int currpal; diff --git a/source/ngc/gcvideo.cpp b/source/ngc/gcvideo.cpp index 401f586..9fc36ea 100644 --- a/source/ngc/gcvideo.cpp +++ b/source/ngc/gcvideo.cpp @@ -41,6 +41,7 @@ static int whichfb = 0; // Frame buffer toggle int screenheight; int screenwidth; bool progressive = false; +static int currentVideoMode = -1; // -1 - not set, 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz) /*** 3D GX ***/ #define TEX_WIDTH 256 @@ -477,6 +478,104 @@ UpdatePadsCB () } } + +/**************************************************************************** + * SetupVideoMode + * + * Finds the optimal video mode, or uses the user-specified one + * Also configures original video modes + ***************************************************************************/ +static void SetupVideoMode() +{ + if(currentVideoMode == GCSettings.videomode) + return; // no need to do anything + + // choose the desired video mode + switch(GCSettings.videomode) + { + case 1: // NTSC (480i) + vmode = &TVNtsc480IntDf; + break; + case 2: // Progressive (480p) + vmode = &TVNtsc480Prog; + break; + case 3: // PAL (50Hz) + vmode = &TVPal574IntDfScale; + break; + case 4: // PAL (60Hz) + vmode = &TVEurgb60Hz480IntDf; + break; + default: + vmode = VIDEO_GetPreferredMode(NULL); + + #ifdef HW_DOL + /* we have component cables, but the preferred mode is interlaced + * why don't we switch into progressive? + * on the Wii, the user can do this themselves on their Wii Settings */ + if(VIDEO_HaveComponentCable()) + vmode = &TVNtsc480Prog; + #endif + + // use hardware vertical scaling to fill screen + if(vmode->viTVMode >> 2 == VI_PAL) + vmode = &TVPal574IntDfScale; + break; + } + + // configure original modes + switch (vmode->viTVMode >> 2) + { + case VI_PAL: + // 576 lines (PAL 50Hz) + vmode_60hz = 0; + + // Original Video modes (forced to PAL 50Hz) + // set video signal mode + NTSC_240p.viTVMode = VI_TVMODE_PAL_DS; + NTSC_240p.viYOrigin = (VI_MAX_HEIGHT_PAL - 480)/2; + break; + + case VI_NTSC: + // 480 lines (NTSC 60Hz) + vmode_60hz = 1; + + // Original Video modes (forced to NTSC 60Hz) + // set video signal mode + PAL_240p.viTVMode = VI_TVMODE_NTSC_DS; + PAL_240p.viYOrigin = (VI_MAX_HEIGHT_NTSC - 480)/2; + NTSC_240p.viTVMode = VI_TVMODE_NTSC_DS; + break; + + default: + // 480 lines (PAL 60Hz) + vmode_60hz = 1; + + // Original Video modes (forced to PAL 60Hz) + // set video signal mode + PAL_240p.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_NON_INTERLACE); + PAL_240p.viYOrigin = (VI_MAX_HEIGHT_NTSC - 480)/2; + NTSC_240p.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_NON_INTERLACE); + break; + } + + // check for progressive scan + if (vmode->viTVMode == VI_TVMODE_NTSC_PROG) + progressive = true; + else + progressive = false; + + #ifdef HW_RVL + // widescreen fix + if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) + { + vmode->viWidth = VI_MAX_WIDTH_PAL-12; + vmode->viXOrigin = ((VI_MAX_WIDTH_PAL - vmode->viWidth) / 2) + 2; + } + #endif + + currentVideoMode = GCSettings.videomode; +} + /**************************************************************************** * InitGCVideo * @@ -486,56 +585,7 @@ UpdatePadsCB () void InitGCVideo () { - // get default video mode - vmode = VIDEO_GetPreferredMode(NULL); - - // set VI modes - switch (vmode->viTVMode >> 2) - { - case VI_PAL: // 574 lines (PAL 50Hz) - vmode_60hz = 0; - // 50Hz only - NTSC_240p.viTVMode = VI_TVMODE_PAL_DS; - NTSC_240p.viYOrigin = (VI_MAX_HEIGHT_PAL - 480)/2; - break; - - case VI_NTSC: // 480 lines (NTSC 60Hz) - vmode_60hz = 1; - // 60Hz only - PAL_240p.viTVMode = VI_TVMODE_NTSC_DS; - PAL_240p.viYOrigin = (VI_MAX_HEIGHT_NTSC - 480)/2; - NTSC_240p.viTVMode = VI_TVMODE_NTSC_DS; - break; - - default: // 480 lines (PAL 60Hz) - vmode_60hz = 1; - // supports both 50/60Hz but better use 60hz by default - PAL_240p.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_NON_INTERLACE); - PAL_240p.viYOrigin = (VI_MAX_HEIGHT_NTSC - 480)/2; - NTSC_240p.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_NON_INTERLACE); - break; - } - -#ifdef HW_DOL -/* we have component cables, but the preferred mode is interlaced - * why don't we switch into progressive? - * on the Wii, the user can do this themselves on their Wii Settings */ - if(VIDEO_HaveComponentCable()) - vmode = &TVNtsc480Prog; -#endif - - // check for progressive scan - if (vmode->viTVMode == VI_TVMODE_NTSC_PROG) - progressive = true; - -#ifdef HW_RVL - // widescreen fix - if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) - { - vmode->viWidth = VI_MAX_WIDTH_PAL-12; - vmode->viXOrigin = ((VI_MAX_WIDTH_PAL - vmode->viWidth) / 2) + 2; - } -#endif + SetupVideoMode(); // configure VI VIDEO_Configure (vmode); @@ -580,14 +630,13 @@ InitGCVideo () void ResetVideo_Emu () { - GXRModeObj *rmode; + SetupVideoMode(); + GXRModeObj *rmode = vmode; // same mode as menu Mtx44 p; - // choose current VI mode - if (GCSettings.render == 0) // original render mode + // change current VI mode if using original render mode + if (GCSettings.render == 0) rmode = tvmodes[GCSettings.timing]; - else // filtered/unfiltered - rmode = vmode; // same mode as menu // reconfigure VI VIDEO_Configure (rmode); @@ -791,6 +840,7 @@ ResetVideo_Menu () f32 yscale; u32 xfbHeight; + SetupVideoMode(); VIDEO_Configure (vmode); VIDEO_Flush(); VIDEO_WaitVSync(); diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 9b8a807..c76728f 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -936,7 +936,7 @@ static int MenuGameSelection() HaltGui(); btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - btnLogo->SetPosition(-30, 24); + btnLogo->SetPosition(-50, 24); mainWindow->Append(&titleTxt); mainWindow->Append(&gameBrowser); mainWindow->Append(&buttonWindow); @@ -1217,7 +1217,7 @@ static int MenuGame() GuiImage closeBtnImgOver(&btnCloseOutlineOver); GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-30, 35); + closeBtn.SetPosition(-50, 35); closeBtn.SetLabel(&closeBtnTxt); closeBtn.SetImage(&closeBtnImg); closeBtn.SetImageOver(&closeBtnImgOver); @@ -1286,7 +1286,7 @@ static int MenuGame() w.Append(&closeBtn); btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - btnLogo->SetPosition(-30, -40); + btnLogo->SetPosition(-50, -40); mainWindow->Append(&w); if(lastMenu == MENU_NONE) @@ -1486,7 +1486,7 @@ static int MenuGameSaves(int action) GuiImage closeBtnImgOver(&btnCloseOutlineOver); GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-30, 35); + closeBtn.SetPosition(-50, 35); closeBtn.SetLabel(&closeBtnTxt); closeBtn.SetImage(&closeBtnImg); closeBtn.SetImageOver(&closeBtnImgOver); @@ -1805,7 +1805,7 @@ static int MenuGameSettings() GuiImage closeBtnImgOver(&btnCloseOutlineOver); GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-30, 35); + closeBtn.SetPosition(-50, 35); closeBtn.SetLabel(&closeBtnTxt); closeBtn.SetImage(&closeBtnImg); closeBtn.SetImageOver(&closeBtnImgOver); @@ -2741,11 +2741,12 @@ static int MenuSettingsVideo() sprintf(options.name[i++], "Scaling"); sprintf(options.name[i++], "Cropping"); sprintf(options.name[i++], "Palette"); - sprintf(options.name[i++], "Timing"); + sprintf(options.name[i++], "Game Timing"); sprintf(options.name[i++], "Screen Zoom"); sprintf(options.name[i++], "Screen Position"); sprintf(options.name[i++], "Zapper Crosshair"); sprintf(options.name[i++], "Sprite Limit"); + sprintf(options.name[i++], "Video Mode"); options.length = i; GuiText titleTxt("Game Settings - Video", 28, (GXColor){255, 255, 255, 255}); @@ -2779,6 +2780,7 @@ static int MenuSettingsVideo() GuiOptionBrowser optionBrowser(552, 248, &options); optionBrowser.SetPosition(0, 108); + optionBrowser.SetCol2Position(200); optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); HaltGui(); @@ -2826,6 +2828,20 @@ static int MenuSettingsVideo() sprintf (options.value[7], "%s", GCSettings.crosshair == 1 ? "On" : "Off"); sprintf (options.value[8], "%s", GCSettings.spritelimit == 1 ? "On" : "Off"); + switch(GCSettings.videomode) + { + case 0: + sprintf (options.value[9], "Automatic (Recommended)"); break; + case 1: + sprintf (options.value[9], "NTSC (480i)"); break; + case 2: + sprintf (options.value[9], "Progressive (480p)"); break; + case 3: + sprintf (options.value[9], "PAL (50Hz)"); break; + case 4: + sprintf (options.value[9], "PAL (60Hz)"); break; + } + ret = optionBrowser.GetClickedOption(); switch (ret) @@ -2871,6 +2887,11 @@ static int MenuSettingsVideo() case 8: GCSettings.spritelimit ^= 1; break; + case 9: + GCSettings.videomode++; + if(GCSettings.videomode > 4) + GCSettings.videomode = 0; + break; } if(backBtn.GetState() == STATE_CLICKED) @@ -3530,7 +3551,7 @@ MainMenu (int menu) logoTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - btnLogo->SetPosition(-30, 24); + btnLogo->SetPosition(-50, 24); btnLogo->SetImage(&logoImg); btnLogo->SetImageOver(&logoImgOver); btnLogo->SetLabel(&logoTxt);