mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
1373 lines
39 KiB
C++
1373 lines
39 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Nestopia - NES/Famicom emulator written in C++
|
|
//
|
|
// Copyright (C) 2003-2008 Martin Freij
|
|
//
|
|
// This file is part of Nestopia.
|
|
//
|
|
// Nestopia is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Nestopia is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Nestopia; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <algorithm>
|
|
#include "NstIoLog.hpp"
|
|
#include "NstWindowUser.hpp"
|
|
#include "NstWindowParam.hpp"
|
|
#include "NstResourceString.hpp"
|
|
#include "NstManagerPaths.hpp"
|
|
#include "NstApplicationInstance.hpp"
|
|
#include "NstDialogPaletteEditor.hpp"
|
|
#include "NstDialogVideoDecoder.hpp"
|
|
#include "NstDialogVideo.hpp"
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Window
|
|
{
|
|
NST_COMPILE_ASSERT
|
|
(
|
|
IDC_VIDEO_NTSC_TOP == IDC_VIDEO_NTSC_LEFT + 1 &&
|
|
IDC_VIDEO_NTSC_RIGHT == IDC_VIDEO_NTSC_LEFT + 2 &&
|
|
IDC_VIDEO_NTSC_BOTTOM == IDC_VIDEO_NTSC_LEFT + 3 &&
|
|
IDC_VIDEO_PAL_LEFT == IDC_VIDEO_NTSC_LEFT + 4 &&
|
|
IDC_VIDEO_PAL_TOP == IDC_VIDEO_NTSC_LEFT + 5 &&
|
|
IDC_VIDEO_PAL_RIGHT == IDC_VIDEO_NTSC_LEFT + 6 &&
|
|
IDC_VIDEO_PAL_BOTTOM == IDC_VIDEO_NTSC_LEFT + 7
|
|
);
|
|
|
|
NST_COMPILE_ASSERT
|
|
(
|
|
IDC_VIDEO_32_BIT == IDC_VIDEO_16_BIT + 1
|
|
);
|
|
|
|
NST_COMPILE_ASSERT
|
|
(
|
|
IDC_VIDEO_PALETTE_YUV == IDC_VIDEO_PALETTE_AUTO + 1 &&
|
|
IDC_VIDEO_PALETTE_RGB == IDC_VIDEO_PALETTE_AUTO + 2 &&
|
|
IDC_VIDEO_PALETTE_CUSTOM == IDC_VIDEO_PALETTE_AUTO + 3 &&
|
|
IDC_VIDEO_PALETTE_PATH == IDC_VIDEO_PALETTE_AUTO + 4 &&
|
|
IDC_VIDEO_PALETTE_BROWSE == IDC_VIDEO_PALETTE_AUTO + 5 &&
|
|
IDC_VIDEO_PALETTE_CLEAR == IDC_VIDEO_PALETTE_AUTO + 6 &&
|
|
IDC_VIDEO_PALETTE_EDITOR == IDC_VIDEO_PALETTE_AUTO + 7
|
|
);
|
|
|
|
NST_COMPILE_ASSERT
|
|
(
|
|
Nes::Video::MIN_BRIGHTNESS == -100 && Nes::Video::DEFAULT_BRIGHTNESS == 0 && Nes::Video::MAX_BRIGHTNESS == +100 &&
|
|
Nes::Video::MIN_SATURATION == -100 && Nes::Video::DEFAULT_SATURATION == 0 && Nes::Video::MAX_SATURATION == +100 &&
|
|
Nes::Video::MIN_CONTRAST == -100 && Nes::Video::DEFAULT_CONTRAST == 0 && Nes::Video::MAX_CONTRAST == +100
|
|
);
|
|
|
|
struct Video::Handlers
|
|
{
|
|
static const MsgHandler::Entry<Video> messages[];
|
|
static const MsgHandler::Entry<Video> commands[];
|
|
};
|
|
|
|
const MsgHandler::Entry<Video> Video::Handlers::messages[] =
|
|
{
|
|
{ WM_INITDIALOG, &Video::OnInitDialog },
|
|
{ WM_DESTROY, &Video::OnDestroy },
|
|
{ WM_HSCROLL, &Video::OnHScroll }
|
|
};
|
|
|
|
const MsgHandler::Entry<Video> Video::Handlers::commands[] =
|
|
{
|
|
{ IDC_VIDEO_DEVICE, &Video::OnCmdDevice },
|
|
{ IDC_VIDEO_MODE, &Video::OnCmdMode },
|
|
{ IDC_VIDEO_16_BIT, &Video::OnCmdBitDepth },
|
|
{ IDC_VIDEO_32_BIT, &Video::OnCmdBitDepth },
|
|
{ IDC_VIDEO_EFFECTS, &Video::OnCmdFilter },
|
|
{ IDC_VIDEO_FILTER_SETTINGS, &Video::OnCmdFilterSettings },
|
|
{ IDC_VIDEO_PALETTE_AUTO, &Video::OnCmdPalType },
|
|
{ IDC_VIDEO_PALETTE_YUV, &Video::OnCmdPalType },
|
|
{ IDC_VIDEO_PALETTE_RGB, &Video::OnCmdPalType },
|
|
{ IDC_VIDEO_PALETTE_CUSTOM, &Video::OnCmdPalType },
|
|
{ IDC_VIDEO_COLORS_ADVANCED, &Video::OnCmdColorsAdvanced },
|
|
{ IDC_VIDEO_COLORS_RESET, &Video::OnCmdColorsReset },
|
|
{ IDC_VIDEO_PALETTE_BROWSE, &Video::OnCmdPalBrowse },
|
|
{ IDC_VIDEO_PALETTE_CLEAR, &Video::OnCmdPalClear },
|
|
{ IDC_VIDEO_PALETTE_EDITOR, &Video::OnCmdPalEditor },
|
|
{ IDC_VIDEO_DEFAULT, &Video::OnCmdDefault },
|
|
{ IDOK, &Video::OnCmdOk }
|
|
};
|
|
|
|
Video::DefaultMode::DefaultMode()
|
|
{
|
|
if (::GetSystemMetrics( SM_CXSCREEN ) == DEFAULT_16_9_WIDTH && ::GetSystemMetrics( SM_CYSCREEN ) == DEFAULT_16_9_HEIGHT)
|
|
{
|
|
width = DEFAULT_16_9_WIDTH;
|
|
height = DEFAULT_16_9_HEIGHT;
|
|
}
|
|
else
|
|
{
|
|
width = DEFAULT_4_3_WIDTH;
|
|
height = DEFAULT_4_3_HEIGHT;
|
|
}
|
|
}
|
|
|
|
const Video::DefaultMode Video::defaultMode;
|
|
|
|
class Video::Settings::Backup
|
|
{
|
|
const Adapters::const_iterator adapter;
|
|
const Modes::const_iterator mode;
|
|
Filter::Settings* const filter;
|
|
Filter::Settings filters[Filter::NUM_TYPES];
|
|
const short screenCurvature;
|
|
const bool autoPalette;
|
|
const schar brightness;
|
|
const schar saturation;
|
|
const schar contrast;
|
|
const schar hue;
|
|
const schar sharpness;
|
|
const schar colorResolution;
|
|
const schar colorBleed;
|
|
const schar colorArtifacts;
|
|
const schar colorFringing;
|
|
const Nes::Video::Decoder decoder;
|
|
const Path palettePath;
|
|
const Nes::Video::Palette::Mode paletteMode;
|
|
const Nes::Video::Palette::CustomType paletteCustomType;
|
|
uchar paletteData[Nes::Video::Palette::NUM_ENTRIES_EXT][3];
|
|
|
|
public:
|
|
|
|
Backup(const Settings& settings,Nes::Video nes)
|
|
:
|
|
adapter (settings.adapter),
|
|
mode (settings.mode),
|
|
filter (settings.filter),
|
|
screenCurvature (settings.screenCurvature),
|
|
autoPalette (settings.autoPalette),
|
|
brightness (nes.GetBrightness()),
|
|
saturation (nes.GetSaturation()),
|
|
contrast (nes.GetContrast()),
|
|
hue (nes.GetHue()),
|
|
sharpness (nes.GetSharpness()),
|
|
colorResolution (nes.GetColorResolution()),
|
|
colorBleed (nes.GetColorBleed()),
|
|
colorArtifacts (nes.GetColorArtifacts()),
|
|
colorFringing (nes.GetColorFringing()),
|
|
decoder (nes.GetDecoder()),
|
|
palettePath (settings.palette),
|
|
paletteMode (nes.GetPalette().GetMode()),
|
|
paletteCustomType (nes.GetPalette().GetCustomType())
|
|
{
|
|
for (uint i=0; i < Filter::NUM_TYPES; ++i)
|
|
filters[i] = settings.filters[i];
|
|
|
|
if (paletteMode == Nes::Video::Palette::MODE_CUSTOM)
|
|
nes.GetPalette().GetCustom( paletteData, paletteCustomType );
|
|
}
|
|
|
|
void Restore(Settings& settings,Nes::Video nes) const
|
|
{
|
|
settings.adapter = adapter;
|
|
settings.mode = mode;
|
|
settings.filter = filter;
|
|
|
|
for (uint i=0; i < Filter::NUM_TYPES; ++i)
|
|
settings.filters[i] = filters[i];
|
|
|
|
settings.screenCurvature = screenCurvature;
|
|
settings.palette = palettePath;
|
|
settings.autoPalette = autoPalette;
|
|
|
|
nes.SetBrightness( brightness );
|
|
nes.SetSaturation( saturation );
|
|
nes.SetContrast( contrast );
|
|
nes.SetHue( hue );
|
|
nes.SetSharpness( sharpness );
|
|
nes.SetColorResolution( colorResolution );
|
|
nes.SetColorBleed( colorBleed );
|
|
nes.SetColorArtifacts( colorArtifacts );
|
|
nes.SetColorFringing( colorFringing );
|
|
nes.SetDecoder( decoder );
|
|
nes.GetPalette().SetMode( paletteMode );
|
|
|
|
if (paletteMode == Nes::Video::Palette::MODE_CUSTOM)
|
|
nes.GetPalette().SetCustom( paletteData, paletteCustomType );
|
|
}
|
|
};
|
|
|
|
Video::Settings::Settings()
|
|
: fullscreenScale(SCREEN_MATCHED), backup(NULL) {}
|
|
|
|
Video::Settings::~Settings()
|
|
{
|
|
delete backup;
|
|
}
|
|
|
|
Video::Video
|
|
(
|
|
Managers::Emulator& emulator,
|
|
const Adapters& a,
|
|
const Managers::Paths& p,
|
|
const Configuration& cfg
|
|
)
|
|
:
|
|
adapters ( a ),
|
|
nes ( emulator ),
|
|
dialog ( IDD_VIDEO, this, Handlers::messages, Handlers::commands ),
|
|
paths ( p )
|
|
{
|
|
if (cfg["view"]["size"]["fullscreen"].Str() == L"stretched")
|
|
settings.fullscreenScale = SCREEN_STRETCHED;
|
|
|
|
Configuration::ConstSection video( cfg["video"] );
|
|
|
|
settings.adapter = std::find
|
|
(
|
|
adapters.begin(),
|
|
adapters.end(),
|
|
System::Guid( video["device"].Str() )
|
|
);
|
|
|
|
if (settings.adapter == adapters.end())
|
|
settings.adapter = adapters.begin();
|
|
|
|
{
|
|
Configuration::ConstSection fullscreen( video["fullscreen"] );
|
|
|
|
settings.mode = settings.adapter->modes.find
|
|
(
|
|
Mode
|
|
(
|
|
fullscreen[ "width" ].Int(),
|
|
fullscreen[ "height" ].Int(),
|
|
fullscreen[ "bpp" ].Int()
|
|
)
|
|
);
|
|
}
|
|
|
|
if (settings.mode == settings.adapter->modes.end())
|
|
settings.mode = GetDefaultMode();
|
|
|
|
settings.texMem =
|
|
(
|
|
video["memory-pool"].Str() == L"system" ? Settings::TEXMEM_SYSMEM :
|
|
Settings::TEXMEM_VIDMEM
|
|
);
|
|
|
|
{
|
|
Configuration::ConstSection region( video["region"] );
|
|
|
|
settings.rects.ntsc.Set
|
|
(
|
|
region[ "ntsc" ][ "left" ].Int( 0 ),
|
|
region[ "ntsc" ][ "top" ].Int( NTSC_CLIP_TOP ),
|
|
region[ "ntsc" ][ "right" ].Int( NES_WIDTH-1 ),
|
|
region[ "ntsc" ][ "bottom" ].Int( NTSC_CLIP_BOTTOM-1 )
|
|
);
|
|
|
|
settings.rects.pal.Set
|
|
(
|
|
region[ "pal" ][ "left" ].Int( 0 ),
|
|
region[ "pal" ][ "top" ].Int( PAL_CLIP_TOP ),
|
|
region[ "pal" ][ "right" ].Int( NES_WIDTH-1 ),
|
|
region[ "pal" ][ "bottom" ].Int( PAL_CLIP_BOTTOM-1 )
|
|
);
|
|
}
|
|
|
|
ValidateRects();
|
|
|
|
{
|
|
Configuration::ConstSection colors( video["colors"] );
|
|
|
|
uint v;
|
|
|
|
if (200 >= (v=colors["brightness"].Int( 100 )))
|
|
Nes::Video(nes).SetBrightness( int(v) - 100 );
|
|
|
|
if (200 >= (v=colors["saturation"].Int( 100 )))
|
|
Nes::Video(nes).SetSaturation( int(v) - 100 );
|
|
|
|
if (200 >= (v=colors["contrast"].Int( 100 )))
|
|
Nes::Video(nes).SetContrast( int(v) - 100 );
|
|
|
|
int hue = colors["hue"].Int( 0 );
|
|
|
|
if (hue > 180 && hue <= 360)
|
|
hue -= 360;
|
|
|
|
if (hue >= Nes::Video::MIN_HUE && hue <= Nes::Video::MAX_HUE)
|
|
Nes::Video(nes).SetHue( hue );
|
|
}
|
|
|
|
{
|
|
settings.autoPalette = false;
|
|
settings.palette = video["palette"]["file"].Str();
|
|
|
|
Nes::Video::Palette::Mode mode;
|
|
const GenericString type( video["palette"]["type"].Str() );
|
|
|
|
if (type == L"yuv")
|
|
{
|
|
mode = Nes::Video::Palette::MODE_YUV;
|
|
}
|
|
else if (type == L"rgb")
|
|
{
|
|
mode = Nes::Video::Palette::MODE_RGB;
|
|
}
|
|
else if (type == L"custom" && settings.palette.Length())
|
|
{
|
|
mode = Nes::Video::Palette::MODE_CUSTOM;
|
|
}
|
|
else
|
|
{
|
|
settings.autoPalette = true;
|
|
mode = Nes::Video::Palette::MODE_YUV;
|
|
}
|
|
|
|
Nes::Video(nes).GetPalette().SetMode( mode );
|
|
}
|
|
|
|
ImportPalette( settings.palette, Managers::Paths::QUIETLY );
|
|
|
|
{
|
|
int v;
|
|
|
|
if (MAX_SCREEN_CURVATURE-MIN_SCREEN_CURVATURE >= (v=video["screen-curvature"].Int( MAX_SCREEN_CURVATURE )))
|
|
v -= MAX_SCREEN_CURVATURE;
|
|
|
|
if (v >= MIN_SCREEN_CURVATURE && v <= MAX_SCREEN_CURVATURE)
|
|
settings.screenCurvature = v;
|
|
else
|
|
settings.screenCurvature = 0;
|
|
}
|
|
|
|
settings.autoHz = !video[ "auto-display-frequency" ].No();
|
|
settings.tvAspect = video[ "tv-aspect-ratio" ].Yes();
|
|
|
|
settings.filter = settings.filters + Filter::Load
|
|
(
|
|
cfg,
|
|
settings.filters,
|
|
Nes::Video(nes),
|
|
settings.adapter->maxScreenSize,
|
|
settings.adapter->filters & Adapter::FILTER_BILINEAR,
|
|
settings.adapter->canDoScanlineEffect,
|
|
GetDesiredPaletteMode()
|
|
);
|
|
|
|
VideoDecoder::Load( cfg, Nes::Video(nes) );
|
|
|
|
UpdateFinalRects();
|
|
}
|
|
|
|
Video::~Video()
|
|
{
|
|
}
|
|
|
|
void Video::Save(Configuration& cfg) const
|
|
{
|
|
cfg["view" ]["size"]["fullscreen"].Str() =
|
|
(
|
|
settings.fullscreenScale == SCREEN_STRETCHED ? "stretched" :
|
|
"matched"
|
|
);
|
|
|
|
Configuration::Section video( cfg["video"] );
|
|
|
|
if (settings.adapter != adapters.end())
|
|
{
|
|
video["device"].Str() = settings.adapter->guid.GetString();
|
|
|
|
if (settings.mode != settings.adapter->modes.end())
|
|
{
|
|
Configuration::Section fullscreen( video["fullscreen"] );
|
|
|
|
fullscreen[ "width" ].Int() = settings.mode->width;
|
|
fullscreen[ "height" ].Int() = settings.mode->height;
|
|
fullscreen[ "bpp" ].Int() = settings.mode->bpp;
|
|
}
|
|
}
|
|
|
|
video["memory-pool"].Str() =
|
|
(
|
|
settings.texMem == Settings::TEXMEM_SYSMEM ? "system" :
|
|
"video"
|
|
);
|
|
|
|
video[ "screen-curvature" ].Int() = MAX_SCREEN_CURVATURE + settings.screenCurvature;
|
|
video[ "auto-display-frequency" ].YesNo() = settings.autoHz;
|
|
video[ "tv-aspect-ratio" ].YesNo() = settings.tvAspect;
|
|
|
|
{
|
|
Configuration::Section palette( video["palette"] );
|
|
|
|
palette["file"].Str() = settings.palette;
|
|
|
|
GenericString type;
|
|
|
|
if (settings.autoPalette)
|
|
{
|
|
type = L"auto";
|
|
}
|
|
else switch (Nes::Video(nes).GetPalette().GetMode())
|
|
{
|
|
case Nes::Video::Palette::MODE_YUV: type = L"yuv"; break;
|
|
case Nes::Video::Palette::MODE_RGB: type = L"rgb"; break;
|
|
default: type = L"custom"; break;
|
|
}
|
|
|
|
palette["type"].Str() = type;
|
|
}
|
|
|
|
{
|
|
Configuration::Section region( video["region"] );
|
|
|
|
region[ "ntsc" ][ "left" ].Int() = settings.rects.ntsc.left;
|
|
region[ "ntsc" ][ "top" ].Int() = settings.rects.ntsc.top;
|
|
region[ "ntsc" ][ "right" ].Int() = settings.rects.ntsc.right - 1;
|
|
region[ "ntsc" ][ "bottom" ].Int() = settings.rects.ntsc.bottom - 1;
|
|
region[ "pal" ][ "left" ].Int() = settings.rects.pal.left;
|
|
region[ "pal" ][ "top" ].Int() = settings.rects.pal.top;
|
|
region[ "pal" ][ "right" ].Int() = settings.rects.pal.right - 1;
|
|
region[ "pal" ][ "bottom" ].Int() = settings.rects.pal.bottom - 1;
|
|
}
|
|
|
|
{
|
|
Configuration::Section colors( video["colors"] );
|
|
|
|
colors[ "brightness" ].Int() = 100 + Nes::Video(nes).GetBrightness();
|
|
colors[ "saturation" ].Int() = 100 + Nes::Video(nes).GetSaturation();
|
|
colors[ "contrast" ].Int() = 100 + Nes::Video(nes).GetContrast();
|
|
colors[ "hue" ].Int() = Nes::Video(nes).GetHue() + (Nes::Video(nes).GetHue() < 0 ? 360 : 0);
|
|
}
|
|
|
|
Filter::Save
|
|
(
|
|
cfg,
|
|
settings.filters,
|
|
Nes::Video(nes),
|
|
static_cast<Filter::Type>(settings.filter - settings.filters)
|
|
);
|
|
|
|
VideoDecoder::Save( cfg, Nes::Video(nes) );
|
|
}
|
|
|
|
Nes::Video::Palette::Mode Video::GetDesiredPaletteMode() const
|
|
{
|
|
if (Nes::Machine(nes).Is(Nes::Machine::VS) || Nes::Machine(nes).Is(Nes::Machine::PC10))
|
|
return Nes::Video::Palette::MODE_RGB;
|
|
else
|
|
return Nes::Video::Palette::MODE_YUV;
|
|
}
|
|
|
|
void Video::UpdateAutoModes() const
|
|
{
|
|
const Nes::Video::Palette::Mode mode = GetDesiredPaletteMode();
|
|
|
|
if (settings.autoPalette)
|
|
Nes::Video(nes).GetPalette().SetMode( mode );
|
|
|
|
VideoFilters::UpdateAutoModes( settings.filters, nes, mode );
|
|
}
|
|
|
|
uint Video::GetScanlines() const
|
|
{
|
|
if (settings.adapter->canDoScanlineEffect)
|
|
{
|
|
switch (settings.filter - settings.filters)
|
|
{
|
|
case Filter::TYPE_STD:
|
|
|
|
return settings.filters[Filter::TYPE_STD].attributes[Filter::ATR_SCANLINES];
|
|
|
|
case Filter::TYPE_NTSC:
|
|
|
|
return settings.filters[Filter::TYPE_NTSC].attributes[Filter::ATR_SCANLINES];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const Rect Video::GetRenderState(Nes::Video::RenderState& state,const Point screen) const
|
|
{
|
|
typedef Nes::Video::RenderState State;
|
|
|
|
Rect rect( Nes::Machine(nes).GetMode() == Nes::Machine::NTSC ? settings.rects.ntsc : settings.rects.pal );
|
|
|
|
state.width = NES_WIDTH;
|
|
state.height = NES_HEIGHT;
|
|
state.filter = State::FILTER_NONE;
|
|
|
|
uint scale = 1;
|
|
|
|
switch (settings.filter - settings.filters)
|
|
{
|
|
case Filter::TYPE_STD:
|
|
break;
|
|
|
|
case Filter::TYPE_NTSC:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NTSC_WIDTH)
|
|
{
|
|
rect.left = (rect.left * (NTSC_WIDTH - 4) + NES_WIDTH / 2) / NES_WIDTH + 3;
|
|
rect.right = (rect.right * (NTSC_WIDTH - 4) + NES_WIDTH / 2) / NES_WIDTH + 3;
|
|
|
|
state.width = NTSC_WIDTH;
|
|
state.filter = State::FILTER_NTSC;
|
|
}
|
|
break;
|
|
|
|
case Filter::TYPE_SCALEX:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*2 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*2)
|
|
{
|
|
int attribute = settings.filters[Filter::TYPE_SCALEX].attributes[Filter::ATR_TYPE];
|
|
|
|
if (attribute == Filter::ATR_SCALEAX)
|
|
{
|
|
const Point nes( rect.Size() );
|
|
|
|
if (screen.x >= nes.x*3 && screen.y >= nes.y*3)
|
|
{
|
|
attribute = Filter::ATR_SCALE3X;
|
|
}
|
|
else if (screen.x >= nes.x*2 && screen.y >= nes.y*2)
|
|
{
|
|
attribute = Filter::ATR_SCALE2X;
|
|
}
|
|
}
|
|
|
|
switch (attribute)
|
|
{
|
|
case Filter::ATR_SCALE3X:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*3 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*3)
|
|
{
|
|
scale = 3;
|
|
state.filter = State::FILTER_SCALE3X;
|
|
break;
|
|
}
|
|
|
|
case Filter::ATR_SCALE2X:
|
|
|
|
scale = 2;
|
|
state.filter = State::FILTER_SCALE2X;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Filter::TYPE_HQX:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*2 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*2)
|
|
{
|
|
int attribute = settings.filters[Filter::TYPE_HQX].attributes[Filter::ATR_TYPE];
|
|
|
|
if (attribute == Filter::ATR_HQAX)
|
|
{
|
|
const Point nes( rect.Size() );
|
|
|
|
if (screen.x >= nes.x*4 && screen.y >= nes.y*4)
|
|
{
|
|
attribute = Filter::ATR_HQ4X;
|
|
}
|
|
else if (screen.x >= nes.x*3 && screen.y >= nes.y*3)
|
|
{
|
|
attribute = Filter::ATR_HQ3X;
|
|
}
|
|
else if (screen.x >= nes.x*2 && screen.y >= nes.y*2)
|
|
{
|
|
attribute = Filter::ATR_HQ2X;
|
|
}
|
|
}
|
|
|
|
switch (attribute)
|
|
{
|
|
case Filter::ATR_HQ4X:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*4 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*4)
|
|
{
|
|
scale = 4;
|
|
state.filter = State::FILTER_HQ4X;
|
|
break;
|
|
}
|
|
|
|
case Filter::ATR_HQ3X:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*3 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*3)
|
|
{
|
|
scale = 3;
|
|
state.filter = State::FILTER_HQ3X;
|
|
break;
|
|
}
|
|
|
|
case Filter::ATR_HQ2X:
|
|
|
|
scale = 2;
|
|
state.filter = State::FILTER_HQ2X;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Filter::TYPE_2XSAI:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*2 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*2)
|
|
{
|
|
scale = 2;
|
|
state.filter = State::FILTER_2XSAI;
|
|
}
|
|
break;
|
|
|
|
case Filter::TYPE_XBR:
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*2 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*2)
|
|
{
|
|
int attribute = settings.filters[Filter::TYPE_XBR].attributes[Filter::ATR_TYPE];
|
|
|
|
if (attribute == Filter::ATR_AXBR)
|
|
{
|
|
const Point nes( rect.Size() );
|
|
|
|
if (screen.x >= nes.x*4 && screen.y >= nes.y*4)
|
|
{
|
|
attribute = Filter::ATR_4XBR;
|
|
}
|
|
else if (screen.x >= nes.x*3 && screen.y >= nes.y*3)
|
|
{
|
|
attribute = Filter::ATR_3XBR;
|
|
}
|
|
else if (screen.x >= nes.x*2 && screen.y >= nes.y*2)
|
|
{
|
|
attribute = Filter::ATR_2XBR;
|
|
}
|
|
}
|
|
|
|
switch (attribute)
|
|
{
|
|
case Filter::ATR_4XBR:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*4 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*4)
|
|
{
|
|
scale = 4;
|
|
state.filter = State::FILTER_4XBR;
|
|
break;
|
|
}
|
|
|
|
case Filter::ATR_HQ3X:
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NES_WIDTH*3 && settings.adapter->maxScreenSize.y >= NES_HEIGHT*3)
|
|
{
|
|
scale = 3;
|
|
state.filter = State::FILTER_3XBR;
|
|
break;
|
|
}
|
|
|
|
case Filter::ATR_HQ2X:
|
|
|
|
scale = 2;
|
|
state.filter = State::FILTER_2XBR;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
state.width = state.width * scale;
|
|
state.height = state.height * scale;
|
|
|
|
rect.left *= scale;
|
|
rect.top *= scale;
|
|
rect.right *= scale;
|
|
rect.bottom *= scale;
|
|
|
|
return rect;
|
|
}
|
|
|
|
Video::Modes::const_iterator Video::GetDialogMode() const
|
|
{
|
|
for (Modes::const_iterator it(settings.adapter->modes.begin()), end(settings.adapter->modes.end()); it != end; ++it)
|
|
{
|
|
if (it->bpp == settings.mode->bpp && it->width >= MIN_DIALOG_WIDTH && it->height >= MIN_DIALOG_HEIGHT)
|
|
return it;
|
|
}
|
|
|
|
return settings.adapter->modes.begin();
|
|
}
|
|
|
|
uint Video::GetFullscreenScaleMethod() const
|
|
{
|
|
return settings.filter == settings.filters+Filter::TYPE_NTSC ? settings.filters[Filter::TYPE_NTSC].attributes[Filter::ATR_RESCALE_PIC] ? 1 : 2 : 0;
|
|
}
|
|
|
|
void Video::UpdateFullscreenScaleMethod(uint prev)
|
|
{
|
|
if (settings.fullscreenScale != SCREEN_STRETCHED && prev != GetFullscreenScaleMethod())
|
|
settings.fullscreenScale = SCREEN_MATCHED;
|
|
}
|
|
|
|
void Video::UpdateFinalRects()
|
|
{
|
|
for (uint i=0; i < 2; ++i)
|
|
{
|
|
Rect& rect = (i ? settings.rects.outPal : settings.rects.outNtsc);
|
|
rect = (i ? settings.rects.pal : settings.rects.ntsc);
|
|
|
|
if (settings.filter == settings.filters + Filter::TYPE_NTSC)
|
|
{
|
|
if (settings.tvAspect || !settings.filters[Filter::TYPE_NTSC].attributes[Filter::ATR_RESCALE_PIC])
|
|
{
|
|
rect.top *= 2;
|
|
rect.bottom *= 2;
|
|
rect.left = (rect.left * (NTSC_WIDTH - 4) + NES_WIDTH / 2) / NES_WIDTH + 3;
|
|
rect.right = (rect.right * (NTSC_WIDTH - 4) + NES_WIDTH / 2) / NES_WIDTH + 3;
|
|
}
|
|
}
|
|
else if (settings.tvAspect)
|
|
{
|
|
rect.left = (rect.left * TV_WIDTH + NES_WIDTH / 2) / NES_WIDTH;
|
|
rect.right = (rect.right * TV_WIDTH + NES_WIDTH / 2) / NES_WIDTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Video::ValidateRects()
|
|
{
|
|
Settings::Rects& r = settings.rects;
|
|
|
|
r.ntsc.left = NST_CLAMP( r.ntsc.left, 0, NES_WIDTH -1 );
|
|
r.ntsc.top = NST_CLAMP( r.ntsc.top, 0, NES_HEIGHT -1 );
|
|
r.ntsc.right = NST_CLAMP( r.ntsc.right, r.ntsc.left, NES_WIDTH -1 ) + 1;
|
|
r.ntsc.bottom = NST_CLAMP( r.ntsc.bottom, r.ntsc.top, NES_HEIGHT -1 ) + 1;
|
|
r.pal.left = NST_CLAMP( r.pal.left, 0, NES_WIDTH -1 );
|
|
r.pal.top = NST_CLAMP( r.pal.top, 0, NES_HEIGHT -1 );
|
|
r.pal.right = NST_CLAMP( r.pal.right, r.pal.left, NES_WIDTH -1 ) + 1;
|
|
r.pal.bottom = NST_CLAMP( r.pal.bottom, r.pal.top, NES_HEIGHT -1 ) + 1;
|
|
}
|
|
|
|
void Video::ResetColors()
|
|
{
|
|
Nes::Video(nes).SetBrightness ( Nes::Video::DEFAULT_BRIGHTNESS );
|
|
Nes::Video(nes).SetSaturation ( Nes::Video::DEFAULT_SATURATION );
|
|
Nes::Video(nes).SetContrast ( Nes::Video::DEFAULT_CONTRAST );
|
|
Nes::Video(nes).SetHue ( Nes::Video::DEFAULT_HUE );
|
|
}
|
|
|
|
Video::Modes::const_iterator Video::GetDefaultMode() const
|
|
{
|
|
for (uint bpp=16; bpp <= 32; bpp += 16)
|
|
{
|
|
const Modes::const_iterator it( settings.adapter->modes.find(Mode(defaultMode.width,defaultMode.height,bpp)) );
|
|
|
|
if (it != settings.adapter->modes.end())
|
|
return it;
|
|
}
|
|
|
|
return settings.adapter->modes.begin();
|
|
}
|
|
|
|
ibool Video::OnInitDialog(Param&)
|
|
{
|
|
NST_ASSERT( settings.backup == NULL );
|
|
settings.backup = new Settings::Backup( settings, Nes::Video(nes) );
|
|
|
|
{
|
|
const Control::ComboBox comboBox( dialog.ComboBox(IDC_VIDEO_DEVICE) );
|
|
|
|
for (Adapters::const_iterator it(adapters.begin()), end(adapters.end()); it != end; ++it)
|
|
{
|
|
comboBox.Add( it->name.Ptr() );
|
|
|
|
if (settings.adapter == it)
|
|
comboBox[it - adapters.begin()].Select();
|
|
}
|
|
}
|
|
|
|
for (uint i=IDC_VIDEO_NTSC_LEFT; i <= IDC_VIDEO_PAL_BOTTOM; ++i)
|
|
dialog.Edit( i ).Limit( 3 );
|
|
|
|
dialog.Slider( IDC_VIDEO_COLORS_BRIGHTNESS ).SetRange( 0, Nes::Video::MAX_BRIGHTNESS-Nes::Video::MIN_BRIGHTNESS );
|
|
dialog.Slider( IDC_VIDEO_COLORS_SATURATION ).SetRange( 0, Nes::Video::MAX_SATURATION-Nes::Video::MIN_SATURATION );
|
|
dialog.Slider( IDC_VIDEO_COLORS_CONTRAST ).SetRange( 0, Nes::Video::MAX_CONTRAST-Nes::Video::MIN_CONTRAST );
|
|
dialog.Slider( IDC_VIDEO_COLORS_HUE ).SetRange( 0, Nes::Video::MAX_HUE-Nes::Video::MIN_HUE );
|
|
|
|
dialog.Slider( IDC_VIDEO_SC_SLIDER ).SetRange( 0, MAX_SCREEN_CURVATURE-MIN_SCREEN_CURVATURE );
|
|
|
|
dialog.CheckBox( IDC_VIDEO_AUTO_HZ ).Check( settings.autoHz );
|
|
|
|
dialog.RadioButton( settings.texMem == Settings::TEXMEM_VIDMEM ? IDC_VIDEO_NESTEXTURE_VIDMEM : IDC_VIDEO_NESTEXTURE_SYSMEM ).Check();
|
|
|
|
UpdateDevice( *settings.mode );
|
|
UpdateRects( settings.rects.ntsc, settings.rects.pal );
|
|
UpdateColors();
|
|
UpdateScreenCurvature();
|
|
UpdatePalette();
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnDestroy(Param&)
|
|
{
|
|
if (settings.backup)
|
|
{
|
|
settings.backup->Restore( settings, Nes::Video(nes) );
|
|
|
|
delete settings.backup;
|
|
settings.backup = NULL;
|
|
}
|
|
else
|
|
{
|
|
settings.autoHz = dialog.CheckBox(IDC_VIDEO_AUTO_HZ).Checked();
|
|
|
|
if (dialog.RadioButton(IDC_VIDEO_NESTEXTURE_VIDMEM).Checked())
|
|
settings.texMem = Settings::TEXMEM_VIDMEM;
|
|
else
|
|
settings.texMem = Settings::TEXMEM_SYSMEM;
|
|
|
|
dialog.Control( IDC_VIDEO_NTSC_LEFT ).Text() >> settings.rects.ntsc.left;
|
|
dialog.Control( IDC_VIDEO_NTSC_TOP ).Text() >> settings.rects.ntsc.top;
|
|
dialog.Control( IDC_VIDEO_NTSC_RIGHT ).Text() >> settings.rects.ntsc.right;
|
|
dialog.Control( IDC_VIDEO_NTSC_BOTTOM ).Text() >> settings.rects.ntsc.bottom;
|
|
dialog.Control( IDC_VIDEO_PAL_LEFT ).Text() >> settings.rects.pal.left;
|
|
dialog.Control( IDC_VIDEO_PAL_TOP ).Text() >> settings.rects.pal.top;
|
|
dialog.Control( IDC_VIDEO_PAL_RIGHT ).Text() >> settings.rects.pal.right;
|
|
dialog.Control( IDC_VIDEO_PAL_BOTTOM ).Text() >> settings.rects.pal.bottom;
|
|
|
|
ValidateRects();
|
|
}
|
|
|
|
UpdateFinalRects();
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnHScroll(Param& param)
|
|
{
|
|
const int value = param.Slider().Scroll();
|
|
|
|
switch (param.Slider().GetId())
|
|
{
|
|
case IDC_VIDEO_COLORS_BRIGHTNESS:
|
|
|
|
Nes::Video(nes).SetBrightness( value + Nes::Video::MIN_BRIGHTNESS );
|
|
break;
|
|
|
|
case IDC_VIDEO_COLORS_SATURATION:
|
|
|
|
Nes::Video(nes).SetSaturation( value + Nes::Video::MIN_SATURATION );
|
|
break;
|
|
|
|
case IDC_VIDEO_COLORS_CONTRAST:
|
|
|
|
Nes::Video(nes).SetContrast( value + Nes::Video::MIN_CONTRAST );
|
|
break;
|
|
|
|
case IDC_VIDEO_COLORS_HUE:
|
|
|
|
Nes::Video(nes).SetHue( value + Nes::Video::MIN_HUE );
|
|
break;
|
|
|
|
case IDC_VIDEO_SC_SLIDER:
|
|
|
|
settings.screenCurvature = value + MIN_SCREEN_CURVATURE;
|
|
UpdateScreenCurvature();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
|
|
default:
|
|
|
|
return true;
|
|
}
|
|
|
|
UpdateColors();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdDevice(Param& param)
|
|
{
|
|
if (param.ComboBox().SelectionChanged())
|
|
{
|
|
settings.adapter = adapters.begin();
|
|
|
|
for (uint i=dialog.ComboBox( IDC_VIDEO_DEVICE ).Selection().GetIndex(); i; --i)
|
|
++settings.adapter;
|
|
|
|
UpdateDevice( *settings.mode );
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdBitDepth(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
UpdateResolutions( Mode(settings.mode->width,settings.mode->height,param.Button().GetId() == IDC_VIDEO_32_BIT ? 32 : 16) );
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdMode(Param& param)
|
|
{
|
|
if (param.ComboBox().SelectionChanged())
|
|
{
|
|
settings.mode = settings.adapter->modes.begin();
|
|
|
|
for (uint i=dialog.ComboBox(IDC_VIDEO_MODE).Selection().Data(); i; --i)
|
|
++settings.mode;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdFilter(Param& param)
|
|
{
|
|
if (param.ComboBox().SelectionChanged())
|
|
{
|
|
const uint method = GetFullscreenScaleMethod();
|
|
settings.filter = settings.filters + dialog.ComboBox( IDC_VIDEO_EFFECTS ).Selection().Data();
|
|
UpdateFullscreenScaleMethod( method );
|
|
|
|
UpdatePalette();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdFilterSettings(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
const uint method = GetFullscreenScaleMethod();
|
|
|
|
static const ushort idd[] =
|
|
{
|
|
IDD_VIDEO_FILTER_STD,
|
|
IDD_VIDEO_FILTER_NTSC,
|
|
IDD_VIDEO_FILTER_SCALEX,
|
|
IDD_VIDEO_FILTER_HQX,
|
|
IDD_VIDEO_FILTER_2XSAI,
|
|
IDD_VIDEO_FILTER_XBR
|
|
};
|
|
|
|
VideoFilters
|
|
(
|
|
Nes::Video(nes),
|
|
idd[settings.filter-settings.filters],
|
|
*settings.filter,
|
|
settings.adapter->maxScreenSize,
|
|
settings.adapter->filters & Adapter::FILTER_BILINEAR,
|
|
settings.adapter->canDoScanlineEffect,
|
|
GetDesiredPaletteMode()
|
|
).Open();
|
|
|
|
UpdateFullscreenScaleMethod( method );
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdPalType(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
const uint cmd = param.Button().GetId();
|
|
|
|
settings.autoPalette = (cmd == IDC_VIDEO_PALETTE_AUTO);
|
|
|
|
Nes::Video(nes).GetPalette().SetMode
|
|
(
|
|
cmd == IDC_VIDEO_PALETTE_YUV ? Nes::Video::Palette::MODE_YUV :
|
|
cmd == IDC_VIDEO_PALETTE_RGB ? Nes::Video::Palette::MODE_RGB :
|
|
cmd == IDC_VIDEO_PALETTE_CUSTOM ? Nes::Video::Palette::MODE_CUSTOM :
|
|
GetDesiredPaletteMode()
|
|
);
|
|
|
|
UpdatePalette();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdColorsReset(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
ResetColors();
|
|
UpdateColors();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdColorsAdvanced(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
VideoDecoder( nes ).Open();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdPalBrowse(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
const Path file
|
|
(
|
|
paths.BrowseLoad
|
|
(
|
|
Managers::Paths::File::PALETTE|Managers::Paths::File::ARCHIVE,
|
|
Application::Instance::GetFullPath( settings.palette )
|
|
)
|
|
);
|
|
|
|
if (file.Length())
|
|
{
|
|
settings.palette = file;
|
|
|
|
ImportPalette( settings.palette, Managers::Paths::NOISY );
|
|
UpdatePalette();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdPalClear(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
if (settings.palette.Length())
|
|
{
|
|
settings.palette.Destroy();
|
|
|
|
if (Nes::Video(nes).GetPalette().GetMode() == Nes::Video::Palette::MODE_CUSTOM)
|
|
{
|
|
Nes::Video(nes).GetPalette().SetMode( GetDesiredPaletteMode() );
|
|
settings.autoPalette = true;
|
|
}
|
|
|
|
UpdatePalette();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdPalEditor(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
Nes::Video video( nes );
|
|
|
|
if (settings.palette.Empty())
|
|
video.GetPalette().ResetCustom();
|
|
|
|
{
|
|
const Path path( PaletteEditor( video, paths, settings.palette ).Open() );
|
|
|
|
if (settings.palette.Empty() && path.Length())
|
|
settings.palette = path;
|
|
}
|
|
|
|
if (settings.palette.Length())
|
|
{
|
|
ImportPalette( settings.palette, Managers::Paths::QUIETLY );
|
|
UpdatePalette();
|
|
}
|
|
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdDefault(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
const uint method = GetFullscreenScaleMethod();
|
|
|
|
settings.adapter = adapters.begin();
|
|
settings.mode = GetDefaultMode();
|
|
|
|
for (uint i=0; i < Filter::NUM_TYPES; ++i)
|
|
settings.filters[i].Reset();
|
|
|
|
settings.filter = settings.filters + Filter::TYPE_STD;
|
|
|
|
UpdateDevice( *settings.mode );
|
|
|
|
dialog.RadioButton( IDC_VIDEO_NESTEXTURE_VIDMEM ).Check();
|
|
dialog.RadioButton( IDC_VIDEO_NESTEXTURE_SYSMEM ).Uncheck();
|
|
|
|
UpdateRects
|
|
(
|
|
Rect( 0, NTSC_CLIP_TOP, NES_WIDTH, NTSC_CLIP_BOTTOM ),
|
|
Rect( 0, PAL_CLIP_TOP, NES_WIDTH, PAL_CLIP_BOTTOM )
|
|
);
|
|
|
|
dialog.CheckBox( IDC_VIDEO_AUTO_HZ ).Check();
|
|
|
|
ResetColors();
|
|
UpdateColors();
|
|
|
|
settings.autoPalette = true;
|
|
|
|
settings.screenCurvature = 0;
|
|
UpdateScreenCurvature();
|
|
|
|
const Nes::Video::Palette::Mode mode = GetDesiredPaletteMode();
|
|
Nes::Video video(nes);
|
|
|
|
video.GetPalette().SetMode( mode );
|
|
|
|
VideoFilters::UpdateAutoModes( settings.filters, video, mode );
|
|
|
|
video.SetDecoder( Nes::Video::DECODER_CANONICAL );
|
|
|
|
UpdateFullscreenScaleMethod( method );
|
|
|
|
UpdatePalette();
|
|
Application::Instance::GetMainWindow().Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Video::OnCmdOk(Param& param)
|
|
{
|
|
if (param.Button().Clicked())
|
|
{
|
|
delete settings.backup;
|
|
settings.backup = NULL;
|
|
|
|
dialog.Close();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Video::UpdateDevice(Mode mode)
|
|
{
|
|
dialog.RadioButton( IDC_VIDEO_NESTEXTURE_VIDMEM ).Enable( settings.adapter->videoMemScreen );
|
|
dialog.RadioButton( IDC_VIDEO_NESTEXTURE_SYSMEM ).Enable( settings.adapter->videoMemScreen );
|
|
|
|
uint available = 0;
|
|
|
|
for (Modes::const_iterator it(settings.adapter->modes.begin()), end(settings.adapter->modes.end()); it != end; ++it)
|
|
{
|
|
switch (it->bpp)
|
|
{
|
|
case 16: available |= 16; break;
|
|
case 32: available |= 32; break;
|
|
}
|
|
|
|
if (available == (16|32))
|
|
break;
|
|
}
|
|
|
|
NST_ASSERT( available & (16|32) );
|
|
|
|
dialog.Control( IDC_VIDEO_16_BIT ).Enable( available & 16 );
|
|
dialog.Control( IDC_VIDEO_32_BIT ).Enable( available & 32 );
|
|
|
|
switch (mode.bpp)
|
|
{
|
|
case 32: mode.bpp = ((available & 32) ? 32 : 16); break;
|
|
case 16: mode.bpp = ((available & 16) ? 16 : 32); break;
|
|
}
|
|
|
|
UpdateResolutions( mode );
|
|
UpdateFilters();
|
|
}
|
|
|
|
void Video::UpdateResolutions(Mode mode)
|
|
{
|
|
settings.mode = settings.adapter->modes.find( mode );
|
|
|
|
if (settings.mode == settings.adapter->modes.end())
|
|
{
|
|
settings.mode = settings.adapter->modes.find( Mode(defaultMode.width,defaultMode.height,mode.bpp) );
|
|
|
|
if (settings.mode == settings.adapter->modes.end())
|
|
settings.mode = settings.adapter->modes.begin();
|
|
|
|
mode = *settings.mode;
|
|
}
|
|
|
|
dialog.RadioButton( IDC_VIDEO_16_BIT ).Check( mode.bpp == 16 );
|
|
dialog.RadioButton( IDC_VIDEO_32_BIT ).Check( mode.bpp == 32 );
|
|
|
|
const Control::ComboBox comboBox( dialog.ComboBox(IDC_VIDEO_MODE) );
|
|
comboBox.Clear();
|
|
|
|
uint idx=0;
|
|
HeapString string;
|
|
|
|
for (Modes::const_iterator it(settings.adapter->modes.begin()), end(settings.adapter->modes.end()); it != end; ++it, ++idx)
|
|
{
|
|
if (mode.bpp == it->bpp)
|
|
{
|
|
string.Clear();
|
|
comboBox.Add( (string << it->width << 'x' << it->height).Ptr() ).Data() = idx;
|
|
|
|
if (mode.width == it->width && mode.height == it->height)
|
|
comboBox[comboBox.Size() - 1].Select();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Video::UpdateFilters()
|
|
{
|
|
const Control::ComboBox comboBox( dialog.ComboBox(IDC_VIDEO_EFFECTS) );
|
|
comboBox.Clear();
|
|
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_STD) ).Data() = Filter::TYPE_STD;
|
|
|
|
if (settings.adapter->maxScreenSize.x >= NTSC_WIDTH)
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_NTSC) ).Data() = Filter::TYPE_NTSC;
|
|
|
|
if
|
|
(
|
|
settings.adapter->maxScreenSize.x >= NES_WIDTH*2 &&
|
|
settings.adapter->maxScreenSize.y >= NES_HEIGHT*2
|
|
)
|
|
{
|
|
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_SCALEX) ).Data() = Filter::TYPE_SCALEX;
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_HQX) ).Data() = Filter::TYPE_HQX;
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_2XSAI) ).Data() = Filter::TYPE_2XSAI;
|
|
comboBox.Add( Resource::String(IDS_VIDEO_FILTER_XBR) ).Data() = Filter::TYPE_XBR;
|
|
}
|
|
|
|
for (uint i=0, size=comboBox.Size(); i < size; ++i)
|
|
{
|
|
if (settings.filter-settings.filters == (Filter::Type) (Control::ComboBox::Value) comboBox[i].Data())
|
|
{
|
|
comboBox[i].Select();
|
|
return;
|
|
}
|
|
}
|
|
|
|
settings.filter = settings.filters + Filter::TYPE_STD;
|
|
comboBox[0].Select();
|
|
}
|
|
|
|
void Video::UpdateColors() const
|
|
{
|
|
const int colors[] =
|
|
{
|
|
Nes::Video(nes).GetBrightness(),
|
|
Nes::Video(nes).GetSaturation(),
|
|
Nes::Video(nes).GetContrast(),
|
|
Nes::Video(nes).GetHue()
|
|
};
|
|
|
|
dialog.Control( IDC_VIDEO_COLORS_RESET ).Enable
|
|
(
|
|
colors[0] != Nes::Video::DEFAULT_BRIGHTNESS ||
|
|
colors[1] != Nes::Video::DEFAULT_SATURATION ||
|
|
colors[2] != Nes::Video::DEFAULT_CONTRAST ||
|
|
colors[3] != Nes::Video::DEFAULT_HUE
|
|
);
|
|
|
|
dialog.Slider( IDC_VIDEO_COLORS_BRIGHTNESS ).Position() = colors[0] - Nes::Video::MIN_BRIGHTNESS;
|
|
dialog.Slider( IDC_VIDEO_COLORS_SATURATION ).Position() = colors[1] - Nes::Video::MIN_SATURATION;
|
|
dialog.Slider( IDC_VIDEO_COLORS_CONTRAST ).Position() = colors[2] - Nes::Video::MIN_CONTRAST;
|
|
dialog.Slider( IDC_VIDEO_COLORS_HUE ).Position() = colors[3] - Nes::Video::MIN_HUE;
|
|
|
|
dialog.Control( IDC_VIDEO_COLORS_BRIGHTNESS_VAL ).Text() << RealString( colors[0] / 100.0, 2 ).Ptr();
|
|
dialog.Control( IDC_VIDEO_COLORS_SATURATION_VAL ).Text() << RealString( (colors[1] + 100) / 100.0, 2 ).Ptr();
|
|
dialog.Control( IDC_VIDEO_COLORS_CONTRAST_VAL ).Text() << RealString( (colors[2] + 100) / 100.0, 2 ).Ptr();
|
|
dialog.Control( IDC_VIDEO_COLORS_HUE_VAL ).Text() << colors[3];
|
|
}
|
|
|
|
void Video::UpdateScreenCurvature() const
|
|
{
|
|
dialog.Slider( IDC_VIDEO_SC_SLIDER ).Position() = settings.screenCurvature - MIN_SCREEN_CURVATURE;
|
|
dialog.Control( IDC_VIDEO_SC_VALUE ).Text() << RealString( settings.screenCurvature / 10.0 ).Ptr();
|
|
}
|
|
|
|
void Video::UpdateRects(const Rect& ntsc,const Rect& pal) const
|
|
{
|
|
dialog.Control( IDC_VIDEO_NTSC_LEFT ).Text() << uint( ntsc.left );
|
|
dialog.Control( IDC_VIDEO_NTSC_TOP ).Text() << uint( ntsc.top );
|
|
dialog.Control( IDC_VIDEO_NTSC_RIGHT ).Text() << uint( ntsc.right - 1 );
|
|
dialog.Control( IDC_VIDEO_NTSC_BOTTOM ).Text() << uint( ntsc.bottom - 1 );
|
|
dialog.Control( IDC_VIDEO_PAL_LEFT ).Text() << uint( pal.left );
|
|
dialog.Control( IDC_VIDEO_PAL_TOP ).Text() << uint( pal.top );
|
|
dialog.Control( IDC_VIDEO_PAL_RIGHT ).Text() << uint( pal.right - 1 );
|
|
dialog.Control( IDC_VIDEO_PAL_BOTTOM ).Text() << uint( pal.bottom - 1 );
|
|
}
|
|
|
|
void Video::UpdatePalette() const
|
|
{
|
|
const Nes::Video::Palette::Mode mode = Nes::Video(nes).GetPalette().GetMode();
|
|
|
|
dialog.Control( IDC_VIDEO_PALETTE_CLEAR ).Enable( settings.palette.Length() );
|
|
dialog.Control( IDC_VIDEO_PALETTE_CUSTOM ).Enable( settings.palette.Length() );
|
|
dialog.Control( IDC_VIDEO_PALETTE_PATH ).Enable( mode == Nes::Video::Palette::MODE_CUSTOM );
|
|
|
|
dialog.Edit( IDC_VIDEO_PALETTE_PATH ) << settings.palette.Ptr();
|
|
|
|
dialog.Control( IDC_VIDEO_COLORS_ADVANCED ).Enable( mode == Nes::Video::Palette::MODE_YUV );
|
|
|
|
dialog.RadioButton( IDC_VIDEO_PALETTE_AUTO ).Check( settings.autoPalette );
|
|
dialog.RadioButton( IDC_VIDEO_PALETTE_YUV ).Check( !settings.autoPalette && mode == Nes::Video::Palette::MODE_YUV );
|
|
dialog.RadioButton( IDC_VIDEO_PALETTE_RGB ).Check( !settings.autoPalette && mode == Nes::Video::Palette::MODE_RGB );
|
|
dialog.RadioButton( IDC_VIDEO_PALETTE_CUSTOM ).Check( !settings.autoPalette && mode == Nes::Video::Palette::MODE_CUSTOM );
|
|
}
|
|
|
|
void Video::ImportPalette(Path& palette,Managers::Paths::Alert alert)
|
|
{
|
|
if (palette.Empty())
|
|
return;
|
|
|
|
palette.MakePretty();
|
|
|
|
Managers::Paths::File file;
|
|
|
|
if (paths.Load( file, Managers::Paths::File::PALETTE|Managers::Paths::File::ARCHIVE, Application::Instance::GetFullPath(palette), alert ))
|
|
{
|
|
if (file.data.Size() >= Nes::Video::Palette::NUM_ENTRIES*3)
|
|
{
|
|
Nes::Video::Palette::CustomType type = Nes::Video::Palette::STD_PALETTE;
|
|
|
|
if (file.data.Size() >= Nes::Video::Palette::NUM_ENTRIES_EXT*3)
|
|
type = Nes::Video::Palette::EXT_PALETTE;
|
|
|
|
if (NES_SUCCEEDED(Nes::Video(nes).GetPalette().SetCustom( reinterpret_cast<Nes::Video::Palette::Colors>(file.data.Begin()), type )))
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (alert == Managers::Paths::QUIETLY)
|
|
Io::Log() << "Video: warning, custom palette file: \"" << palette << "\" invalid or not found!\r\n";
|
|
else
|
|
User::Fail( IDS_DIALOG_VIDEO_INVALID_PALETTE );
|
|
|
|
palette.Destroy();
|
|
Nes::Video(nes).GetPalette().SetMode( GetDesiredPaletteMode() );
|
|
}
|
|
}
|
|
}
|