//////////////////////////////////////////////////////////////////////////////////////// // // 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; case DECODER_CXA2025AS_JP: axes[0].angle = 95; axes[0].gain = 0.78f; axes[1].angle = 240; axes[1].gain = 0.3f; axes[2].angle = 0; axes[2].gain = 1.0f; boostYellow = false; break; case DECODER_CXA2025AS_US: axes[0].angle = 112; axes[0].gain = 0.83f; axes[1].angle = 252; axes[1].gain = 0.3f; axes[2].angle = 0; axes[2].gain = 1.0f; boostYellow = false; 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 } }