mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
357 lines
8.4 KiB
C++
357 lines
8.4 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 "../NstMachine.hpp"
|
|
#include "../NstVideoRenderer.hpp"
|
|
#include "NstApiVideo.hpp"
|
|
|
|
namespace Nes
|
|
{
|
|
namespace Core
|
|
{
|
|
namespace Video
|
|
{
|
|
Output::Locker Output::lockCallback;
|
|
Output::Unlocker Output::unlockCallback;
|
|
}
|
|
}
|
|
|
|
namespace Api
|
|
{
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("s", on)
|
|
#endif
|
|
|
|
Result Video::EnableUnlimSprites(bool state) throw()
|
|
{
|
|
if (emulator.tracker.IsLocked( true ))
|
|
return RESULT_ERR_NOT_READY;
|
|
|
|
if (!emulator.ppu.HasSpriteLimit() != state)
|
|
{
|
|
emulator.ppu.EnableSpriteLimit( !state );
|
|
emulator.tracker.Resync( true );
|
|
return RESULT_OK;
|
|
}
|
|
|
|
return RESULT_NOP;
|
|
}
|
|
|
|
bool Video::AreUnlimSpritesEnabled() const throw()
|
|
{
|
|
return !emulator.ppu.HasSpriteLimit();
|
|
}
|
|
|
|
int Video::GetBrightness() const throw()
|
|
{
|
|
return emulator.renderer.GetBrightness();
|
|
}
|
|
|
|
int Video::GetSaturation() const throw()
|
|
{
|
|
return emulator.renderer.GetSaturation();
|
|
}
|
|
|
|
int Video::GetContrast() const throw()
|
|
{
|
|
return emulator.renderer.GetContrast();
|
|
}
|
|
|
|
int Video::GetSharpness() const throw()
|
|
{
|
|
return emulator.renderer.GetSharpness();
|
|
}
|
|
|
|
int Video::GetColorResolution() const throw()
|
|
{
|
|
return emulator.renderer.GetColorResolution();
|
|
}
|
|
|
|
int Video::GetColorBleed() const throw()
|
|
{
|
|
return emulator.renderer.GetColorBleed();
|
|
}
|
|
|
|
int Video::GetColorArtifacts() const throw()
|
|
{
|
|
return emulator.renderer.GetColorArtifacts();
|
|
}
|
|
|
|
int Video::GetColorFringing() const throw()
|
|
{
|
|
return emulator.renderer.GetColorFringing();
|
|
}
|
|
|
|
int Video::GetHue() const throw()
|
|
{
|
|
return emulator.renderer.GetHue();
|
|
}
|
|
|
|
bool Video::GetBlend() const throw()
|
|
{
|
|
return emulator.renderer.GetBlend() != 0;
|
|
}
|
|
|
|
int Video::GetCornerRounding() const throw()
|
|
{
|
|
return emulator.renderer.GetCornerRounding();
|
|
}
|
|
|
|
Result Video::SetBrightness(int value) throw()
|
|
{
|
|
return emulator.renderer.SetBrightness( value );
|
|
}
|
|
|
|
Result Video::SetSaturation(int value) throw()
|
|
{
|
|
return emulator.renderer.SetSaturation( value );
|
|
}
|
|
|
|
Result Video::SetContrast(int value) throw()
|
|
{
|
|
return emulator.renderer.SetContrast( value );
|
|
}
|
|
|
|
Result Video::SetSharpness(int value) throw()
|
|
{
|
|
return emulator.renderer.SetSharpness( value );
|
|
}
|
|
|
|
Result Video::SetColorResolution(int value) throw()
|
|
{
|
|
return emulator.renderer.SetColorResolution( value );
|
|
}
|
|
|
|
Result Video::SetColorBleed(int value) throw()
|
|
{
|
|
return emulator.renderer.SetColorBleed( value );
|
|
}
|
|
|
|
Result Video::SetColorArtifacts(int value) throw()
|
|
{
|
|
return emulator.renderer.SetColorArtifacts( value );
|
|
}
|
|
|
|
Result Video::SetColorFringing(int value) throw()
|
|
{
|
|
return emulator.renderer.SetColorFringing( value );
|
|
}
|
|
|
|
Result Video::SetHue(int value) throw()
|
|
{
|
|
return emulator.renderer.SetHue( value );
|
|
}
|
|
|
|
Result Video::SetBlend(bool value) throw()
|
|
{
|
|
return emulator.renderer.SetBlend(value);
|
|
}
|
|
|
|
Result Video::SetCornerRounding(int value) throw()
|
|
{
|
|
return emulator.renderer.SetCornerRounding(value);
|
|
}
|
|
|
|
void Video::ClearFilterUpdateFlag() throw()
|
|
{
|
|
emulator.renderer.ClearFilterUpdateFlag();
|
|
}
|
|
|
|
void Video::EnableFieldMerging(bool state) throw()
|
|
{
|
|
emulator.renderer.EnableFieldMerging( state );
|
|
}
|
|
|
|
bool Video::IsFieldMergingEnabled() const throw()
|
|
{
|
|
return emulator.renderer.IsFieldMergingEnabled();
|
|
}
|
|
|
|
Result Video::SetRenderState(const RenderState& state) throw()
|
|
{
|
|
const Result result = emulator.renderer.SetState( state );
|
|
|
|
if (NES_SUCCEEDED(result) && result != RESULT_NOP)
|
|
emulator.UpdateColorMode();
|
|
|
|
return result;
|
|
}
|
|
|
|
Result Video::GetRenderState(RenderState& state) const throw()
|
|
{
|
|
return emulator.renderer.GetState( state );
|
|
}
|
|
|
|
Result Video::Blit(Output& output) throw()
|
|
{
|
|
if (emulator.renderer.IsReady())
|
|
{
|
|
emulator.renderer.Blit( output, emulator.ppu.GetScreen(), emulator.ppu.GetBurstPhase() );
|
|
return RESULT_OK;
|
|
}
|
|
|
|
return RESULT_ERR_NOT_READY;
|
|
}
|
|
|
|
Video::RenderState::RenderState() throw()
|
|
:
|
|
width (0),
|
|
height (0),
|
|
filter (FILTER_NONE)
|
|
{
|
|
bits.count = 0;
|
|
bits.mask.r = 0;
|
|
bits.mask.g = 0;
|
|
bits.mask.b = 0;
|
|
}
|
|
|
|
Video::Decoder::Decoder(DecoderPreset preset) throw()
|
|
{
|
|
switch (preset)
|
|
{
|
|
case DECODER_CONSUMER:
|
|
|
|
axes[0].angle = 105;
|
|
axes[0].gain = 0.78f;
|
|
axes[1].angle = 236;
|
|
axes[1].gain = 0.33f;
|
|
axes[2].angle = 0;
|
|
axes[2].gain = 1.0f;
|
|
boostYellow = false;
|
|
break;
|
|
|
|
case DECODER_ALTERNATIVE:
|
|
|
|
axes[0].angle = 105;
|
|
axes[0].gain = 0.570f;
|
|
axes[1].angle = 251;
|
|
axes[1].gain = 0.351f;
|
|
axes[2].angle = 15;
|
|
axes[2].gain = 1.015f;
|
|
boostYellow = true;
|
|
break;
|
|
|
|
default:
|
|
|
|
axes[0].angle = 105;
|
|
axes[0].gain = 0.570f;
|
|
axes[1].angle = 251;
|
|
axes[1].gain = 0.351f;
|
|
axes[2].angle = 15;
|
|
axes[2].gain = 1.015f;
|
|
boostYellow = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool Video::Decoder::operator == (const Decoder& decoder) const throw()
|
|
{
|
|
for (uint i=0; i < NUM_AXES; ++i)
|
|
{
|
|
if (axes[i].angle != decoder.axes[i].angle || axes[i].gain != decoder.axes[i].gain)
|
|
return false;
|
|
}
|
|
|
|
if (boostYellow != decoder.boostYellow)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Video::Decoder::operator != (const Decoder& decoder) const throw()
|
|
{
|
|
return !(*this == decoder);
|
|
}
|
|
|
|
Result Video::SetDecoder(const Decoder& decoder) throw()
|
|
{
|
|
return emulator.renderer.SetDecoder( decoder );
|
|
}
|
|
|
|
const Video::Decoder& Video::GetDecoder() const throw()
|
|
{
|
|
return emulator.renderer.GetDecoder();
|
|
}
|
|
|
|
Result Video::Palette::SetMode(const Mode mode) throw()
|
|
{
|
|
return emulator.UpdateColorMode
|
|
(
|
|
mode == MODE_RGB ? Core::Machine::COLORMODE_RGB :
|
|
mode == MODE_CUSTOM ? Core::Machine::COLORMODE_CUSTOM :
|
|
Core::Machine::COLORMODE_YUV
|
|
);
|
|
}
|
|
|
|
Video::Palette::Mode Video::Palette::GetMode() const throw()
|
|
{
|
|
if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_YUV)
|
|
{
|
|
return MODE_YUV;
|
|
}
|
|
else if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_CUSTOM)
|
|
{
|
|
return MODE_CUSTOM;
|
|
}
|
|
|
|
return MODE_RGB;
|
|
}
|
|
|
|
Video::Palette::Mode Video::Palette::GetDefaultMode() const throw()
|
|
{
|
|
NST_COMPILE_ASSERT( Core::Video::Renderer::NST_DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 );
|
|
|
|
return MODE_YUV;
|
|
}
|
|
|
|
Result Video::Palette::SetCustom(Colors colors,CustomType type) throw()
|
|
{
|
|
return emulator.renderer.LoadCustomPalette( colors, type == EXT_PALETTE );
|
|
}
|
|
|
|
uint Video::Palette::GetCustom(uchar (*colors)[3],CustomType type) const throw()
|
|
{
|
|
return emulator.renderer.SaveCustomPalette( colors, type == EXT_PALETTE );
|
|
}
|
|
|
|
void Video::Palette::ResetCustom() throw()
|
|
{
|
|
return emulator.renderer.ResetCustomPalette();
|
|
}
|
|
|
|
Video::Palette::CustomType Video::Palette::GetCustomType() const throw()
|
|
{
|
|
return emulator.renderer.HasCustomPaletteEmphasis() ? EXT_PALETTE : STD_PALETTE;
|
|
}
|
|
|
|
Video::Palette::Colors Video::Palette::GetColors() const throw()
|
|
{
|
|
return emulator.renderer.GetPalette();
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
}
|
|
}
|