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 EnableOverclocking(bool state)61 Result Video::EnableOverclocking(bool state) throw() 62 { 63 if (emulator.tracker.IsLocked( true )) 64 return RESULT_ERR_NOT_READY; 65 66 if (emulator.ppu.GetOverclockState() != state) 67 { 68 emulator.ppu.SetOverclockState( state ); 69 return RESULT_OK; 70 } 71 72 return RESULT_NOP; 73 } 74 AreUnlimSpritesEnabled() const75 bool Video::AreUnlimSpritesEnabled() const throw() 76 { 77 return !emulator.ppu.HasSpriteLimit(); 78 } 79 GetBrightness() const80 int Video::GetBrightness() const throw() 81 { 82 return emulator.renderer.GetBrightness(); 83 } 84 GetSaturation() const85 int Video::GetSaturation() const throw() 86 { 87 return emulator.renderer.GetSaturation(); 88 } 89 GetContrast() const90 int Video::GetContrast() const throw() 91 { 92 return emulator.renderer.GetContrast(); 93 } 94 GetSharpness() const95 int Video::GetSharpness() const throw() 96 { 97 return emulator.renderer.GetSharpness(); 98 } 99 GetColorResolution() const100 int Video::GetColorResolution() const throw() 101 { 102 return emulator.renderer.GetColorResolution(); 103 } 104 GetColorBleed() const105 int Video::GetColorBleed() const throw() 106 { 107 return emulator.renderer.GetColorBleed(); 108 } 109 GetColorArtifacts() const110 int Video::GetColorArtifacts() const throw() 111 { 112 return emulator.renderer.GetColorArtifacts(); 113 } 114 GetColorFringing() const115 int Video::GetColorFringing() const throw() 116 { 117 return emulator.renderer.GetColorFringing(); 118 } 119 GetHue() const120 int Video::GetHue() const throw() 121 { 122 return emulator.renderer.GetHue(); 123 } 124 GetBlend() const125 bool Video::GetBlend() const throw() 126 { 127 return emulator.renderer.GetBlend() != 0; 128 } 129 GetCornerRounding() const130 int Video::GetCornerRounding() const throw() 131 { 132 return emulator.renderer.GetCornerRounding(); 133 } 134 SetBrightness(int value)135 Result Video::SetBrightness(int value) throw() 136 { 137 return emulator.renderer.SetBrightness( value ); 138 } 139 SetSaturation(int value)140 Result Video::SetSaturation(int value) throw() 141 { 142 return emulator.renderer.SetSaturation( value ); 143 } 144 SetContrast(int value)145 Result Video::SetContrast(int value) throw() 146 { 147 return emulator.renderer.SetContrast( value ); 148 } 149 SetSharpness(int value)150 Result Video::SetSharpness(int value) throw() 151 { 152 return emulator.renderer.SetSharpness( value ); 153 } 154 SetColorResolution(int value)155 Result Video::SetColorResolution(int value) throw() 156 { 157 return emulator.renderer.SetColorResolution( value ); 158 } 159 SetColorBleed(int value)160 Result Video::SetColorBleed(int value) throw() 161 { 162 return emulator.renderer.SetColorBleed( value ); 163 } 164 SetColorArtifacts(int value)165 Result Video::SetColorArtifacts(int value) throw() 166 { 167 return emulator.renderer.SetColorArtifacts( value ); 168 } 169 SetColorFringing(int value)170 Result Video::SetColorFringing(int value) throw() 171 { 172 return emulator.renderer.SetColorFringing( value ); 173 } 174 SetHue(int value)175 Result Video::SetHue(int value) throw() 176 { 177 return emulator.renderer.SetHue( value ); 178 } 179 SetBlend(bool value)180 Result Video::SetBlend(bool value) throw() 181 { 182 return emulator.renderer.SetBlend(value); 183 } 184 SetCornerRounding(int value)185 Result Video::SetCornerRounding(int value) throw() 186 { 187 return emulator.renderer.SetCornerRounding(value); 188 } 189 ClearFilterUpdateFlag()190 void Video::ClearFilterUpdateFlag() throw() 191 { 192 emulator.renderer.ClearFilterUpdateFlag(); 193 } 194 EnableFieldMerging(bool state)195 void Video::EnableFieldMerging(bool state) throw() 196 { 197 emulator.renderer.EnableFieldMerging( state ); 198 } 199 IsFieldMergingEnabled() const200 bool Video::IsFieldMergingEnabled() const throw() 201 { 202 return emulator.renderer.IsFieldMergingEnabled(); 203 } 204 SetRenderState(const RenderState & state)205 Result Video::SetRenderState(const RenderState& state) throw() 206 { 207 const Result result = emulator.renderer.SetState( state ); 208 209 if (NES_SUCCEEDED(result) && result != RESULT_NOP) 210 emulator.UpdateColorMode(); 211 212 return result; 213 } 214 GetRenderState(RenderState & state) const215 Result Video::GetRenderState(RenderState& state) const throw() 216 { 217 return emulator.renderer.GetState( state ); 218 } 219 Blit(Output & output)220 Result Video::Blit(Output& output) throw() 221 { 222 if (emulator.renderer.IsReady()) 223 { 224 emulator.renderer.Blit( output, emulator.ppu.GetScreen(), emulator.ppu.GetBurstPhase() ); 225 return RESULT_OK; 226 } 227 228 return RESULT_ERR_NOT_READY; 229 } 230 RenderState()231 Video::RenderState::RenderState() throw() 232 : 233 width (0), 234 height (0), 235 filter (FILTER_NONE) 236 { 237 bits.count = 0; 238 bits.mask.r = 0; 239 bits.mask.g = 0; 240 bits.mask.b = 0; 241 } 242 Decoder(DecoderPreset preset)243 Video::Decoder::Decoder(DecoderPreset preset) throw() 244 { 245 switch (preset) 246 { 247 case DECODER_CONSUMER: 248 249 axes[0].angle = 105; 250 axes[0].gain = 0.78f; 251 axes[1].angle = 236; 252 axes[1].gain = 0.33f; 253 axes[2].angle = 0; 254 axes[2].gain = 1.0f; 255 boostYellow = false; 256 break; 257 258 case DECODER_ALTERNATIVE: 259 260 axes[0].angle = 105; 261 axes[0].gain = 0.570f; 262 axes[1].angle = 251; 263 axes[1].gain = 0.351f; 264 axes[2].angle = 15; 265 axes[2].gain = 1.015f; 266 boostYellow = true; 267 break; 268 269 default: 270 271 axes[0].angle = 105; 272 axes[0].gain = 0.570f; 273 axes[1].angle = 251; 274 axes[1].gain = 0.351f; 275 axes[2].angle = 15; 276 axes[2].gain = 1.015f; 277 boostYellow = false; 278 break; 279 } 280 } 281 operator ==(const Decoder & decoder) const282 bool Video::Decoder::operator == (const Decoder& decoder) const throw() 283 { 284 for (uint i=0; i < NUM_AXES; ++i) 285 { 286 if (axes[i].angle != decoder.axes[i].angle || axes[i].gain != decoder.axes[i].gain) 287 return false; 288 } 289 290 if (boostYellow != decoder.boostYellow) 291 return false; 292 293 return true; 294 } 295 operator !=(const Decoder & decoder) const296 bool Video::Decoder::operator != (const Decoder& decoder) const throw() 297 { 298 return !(*this == decoder); 299 } 300 SetDecoder(const Decoder & decoder)301 Result Video::SetDecoder(const Decoder& decoder) throw() 302 { 303 return emulator.renderer.SetDecoder( decoder ); 304 } 305 GetDecoder() const306 const Video::Decoder& Video::GetDecoder() const throw() 307 { 308 return emulator.renderer.GetDecoder(); 309 } 310 SetMode(const Mode mode)311 Result Video::Palette::SetMode(const Mode mode) throw() 312 { 313 return emulator.UpdateColorMode 314 ( 315 mode == MODE_RGB ? Core::Machine::COLORMODE_RGB : 316 mode == MODE_CUSTOM ? Core::Machine::COLORMODE_CUSTOM : 317 Core::Machine::COLORMODE_YUV 318 ); 319 } 320 GetMode() const321 Video::Palette::Mode Video::Palette::GetMode() const throw() 322 { 323 if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_YUV) 324 { 325 return MODE_YUV; 326 } 327 else if (emulator.renderer.GetPaletteType() == Core::Video::Renderer::PALETTE_CUSTOM) 328 { 329 return MODE_CUSTOM; 330 } 331 332 return MODE_RGB; 333 } 334 GetDefaultMode() const335 Video::Palette::Mode Video::Palette::GetDefaultMode() const throw() 336 { 337 NST_COMPILE_ASSERT( Core::Video::Renderer::DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 ); 338 339 return MODE_YUV; 340 } 341 SetCustom(Colors colors,CustomType type)342 Result Video::Palette::SetCustom(Colors colors,CustomType type) throw() 343 { 344 return emulator.renderer.LoadCustomPalette( colors, type == EXT_PALETTE ); 345 } 346 GetCustom(uchar (* colors)[3],CustomType type) const347 uint Video::Palette::GetCustom(uchar (*colors)[3],CustomType type) const throw() 348 { 349 return emulator.renderer.SaveCustomPalette( colors, type == EXT_PALETTE ); 350 } 351 ResetCustom()352 void Video::Palette::ResetCustom() throw() 353 { 354 return emulator.renderer.ResetCustomPalette(); 355 } 356 GetCustomType() const357 Video::Palette::CustomType Video::Palette::GetCustomType() const throw() 358 { 359 return emulator.renderer.HasCustomPaletteEmphasis() ? EXT_PALETTE : STD_PALETTE; 360 } 361 GetColors() const362 Video::Palette::Colors Video::Palette::GetColors() const throw() 363 { 364 return emulator.renderer.GetPalette(); 365 } 366 367 #ifdef NST_MSVC_OPTIMIZE 368 #pragma optimize("", on) 369 #endif 370 } 371 } 372