1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef TIASURFACE_HXX
19#define TIASURFACE_HXX
20
21class TIA;
22class Console;
23class OSystem;
24class FBSurface;
25
26#include <thread>
27
28#include "Rect.hxx"
29#include "FrameBuffer.hxx"
30#include "NTSCFilter.hxx"
31#include "bspf.hxx"
32#include "TIAConstants.hxx"
33
34/**
35 This class is basically a wrapper around all things related to rendering
36 the TIA image to FBSurface's, and presenting the results to the screen.
37 This is placed in a separate class since currently, rendering a TIA image
38 can consist of TV filters, a separate scanline surface, phosphor modes, etc.
39
40 @author Stephen Anthony
41*/
42
43class TIASurface
44{
45 public:
46 /**
47 Creates a new TIASurface object
48 */
49 explicit TIASurface(OSystem& system);
50
51 /**
52 Set the TIA object, which is needed for actually rendering the TIA image.
53 */
54 void initialize(const Console& console, const FrameBuffer::VideoMode& mode);
55
56 /**
57 Set the palette for TIA rendering. This currently consists of two
58 components: the actual TIA palette, and a mixed TIA palette used
59 in phosphor mode. The latter may eventually disappear once a better
60 phosphor emulation is developed.
61
62 @param tia_palette An actual TIA palette, converted to data values
63 that are actually usable by the framebuffer
64 @param rgb_palette The RGB components of the palette, needed for
65 calculating a phosphor palette
66 */
67 void setPalette(const uInt32* tia_palette, const uInt32* rgb_palette);
68
69 /**
70 Get the TIA base surface for use in saving to a PNG image.
71 */
72 const FBSurface& baseSurface(Common::Rect& rect) const;
73
74 /**
75 Use the palette to map a single indexed pixel color. This is used by the TIA output widget.
76 */
77 uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0);
78
79 /**
80 Get the NTSCFilter object associated with the framebuffer
81 */
82 NTSCFilter& ntsc() { return myNTSCFilter; }
83
84 /**
85 Use NTSC filtering effects specified by the given preset.
86 */
87 void setNTSC(NTSCFilter::Preset preset, bool show = true);
88
89 /**
90 Increase/decrease current scanline intensity by given relative amount.
91 */
92 void setScanlineIntensity(int relative);
93
94 /**
95 Change scanline intensity and interpolation.
96
97 @param relative If non-zero, change current intensity by
98 'relative' amount, otherwise set to 'absolute'
99 @return New current intensity
100 */
101 uInt32 enableScanlines(int relative, int absolute = 50);
102 void enableScanlineInterpolation(bool enable);
103
104 /**
105 Enable/disable/query phosphor effect.
106 */
107 void enablePhosphor(bool enable, int blend = -1);
108 bool phosphorEnabled() const { return myUsePhosphor; }
109
110 /**
111 Used to calculate an averaged color for the 'phosphor' effect.
112
113 @param c1 Color 1
114 @param c2 Color 2
115
116 @return Averaged value of the two colors
117 */
118 inline uInt8 getPhosphor(const uInt8 c1, uInt8 c2) const {
119 // Use maximum of current and decayed previous values
120 c2 = uInt8(c2 * myPhosphorPercent);
121 if(c1 > c2) return c1; // raise (assumed immediate)
122 else return c2; // decay
123 }
124
125 /**
126 Used to calculate an averaged color for the 'phosphor' effect.
127
128 @param c RGB Color 1 (current frame)
129 @param cp RGB Color 2 (previous frame)
130
131 @return Averaged value of the two RGB colors
132 */
133 uInt32 getRGBPhosphor(const uInt32 c, const uInt32 cp) const;
134
135 /**
136 Enable/disable/query NTSC filtering effects.
137 */
138 void enableNTSC(bool enable);
139 bool ntscEnabled() const { return uInt8(myFilter) & 0x10; }
140 string effectsInfo() const;
141
142 /**
143 This method should be called to draw the TIA image(s) to the screen.
144 */
145 void render();
146
147 /**
148 This method prepares the current frame for taking a snapshot.
149 In particular, in phosphor modes the blending is adjusted slightly to
150 generate better images.
151 */
152 void renderForSnapshot();
153
154 /**
155 Save a snapshot after rendering.
156 */
157 void saveSnapShot() { mySaveSnapFlag = true; }
158
159 private:
160 /**
161 Average current calculated buffer's pixel with previous calculated buffer's pixel (50:50).
162 */
163 uInt32 averageBuffers(uInt32 bufOfs);
164
165 private:
166 OSystem& myOSystem;
167 FrameBuffer& myFB;
168 TIA* myTIA;
169
170 shared_ptr<FBSurface> myTiaSurface, mySLineSurface, myBaseTiaSurface;
171
172 // Enumeration created such that phosphor off/on is in LSB,
173 // and Blargg off/on is in MSB
174 enum class Filter: uInt8 {
175 Normal = 0x00,
176 Phosphor = 0x01,
177 BlarggNormal = 0x10,
178 BlarggPhosphor = 0x11
179 };
180 Filter myFilter;
181
182 // NTSC object to use in TIA rendering mode
183 NTSCFilter myNTSCFilter;
184
185 /////////////////////////////////////////////////////////////
186 // Phosphor mode items (aka reduced flicker on 30Hz screens)
187 // RGB frame buffer
188 std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
189 TIAConstants::frameBufferHeight> myRGBFramebuffer;
190 std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
191 TIAConstants::frameBufferHeight> myPrevRGBFramebuffer;
192
193 // Use phosphor effect
194 bool myUsePhosphor;
195
196 // Amount to blend when using phosphor effect
197 float myPhosphorPercent;
198
199 // Precalculated averaged phosphor colors
200 uInt8 myPhosphorPalette[256][256];
201 /////////////////////////////////////////////////////////////
202
203 // Use scanlines in TIA rendering mode
204 bool myScanlinesEnabled;
205
206 // Palette for normal TIA rendering mode
207 const uInt32* myPalette;
208
209 // Flag for saving a snapshot
210 bool mySaveSnapFlag;
211
212 private:
213 // Following constructors and assignment operators not supported
214 TIASurface() = delete;
215 TIASurface(const TIASurface&) = delete;
216 TIASurface(TIASurface&&) = delete;
217 TIASurface& operator=(const TIASurface&) = delete;
218 TIASurface& operator=(TIASurface&&) = delete;
219};
220
221#endif
222