1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #include "../NstMachine.hpp" 26 #include "../NstVideoRenderer.hpp" 27 #include "NstApiVideo.hpp" 28 29 namespace Nes 30 { 31 namespace Core 32 { 33 namespace Video 34 { 35 Output::Locker Output::lockCallback; 36 Output::Unlocker Output::unlockCallback; 37 } 38 } 39 40 namespace Api 41 { 42 #ifdef NST_MSVC_OPTIMIZE 43 #pragma optimize("s", on) 44 #endif 45 EnableUnlimSprites(bool state)46 Result Video::EnableUnlimSprites(bool state) throw() 47 { 48 if (emulator.tracker.IsLocked( true )) 49 return RESULT_ERR_NOT_READY; 50 51 if (!emulator.ppu.HasSpriteLimit() != state) 52 { 53 emulator.ppu.EnableSpriteLimit( !state ); 54 emulator.tracker.Resync( true ); 55 return RESULT_OK; 56 } 57 58 return RESULT_NOP; 59 } 60 AreUnlimSpritesEnabled() const61 bool Video::AreUnlimSpritesEnabled() const throw() 62 { 63 return !emulator.ppu.HasSpriteLimit(); 64 } 65 GetBrightness() const66 int Video::GetBrightness() const throw() 67 { 68 return emulator.renderer.GetBrightness(); 69 } 70 GetSaturation() const71 int Video::GetSaturation() const throw() 72 { 73 return emulator.renderer.GetSaturation(); 74 } 75 GetContrast() const76 int Video::GetContrast() const throw() 77 { 78 return emulator.renderer.GetContrast(); 79 } 80 GetSharpness() const81 int Video::GetSharpness() const throw() 82 { 83 return emulator.renderer.GetSharpness(); 84 } 85 GetColorResolution() const86 int Video::GetColorResolution() const throw() 87 { 88 return emulator.renderer.GetColorResolution(); 89 } 90 GetColorBleed() const91 int Video::GetColorBleed() const throw() 92 { 93 return emulator.renderer.GetColorBleed(); 94 } 95 GetColorArtifacts() const96 int Video::GetColorArtifacts() const throw() 97 { 98 return emulator.renderer.GetColorArtifacts(); 99 } 100 GetColorFringing() const101 int Video::GetColorFringing() const throw() 102 { 103 return emulator.renderer.GetColorFringing(); 104 } 105 GetHue() const106 int Video::GetHue() const throw() 107 { 108 return emulator.renderer.GetHue(); 109 } 110 GetBlend() const111 bool Video::GetBlend() const throw() 112 { 113 return emulator.renderer.GetBlend() != 0; 114 } 115 GetCornerRounding() const116 int Video::GetCornerRounding() const throw() 117 { 118 return emulator.renderer.GetCornerRounding(); 119 } 120 SetBrightness(int value)121 Result Video::SetBrightness(int value) throw() 122 { 123 return emulator.renderer.SetBrightness( value ); 124 } 125 SetSaturation(int value)126 Result Video::SetSaturation(int value) throw() 127 { 128 return emulator.renderer.SetSaturation( value ); 129 } 130 SetContrast(int value)131 Result Video::SetContrast(int value) throw() 132 { 133 return emulator.renderer.SetContrast( value ); 134 } 135 SetSharpness(int value)136 Result Video::SetSharpness(int value) throw() 137 { 138 return emulator.renderer.SetSharpness( value ); 139 } 140 SetColorResolution(int value)141 Result Video::SetColorResolution(int value) throw() 142 { 143 return emulator.renderer.SetColorResolution( value ); 144 } 145 SetColorBleed(int value)146 Result Video::SetColorBleed(int value) throw() 147 { 148 return emulator.renderer.SetColorBleed( value ); 149 } 150 SetColorArtifacts(int value)151 Result Video::SetColorArtifacts(int value) throw() 152 { 153 return emulator.renderer.SetColorArtifacts( value ); 154 } 155 SetColorFringing(int value)156 Result Video::SetColorFringing(int value) throw() 157 { 158 return emulator.renderer.SetColorFringing( value ); 159 } 160 SetHue(int value)161 Result Video::SetHue(int value) throw() 162 { 163 return emulator.renderer.SetHue( value ); 164 } 165 SetBlend(bool value)166 Result Video::SetBlend(bool value) throw() 167 { 168 return emulator.renderer.SetBlend(value); 169 } 170 SetCornerRounding(int value)171 Result Video::SetCornerRounding(int value) throw() 172 { 173 return emulator.renderer.SetCornerRounding(value); 174 } 175 ClearFilterUpdateFlag()176 void Video::ClearFilterUpdateFlag() throw() 177 { 178 emulator.renderer.ClearFilterUpdateFlag(); 179 } 180 EnableFieldMerging(bool state)181 void Video::EnableFieldMerging(bool state) throw() 182 { 183 emulator.renderer.EnableFieldMerging( state ); 184 } 185 IsFieldMergingEnabled() const186 bool Video::IsFieldMergingEnabled() const throw() 187 { 188 return emulator.renderer.IsFieldMergingEnabled(); 189 } 190 SetRenderState(const RenderState & state)191 Result Video::SetRenderState(const RenderState& state) throw() 192 { 193 const Result result = emulator.renderer.SetState( state ); 194 195 if (NES_SUCCEEDED(result) && result != RESULT_NOP) 196 emulator.UpdateColorMode(); 197 198 return result; 199 } 200 GetRenderState(RenderState & state) const201 Result Video::GetRenderState(RenderState& state) const throw() 202 { 203 return emulator.renderer.GetState( state ); 204 } 205 Blit(Output & output)206 Result Video::Blit(Output& output) throw() 207 { 208 if (emulator.renderer.IsReady()) 209 { 210 emulator.renderer.Blit( output, emulator.ppu.GetScreen(), emulator.ppu.GetBurstPhase() ); 211 return RESULT_OK; 212 } 213 214 return RESULT_ERR_NOT_READY; 215 } 216 RenderState()217 Video::RenderState::RenderState() throw() 218 : 219 width (0), 220 height (0), 221 filter (FILTER_NONE) 222 { 223 bits.count = 0; 224 bits.mask.r = 0; 225 bits.mask.g = 0; 226 bits.mask.b = 0; 227 } 228 Decoder(DecoderPreset preset)229 Video::Decoder::Decoder(DecoderPreset preset) throw() 230 { 231 switch (preset) 232 { 233 case DECODER_CONSUMER: 234 235 axes[0].angle = 105; 236 axes[0].gain = 0.78f; 237 axes[1].angle = 236; 238 axes[1].gain = 0.33f; 239 axes[2].angle = 0; 240 axes[2].gain = 1.0f; 241 boostYellow = false; 242 break; 243 244 case DECODER_ALTERNATIVE: 245 246 axes[0].angle = 105; 247 axes[0].gain = 0.570f; 248 axes[1].angle = 251; 249 axes[1].gain = 0.351f; 250 axes[2].angle = 15; 251 axes[2].gain = 1.015f; 252 boostYellow = true; 253 break; 254 255 default: 256 257 axes[0].angle = 105; 258 axes[0].gain = 0.570f; 259 axes[1].angle = 251; 260 axes[1].gain = 0.351f; 261 axes[2].angle = 15; 262 axes[2].gain = 1.015f; 263 boostYellow = false; 264 break; 265 } 266 } 267 operator ==(const Decoder & decoder) const268 bool Video::Decoder::operator == (const Decoder& decoder) const throw() 269 { 270 for (uint i=0; i < NUM_AXES; ++i) 271 { 272 if (axes[i].angle != decoder.axes[i].angle || axes[i].gain != decoder.axes[i].gain) 273 return false; 274 } 275 276 if (boostYellow != decoder.boostYellow) 277 return false; 278 279 return true; 280 } 281 operator !=(const Decoder & decoder) const282 bool Video::Decoder::operator != (const Decoder& decoder) const throw() 283 { 284 return !(*this == decoder); 285 } 286 SetDecoder(const Decoder & decoder)287 Result Video::SetDecoder(const Decoder& decoder) throw() 288 { 289 return emulator.renderer.SetDecoder( decoder ); 290 } 291 GetDecoder() const292 const Video::Decoder& Video::GetDecoder() const throw() 293 { 294 return emulator.renderer.GetDecoder(); 295 } 296 SetMode(const Mode mode)297 Result Video::Palette::SetMode(const Mode mode) throw() 298 { 299 return emulator.UpdateColorMode 300 ( 301 mode == MODE_RGB ? Core::Machine::COLORMODE_RGB : 302 mode == MODE_CUSTOM ? Core::Machine::COLORMODE_CUSTOM : 303 Core::Machine::COLORMODE_YUV 304 ); 305 } 306 GetMode() const307 Video::Palette::Mode Video::Palette::GetMode() const throw() 308 { 309 if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_YUV) 310 { 311 return MODE_YUV; 312 } 313 else if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_CUSTOM) 314 { 315 return MODE_CUSTOM; 316 } 317 318 return MODE_RGB; 319 } 320 GetDefaultMode() const321 Video::Palette::Mode Video::Palette::GetDefaultMode() const throw() 322 { 323 NST_COMPILE_ASSERT( Core::Video::Renderer::DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 ); 324 325 return MODE_YUV; 326 } 327 SetCustom(Colors colors,CustomType type)328 Result Video::Palette::SetCustom(Colors colors,CustomType type) throw() 329 { 330 return emulator.renderer.LoadCustomPalette( colors, type == EXT_PALETTE ); 331 } 332 GetCustom(uchar (* colors)[3],CustomType type) const333 uint Video::Palette::GetCustom(uchar (*colors)[3],CustomType type) const throw() 334 { 335 return emulator.renderer.SaveCustomPalette( colors, type == EXT_PALETTE ); 336 } 337 ResetCustom()338 void Video::Palette::ResetCustom() throw() 339 { 340 return emulator.renderer.ResetCustomPalette(); 341 } 342 GetCustomType() const343 Video::Palette::CustomType Video::Palette::GetCustomType() const throw() 344 { 345 return emulator.renderer.HasCustomPaletteEmphasis() ? EXT_PALETTE : STD_PALETTE; 346 } 347 GetColors() const348 Video::Palette::Colors Video::Palette::GetColors() const throw() 349 { 350 return emulator.renderer.GetPalette(); 351 } 352 353 #ifdef NST_MSVC_OPTIMIZE 354 #pragma optimize("", on) 355 #endif 356 } 357 } 358