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 NTSC_FILTER_HXX
19#define NTSC_FILTER_HXX
20
21class TIASurface;
22class Settings;
23
24#include "bspf.hxx"
25#include "AtariNTSC.hxx"
26
27/**
28 This class is based on the Blargg NTSC filter code from Atari800,
29 and is derived from 'filter_ntsc.(h|c)'. Original code based on
30 implementation from http://www.slack.net/~ant.
31
32 The class is basically a thin wrapper around the AtariNTSC class.
33*/
34class NTSCFilter
35{
36 public:
37 NTSCFilter();
38
39 public:
40 // Set one of the available preset adjustments (Composite, S-Video, RGB, etc)
41 enum class Preset {
42 OFF,
43 RGB,
44 SVIDEO,
45 COMPOSITE,
46 BAD,
47 CUSTOM
48 };
49
50 /* Normally used in conjunction with custom mode, contains all
51 aspects currently adjustable in NTSC TV emulation. */
52 struct Adjustable {
53 uInt32 hue, saturation, contrast, brightness, gamma,
54 sharpness, resolution, artifacts, fringing, bleed;
55 };
56
57 public:
58 /* Informs the NTSC filter about the current TIA palette. The filter
59 uses this as a baseline for calculating its own internal palette
60 in YIQ format.
61 */
62 inline void setTIAPalette(const uInt32* palette) {
63 uInt8* ptr = myTIAPalette;
64
65 // Set palette for normal fill
66 for(uInt32 i = 0; i < AtariNTSC::palette_size; ++i)
67 {
68 *ptr++ = (palette[i] >> 16) & 0xff;
69 *ptr++ = (palette[i] >> 8) & 0xff;
70 *ptr++ = palette[i] & 0xff;
71 }
72 myNTSC.initializePalette(myTIAPalette);
73 }
74
75 inline void setPhosphorPalette(uInt8 palette[256][256]) {
76 myNTSC.setPhosphorPalette(palette);
77 }
78
79 // The following are meant to be used strictly for toggling from the GUI
80 string setPreset(Preset preset);
81
82 // Get current preset info encoded as a string
83 string getPreset() const;
84
85 // Get adjustables for the given preset
86 // Values will be scaled to 0 - 100 range, independent of how
87 // they're actually stored internally
88 void getAdjustables(Adjustable& adjustable, Preset preset) const;
89
90 // Set custom adjustables to given values
91 // Values will be scaled to 0 - 100 range, independent of how
92 // they're actually stored internally
93 void setCustomAdjustables(Adjustable& adjustable);
94
95 // The following methods cycle through each custom adjustable
96 // They are used in conjunction with the increase/decrease
97 // methods, which change the currently selected adjustable
98 // Changes are made this way since otherwise 20 key-combinations
99 // would be needed to dynamically change each setting, and now
100 // only 4 combinations are necessary
101 string setNextAdjustable();
102 string setPreviousAdjustable();
103 string increaseAdjustable();
104 string decreaseAdjustable();
105
106 // Load and save NTSC-related settings
107 void loadConfig(const Settings& settings);
108 void saveConfig(Settings& settings) const;
109
110 // Perform Blargg filtering on input buffer, place results in
111 // output buffer
112 inline void render(uInt8* src_buf, uInt32 src_width, uInt32 src_height,
113 uInt32* dest_buf, uInt32 dest_pitch)
114 {
115 myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch);
116 }
117 inline void render(uInt8* src_buf, uInt32 src_width, uInt32 src_height,
118 uInt32* dest_buf, uInt32 dest_pitch, uInt32* prev_buf)
119 {
120 myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch, prev_buf);
121 }
122
123 // Enable threading for the NTSC rendering
124 inline void enableThreading(bool enable)
125 {
126 myNTSC.enableThreading(enable);
127 }
128
129 private:
130 // Convert from atari_ntsc_setup_t values to equivalent adjustables
131 void convertToAdjustable(Adjustable& adjustable,
132 const AtariNTSC::Setup& setup) const;
133
134 private:
135 // The NTSC object
136 AtariNTSC myNTSC;
137
138 // Contains controls used to adjust the palette in the NTSC filter
139 // This is the main setup object used by the underlying ntsc code
140 AtariNTSC::Setup mySetup;
141
142 // This setup is used only in custom mode (after it is modified,
143 // it is copied to mySetup)
144 static AtariNTSC::Setup myCustomSetup;
145
146 // Current preset in use
147 Preset myPreset;
148
149 // The base 2600 palette contains 128 normal colours
150 // and 128 black&white colours (PAL colour loss)
151 // Each colour is represented by 3 bytes, in R,G,B order
152 uInt8 myTIAPalette[AtariNTSC::palette_size * 3];
153
154 struct AdjustableTag {
155 const char* const type;
156 float* value;
157 };
158 uInt32 myCurrentAdjustable;
159 static const AdjustableTag ourCustomAdjustables[10];
160
161 private:
162 // Following constructors and assignment operators not supported
163 NTSCFilter(const NTSCFilter&) = delete;
164 NTSCFilter(NTSCFilter&&) = delete;
165 NTSCFilter& operator=(const NTSCFilter&) = delete;
166 NTSCFilter& operator=(NTSCFilter&&) = delete;
167};
168
169#endif
170