This commit is contained in:
Thomas Jentzsch 2020-05-19 08:28:06 +02:00
commit e903bcf516
153 changed files with 4448 additions and 2979 deletions

View File

@ -14,26 +14,39 @@
6.1.2 to 6.2: (??? ??, 2020)
* Added that paddle centering and sensitivity can be adjusted (TODO: Doc)
* Added that Driving controller sensitivity can be adjusted (TODO: Doc)
* Added high scores: Score addresses, game variation etc. can be defined for
a game. This allows the user to save high scores for these games. For each
game and variation, the top 10 scores can be saved. (TODO: Doc)
* Added interactive palette to Video & Audio settings.
* Added 'Custom' palette, generated from user controlled phase shifts.
* Added that adjustable audio & video settings are displayed as gauge bars
* Added four global hotkeys which allow selecting and changing numerous
audio & video settings without having to remember the dedicated hotkeys
* Added 'Turbo' mode, runs the game as fast as the computer allows.
* Added that paddle centering (per ROM) and sensitivity can be adjusted
* Added that mouse sensitivity for Driving controller can be adjusted
* Added selectable dialog fonts
* Added separate positioning of launcher, emulator and debugger
* Added option which lets default ROM path follow launcher navigation
* Added debugger 'saveaccess' function, which saves memory access counts to
a CSV file.
* Added displaying last write address in the debugger.
* Added debugger pseudo-register '_scanend', which gives the number of
scanlines at the end of the last frame.
* Added detection of color and audio data in DiStella.
* Restored 'cfg' directory for Distella config files.
@ -42,9 +55,6 @@
* Removed unused CV+ and DASH bank switching types.
* Added debugger pseudo-register '_scanend', which gives the number of
scanlines at the end of the last frame.
-Have fun!

View File

@ -978,6 +978,7 @@ clearsavestateifs - Clear all savestate points
runtopc - Run until PC is set to value xx
s - Set Stack Pointer to value xx
save - Save breaks, watches, traps and functions to file xx
saveaccess - Save access counters to CSV file
saveconfig - Save Distella config file (with default name)
savedis - Save Distella disassembly (with default name)
saverom - Save (possibly patched) ROM (with default name)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -19,7 +19,7 @@
<br><br>
<center><h2><b>A multi-platform Atari 2600 VCS emulator</b></h2></center>
<center><h4><b>Release 6.1</b></h4></center>
<center><h4><b>Release 6.2</b></h4></center>
<br><br>
<center><h2><b>User's Guide</b></h2></center>
@ -70,7 +70,7 @@
<br><br><br>
<center><b>February 1999 - March 2020</b></center>
<center><b>February 1999 - ??? 2020</b></center>
<center><b>The Stella Team</b></center>
<center><b><a href="https://stella-emu.github.io">Stella Homepage</a></b></center>
@ -1336,7 +1336,150 @@
</table>
<p><b>TV effects (can be remapped, only active in TIA mode)</b></p>
<p><b>Audio & Video Keys (can be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr>
<th>Function</th>
<th>Key (Standard)</th>
<th>Key (macOS)</th>
</tr>
<tr>
<td>Toggle sound</td>
<td>Control + ]</td>
<td>Control + ]</td>
</tr>
<tr>
<td><i>Decrease</i> volume</td>
<td>Alt + [</td>
<td>Cmd + [</td>
</tr>
<tr>
<td><i>Increase</i> volume</td>
<td>Alt + ]</td>
<td>Cmd + ]</td>
</tr>
<tr>
<td>Switch to next <i>larger</i> zoom level in windowed mode,
</br>toggle stretching in fullscreen mode</td>
<td>Alt + =</td>
<td>Cmd + =</td>
</tr>
<tr>
<td>Switch to next <i>smaller</i> zoom level in windowed mode,
</br>toggle stretching in fullscreen mode</td>
<td>Alt + -</td>
<td>Cmd + -</td>
</tr>
<tr>
<td>Toggle windowed/fullscreen mode</td>
<td>Alt + Enter</td>
<td>Cmd + Enter</td>
</tr>
<tr>
<td><i>Decrease</i> overscan in fullscreen mode</td>
<td>Shift + PageDown</td>
<td>Shift-Fn + Down arrow</td>
</tr>
<tr>
<td><i>Increase</i> overscan in fullscreen mode</td>
<td>Shift + PageUp</td>
<td>Shift-Fn + Up arrow</td>
</tr>
<tr>
<td>Move display <i>down</i> (uses "Display.VCenter")</td>
<td>Alt + PageDown</td>
<td>Cmd-Fn + Down arrow</td>
</tr>
<tr>
<td>Move display <i>up</i> (uses "Display.VCenter")</td>
<td>Alt + PageUp</td>
<td>Cmd-Fn + Up arrow</td>
</tr>
<tr>
<td><i>Decrease</i> vertical display size</td>
<td>Shift-Alt + PageUp</td>
<td>Shift-Cmd-Fn + Up arrow</td>
</tr>
<tr>
<td><i>Increase</i> vertical display size</td>
<td>Shift-Alt + PageDown</td>
<td>Shift-Cmd-Fn + Down arrow</td>
</tr>
<tr>
<td>Switch to <i>previous</i> display format (NTSC/PAL/SECAM etc.)</td>
<td>Shift-Control + f</td>
<td>Shift-Control + f</td>
</tr>
<tr>
<td>Switch to <i>next</i> display format (NTSC/PAL/SECAM etc.)</td>
<td>Control + f</td>
<td>Control + f</td>
</tr>
<tr>
<td>Toggle display interpolation</td>
<td>Control + i</td>
<td>Control + i</td>
</tr>
<tr>
<td colspan="3"><center><font size="-1">
These settings can also be changed using <a href="#GlobalKeys"><b>Global Audio & Video Keys</a></font></center>
</td>
</tr>
</table>
<p><b>Palettes Keys (can be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr>
<th>Function</th>
<th>Key (Standard)</th>
<th>Key (macOS)</th>
</tr>
<tr>
<td>Select <i>previous</i> palette (Standard/z26/User/Custom)</td>
<td>Shift-Control + p</td>
<td>Shift-Control + p</td>
</tr>
<tr>
<td>Select <i>next</i> palette (Standard/z26/User/Custom)</td>
<td>Control + p</td>
<td>Control + p</td>
</tr>
<tr>
<td>Select <i>previous</i> palette attribute</td>
<td>Shift-Alt + 9</td>
<td>Shift-Cmd + 9</td>
</tr>
<tr>
<td>Select <i>next</i> palette attribute</td>
<td>Alt + 9</td>
<td>Cmd + 9</td>
</tr>
<tr>
<td><i>Decrease</i> selected palette attribute</td>
<td>Shift-Alt + 0</td>
<td>Shift-Cmd + 0</td>
</tr>
<tr>
<td><i>Increase</i> selected palette attribute</td>
<td>Alt + 0</td>
<td>Cmd + 0</td>
</tr>
<tr>
<td colspan="3"><center><font size="-1">
These settings can also be changed using <a href="#GlobalKeys"><b>Global Audio & Video Keys</a></font></center>
</td>
</tr>
</table>
<p><b>TV effects Keys (can be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr>
@ -1345,93 +1488,112 @@
<th>Key (macOS)</th>
</tr>
<tr>
<td>Disable TV effects</td>
<td>Select <i>previous</i> TV effects preset</td>
<td>Shift-Alt + 1</td>
<td>Shift-Cmd + 1</td>
</tr>
<tr>
<td>Select <i>next</i> TV effects preset</td>
<td>Alt + 1</td>
<td>Cmd + 1</td>
</tr>
<tr>
<td>Select 'RGB' preset</td>
<td>Select <i>previous</i> 'Custom' mode attribute (*)</td>
<td>Shift-Alt + 2</td>
<td>Shift-Cmd + 2</td>
</tr>
<tr>
<td>Select <i>next</i> 'Custom' mode attribute (*)</td>
<td>Alt + 2</td>
<td>Cmd + 2</td>
</tr>
<tr>
<td>Select 'S-Video' preset</td>
<td><i>Decrease</i> 'Custom' selected attribute value (*)</td>
<td>Shift-Alt + 3</td>
<td>Shift-Cmd + 3</td>
</tr>
<tr>
<td><i>Increase</i> 'Custom' selected attribute value (*)</td>
<td>Alt + 3</td>
<td>Cmd + 3</td>
</tr>
<tr>
<td>Select 'Composite' preset</td>
<td>Alt + 4</td>
<td>Cmd + 4</td>
</tr>
<tr>
<td>Select 'Badly adjusted' preset</td>
<td>Alt + 5</td>
<td>Cmd + 5</td>
</tr>
<tr>
<td>Select 'Custom' preset</td>
<td>Alt + 6</td>
<td>Cmd + 6</td>
</tr>
<tr>
<td>Select previous 'Custom' mode attribute (*)</td>
<td>Shift-Alt + 7</td>
<td>Shift-Cmd + 7</td>
</tr>
<tr>
<td>Select next 'Custom' mode attribute (*)</td>
<td>Alt + 7</td>
<td>Cmd + 7</td>
</tr>
<tr>
<td>Decrease 'Custom' selected attribute value (*)</td>
<td>Shift-Alt + 8</td>
<td>Shift-Cmd + 8</td>
</tr>
<tr>
<td>Increase 'Custom' selected attribute value (*)</td>
<td>Alt + 8</td>
<td>Cmd + 8</td>
</tr>
<tr>
<td>Toggle 'phosphor' mode</td>
<td>Alt + p</td>
<td>Cmd + p</td>
</tr>
<tr>
<td>Decrease 'phosphor' blend</td>
<td>Shift-Alt + 9</td>
<td>Shift-Cmd + 9</td>
</tr>
<tr>
<td>Increase 'phosphor' blend</td>
<td>Alt + 9</td>
<td>Cmd + 9</td>
</tr>
<tr>
<td>Decrease scanline intensity</td>
<td>Shift-Alt + 0</td>
<td>Shift-Cmd + 0</td>
<td><i>Decrease</i> 'phosphor' blend</td>
<td>Shift-Alt + 4</td>
<td>Shift-Cmd + 4</td>
</tr>
<tr>
<td>Increase scanline intensity</td>
<td>Alt + 0</td>
<td>Cmd + 0</td>
<td><i>Increase</i> 'phosphor' blend</td>
<td>Alt + 4</td>
<td>Cmd + 4</td>
</tr>
<tr>
<td><i>Decrease</i> scanline intensity</td>
<td>Shift-Alt + 5</td>
<td>Shift-Cmd + 5</td>
</tr>
<tr>
<td><i>Increase</i> scanline intensity</td>
<td>Alt + 5</td>
<td>Cmd + 5</td>
</tr>
<tr>
<td colspan="3"><center><font size="-1">
Items marked as (*) will also switch to 'Custom' preset mode</font></center></td>
These settings can also be changed using <a href="#GlobalKeys"><b>Global Audio & Video Keys</a></font></center>
</td>
</tr>
<tr>
<td colspan="3"><center><font size="-1">
Items marked as (*) will also switch to 'Custom' mode</font></center></td>
</tr>
</table>
<p><b><a name="GlobalKeys">Global Audio & Video Keys</a> (can be remapped)</b></p>
<p>These keys allow selecting and changing audio & video settings without having to remember the
dedicated keys.</p>
<table BORDER=2 cellpadding=4>
<tr>
<th>Function</th>
<th>Key (Standard)</th>
<th>Key (macOS)</th>
</tr>
<tr>
<td>Select <i>previous</i> AV setting</td>
<td>End</td>
<td>Fn + Left arrow</td>
</tr>
<tr>
<td>Select <i>next</i> AV setting</td>
<td>Home</td>
<td>Fn + Right arrow</td>
</tr>
<tr>
<td><i>Decrease</i> current AV setting</td>
<td>PageDown</td>
<td>Fn + Down arrow</td>
</tr>
<tr>
<td><i>Increase</i> current AV setting
<td>PageUp</td>
<td>Fn + Up arrow</td>
</tr>
</table>
<p>Notes:
<ul>
<li>Only available if UI messages are enabled.</li>
<li>Currently not available settings are automatically skipped.</li>
<li>If a setting was selected via dedicated key, its value can also be changed with the
global keys.</li>
</ul>
</p></br>
<a name="DeveloperKeys"></a>
<p><b>Developer Keys in TIA mode (can be remapped)</b></p>
<p><b>Developer Keys (can be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr>
@ -1549,7 +1711,7 @@
</tr>
</table>
<p><b>Other Keys (can be remapped)</b></p>
<p><b>Other Emulation Keys (can be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr>
@ -1557,111 +1719,11 @@
<th>Key (Standard)</th>
<th>Key (macOS)</th>
</tr>
<tr>
<td>Switch to next <i>larger</i> zoom level in windowed mode,
</br>toggle stretching in fullscreen mode</td>
<td>Alt + =</td>
<td>Cmd + =</td>
</tr>
<tr>
<td>Switch to next <i>smaller</i> zoom level in windowed mode,
</br>toggle stretching in fullscreen mode</td>
<td>Alt + -</td>
<td>Cmd + -</td>
</tr>
<tr>
<td>Toggle fullscreen/windowed mode</td>
<td>Alt + Enter</td>
<td>Cmd + Enter</td>
</tr>
<tr>
<td>Decrease overscan in fullscreen mode</td>
<td>Shift + PageDown</td>
<td>Shift + PageDown</td>
</tr>
<tr>
<td>Increase overscan in fullscreen mode</td>
<td>Shift + PageUp</td>
<td>Shift + PageUp</td>
</tr>
<tr>
<td>Move display <i>up</i> (uses "Display.VCenter")</td>
<td>Alt + PageUp</td>
<td>Cmd + PageUp</td>
</tr>
<tr>
<td>Move display <i>down</i> (uses "Display.VCenter")</td>
<td>Alt + PageDown</td>
<td>Cmd + PageDown</td>
</tr>
<tr>
<td>Switch display format in <i>decreasing</i> order (NTSC/PAL/SECAM etc.)</td>
<td>Shift-Control + f</td>
<td>Shift-Control + f</td>
</tr>
<tr>
<td>Switch display format in <i>increasing</i> order (NTSC/PAL/SECAM etc.)</td>
<td>Control + f</td>
<td>Control + f</td>
</tr>
<tr>
<td>Switch palette (Standard/Z26/User/Custom)</td>
<td>Control + p</td>
<td>Control + p</td>
</tr>
<tr>
<td>Decrease custom palette phase shift (switches to 'Custom' palette)</td>
<td>Shift-Control + 9</td>
<td>Shift-Control + 9</td>
</tr>
<tr>
<td>Increase custom palette phase shift (switches to 'Custom' palette)</td>
<td>Control + 9</td>
<td>Control + 9</td>
</tr>
<tr>
<td>Toggle display interpolation</td>
<td>Control + i</td>
<td>Control + i</td>
</tr>
<tr>
<td>Toggle 'Turbo' mode</td>
<td>Control + t</td>
<td>Control + t</td>
</tr>
<tr>
<td>Toggle sound on/off</td>
<td>Control + ]</td>
<td>Control + ]</td>
</tr>
<tr>
<td>Decrease volume</td>
<td>Alt + [</td>
<td>Cmd + [</td>
</tr>
<tr>
<td>Increase volume</td>
<td>Alt + ]</td>
<td>Cmd + ]</td>
</tr>
<tr>
<td>Switch mouse between controller emulation modes</br>(see <b>Game Properties - <a href="#Controller">Controller</a></b>)</td>
<td>Control + 0</td>
@ -1761,7 +1823,7 @@
</tr>
</table>
<p><b>UI keys in Text Editing areas (cannot be remapped)</b></p>
<p><b>UI Keys in Text Editing areas (cannot be remapped)</b></p>
<table BORDER=2 cellpadding=4>
<tr><th>Key</th><th>Editor Function</th></tr>
@ -2008,11 +2070,11 @@
<tr>
<td><pre>-center &lt;1|0&gt;</pre></td>
<td>Centers game window (if possible).</td>
<td>Centers all windows (if possible).</td>
</tr>
<tr>
<td><pre>-windowedpos &lt;WxH&gt;</pre></td>
<td><pre>-windowedpos &lt;XxY&gt;</pre></td>
<td>Sets the window position in windowed emulator mode.</td>
</tr>
@ -2029,13 +2091,38 @@
</tr>
<tr>
<td><pre>-phase_ntsc &lt;number&gt;</pre></td>
<td>Set phase shift for custom NTSC palette.</td>
<td><pre>-pal.phase_ntsc &lt;number&gt;</pre></td>
<td>Adjust phase shift of 'custom' NTSC palette.</td>
</tr>
<tr>
<td><pre>-phase_pal &lt;number&gt;</pre></td>
<td>Set phase shift for custom PAL palette.</td>
<td><pre>-pal.phase_pal &lt;number&gt;</pre></td>
<td>Adjust phase shift of 'custom' PAL palette.</td>
</tr>
<tr>
<td><pre>-pal.hue &lt;number&gt;</pre></td>
<td>Adjust hue of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.saturation &lt;number&gt;</pre></td>
<td>Adjust saturation of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.contrast &lt;number&gt;</pre></td>
<td>Adjust contrast of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.brightness &lt;number&gt;</pre></td>
<td>Adjust brightness of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.gamma &lt;number&gt;</pre></td>
<td>Adjust gamma of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
@ -2152,36 +2239,6 @@
and 'Custom' modes.</td>
</tr>
<tr>
<td><pre>-tv.contrast &lt;number&gt;</pre></td>
<td>Blargg TV effects 'contrast' (only available in custom mode,
range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-tv.brightness &lt;number&gt;</pre></td>
<td>Blargg TV effects 'brightness' (only available in custom mode,
range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-tv.hue &lt;number&gt;</pre></td>
<td>Blargg TV effects 'hue' (only available in custom mode,
range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-tv.saturation &lt;number&gt;</pre></td>
<td>Blargg TV effects 'saturation' (only available in custom mode,
range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-tv.gamma &lt;number&gt;</pre></td>
<td>Blargg TV effects 'gamma' (only available in custom mode,
range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-tv.sharpness &lt;number&gt;</pre></td>
<td>Blargg TV effects 'sharpness' (only available in custom mode,
@ -2319,6 +2376,13 @@
faster movement.</td>
</tr>
<tr>
<td><pre>-dcsense &lt;number&gt;</pre></td>
<td>Sensitivity for emulation of driving controllers when using a mouse.
Valid range of values is from 1 to 20, with larger numbers causing
faster movement.</td>
</tr>
<tr>
<td><pre>-saport &lt;lr|rl&gt;</pre></td>
<td>Determines how to enumerate the Stelladaptor/2600-daptor devices in the
@ -2410,7 +2474,7 @@
</tr>
<tr>
<td><pre>-launcherpos &lt;WxH&gt;</pre></td>
<td><pre>-launcherpos &lt;XxY&gt;</pre></td>
<td>Sets the window position in windowed ROM launcher mode.</td>
</tr>
@ -2566,7 +2630,7 @@
</tr>
<tr>
<td><pre>-dbg.pos &lt;WxH&gt;</pre></td>
<td><pre>-dbg.pos &lt;XxY&gt;</pre></td>
<td>Sets the window position in windowed debugger mode.</td>
</tr>
@ -2703,6 +2767,16 @@
<td>Set "Controller.SwapPaddles" property.</td>
</tr>
<tr>
<td><pre>-pxcenter &lt;-10..30&gt;</pre></td>
<td>Set "Controller.PaddlesXCenter" property.</td>
</tr>
<tr>
<td><pre>-pycenter &lt;-10..30&gt;</pre></td>
<td>Set "Controller.PaddlesYCenter" property.</td>
</tr>
<tr>
<td><pre>-ma &lt;Auto|XY&gt;</pre></td>
<td>Set "Controller.MouseAxis" property.
@ -2860,7 +2934,7 @@
<p><b>Options Menu</b> dialog:<br><br>
<img src="graphics/options.png">
<br><br>
<p><b>Video Settings</b> dialog:</p>
<p><b>Video & Audio Settings</b> dialog (Display):</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/options_video.png"></td>
@ -2869,29 +2943,42 @@
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Renderer</td><td>Use specified rendering mode</td><td>-video</td></tr>
<tr><td>Palette</td><td>Palette for emulation mode</td><td>-palette</td></tr>
<tr><td>NTSC phase</td><td>Phase shift for custom NTSC palette</td><td>-phase_ntsc</td></tr>
<tr><td>PAL phase</td><td>Phase shift for custom PAL palette</td><td>-phase_pal</td></tr>
<tr><td>Interpolation</td><td>Interpolation for TIA image</td><td>-tia.inter</td></tr>
<tr><td>Zoom</td><td>Zoom level for emulation mode </td><td>-tia.zoom</td></tr>
<tr><td>V-Size adjust</td><td>Adjust height of TIA image</td><td>-tia.vsizeadjust</td></tr>
<tr><td>Emul. speed</td><td>Emulation speed</td><td>-speed</td></tr>
<tr><td>VSync</td><td>Enable vertical synced updates</td><td>-vsync</td></tr>
<tr><td>Interpolation</td><td>Interpolation of TIA image</td><td>-tia.inter</td></tr>
<tr><td>Zoom</td><td>Zoom level of TIA image</td><td>-tia.zoom</td></tr>
<tr><td>Fullscreen</td><td>Self-explanatory - Note that colors may slightly change.
This depends on the OS and renderer used.</td><td>-fullscreen</td></tr>
<tr><td>Stretch</td><td>In fullscreen mode, completely fill screen with TIA image</td><td>-tia.fs_stretch</td></tr>
<tr><td>Overscan</td><td>In fullscreen mode, add overscan to the TIA image</td><td>-tia.fs_overscan</td></tr>
<tr><td>Fast SuperCharger load</td><td>Skip progress loading bars for SuperCharger ROMs</td><td>-fastscbios</td></tr>
<tr><td>Show UI messages</td><td>Overlay UI messages onscreen</td><td>-uimessages</td></tr>
<tr><td>Center window</td><td>Attempt to center application windows, else position at last position</td><td>-center</td></tr>
<tr><td>Multi-threading</td><td>Enable multi-threaded rendering</td><td>-threads</td></tr>
<tr><td>V-Size adjust</td><td>Adjust height of TIA image</td><td>-tia.vsizeadjust</td></tr>
</table>
</td>
</tr>
</table>
<br>
<p><b>Video Settings</b> dialog (TV Effects):</p>
<p><b>Video & Audio Settings</b> dialog (Palettes):</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/options_video_palettes.png"></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign="top">
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr>
<tr><td>NTSC phase</td><td>Adjust phase shift for 'Custom' NTSC palette</td><td>-pal.phase_ntsc</td></tr>
<tr><td>PAL phase</td><td>Adjust phase shift for 'Custom' PAL palette</td><td>-pal.phase_pal</td></tr>
<tr><td>Hue</td><td>Adjust hue of currently selected palette</td><td>-pal.hue</td></tr>
<tr><td>Saturation</td><td>Adjust saturation of currently selected palette</td><td>-pal.saturation</td></tr>
<tr><td>Contrast</td><td>Adjust contrast of currently selected palette</td><td>-pal.contrast</td></tr>
<tr><td>Brightness</td><td>Adjust brightness of currently selected palette</td><td>-pal.brightness</td></tr>
<tr><td>Gamma</td><td>Adjust gamma of currently selected palette</td><td>-pal.gamma</td></tr>
</table>
</td>
</tr>
</table>
<br>
<p><b>Video & Audio Settings</b> dialog (TV Effects):</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/options_video_tv.png"></td>
@ -2900,24 +2987,24 @@
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>TV mode</td><td>Disable TV effects, or select TV preset</td><td>-tv.filter</td></tr>
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.contrast, -tv.hue, etc.</td></tr>
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.sharpness, -tv.resolution, etc.</td></tr>
<tr><td>Phosphor for all ROMs</td><td>Enable phosphor mode for all ROMs</td><td>-tv.phosphor</td></tr>
<tr><td>Blend (phosphor)</td><td>Blend level to use in phosphor mode for all ROMs
(needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>
<tr><td>Scanline intensity</td><td>Sets scanline black-level intensity.</br>
Note: No scanlines in 1x mode snapshots.</td><td>-tv.scanlines</td></tr>
<tr><td>Clone Composite</td><td>Copy 'Composite' attributes to 'Custom' sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone S-Video</td><td>Copy 'S-Video' attributes to 'Custom' sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone RGB</td><td>Copy 'RGB' attributes to 'Custom' sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Bad adjust</td><td>Copy 'Bad Adjust' attributes to 'Custom' sliders</td><td>&nbsp;</td></tr>
<tr><td>Revert</td><td>Revert attribute sliders to saved 'Custom' settings</td><td>&nbsp;</td></tr>
<tr><td>Clone RGB</td><td>Copy 'RGB' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone S-Video</td><td>Copy 'S-Video' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Composite</td><td>Copy 'Composite' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Clone Bad adjust</td><td>Copy 'Bad Adjust' attributes to 'Custom' TV mode sliders</td><td>&nbsp;</td></tr>
<tr><td>Revert</td><td>Revert attribute sliders to saved 'Custom' TV mode settings</td><td>&nbsp;</td></tr>
</table>
</td>
</tr>
</table>
<br>
<p><b>Audio Settings</b> dialog:</p>
<p><b>Video & Audio Settings</b> dialog (Audio):</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/options_audio.png"></td>
@ -2941,7 +3028,7 @@
</td><td>-audio.resampling_quality</td></tr>
<tr><td>Headroom</td><td>Number of frames to buffer before playback starts. Higher values increase latency, but reduce the potential for dropouts.</td><td>-audio.headroom</td></tr>
<tr><td>Buffer size</td><td>Maximum size of the audio buffer. Higher values increase maximum latency, but reduce the potential for dropouts</td><td>-audio.buffer_size</td></tr>
<tr><td>Stereo for all ROMs</td><td>Enables stereo mode for all ROMs.</td><td>-audio.stereo</td></tr>
<tr><td>Stereo for all ROMs</td><td>Enable stereo mode for all ROMs.</td><td>-audio.stereo</td></tr>
<tr><td>Pitfall II music pitch</td><td>Defines the pitch of Pitfall II music (which may vary between carts).</td><td>-audio.dpc_pitch</td></tr>
</table>
<p>
@ -2960,6 +3047,44 @@
</tr>
</table>
<br>
<p><b>Emulation</b> dialog:</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/options_emulation.png"></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign="top">
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Emulation speed</td><td>Emulation speed</td><td>-speed</td></tr>
<tr><td>VSync</td><td>Enable vertical synced updates</td><td>-vsync</td></tr>
<tr><td>Turbo</td><td>Enable 'Turbo' mode for maximum emulation speed. This overwrites 'Emulation speed' setting and disables 'VSync'.</td><td>-turbo</td></tr>
<tr><td>Multi-threading</td><td>Enable multi-threaded rendering</td><td>-threads</td></tr>
<tr><td>Fast SuperCharger load</td><td>Skip progress loading bars for SuperCharger ROMs</td><td>-fastscbios</td></tr>
<tr><td>Show UI messages</td><td>Overlay UI messages onscreen</td><td>-uimessages</td></tr>
<tr><td>Confirm exiting...</td><td>Display a popup when emulation is exited</td><td>-confirmexit</td></tr>
<tr>
<td>When entering/exiting emulation:</td>
<td>
Automatically save no, current or all Time Machine states when exiting emulation.<br/>
The latter also loads all states when entering emulation. When this is enabled, you
can always continue your game session from where you exited it. Even including the
Time Machine buffer!
</td>
<td>-saveonexit</td>
</tr><tr>
<td>Automatically change...</td>
<td>
Automatically change to the next available save state slot after saving a ROM state file.
</td>
<td>-autoslot</td>
</tr>
</table>
</td>
</tr>
</table>
<br>
<p><b>Input Settings</b> dialog:</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
@ -2980,9 +3105,9 @@
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Theme</td><td>Theme to use for UI elements (see examples)</td><td>-uipalette</td></tr>
<tr><td>Dialogs font</td><td>The font used in the dialogs</td><td>-dialogfont</td></tr>
<tr><td>HiDPI mode</td><td>Scales the UI by a factor of two when enabled</td><td>-hidpi</td></tr>
<tr><td>HiDPI mode</td><td>Scale the UI by a factor of two when enabled</td><td>-hidpi</td></tr>
<tr><td>Dialogs position</td><td>Position of dialogs with Stella window</td><td>-dialogpos</td></tr>
<tr><td>Confirm exiting...</td><td>Display a popup when emulation is exited</td><td>-confirmexit</td></tr>
<tr><td>Center windows</td><td>Attempt to center application windows, else position at last position</td><td>-center</td></tr>
<tr><td>List input delay</td><td>Maximum delay between keypresses in filelist-widgets before a search string resets. </td><td>-listdelay</td></tr>
<tr><td>Mouse wheel scroll</td><td>Number of lines a mouse scroll will move in list-widgets</td><td>-mwheel</td></tr>
<tr><td>Double-click speed</td><td>Speed of mouse double-clicks</td><td>-mdouble</td></tr>
@ -3129,16 +3254,12 @@
<td valign="top">
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Use mouse as ...</td><td>Allow the mouse to emulate various controllers</td><td>-usemouse</td></tr>
<tr><td>Mouse cursor visibility</td><td>Show/hide cursor depending on current state</td><td>-cursor</td></tr>
<tr><td>Joystick deadzone size</td><td>Deadzone area for axes on joysticks/gamepads</td><td>-joydeadzone</td></tr>
<tr><td>Paddle dejitter strength</td><td>Strenght of paddle input averaging (base) and reaction to fast paddle movements (diff)</td><td>-dejitter.base, -dejitter.diff</td></tr>
<tr><td>(Analog paddle) Sensitivity</td><td>Sensitivity of an analog paddle</td><td>-psense</td></tr>
<tr><td>Analog paddle) Dejitter averaging</td><td>Strength of paddle input averaging, suppresses mouse jitter</td><td>-dejitter.base</td></tr>
<tr><td>(Analog paddle) Dejitter reaction</td><td>Strength of paddle reaction to fast paddle movements, suppresses mouse jitter</td><td>-dejitter.diff</td></tr>
<tr><td>Digital paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a digital device</td><td>-dsense</td></tr>
<tr><td>Mouse paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a mouse</td><td>-msense</td></tr>
<tr><td>Trackball sensitivity</td><td>Sensitivity used when emulating a trackball device using a mouse</td><td>-tsense</td></tr>
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Grab mouse ...</td><td>Keep mouse in window in emulation mode<br/>(only when used as controller)<br/>
Note: The sensitivity may greatly vary when the mouse is not grabbed.</td><td>-grabmouse</td></tr>
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>
<tr><td>Joystick database</td><td>Show all joysticks that Stella knows about, with the option to remove them</td><td>&nbsp;</td></tr>
@ -3148,6 +3269,27 @@
</td>
</tr>
</table>
<p><b>Mouse</b> settings can be configured under the 'Mouse' tab, shown below:</p>
<table border="5" cellpadding="2" frame="box" rules="none">
<tr>
<td><img src="graphics/eventmapping_mouse.png"></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign="top">
<table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Use mouse as ...</td><td>Allow the mouse to emulate various controllers</td><td>-usemouse</td></tr>
<tr><td>(Sensitivity) Paddle</td><td>Sensitivity used when emulating a paddle using a mouse</td><td>-msense</td></tr>
<tr><td>(Sensitivity) Trackball</td><td>Sensitivity used when emulating a trackball device using a mouse</td><td>-tsense</td></tr>
<tr><td>(Sensitivity) Driving controller</td><td>Sensitivity used when emulating a driving controller device using a mouse</td><td>-dcsense</td></tr>
<tr><td>Mouse cursor visibility</td><td>Show/hide cursor depending on current state</td><td>-cursor</td></tr>
<tr><td>Grab mouse ...</td><td>Keep mouse in window in emulation mode<br/>(only when used as controller)<br/>
Note: The sensitivity may greatly vary when the mouse is not grabbed.</td><td>-grabmouse</td></tr>
</table>
</td>
</tr>
</table>
</blockquote></br>
<h2><b><a name="ROMInfo">ROM Launcher</a></b></h2>
@ -3233,8 +3375,6 @@
</tr>
</table>
</li>
<br><li><b>Show only ROM files</b>: Selecting this reloads the current listing,
showing only files that have a valid ROM extension.</li>
@ -3518,21 +3658,6 @@
'Buffer size'.
</td>
<td>-plr.tm.horizon<br>-dev.tm.horizon</td>
</tr><tr>
<td>When entering/exiting emulation:</td>
<td>
Automatically save no, current or all Time Machine states when exiting emulation.<br/>
The latter also loads all states when entering emulation. When this is enabled, you
can always continue your game session from where you exited it. Even including the
Time Machine buffer!
</td>
<td>-saveonexit</td>
</tr><tr>
<td>Automatically change...</td>
<td>
Automatically change to the next available save state slot after saving a ROM state file.
</td>
<td>-autoslot</td>
</tr>
</table>
</td>
@ -4032,6 +4157,16 @@ Ms Pac-Man (Stella extended codes):
'Console.SwapPorts'. The value must be <b>Yes</b> or <b>No</b>.</td>
</tr>
<tr>
<td VALIGN="TOP"><i>Controller.PaddlesXCenter:</i></td>
<td>Defines the horizontal center of the paddles (range -10..30).</td>
</tr>
<tr>
<td VALIGN="TOP"><i>Controller.PaddlesYCenter:</i></td>
<td>Defines the vertical center of the paddles (range -10..30).</td>
</tr>
<tr>
<td VALIGN="TOP"><i>Controller.MouseAxis:</i></td>
<td>Indicates how the mouse should emulate virtual controllers.

View File

@ -19,6 +19,7 @@
#define CONTROLLERMAP_HXX
#include <unordered_map>
#include "Event.hxx"
#include "EventHandlerConstants.hxx"

View File

@ -21,6 +21,7 @@
#include <unordered_map>
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
#include "StellaKeys.hxx"
/**
This class handles keyboard mappings in Stella.

View File

@ -17,13 +17,7 @@
#include "OSystem.hxx"
#include "Console.hxx"
#include "Settings.hxx"
#include "EventHandler.hxx"
#include "Sound.hxx"
#include "StateManager.hxx"
#include "StellaKeys.hxx"
#include "TIASurface.hxx"
#include "PNGLibrary.hxx"
#include "PKeyboardHandler.hxx"
#ifdef DEBUGGER_SUPPORT
@ -466,8 +460,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::VidmodeIncrease, KBDK_EQUALS, MOD3},
{Event::VCenterDecrease, KBDK_PAGEUP, MOD3},
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
{Event::ScanlineAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
{Event::ScanlineAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
{Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
{Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
@ -475,30 +469,47 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::ToggleFullScreen, KBDK_RETURN, MOD3},
{Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT},
{Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT},
{Event::VidmodeStd, KBDK_1, MOD3},
{Event::VidmodeRGB, KBDK_2, MOD3},
{Event::VidmodeSVideo, KBDK_3, MOD3},
{Event::VidModeComposite, KBDK_4, MOD3},
{Event::VidModeBad, KBDK_5, MOD3},
{Event::VidModeCustom, KBDK_6, MOD3},
{Event::PreviousAttribute, KBDK_7, KBDM_SHIFT | MOD3},
{Event::NextAttribute, KBDK_7, MOD3},
{Event::DecreaseAttribute, KBDK_8, KBDM_SHIFT | MOD3},
{Event::IncreaseAttribute, KBDK_8, MOD3},
{Event::PhosphorDecrease, KBDK_9, KBDM_SHIFT | MOD3},
{Event::PhosphorIncrease, KBDK_9, MOD3},
//{Event::VidmodeStd, KBDK_1, MOD3},
//{Event::VidmodeRGB, KBDK_2, MOD3},
//{Event::VidmodeSVideo, KBDK_3, MOD3},
//{Event::VidModeComposite, KBDK_4, MOD3},
//{Event::VidModeBad, KBDK_5, MOD3},
//{Event::VidModeCustom, KBDK_6, MOD3},
{Event::PreviousVideoMode, KBDK_1, KBDM_SHIFT | MOD3},
{Event::NextVideoMode, KBDK_1, MOD3},
{Event::PreviousAttribute, KBDK_2, KBDM_SHIFT | MOD3},
{Event::NextAttribute, KBDK_2, MOD3},
{Event::DecreaseAttribute, KBDK_3, KBDM_SHIFT | MOD3},
{Event::IncreaseAttribute, KBDK_3, MOD3},
{Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3},
{Event::PhosphorIncrease, KBDK_4, MOD3},
{Event::TogglePhosphor, KBDK_P, MOD3},
{Event::ScanlinesDecrease, KBDK_0, KBDM_SHIFT | MOD3},
{Event::ScanlinesIncrease, KBDK_0, MOD3},
{Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3},
{Event::ScanlinesIncrease, KBDK_5, MOD3},
{Event::PreviousPaletteAttribute, KBDK_9, KBDM_SHIFT | MOD3},
{Event::NextPaletteAttribute, KBDK_9, MOD3},
{Event::PaletteAttributeDecrease, KBDK_0, KBDM_SHIFT | MOD3},
{Event::PaletteAttributeIncrease, KBDK_0, MOD3},
{Event::ToggleColorLoss, KBDK_L, KBDM_CTRL},
{Event::TogglePalette, KBDK_P, KBDM_CTRL},
{Event::ColorShiftDecrease, KBDK_9, KBDM_SHIFT | KBDM_CTRL},
{Event::ColorShiftIncrease, KBDK_9, KBDM_CTRL},
{Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL},
{Event::PaletteIncrease, KBDK_P, KBDM_CTRL},
#ifndef BSPF_MACOS
{Event::PreviousSetting, KBDK_END},
{Event::NextSetting, KBDK_HOME},
#else
{Event::PreviousSetting, KBDK_HOME},
{Event::NextSetting, KBDK_END},
#endif
{Event::SettingDecrease, KBDK_PAGEDOWN},
{Event::SettingIncrease, KBDK_PAGEUP},
{Event::ToggleInter, KBDK_I, KBDM_CTRL},
{Event::ToggleTurbo, KBDK_T, KBDM_CTRL},
{Event::ToggleJitter, KBDK_J, MOD3},
{Event::ToggleFrameStats, KBDK_L, MOD3},
{Event::ToggleTimeMachine, KBDK_T, MOD3},
#ifdef PNG_SUPPORT
{Event::ToggleContSnapshots, KBDK_S, MOD3},
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3},

View File

@ -0,0 +1,725 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include <cmath>
#include "Console.hxx"
#include "FrameBuffer.hxx"
#include "PaletteHandler.hxx"
PaletteHandler::PaletteHandler(OSystem& system)
: myOSystem(system)
{
// Load user-defined palette for this ROM
loadUserPalette();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) const
{
if(name == SETTING_Z26)
return PaletteType::Z26;
if(name == SETTING_USER && myUserPaletteDefined)
return PaletteType::User;
if(name == SETTING_CUSTOM)
return PaletteType::Custom;
return PaletteType::Standard;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PaletteHandler::toPaletteName(PaletteType type) const
{
const string SETTING_NAMES[int(PaletteType::NumTypes)] = {
SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM
};
return SETTING_NAMES[type];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::cyclePalette(int direction)
{
const string MESSAGES[PaletteType::NumTypes] = {
"Standard Stella", "Z26", "User-defined", "Custom"
};
int type = toPaletteType(myOSystem.settings().getString("palette"));
do {
type = BSPF::clampw(type + direction, int(PaletteType::MinType), int(PaletteType::MaxType));
} while(type == PaletteType::User && !myUserPaletteDefined);
const string palette = toPaletteName(PaletteType(type));
const string message = MESSAGES[type] + " palette";
myOSystem.frameBuffer().showMessage(message);
setPalette(palette);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::showAdjustableMessage()
{
const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
ostringstream msg, buf;
msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
if(isPhaseShift)
{
const ConsoleTiming timing = myOSystem.console().timing();
const bool isNTSC = timing == ConsoleTiming::ntsc;
const float value = myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
buf << std::fixed << std::setprecision(1) << value << DEGREE;
myOSystem.frameBuffer().showMessage("Palette phase shift", buf.str(), value,
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT,
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT);
}
else
{
const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
buf << value << "%";
myOSystem.frameBuffer().showMessage(
msg.str(), buf.str(), value);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::cycleAdjustable(int direction)
{
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
bool isPhaseShift;
do {
myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1);
isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
// skip phase shift when 'Custom' palette is not selected
if(!direction && isPhaseShift && !isCustomPalette)
myCurrentAdjustable++;
} while(isPhaseShift && !isCustomPalette);
showAdjustableMessage();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeAdjustable(int adjustable, int direction)
{
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
const bool isPhaseShift = myAdjustables[adjustable].value == nullptr;
myCurrentAdjustable = adjustable;
if(isPhaseShift && !isCustomPalette)
myCurrentAdjustable++;
changeCurrentAdjustable(direction);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeCurrentAdjustable(int direction)
{
if(myAdjustables[myCurrentAdjustable].value == nullptr)
changeColorPhaseShift(direction);
else
{
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
newVal = BSPF::clamp(newVal + direction * 2, 0, 100);
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
showAdjustableMessage();
setPalette();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeColorPhaseShift(int direction)
{
const ConsoleTiming timing = myOSystem.console().timing();
// SECAM is not supported
if(timing != ConsoleTiming::secam)
{
const bool isNTSC = timing == ConsoleTiming::ntsc;
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL;
newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_SHIFT, shift + MAX_SHIFT);
if(isNTSC)
myPhaseNTSC = newPhase;
else
myPhasePAL = newPhase;
generateCustomPalette(timing);
setPalette(SETTING_CUSTOM);
showAdjustableMessage();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::loadConfig(const Settings& settings)
{
// Load adjustables
myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"),
DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT);
myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"),
DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT);
myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F);
myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F);
myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::saveConfig(Settings& settings) const
{
// Save adjustables
settings.setValue("pal.phase_ntsc", myPhaseNTSC);
settings.setValue("pal.phase_pal", myPhasePAL);
settings.setValue("pal.hue", myHue);
settings.setValue("pal.saturation", mySaturation);
settings.setValue("pal.contrast", myContrast);
settings.setValue("pal.brightness", myBrightness);
settings.setValue("pal.gamma", myGamma);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
{
myPhaseNTSC = adjustable.phaseNtsc / 10.F;
myPhasePAL = adjustable.phasePal / 10.F;
myHue = scaleFrom100(adjustable.hue);
mySaturation = scaleFrom100(adjustable.saturation);
myContrast = scaleFrom100(adjustable.contrast);
myBrightness = scaleFrom100(adjustable.brightness);
myGamma = scaleFrom100(adjustable.gamma);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
{
adjustable.phaseNtsc = myPhaseNTSC * 10.F;
adjustable.phasePal = myPhasePAL * 10.F;
adjustable.hue = scaleTo100(myHue);
adjustable.saturation = scaleTo100(mySaturation);
adjustable.contrast = scaleTo100(myContrast);
adjustable.brightness = scaleTo100(myBrightness);
adjustable.gamma = scaleTo100(myGamma);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setPalette(const string& name)
{
myOSystem.settings().setValue("palette", name);
setPalette();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setPalette()
{
if(myOSystem.hasConsole())
{
const string& name = myOSystem.settings().getString("palette");
// Look at all the palettes, since we don't know which one is
// currently active
static constexpr BSPF::array2D<const PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
{ &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
{ &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
{ &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
{ &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette }
}};
// See which format we should be using
const ConsoleTiming timing = myOSystem.console().timing();
const PaletteType paletteType = toPaletteType(name);
// Now consider the current display format
const PaletteArray* palette = palettes[paletteType][int(timing)];
if(paletteType == PaletteType::Custom)
generateCustomPalette(timing);
myOSystem.frameBuffer().setTIAPalette(adjustedPalette(*palette));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette)
{
PaletteArray destPalette;
// Constants for saturation and gray scale calculation
constexpr float PR = .2989F;
constexpr float PG = .5870F;
constexpr float PB = .1140F;
// Generate adjust table
constexpr int ADJUST_SIZE = 256;
constexpr int RGB_UNIT = 1 << 8;
constexpr float RGB_OFFSET = 0.5F;
const float hue = myHue;
const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET;
const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT;
const float saturation = mySaturation + 1;
const float gamma = 1.1333F - myGamma * 0.5F;
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
constexpr float toFloat = 1.F / (ADJUST_SIZE - 1);
std::array<float, ADJUST_SIZE> adjust;
for(int i = 0; i < ADJUST_SIZE; i++)
adjust[i] = powf(i * toFloat, gamma) * contrast + brightness;
// Transform original palette into destination palette
for(size_t i = 0; i < destPalette.size(); i += 2)
{
const uInt32 pixel = palette[i];
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = (pixel >> 0) & 0xff;
// adjust hue (different for NTSC and PAL?) and saturation
adjustHueSaturation(r, g, b, hue, saturation);
// adjust contrast, brightness, gamma
r = adjust[r];
g = adjust[g];
b = adjust[b];
r = BSPF::clamp(r, 0, 255);
g = BSPF::clamp(g, 0, 255);
b = BSPF::clamp(b, 0, 255);
destPalette[i] = (r << 16) + (g << 8) + b;
// Fill the odd numbered palette entries with gray values (calculated
// using the standard RGB -> grayscale conversion formula)
// Used for PAL color-loss data and 'greying out' the frame in the debugger.
const uInt8 lum = static_cast<uInt8>((r * PR) + (g * PG) + (b * PB));
destPalette[i + 1] = (lum << 16) + (lum << 8) + lum;
}
return destPalette;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::loadUserPalette()
{
if (!myOSystem.checkUserPalette(true))
return;
const string& palette = myOSystem.paletteFile();
ifstream in(palette, std::ios::binary);
// Now that we have valid data, create the user-defined palettes
std::array<uInt8, 3> pixbuf; // Temporary buffer for one 24-bit pixel
for(int i = 0; i < 128; i++) // NTSC palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserNTSCPalette[(i<<1)] = pixel;
}
for(int i = 0; i < 128; i++) // PAL palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserPALPalette[(i<<1)] = pixel;
}
std::array<uInt32, 16> secam; // All 8 24-bit pixels, plus 8 colorloss pixels
for(int i = 0; i < 8; i++) // SECAM palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
secam[(i<<1)] = pixel;
secam[(i<<1)+1] = 0;
}
uInt32* ptr = ourUserSECAMPalette.data();
for(int i = 0; i < 16; ++i)
{
const uInt32* s = secam.data();
for(int j = 0; j < 16; ++j)
*ptr++ = *s++;
}
myUserPaletteDefined = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
{
constexpr int NUM_CHROMA = 16;
constexpr int NUM_LUMA = 8;
constexpr float SATURATION = 0.25F; // default saturation
float color[NUM_CHROMA][2] = {{0.0F}};
if(timing == ConsoleTiming::ntsc)
{
// YIQ is YUV shifted by 33°
constexpr float offset = 33 * BSPF::PI_f / 180;
const float shift = myPhaseNTSC * BSPF::PI_f / 180;
// color 0 is grayscale
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
{
color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1));
color[chroma][1] = SATURATION * sinf(offset + shift * (chroma - 1 - BSPF::PI_f));
}
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{
const float I = color[chroma][0];
const float Q = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++)
{
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
float R = Y + 0.956F * I + 0.621F * Q;
float G = Y - 0.272F * I - 0.647F * Q;
float B = Y - 1.106F * I + 1.703F * Q;
if(R < 0) R = 0;
if(G < 0) G = 0;
if(B < 0) B = 0;
R = powf(R, 0.9F);
G = powf(G, 0.9F);
B = powf(B, 0.9F);
int r = BSPF::clamp(R * 255.F, 0.F, 255.F);
int g = BSPF::clamp(G * 255.F, 0.F, 255.F);
int b = BSPF::clamp(B * 255.F, 0.F, 255.F);
ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
}
}
}
else if(timing == ConsoleTiming::pal)
{
constexpr float offset = BSPF::PI_f;
const float shift = myPhasePAL * BSPF::PI_f / 180;
constexpr float fixedShift = 22.5F * BSPF::PI_f / 180;
// colors 0, 1, 14 and 15 are grayscale
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
{
int idx = NUM_CHROMA - 1 - chroma;
color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma);
if ((idx & 1) == 0)
color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F);
else
color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F);
}
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{
const float U = color[chroma][0];
const float V = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++)
{
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
// Most sources
float R = Y + 1.403F * V;
float G = Y - 0.344F * U - 0.714F * V;
float B = Y + 1.770F * U;
// German Wikipedia, huh???
//float B = Y + 1 / 0.493 * U;
//float R = Y + 1 / 0.877 * V;
//float G = 1.704 * Y - 0.590 * R - 0.194 * B;
if(R < 0) R = 0.0;
if(G < 0) G = 0.0;
if(B < 0) B = 0.0;
R = powf(R, 1.2F);
G = powf(G, 1.2F);
B = powf(B, 1.2F);
int r = BSPF::clamp(R * 255.F, 0.F, 255.F);
int g = BSPF::clamp(G * 255.F, 0.F, 255.F);
int b = BSPF::clamp(B * 255.F, 0.F, 255.F);
ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float S)
{
// Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms
// (C) J. “Fluffy” Shagam
// License: CC BY-SA 4.0
const float su = S * cosf(-H * BSPF::PI_f);
const float sw = S * sinf(-H * BSPF::PI_f);
const float r = (.299F + .701F * su + .168F * sw) * R
+ (.587F - .587F * su + .330F * sw) * G
+ (.114F - .114F * su - .497F * sw) * B;
const float g = (.299F - .299F * su - .328F * sw) * R
+ (.587F + .413F * su + .035F * sw) * G
+ (.114F - .114F * su + .292F * sw) * B;
const float b = (.299F - .300F * su + 1.25F * sw) * R
+ (.587F - .588F * su - 1.05F * sw) * G
+ (.114F + .886F * su - .203F * sw) * B;
R = BSPF::clamp(r, 0.F, 255.F);
G = BSPF::clamp(g, 0.F, 255.F);
B = BSPF::clamp(b, 0.F, 255.F);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourNTSCPalette = {
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0,
0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0,
0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0,
0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0,
0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0,
0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0,
0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0,
0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0,
0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0,
0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0,
0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0,
0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0,
0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0,
0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0,
0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0,
0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0,
0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0,
0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0,
0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0,
0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0,
0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0,
0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0,
0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0,
0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0,
0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0,
0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0,
0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0,
0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0,
0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourPALPalette = {
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2
0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389
0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3
0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0,
0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4
0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac
0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5
0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0,
0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6
0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd
0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7
0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff
0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8
0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff
0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9
0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0,
0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a
0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff
0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b
0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0,
0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c
0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff,
0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d
0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0,
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourSECAMPalette = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0,
0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0,
0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0,
0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0,
0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0,
0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0,
0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0,
0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0,
0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0,
0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0,
0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0,
0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0,
0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0,
0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0,
0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0,
0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0,
0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0,
0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0,
0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0,
0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0,
0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0,
0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0,
0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0,
0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0,
0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0,
0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0,
0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0,
0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0,
0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourPALPaletteZ26 = {
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0,
0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0,
0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0,
0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0,
0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0,
0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0,
0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0,
0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0,
0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0,
0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0,
0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0,
0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0,
0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0,
0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0,
0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0,
0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0,
0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0,
0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0,
0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0,
0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0,
0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0,
0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0,
0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0,
0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourUserNTSCPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourUserPALPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourUserSECAMPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourCustomNTSCPalette = { 0 }; // filled by function
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourCustomPALPalette = { 0 }; // filled by function

View File

@ -0,0 +1,261 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef PALETTE_HANDLER_HXX
#define PALETTE_HANDLER_HXX
#include "bspf.hxx"
#include "OSystem.hxx"
#include "ConsoleTiming.hxx"
#include "EventHandlerConstants.hxx"
class PaletteHandler
{
public:
// Setting names of palette types
static constexpr const char* SETTING_STANDARD = "standard";
static constexpr const char* SETTING_Z26 = "z26";
static constexpr const char* SETTING_USER = "user";
static constexpr const char* SETTING_CUSTOM = "custom";
// Phase shift default and limits
static constexpr float DEF_NTSC_SHIFT = 26.2F;
static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
static constexpr float MAX_SHIFT = 4.5F;
enum Adjustables {
PHASE_SHIFT,
HUE,
SATURATION,
CONTRAST,
BRIGHTNESS,
GAMMA
};
// Externally used adjustment parameters
struct Adjustable {
float phaseNtsc{0.F}, phasePal{0.F};
uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0};
};
public:
PaletteHandler(OSystem& system);
virtual ~PaletteHandler() = default;
/**
Cycle through available palettes.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void cyclePalette(int direction = +1);
/*
Cycle through each palette adjustable.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void cycleAdjustable(int direction = +1);
/*
Increase or decrease given palette adjustable.
@param adjustable The adjustable to change
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeAdjustable(int adjustable, int direction);
/*
Increase or decrease current palette adjustable.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeCurrentAdjustable(int direction = +1);
// Load adjustables from settings
void loadConfig(const Settings& settings);
// Save adjustables to settings
void saveConfig(Settings& settings) const;
// Set adjustables
void setAdjustables(const Adjustable& adjustable);
// Retrieve current adjustables
void getAdjustables(Adjustable& adjustable) const;
/**
Sets the palette according to the given palette name.
@param name The palette to switch to
*/
void setPalette(const string& name);
/**
Sets the palette from current settings.
*/
void setPalette();
private:
static constexpr char DEGREE = 0x1c;
enum PaletteType {
Standard,
Z26,
User,
Custom,
NumTypes,
MinType = Standard,
MaxType = Custom
};
/**
Convert adjustables from/to 100% scale
*/
constexpr float scaleFrom100(float x) const { return (x / 50.F) - 1.F; }
constexpr uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); }
/**
Convert palette settings name to enumeration.
@param name The given palette's settings name
@return The palette type
*/
PaletteType toPaletteType(const string& name) const;
/**
Convert enumeration to palette settings name.
@param type The given palette type
@return The palette's settings name
*/
string toPaletteName(PaletteType type) const;
/**
Display current adjustable with gauge bar message
*/
void showAdjustableMessage();
/**
Change the "phase shift" variable.
Note that there are two of these (NTSC and PAL). The currently
active mode will determine which one is used.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeColorPhaseShift(int direction = +1);
/**
Generates a custom palette, based on user defined phase shifts.
@param timing Use NTSC or PAL phase shift and generate according palette
*/
void generateCustomPalette(ConsoleTiming timing);
/**
Create new palette by applying palette adjustments on given palette.
@param source The palette which should be adjusted
@return An adjusted palette
*/
PaletteArray adjustedPalette(const PaletteArray& source);
/**
Adjust hue and saturation for given RGB values.
@param R The red value to adjust
@param G The green value to adjust
@param B The blue value to adjust
@param H The hue adjustment value
@param S The saturation
*/
void adjustHueSaturation(int& R, int& G, int& B, float H, float S);
/**
Loads a user-defined palette file (from OSystem::paletteFile), filling the
appropriate user-defined palette arrays.
*/
void loadUserPalette();
private:
static constexpr int NUM_ADJUSTABLES = 6;
OSystem& myOSystem;
// The currently selected adjustable
uInt32 myCurrentAdjustable{0};
struct AdjustableTag {
const char* const name{nullptr};
float* value{nullptr};
};
const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables =
{ {
{ "phase shift", nullptr },
{ "hue", &myHue },
{ "saturation", &mySaturation },
{ "contrast", &myContrast },
{ "brightness", &myBrightness },
{ "gamma", &myGamma },
} };
// NTSC and PAL color phase shifts
float myPhaseNTSC{DEF_NTSC_SHIFT};
float myPhasePAL{DEF_PAL_SHIFT};
// range -1.0 to +1.0 (as in AtariNTSC)
// Basic parameters
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
// Advanced parameters
float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5)
// Indicates whether an external palette was found and
// successfully loaded
bool myUserPaletteDefined{false};
// Table of RGB values for NTSC, PAL and SECAM
static const PaletteArray ourNTSCPalette;
static const PaletteArray ourPALPalette;
static const PaletteArray ourSECAMPalette;
// Table of RGB values for NTSC, PAL and SECAM - Z26 version
static const PaletteArray ourNTSCPaletteZ26;
static const PaletteArray ourPALPaletteZ26;
static const PaletteArray ourSECAMPaletteZ26;
// Table of RGB values for NTSC, PAL and SECAM - user-defined
static PaletteArray ourUserNTSCPalette;
static PaletteArray ourUserPALPalette;
static PaletteArray ourUserSECAMPalette;
// Table of RGB values for NTSC, PAL - custom-defined and generated
static PaletteArray ourCustomNTSCPalette;
static PaletteArray ourCustomPALPalette;
private:
PaletteHandler() = delete;
PaletteHandler(const PaletteHandler&) = delete;
PaletteHandler(PaletteHandler&&) = delete;
PaletteHandler& operator=(const PaletteHandler&) = delete;
PaletteHandler& operator=(const PaletteHandler&&) = delete;
};
#endif // PALETTE_HANDLER_HXX

View File

@ -18,6 +18,7 @@
#include <cmath>
#include "OSystem.hxx"
#include "Console.hxx"
#include "Serializer.hxx"
#include "StateManager.hxx"
#include "TIA.hxx"

View File

@ -18,12 +18,13 @@
#ifndef SOUND_NULL_HXX
#define SOUND_NULL_HXX
class OSystem;
class AudioQueue;
class EmulationTiming;
#include "bspf.hxx"
#include "Logger.hxx"
#include "Sound.hxx"
#include "OSystem.hxx"
#include "AudioQueue.hxx"
#include "EmulationTiming.hxx"
/**
This class implements a Null sound object, where-by sound generation
@ -96,10 +97,9 @@ class SoundNull : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 =decrease)
@param direction +1 indicates increase, -1 indicates decrease.
*/
void adjustVolume(Int8 direction) override { }
void adjustVolume(int direction = 1) override { }
/**
This method is called to provide information about the sound device.

View File

@ -186,16 +186,31 @@ bool SoundSDL2::mute(bool state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SoundSDL2::toggleMute()
{
bool enabled = myAudioSettings.enabled();
bool enabled = !myAudioSettings.enabled();
setEnabled(!enabled);
setEnabled(enabled);
myOSystem.console().initializeAudio();
string message = "Sound ";
message += !enabled ? "unmuted" : "muted";
message += enabled ? "unmuted" : "muted";
myOSystem.frameBuffer().showMessage(message);
//ostringstream strval;
//uInt32 volume;
//// Now show an onscreen message
//if(enabled)
//{
// volume = myVolume;
// strval << volume << "%";
//}
//else
//{
// volume = 0;
// strval << "Muted";
//}
//myOSystem.frameBuffer().showMessage("Volume", strval.str(), volume);
return enabled;
}
@ -214,20 +229,12 @@ void SoundSDL2::setVolume(uInt32 percent)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SoundSDL2::adjustVolume(Int8 direction)
void SoundSDL2::adjustVolume(int direction)
{
ostringstream strval;
string message;
Int32 percent = myVolume;
if(direction == -1)
percent -= 2;
else if(direction == 1)
percent += 2;
if((percent < 0) || (percent > 100))
return;
percent = BSPF::clamp(percent + direction * 2, 0, 100);
setVolume(percent);
@ -241,11 +248,11 @@ void SoundSDL2::adjustVolume(Int8 direction)
}
// Now show an onscreen message
strval << percent;
message = "Volume set to ";
message += strval.str();
myOSystem.frameBuffer().showMessage(message);
if(percent)
strval << percent << "%";
else
strval << "Off";
myOSystem.frameBuffer().showMessage("Volume", strval.str(), percent);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -24,12 +24,12 @@ class OSystem;
class AudioQueue;
class EmulationTiming;
class AudioSettings;
class Resampler;
#include "SDL_lib.hxx"
#include "bspf.hxx"
#include "Sound.hxx"
#include "audio/Resampler.hxx"
/**
This class implements the sound API for SDL.
@ -98,10 +98,9 @@ class SoundSDL2 : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 = decrease)
*/
void adjustVolume(Int8 direction) override;
@param direction +1 indicates increase, -1 indicates decrease.
*/
void adjustVolume(int direction = 1) override;
/**
This method is called to provide information about the sound device.

View File

@ -299,15 +299,14 @@ void StateManager::saveState(int slot)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StateManager::changeState(int direction)
{
myCurrentSlot += direction;
if (myCurrentSlot < 0)
myCurrentSlot = 9;
else
myCurrentSlot %= 10;
myCurrentSlot = BSPF::clampw(myCurrentSlot + direction, 0, 9);
// Print appropriate message
ostringstream buf;
buf << "Changed to slot " << myCurrentSlot;
if(direction)
buf << "Changed to state slot " << myCurrentSlot;
else
buf << "State slot " << myCurrentSlot;
myOSystem.frameBuffer().showMessage(buf.str());
}

View File

@ -115,8 +115,10 @@ class StateManager
/**
Switches to the next higher or lower state slot (circular queue style).
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeState(int direction);
void changeState(int direction = +1);
/**
Toggles auto slot mode.

View File

@ -43,6 +43,7 @@ using uInt64 = uint64_t;
#include <algorithm>
#include <iostream>
#include <fstream>
#include <functional>
#include <iomanip>
#include <memory>
#include <string>
@ -86,6 +87,8 @@ using StringList = std::vector<std::string>;
using ByteBuffer = std::unique_ptr<uInt8[]>; // NOLINT
using DWordBuffer = std::unique_ptr<uInt32[]>; // NOLINT
using AdjustFunction = std::function<void(int)>;
// We use KB a lot; let's make a literal for it
constexpr uInt32 operator "" _KB(unsigned long long size)
{
@ -133,6 +136,10 @@ namespace BSPF
{
if(val < lower || val > upper) val = setVal;
}
template<typename T> inline T clampw(T val, T lower, T upper)
{
return (val < lower) ? upper : (val > upper) ? lower : val;
}
// Convert string to given case
inline const string& toUpperCase(string& s)

View File

@ -11,6 +11,7 @@ MODULE_OBJS := \
src/common/Logger.o \
src/common/main.o \
src/common/MouseControl.o \
src/common/PaletteHandler.o \
src/common/PhosphorHandler.o \
src/common/PhysicalJoystick.o \
src/common/PJoystickHandler.o \

View File

@ -15,9 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "BilinearBlitter.hxx"
#include "FrameBufferSDL2.hxx"
#include "ThreadDebugging.hxx"
#include "BilinearBlitter.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)

View File

@ -18,8 +18,9 @@
#ifndef BILINEAR_BLITTER_HXX
#define BILINEAR_BLITTER_HXX
class FrameBufferSDL2;
#include "Blitter.hxx"
#include "FrameBufferSDL2.hxx"
#include "SDL_lib.hxx"
class BilinearBlitter : public Blitter {

View File

@ -15,9 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "QisBlitter.hxx"
#include "FrameBufferSDL2.hxx"
#include "ThreadDebugging.hxx"
#include "QisBlitter.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QisBlitter::QisBlitter(FrameBufferSDL2& fb)

View File

@ -18,8 +18,9 @@
#ifndef QIS_BLITTER_HXX
#define QIS_BLITTER_HXX
class FrameBufferSDL2;
#include "Blitter.hxx"
#include "FrameBufferSDL2.hxx"
#include "SDL_lib.hxx"
class QisBlitter : public Blitter {

View File

@ -57,9 +57,15 @@ void AtariNTSC::generateKernels()
const uInt8* ptr = myRGBPalette.data();
for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry)
{
#ifdef BLARGG_PALETTE
float r = myImpl.to_float[*ptr++],
g = myImpl.to_float[*ptr++],
b = myImpl.to_float[*ptr++];
#else
float r = (*ptr++) / 255.F * rgb_unit + rgb_offset,
g = (*ptr++) / 255.F * rgb_unit + rgb_offset,
b = (*ptr++) / 255.F * rgb_unit + rgb_offset;
#endif
float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q );
// Generate kernel
@ -319,8 +325,10 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariNTSC::init(init_t& impl, const Setup& setup)
{
#ifdef BLARGG_PALETTE
impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset;
impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit;
#endif
impl.artifacts = setup.artifacts;
if ( impl.artifacts > 0 )
@ -334,6 +342,7 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
initFilters(impl, setup);
#ifdef BLARGG_PALETTE
/* generate gamma table */
if (true) /* was (gamma_size > 1) */
{
@ -341,19 +350,22 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
float const gamma = 1.1333F - setup.gamma * 0.5F;
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
int i;
for ( i = 0; i < gamma_size; i++ )
impl.to_float [i] =
powf( i * to_float, gamma ) * impl.contrast + impl.brightness;
for(i = 0; i < gamma_size; i++)
impl.to_float[i] =
powf(i * to_float, gamma) * impl.contrast + impl.brightness;
}
#endif
/* setup decoder matricies */
{
#ifdef BLARGG_PALETTE
float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue;
float sat = setup.saturation + 1;
hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue);
float s = sinf( hue ) * sat;
float c = cosf( hue ) * sat;
float s = sinf(hue)*sat;
float c = cosf(hue)*sat;
#endif
float* out = impl.to_rgb.data();
int n;
@ -366,8 +378,13 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
{
float i = *in++;
float q = *in++;
#ifdef BLARGG_PALETTE
*out++ = i * c - q * s;
*out++ = i * s + q * c;
#else
*out++ = i ;
*out++ = q;
#endif
}
while ( --n2 );
#if 0 // burst_count is always 0
@ -544,16 +561,32 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const AtariNTSC::Setup AtariNTSC::TV_Composite = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F
#else
0.0F, 0.15F, 0.0F, 0.0F, 0.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_SVideo = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F
#else
0.0F, 0.45F, -1.0F, -1.0F, 0.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_RGB = {
#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F
#else
0.2F, 0.70F, -1.0F, -1.0F, -1.0F
#endif
};
const AtariNTSC::Setup AtariNTSC::TV_Bad = {
#ifdef BLARGG_PALETTE
0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F
#else
0.2F, 0.1F, 0.5F, 0.5F, 0.5F
#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -46,6 +46,8 @@
#include "FrameBufferConstants.hxx"
#include "bspf.hxx"
//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined
class AtariNTSC
{
public:
@ -57,14 +59,18 @@ class AtariNTSC
struct Setup
{
// Basic parameters
#ifdef BLARGG_PALETTE
float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees
float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5)
float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5)
#endif
float sharpness{0.F}; // edge contrast enhancement/blurring
// Advanced parameters
#ifdef BLARGG_PALETTE
float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5)
#endif
float resolution{0.F}; // image resolution
float artifacts{0.F}; // artifacts caused by color changes
float fringing{0.F}; // color artifacts caused by brightness changes
@ -127,7 +133,9 @@ class AtariNTSC
burst_size = entry_size / burst_count,
kernel_half = 16,
kernel_size = kernel_half * 2 + 1,
#ifdef BLARGG_PALETTE
gamma_size = 256,
#endif
rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)),
rgb_kernel_size = burst_size / alignment_count,
@ -162,16 +170,20 @@ class AtariNTSC
struct init_t
{
std::array<float, burst_count * 6> to_rgb{0.F};
#ifdef BLARGG_PALETTE
std::array<float, gamma_size> to_float{0.F};
float contrast{0.F};
float brightness{0.F};
#endif
float artifacts{0.F};
float fringing{0.F};
std::array<float, rescale_out * kernel_size * 2> kernel{0.F};
init_t() {
to_rgb.fill(0.0);
#ifdef BLARGG_PALETTE
to_float.fill(0.0);
#endif
kernel.fill(0.0);
}
};

View File

@ -62,9 +62,9 @@ string NTSCFilter::getPreset() const
{
switch(myPreset)
{
case Preset::COMPOSITE: return "COMPOSITE";
case Preset::SVIDEO: return "S-VIDEO";
case Preset::RGB: return "RGB";
case Preset::SVIDEO: return "S-VIDEO";
case Preset::COMPOSITE: return "COMPOSITE";
case Preset::BAD: return "BAD ADJUST";
case Preset::CUSTOM: return "CUSTOM";
default: return "Disabled";
@ -72,81 +72,81 @@ string NTSCFilter::getPreset() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::setNextAdjustable()
void NTSCFilter::selectAdjustable(int direction,
string& text, string& valueText, Int32& value)
{
if(myPreset != Preset::CUSTOM)
return "'Custom' TV mode not selected";
if(direction == +1)
{
#ifdef BLARGG_PALETTE
myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
#else
myCurrentAdjustable = (myCurrentAdjustable + 1) % 5;
#endif
}
else if(direction == -1)
{
#ifdef BLARGG_PALETTE
if(myCurrentAdjustable == 0) myCurrentAdjustable = 9;
#else
if(myCurrentAdjustable == 0) myCurrentAdjustable = 4;
#endif
else --myCurrentAdjustable;
}
myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
ostringstream buf;
buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' selected";
ostringstream msg, val;
return buf.str();
value = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type;
val << value << "%";
text = msg.str();
valueText = val.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::setPreviousAdjustable()
void NTSCFilter::changeAdjustable(int adjustable, int direction,
string& text, string& valueText, Int32& newValue)
{
if(myPreset != Preset::CUSTOM)
return "'Custom' TV mode not selected";
if(myCurrentAdjustable == 0) myCurrentAdjustable = 9;
else --myCurrentAdjustable;
ostringstream buf;
buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' selected";
return buf.str();
myCurrentAdjustable = adjustable;
changeCurrentAdjustable(direction, text, valueText, newValue);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::increaseAdjustable()
void NTSCFilter::changeCurrentAdjustable(int direction,
string& text, string& valueText, Int32& newValue)
{
if(myPreset != Preset::CUSTOM)
return "'Custom' TV mode not selected";
//if(myPreset != Preset::CUSTOM)
// return "'Custom' TV mode not selected";
uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
newval += 2; if(newval > 100) newval = 100;
*ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval);
newValue = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
newValue = BSPF::clamp(newValue + direction * 2, 0, 100);
ostringstream buf;
buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' set to " << newval;
*ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newValue);
setPreset(myPreset);
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::decreaseAdjustable()
{
if(myPreset != Preset::CUSTOM)
return "'Custom' TV mode not selected";
ostringstream msg, val;
uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
if(newval < 2) newval = 0;
else newval -= 2;
*ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval);
msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type;
val << newValue << "%";
ostringstream buf;
buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' set to " << newval;
setPreset(myPreset);
return buf.str();
text = msg.str();
valueText = val.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::loadConfig(const Settings& settings)
{
// Load adjustables for custom mode
#ifdef BLARGG_PALETTE
myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F);
myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F);
myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F);
myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F);
myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F);
myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F);
#endif
myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F);
myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F);
myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F);
myCustomSetup.fringing = BSPF::clamp(settings.getFloat("tv.fringing"), -1.0F, 1.0F);
@ -157,12 +157,14 @@ void NTSCFilter::loadConfig(const Settings& settings)
void NTSCFilter::saveConfig(Settings& settings) const
{
// Save adjustables for custom mode
#ifdef BLARGG_PALETTE
settings.setValue("tv.hue", myCustomSetup.hue);
settings.setValue("tv.saturation", myCustomSetup.saturation);
settings.setValue("tv.contrast", myCustomSetup.contrast);
settings.setValue("tv.brightness", myCustomSetup.brightness);
settings.setValue("tv.sharpness", myCustomSetup.sharpness);
settings.setValue("tv.gamma", myCustomSetup.gamma);
#endif
settings.setValue("tv.sharpness", myCustomSetup.sharpness);
settings.setValue("tv.resolution", myCustomSetup.resolution);
settings.setValue("tv.artifacts", myCustomSetup.artifacts);
settings.setValue("tv.fringing", myCustomSetup.fringing);
@ -174,12 +176,12 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const
{
switch(preset)
{
case Preset::COMPOSITE:
convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break;
case Preset::SVIDEO:
convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break;
case Preset::RGB:
convertToAdjustable(adjustable, AtariNTSC::TV_RGB); break;
case Preset::SVIDEO:
convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break;
case Preset::COMPOSITE:
convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break;
case Preset::BAD:
convertToAdjustable(adjustable, AtariNTSC::TV_Bad); break;
case Preset::CUSTOM:
@ -192,12 +194,14 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
{
myCustomSetup.hue = scaleFrom100(adjustable.hue);
myCustomSetup.saturation = scaleFrom100(adjustable.saturation);
myCustomSetup.contrast = scaleFrom100(adjustable.contrast);
myCustomSetup.brightness = scaleFrom100(adjustable.brightness);
#ifdef BLARGG_PALETTE
//myCustomSetup.hue = scaleFrom100(adjustable.hue);
//myCustomSetup.saturation = scaleFrom100(adjustable.saturation);
//myCustomSetup.contrast = scaleFrom100(adjustable.contrast);
//myCustomSetup.brightness = scaleFrom100(adjustable.brightness);
//myCustomSetup.gamma = scaleFrom100(adjustable.gamma);
#endif
myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness);
myCustomSetup.gamma = scaleFrom100(adjustable.gamma);
myCustomSetup.resolution = scaleFrom100(adjustable.resolution);
myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts);
myCustomSetup.fringing = scaleFrom100(adjustable.fringing);
@ -208,12 +212,14 @@ void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
const AtariNTSC::Setup& setup) const
{
adjustable.hue = scaleTo100(setup.hue);
adjustable.saturation = scaleTo100(setup.saturation);
adjustable.contrast = scaleTo100(setup.contrast);
adjustable.brightness = scaleTo100(setup.brightness);
#ifdef BLARGG_PALETTE
//adjustable.hue = scaleTo100(setup.hue);
//adjustable.saturation = scaleTo100(setup.saturation);
//adjustable.contrast = scaleTo100(setup.contrast);
//adjustable.brightness = scaleTo100(setup.brightness);
//adjustable.gamma = scaleTo100(setup.gamma);
#endif
adjustable.sharpness = scaleTo100(setup.sharpness);
adjustable.gamma = scaleTo100(setup.gamma);
adjustable.resolution = scaleTo100(setup.resolution);
adjustable.artifacts = scaleTo100(setup.artifacts);
adjustable.fringing = scaleTo100(setup.fringing);
@ -224,12 +230,16 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#ifdef BLARGG_PALETTE
const std::array<NTSCFilter::AdjustableTag, 10> NTSCFilter::ourCustomAdjustables = { {
{ "contrast", &myCustomSetup.contrast },
{ "brightness", &myCustomSetup.brightness },
{ "hue", &myCustomSetup.hue },
{ "saturation", &myCustomSetup.saturation },
{ "gamma", &myCustomSetup.gamma },
#else
const std::array<NTSCFilter::AdjustableTag, int(NTSCFilter::Adjustables::NUM_ADJUSTABLES)> NTSCFilter::ourCustomAdjustables = { {
#endif
{ "sharpness", &myCustomSetup.sharpness },
{ "resolution", &myCustomSetup.resolution },
{ "artifacts", &myCustomSetup.artifacts },

View File

@ -47,12 +47,24 @@ class NTSCFilter
BAD,
CUSTOM
};
enum class Adjustables {
SHARPNESS,
RESOLUTION,
ARTIFACTS,
FRINGING,
BLEEDING,
NUM_ADJUSTABLES
};
/* Normally used in conjunction with custom mode, contains all
aspects currently adjustable in NTSC TV emulation. */
struct Adjustable {
#ifdef BLARGG_PALETTE
uInt32 hue, saturation, contrast, brightness, gamma,
sharpness, resolution, artifacts, fringing, bleed;
#else
uInt32 sharpness, resolution, artifacts, fringing, bleed;
#endif
};
public:
@ -86,10 +98,12 @@ class NTSCFilter
// Changes are made this way since otherwise 20 key-combinations
// would be needed to dynamically change each setting, and now
// only 4 combinations are necessary
string setNextAdjustable();
string setPreviousAdjustable();
string increaseAdjustable();
string decreaseAdjustable();
void selectAdjustable(int direction,
string& text, string& valueText, Int32& value);
void changeAdjustable(int adjustable, int direction,
string& text, string& valueText, Int32& newValue);
void changeCurrentAdjustable(int direction,
string& text, string& valueText, Int32& newValue);
// Load and save NTSC-related settings
void loadConfig(const Settings& settings);
@ -139,7 +153,11 @@ class NTSCFilter
float* value{nullptr};
};
uInt32 myCurrentAdjustable{0};
#ifdef BLARGG_PALETTE
static const std::array<AdjustableTag, 10> ourCustomAdjustables;
#else
static const std::array<AdjustableTag, 5> ourCustomAdjustables;
#endif
private:
// Following constructors and assignment operators not supported

View File

@ -293,9 +293,10 @@ void Debugger::loadAllStates()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::step()
int Debugger::step(bool save)
{
saveOldState();
if(save)
saveOldState();
uInt64 startCycle = mySystem.cycles();
@ -303,7 +304,8 @@ int Debugger::step()
myOSystem.console().tia().updateScanlineByStep().flushLineCache();
lockSystem();
addState("step");
if(save)
addState("step");
return int(mySystem.cycles() - startCycle);
}

View File

@ -306,7 +306,7 @@ class Debugger : public DialogContainer
*/
void setQuitState();
int step();
int step(bool save = true);
int trace();
void nextScanline(int lines);
void nextFrame(int frames);

View File

@ -30,6 +30,7 @@
#include "M6502.hxx"
#include "Expression.hxx"
#include "FSNode.hxx"
#include "OSystem.hxx"
#include "Settings.hxx"
#include "PromptWidget.hxx"
#include "RomWidget.hxx"
@ -1743,7 +1744,7 @@ void DebuggerParser::executeRunTo()
bool done = false;
do {
debugger.step();
debugger.step(false);
// Update romlist to point to current PC
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
@ -1777,22 +1778,32 @@ void DebuggerParser::executeRunToPc()
uInt32 count = 0;
bool done = false;
constexpr uInt32 max_iterations = 1000000;
// Create a progress dialog box to show the progress searching through the
// disassembly, since this may be a time-consuming operation
ostringstream buf;
buf << "RunTo PC searching through " << max_iterations << " instructions";
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
progress.setRange(0, max_iterations, 5);
do {
debugger.step();
debugger.step(false);
// Update romlist to point to current PC
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
done = (pcline >= 0) && (list[pcline].address == args[0]);
} while(!done && ++count < list.size());
progress.setProgress(count);
} while(!done && ++count < max_iterations/*list.size()*/);
progress.close();
if(done)
commandResult
<< "set PC to " << Base::HEX4 << args[0] << " in "
<< dec << count << " disassembled instructions";
<< "Set PC to $" << Base::HEX4 << args[0] << " in "
<< dec << count << " instructions";
else
commandResult
<< "PC " << Base::HEX4 << args[0] << " not reached or found in "
<< dec << count << " disassembled instructions";
<< "PC $" << Base::HEX4 << args[0] << " not reached or found in "
<< dec << count << " instructions";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1930,9 +1941,23 @@ void DebuggerParser::executeStepwhile()
}
Expression* expr = YaccParser::getResult();
int ncycles = 0;
uInt32 count = 0;
constexpr uInt32 max_iterations = 1000000;
// Create a progress dialog box to show the progress searching through the
// disassembly, since this may be a time-consuming operation
ostringstream buf;
buf << "stepwhile running through " << max_iterations << " disassembled instructions";
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
progress.setRange(0, max_iterations, 5);
do {
ncycles += debugger.step();
} while (expr->evaluate());
ncycles += debugger.step(false);
progress.setProgress(count);
} while (expr->evaluate() && ++count < max_iterations);
progress.close();
commandResult << "executed " << ncycles << " cycles";
}

View File

@ -1179,7 +1179,7 @@ void DiStella::outputColors()
color = SECAM_COLOR[(byte >> 1) & 0x7];
myDisasmBuf << "$" << Base::HEX1 << (byte >> 4) << "|" << color;
}
myDisasmBuf << std::setw(16 - color.length()) << std::setfill(' ');
myDisasmBuf << std::setw(int(16 - color.length())) << std::setfill(' ');
// output address
myDisasmBuf << "; $" << Base::HEX4 << myPC + myOffset << " "

View File

@ -16,6 +16,9 @@
//============================================================================
#include "CartAR.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "PopUpWidget.hxx"
#include "CartARWidget.hxx"

View File

@ -16,6 +16,7 @@
//============================================================================
#include "CartCM.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "RiotDebug.hxx"

View File

@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "CartCTY.hxx"

View File

@ -19,7 +19,6 @@
#define CART_DEBUG_WIDGET_HXX
class GuiObject;
class ButtonWidget;
class StringListWidget;
namespace GUI {
@ -29,8 +28,6 @@ namespace GUI {
#include "Base.hxx" // not needed here, but all child classes need it
#include "Command.hxx"
#include "Widget.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
class CartDebugWidget : public Widget, public CommandSender
{

View File

@ -49,7 +49,7 @@ string CartridgeE0Widget::romDescription()
info << "Segment #" << seg << " accessible @ $"
<< Common::Base::HEX4 << (ADDR_BASE | segmentOffset)
<< " - $" << (ADDR_BASE | segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF) << ",\n";
<< " - $" << (ADDR_BASE | (segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF)) << ",\n";
if (seg < 3)
info << " Hotspots " << hotspotStr(0, seg, true) << " - " << hotspotStr(7, seg, true) << "\n";
else

View File

@ -15,8 +15,10 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "PopUpWidget.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "CartEnhanced.hxx"
#include "CartEnhancedWidget.hxx"

View File

@ -25,6 +25,7 @@ namespace GUI {
class Font;
}
#include "Variant.hxx"
#include "CartDebugWidget.hxx"
class CartridgeEnhancedWidget : public CartDebugWidget

View File

@ -23,6 +23,7 @@ class ButtonWidget;
#include "Font.hxx"
#include "Widget.hxx"
#include "OSystem.hxx"
#include "Console.hxx"
#include "Command.hxx"
#include "ControlLowLevel.hxx"

View File

@ -18,6 +18,7 @@
#include "Widget.hxx"
#include "Dialog.hxx"
#include "Font.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "FrameBuffer.hxx"
#include "FBSurface.hxx"

View File

@ -47,6 +47,8 @@
#include "OptionsDialog.hxx"
#include "StateManager.hxx"
#include "FrameManager.hxx"
#include "OSystem.hxx"
#include "Console.hxx"
#include "DebuggerDialog.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -68,6 +70,11 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent,
Menu::AppMode::debugger);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DebuggerDialog::~DebuggerDialog()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::loadConfig()
{

View File

@ -33,14 +33,16 @@ class TiaOutputWidget;
class TiaZoomWidget;
class CartDebugWidget;
class CartRamWidget;
class OptionsDialog;
namespace GUI {
class MessageBox;
}
namespace Common {
struct Rect;
}
#include "Dialog.hxx"
#include "MessageBox.hxx"
#include "OptionsDialog.hxx"
class DebuggerDialog : public Dialog
{
@ -55,7 +57,7 @@ class DebuggerDialog : public Dialog
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
int x, int y, int w, int h);
virtual ~DebuggerDialog() = default;
virtual ~DebuggerDialog();
const GUI::Font& lfont() const { return *myLFont; }
const GUI::Font& nfont() const { return *myNFont; }

View File

@ -20,6 +20,7 @@
#include "Font.hxx"
#include "StellaKeys.hxx"
#include "Version.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "DebuggerDialog.hxx"
#include "DebuggerParser.hxx"

View File

@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"

View File

@ -16,6 +16,7 @@
//============================================================================
#include "bspf.hxx"
#include "OSystem.hxx"
#include "Debugger.hxx"
#include "DiStella.hxx"
#include "Widget.hxx"

View File

@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "Settings.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
@ -199,7 +200,8 @@ void RomWidget::runtoPC(int disasm_line)
{
ostringstream command;
command << "runtopc #" << list[disasm_line].address;
instance().debugger().run(command.str());
string msg = instance().debugger().run(command.str());
instance().frameBuffer().showMessage(msg);
}
}

View File

@ -36,6 +36,11 @@ AtariVox::AtariVox(Jack jack, const Event& event, const System& system,
setPin(DigitalPin::Four, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AtariVox::~AtariVox()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AtariVox::read(DigitalPin pin)
{

View File

@ -19,10 +19,10 @@
#define ATARIVOX_HXX
class OSystem;
class SerialPort;
#include "Control.hxx"
#include "SaveKey.hxx"
#include "SerialPort.hxx"
/**
Richard Hutchinson's AtariVox "controller": A speech synthesizer and
@ -49,7 +49,7 @@ class AtariVox : public SaveKey
AtariVox(Jack jack, const Event& event, const System& system,
const string& portname, const string& eepromfile,
const onMessageCallback& callback);
virtual ~AtariVox() = default;
virtual ~AtariVox();
public:
using Controller::read;

View File

@ -23,15 +23,18 @@ class Properties;
class CartDebugWidget;
class CartRamWidget;
class GuiObject;
class Settings;
#include <functional>
#include "bspf.hxx"
#include "Device.hxx"
#include "Settings.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Font.hxx"
namespace GUI {
class Font;
}
#endif
/**
A cartridge is a device which contains the machine code for a
game and handles any bankswitching performed by the cartridge.

View File

@ -24,7 +24,6 @@ class System;
#include "Cart3E.hxx"
#ifdef DEBUGGER_SUPPORT
class Cartridge3EPlusWidget;
#include "Cart3EPlusWidget.hxx"
#endif

View File

@ -19,7 +19,9 @@
#define CARTRIDGE3EX_HXX
class System;
class Settings;
#include "bspf.hxx"
#include "Cart3E.hxx"
/**
@ -30,39 +32,38 @@ class System;
class Cartridge3EX : public Cartridge3E
{
public:
/**
Create a new cartridge using the specified image and size
public:
/**
Create a new cartridge using the specified image and size
@param image Pointer to the ROM image
@param size The size of the ROM image
@param md5 The md5sum of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge3EX(const ByteBuffer& image, size_t size, const string& md5,
const Settings& settings);
virtual ~Cartridge3EX() = default;
@param image Pointer to the ROM image
@param size The size of the ROM image
@param md5 The md5sum of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge3EX(const ByteBuffer& image, size_t size, const string& md5,
const Settings& settings);
virtual ~Cartridge3EX() = default;
public:
/**
Get a descriptor for the device name (used in error checking).
public:
/**
Get a descriptor for the device name (used in error checking).
@return The name of the object
*/
string name() const override { return "Cartridge3EX"; }
@return The name of the object
*/
string name() const override { return "Cartridge3EX"; }
private:
// RAM size
static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000;
private:
// RAM size
static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000;
private:
// Following constructors and assignment operators not supported
Cartridge3EX() = delete;
Cartridge3EX(const Cartridge3EX&) = delete;
Cartridge3EX(Cartridge3EX&&) = delete;
Cartridge3EX& operator=(const Cartridge3EX&) = delete;
Cartridge3EX& operator=(Cartridge3EX&&) = delete;
private:
// Following constructors and assignment operators not supported
Cartridge3EX() = delete;
Cartridge3EX(const Cartridge3EX&) = delete;
Cartridge3EX(Cartridge3EX&&) = delete;
Cartridge3EX& operator=(const Cartridge3EX&) = delete;
Cartridge3EX& operator=(Cartridge3EX&&) = delete;
};
#endif

View File

@ -17,6 +17,7 @@
#include "M6502.hxx"
#include "System.hxx"
#include "Settings.hxx"
#include "CartAR.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Settings.hxx"
#include "System.hxx"
#include "AudioSettings.hxx"
#include "CartDPC.hxx"

View File

@ -62,6 +62,7 @@
#include "MD5.hxx"
#include "Props.hxx"
#include "Logger.hxx"
#include "OSystem.hxx"
#include "CartDetector.hxx"

View File

@ -20,10 +20,10 @@
class Cartridge;
class Properties;
class Settings;
#include "Bankswitch.hxx"
#include "bspf.hxx"
#include "Settings.hxx"
/**
Auto-detect cart type based on various attributes (file size, signatures,

View File

@ -35,12 +35,15 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
void CartridgeEnhanced::install(System& system)
{
// limit banked RAM size to the size of one RAM bank
uInt32 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : uInt32(myRamSize);
const uInt32 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : uInt32(myRamSize);
// calculate bank switching and RAM sizes and masks
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
myBankSegs = 1 << (MAX_BANK_SHIFT - myBankShift); // e.g. = 1
// Either the bankswitching supports multiple segments
// or the ROM is < 4K (-> 1 segment)
myBankSegs = std::min(1 << (MAX_BANK_SHIFT - myBankShift),
int(mySize) / myBankSize); // e.g. = 1
myRomOffset = myRamBankCount > 0 ? 0 : uInt32(myRamSize) * 2;
myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
myWriteOffset = myRamWpHigh ? ramSize : 0; // e.g. = 0x0000
@ -52,7 +55,8 @@ void CartridgeEnhanced::install(System& system)
myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs);
// Allocate array for the RAM area
myRAM = make_unique<uInt8[]>(myRamSize);
if(myRamSize > 0)
myRAM = make_unique<uInt8[]>(myRamSize);
mySystem = &system;
@ -67,7 +71,7 @@ void CartridgeEnhanced::install(System& system)
access.type = System::PageAccessType::WRITE;
for(uInt16 addr = ROM_OFFSET + myWriteOffset; addr < ROM_OFFSET + myWriteOffset + myRamSize; addr += System::PAGE_SIZE)
{
uInt16 offset = addr & myRamMask;
const uInt16 offset = addr & myRamMask;
access.directPokeBase = &myRAM[offset];
access.romAccessBase = &myRomAccessBase[myWriteOffset + offset];
@ -81,7 +85,7 @@ void CartridgeEnhanced::install(System& system)
access.directPokeBase = nullptr;
for(uInt16 addr = ROM_OFFSET + myReadOffset; addr < ROM_OFFSET + myReadOffset + myRamSize; addr += System::PAGE_SIZE)
{
uInt16 offset = addr & myRamMask;
const uInt16 offset = addr & myRamMask;
access.directPeekBase = &myRAM[offset];
access.romAccessBase = &myRomAccessBase[myReadOffset + offset];
@ -101,7 +105,8 @@ void CartridgeEnhanced::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhanced::reset()
{
initializeRAM(myRAM.get(), myRamSize);
if(myRamSize > 0)
initializeRAM(myRAM.get(), myRamSize);
initializeStartBank(getStartBank());
@ -112,7 +117,7 @@ void CartridgeEnhanced::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeEnhanced::peek(uInt16 address)
{
uInt16 peekAddress = address;
const uInt16 peekAddress = address;
// hotspots in TIA range are reacting to pokes only
if (hotspot() >= 0x80)
@ -152,7 +157,7 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
if(myRamSize > 0)
{
// Code should never get here (System::PageAccess::directPoke() handles this)
uInt16 pokeAddress = address;
const uInt16 pokeAddress = address;
if(isRamBank(address))
{
@ -188,20 +193,20 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
{
if(bankLocked()) return false;
uInt16 segmentOffset = segment << myBankShift;
const uInt16 segmentOffset = segment << myBankShift;
if(myRamBankCount == 0 || bank < romBankCount())
{
// Setup ROM bank
uInt16 romBank = bank % romBankCount();
const uInt16 romBank = bank % romBankCount();
// Remember what bank is in this segment
uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
uInt16 hotspot = this->hotspot();
const uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
const uInt16 hotspot = this->hotspot();
uInt16 hotSpotAddr;
// Skip extra RAM; if existing it is only mapped into first segment
uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK;
const uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK;
// for ROMs < 4_KB, the whole address space will be mapped.
uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
const uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
if(hotspot & 0x1000)
hotSpotAddr = (hotspot & ~System::PAGE_MASK);
@ -212,7 +217,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
// Setup the page access methods for the current bank
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
uInt32 offset = bankOffset + (addr & myBankMask);
const uInt32 offset = bankOffset + (addr & myBankMask);
if(myDirectPeek && addr != hotSpotAddr)
access.directPeekBase = &myImage[offset];
@ -227,9 +232,9 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
else
{
// Setup RAM bank
uInt16 ramBank = (bank - romBankCount()) % myRamBankCount;
const uInt16 ramBank = (bank - romBankCount()) % myRamBankCount;
// The RAM banks follow the ROM banks and are half the size of a ROM bank
uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1));
const uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1));
// Remember what bank is in this segment
myCurrentSegOffset[segment] = uInt32(mySize) + (ramBank << myBankShift);
@ -241,7 +246,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
uInt32 offset = bankOffset + (addr & myRamMask);
const uInt32 offset = bankOffset + (addr & myRamMask);
access.directPokeBase = &myRAM[offset - mySize];
access.romAccessBase = &myRomAccessBase[offset];
@ -258,7 +263,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
uInt32 offset = bankOffset + (addr & myRamMask);
const uInt32 offset = bankOffset + (addr & myRamMask);
access.directPeekBase = &myRAM[offset - mySize];
access.romAccessBase = &myRomAccessBase[offset];

View File

@ -15,6 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Console.hxx"
#include "Event.hxx"
#include "System.hxx"
#include "CompuMate.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -18,11 +18,12 @@
#ifndef COMPUMATE_HXX
#define COMPUMATE_HXX
class Console;
class Event;
class System;
#include "bspf.hxx"
#include "CartCM.hxx"
#include "Control.hxx"
#include "Event.hxx"
#include "Console.hxx"
/**
Handler for SpectraVideo CompuMate bankswitched games.

View File

@ -24,6 +24,7 @@
#include "Cart.hxx"
#include "Control.hxx"
#include "Cart.hxx"
#include "CartCM.hxx"
#include "Driving.hxx"
#include "Event.hxx"
#include "EventHandler.hxx"
@ -81,13 +82,6 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
myCart(std::move(cart)),
myAudioSettings(audioSettings)
{
// Load user-defined palette for this ROM
loadUserPalette();
// Generate custom palette
generateCustomPalette(0);
generateCustomPalette(1);
// Create subsystems for the console
my6502 = make_unique<M6502>(myOSystem.settings());
myRiot = make_unique<M6532>(*this, myOSystem.settings());
@ -355,23 +349,20 @@ bool Console::load(Serializer& in)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleFormat(int direction)
void Console::selectFormat(int direction)
{
string saveformat, message;
uInt32 format = myCurrentFormat;
Int32 format = myCurrentFormat;
if(direction == 1)
format = (myCurrentFormat + 1) % 7;
else if(direction == -1)
format = myCurrentFormat > 0 ? (myCurrentFormat - 1) : 6;
format = BSPF::clampw(format + direction, 0, 6);
setFormat(format);
setFormat(format, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setFormat(uInt32 format)
void Console::setFormat(uInt32 format, bool force)
{
if(myCurrentFormat == format)
if(!force && myCurrentFormat == format)
return;
string saveformat, message;
@ -382,7 +373,7 @@ void Console::setFormat(uInt32 format)
{
case 0: // auto-detect
{
if (myFormatAutodetected) return;
if (!force && myFormatAutodetected) return;
myDisplayFormat = formatFromFilename();
if (myDisplayFormat == "AUTO")
@ -441,7 +432,6 @@ void Console::setFormat(uInt32 format)
myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected;
setPalette(myOSystem.settings().getString("palette"));
setTIAProperties();
initializeVideo(); // takes care of refreshing the screen
initializeAudio(); // ensure that audio synthesis is set up to match emulation speed
@ -478,107 +468,20 @@ void Console::enableColorLoss(bool state)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Console::getPaletteNum(const string& name) const
{
if(name == "z26")
return PaletteType::Z26;
if(name == "user" && myUserPaletteDefined)
return PaletteType::User;
if(name == "custom")
return PaletteType::Custom;
return PaletteType::Standard;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::togglePalette()
{
string palette, message;
palette = myOSystem.settings().getString("palette");
if(palette == "standard") // switch to z26
{
palette = "z26";
message = "Z26 palette";
}
else if(palette == "z26") // switch to user or standard
{
// If we have a user-defined palette, it will come next in
// the sequence; otherwise loop back to the standard one
if(myUserPaletteDefined)
{
palette = "user";
message = "User-defined palette";
}
else
{
palette = "custom";
message = "Custom palette";
}
}
else if(palette == "user") // switch to custom
{
palette = "custom";
message = "Custom palette";
}
else // switch to standard mode if we get this far
{
palette = "standard";
message = "Standard Stella palette";
}
myOSystem.settings().setValue("palette", palette);
myOSystem.frameBuffer().showMessage(message);
setPalette(palette);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setPalette(const string& type)
{
// Look at all the palettes, since we don't know which one is
// currently active
static constexpr BSPF::array2D<PaletteArray*, PaletteType::NumTypes, 3> palettes = {{
{ &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
{ &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
{ &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
{ &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette }
}};
// See which format we should be using
int paletteNum = getPaletteNum(type);
if(paletteNum == PaletteType::Custom)
{
}
// Now consider the current display format
const PaletteArray* palette =
(myDisplayFormat.compare(0, 3, "PAL") == 0) ? palettes[paletteNum][1] :
(myDisplayFormat.compare(0, 5, "SECAM") == 0) ? palettes[paletteNum][2] :
palettes[paletteNum][0];
myOSystem.frameBuffer().setTIAPalette(*palette);
if(myTIA->usingFixedColors())
myTIA->enableFixedColors(true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleInter()
void Console::toggleInter(bool toggle)
{
bool enabled = myOSystem.settings().getBool("tia.inter");
myOSystem.settings().setValue("tia.inter", !enabled);
if(toggle)
enabled = !enabled;
myOSystem.settings().setValue("tia.inter", enabled);
// ... and apply potential setting changes to the TIA surface
myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings();
ostringstream ss;
ss << "Interpolation " << (!enabled ? "enabled" : "disabled");
ss << "Interpolation " << (enabled ? "enabled" : "disabled");
myOSystem.frameBuffer().showMessage(ss.str());
}
@ -622,36 +525,20 @@ void Console::changePhosphor(int direction)
{
int blend = BSPF::stringToInt(myProperties.get(PropType::Display_PPBlend));
if(direction == +1) // increase blend
{
if(blend >= 100)
{
myOSystem.frameBuffer().showMessage("Phosphor blend at maximum");
myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 100);
return;
}
else
blend = std::min(blend+2, 100);
}
else if(direction == -1) // decrease blend
{
if(blend <= 2)
{
myOSystem.frameBuffer().showMessage("Phosphor blend at minimum");
myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 0);
return;
}
else
blend = std::max(blend-2, 0);
}
else
return;
blend = BSPF::clamp(blend + direction * 2, 0, 100);
myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend);
ostringstream val;
val << blend;
myProperties.set(PropType::Display_PPBlend, val.str());
myOSystem.frameBuffer().showMessage("Phosphor blend " + val.str());
myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend);
if(blend)
val << "%";
else
{
val.str("");
val << "Off";
}
myOSystem.frameBuffer().showMessage("Phosphor blend", val.str(), blend);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -677,12 +564,7 @@ FBInitStatus Console::initializeVideo(bool full)
myOSystem.frameBuffer().showFrameStats(
myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats"));
generateCustomPalette(0);
generateCustomPalette(1);
generateColorLossPalette();
}
setPalette(myOSystem.settings().getString("palette"));
return fbstatus;
}
@ -737,41 +619,17 @@ void Console::changeVerticalCenter(int direction)
{
Int32 vcenter = myTIA->vcenter();
if(direction == +1) // increase vcenter
{
if(vcenter >= myTIA->maxVcenter())
{
myOSystem.frameBuffer().showMessage("V-Center at maximum");
return;
}
++vcenter;
}
else if(direction == -1) // decrease vcenter
{
if (vcenter <= myTIA->minVcenter())
{
myOSystem.frameBuffer().showMessage("V-Center at minimum");
return;
}
--vcenter;
}
else
return;
vcenter = BSPF::clamp(vcenter + direction, myTIA->minVcenter(), myTIA->maxVcenter());
ostringstream ss;
ostringstream ss, val;
ss << vcenter;
myProperties.set(PropType::Display_VCenter, ss.str());
if (vcenter != myTIA->vcenter()) myTIA->setVcenter(vcenter);
ss.str("");
ss << "V-Center ";
if (!vcenter)
ss << "default";
else
ss << (vcenter > 0 ? "+" : "") << vcenter << "px";
myOSystem.frameBuffer().showMessage(ss.str());
val << (vcenter ? vcenter > 0 ? "+" : "" : " ") << vcenter << "px";
myOSystem.frameBuffer().showMessage("V-Center", val.str(), vcenter,
myTIA->minVcenter(), myTIA->maxVcenter());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -784,30 +642,11 @@ void Console::updateVcenter(Int32 vcenter)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::changeScanlineAdjust(int direction)
void Console::changeVSizeAdjust(int direction)
{
Int32 newAdjustVSize = myTIA->adjustVSize();
if (direction != -1 && direction != +1) return;
if(direction == +1) // increase scanline adjustment
{
if (newAdjustVSize >= 5)
{
myOSystem.frameBuffer().showMessage("V-Size at maximum");
return;
}
newAdjustVSize++;
}
else if(direction == -1) // decrease scanline adjustment
{
if (newAdjustVSize <= -5)
{
myOSystem.frameBuffer().showMessage("V-Size at minimum");
return;
}
newAdjustVSize--;
}
newAdjustVSize = BSPF::clamp(newAdjustVSize + direction, -5, 5);
if (newAdjustVSize != myTIA->adjustVSize()) {
myTIA->setAdjustVSize(newAdjustVSize);
@ -815,55 +654,10 @@ void Console::changeScanlineAdjust(int direction)
initializeVideo();
}
ostringstream ss;
ostringstream val;
ss << "V-Size ";
if (!newAdjustVSize)
ss << "default";
else
ss << (newAdjustVSize > 0 ? "+" : "") << newAdjustVSize << "%";
myOSystem.frameBuffer().showMessage(ss.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::changeColorPhaseShift(int direction)
{
const char DEGREE = 0x1c;
const float NTSC_SHIFT = 26.2F;
const float PAL_SHIFT = 31.3F; // 360 / 11.5
const bool isNTSC = myDisplayFormat == "NTSC" || myDisplayFormat == "NTSC50";
const bool isPAL = myDisplayFormat == "PAL" || myDisplayFormat == "PAL60";
// SECAM is not supported
if(isNTSC || isPAL)
{
const string key = isNTSC ? "phase_ntsc" : "phase_pal";
const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT;
float phase = myOSystem.settings().getFloat(key);
if(direction == +1) // increase color phase shift
{
phase += 0.3F;
phase = std::min(phase, shift + 4.5F);
}
else if(direction == -1) // decrease color phase shift
{
phase -= 0.3F;
phase = std::max(phase, shift - 4.5F);
}
myOSystem.settings().setValue(key, phase);
generateCustomPalette(isNTSC ? 0 : 1);
myOSystem.settings().setValue("palette", "custom");
setPalette("custom");
ostringstream ss;
ss << "Color phase shift at "
<< std::fixed << std::setprecision(1) << phase << DEGREE;
myOSystem.frameBuffer().showMessage(ss.str());
}
val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ") << newAdjustVSize << "%";
myOSystem.frameBuffer().showMessage("V-Size", val.str(), newAdjustVSize, -5, 5);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1073,200 +867,6 @@ unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
return controller;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::loadUserPalette()
{
if (!myOSystem.checkUserPalette(true))
return;
const string& palette = myOSystem.paletteFile();
ifstream in(palette, std::ios::binary);
// Now that we have valid data, create the user-defined palettes
std::array<uInt8, 3> pixbuf; // Temporary buffer for one 24-bit pixel
for(int i = 0; i < 128; i++) // NTSC palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserNTSCPalette[(i<<1)] = pixel;
}
for(int i = 0; i < 128; i++) // PAL palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserPALPalette[(i<<1)] = pixel;
}
std::array<uInt32, 16> secam; // All 8 24-bit pixels, plus 8 colorloss pixels
for(int i = 0; i < 8; i++) // SECAM palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
secam[(i<<1)] = pixel;
secam[(i<<1)+1] = 0;
}
uInt32* ptr = ourUserSECAMPalette.data();
for(int i = 0; i < 16; ++i)
{
const uInt32* s = secam.data();
for(int j = 0; j < 16; ++j)
*ptr++ = *s++;
}
myUserPaletteDefined = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::generateCustomPalette(int type)
{
const int NUM_CHROMA = 16;
const int NUM_LUMA = 8;
const double SATURATION = 0.25;
double color[NUM_CHROMA][2] = {{0.0}};
if(type == 0)
{
// YIQ is YUV shifted by 33°
const double offset = 33 * (2 * M_PI / 360);
const double shift = myOSystem.settings().getFloat("phase_ntsc") * (2 * M_PI / 360);
// color 0 is grayscale
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
{
color[chroma][0] = SATURATION * sin(offset + shift * (chroma - 1));
color[chroma][1] = SATURATION * sin(offset + shift * (chroma - 1 - M_PI));
}
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{
const double I = color[chroma][0];
const double Q = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++)
{
const double Y = 0.05 + luma / 8.24; // 0.05..~0.90
double R = Y + 0.956 * I + 0.621 * Q;
double G = Y - 0.272 * I - 0.647 * Q;
double B = Y - 1.106 * I + 1.703 * Q;
if(R < 0) R = 0;
if(G < 0) G = 0;
if(B < 0) B = 0;
R = pow(R, 0.9);
G = pow(G, 0.9);
B = pow(B, 0.9);
if(R > 1) R = 1;
if(G > 1) G = 1;
if(B > 1) B = 1;
int r = R * 255.F;
int g = G * 255.F;
int b = B * 255.F;
ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
}
}
}
else
{
const double offset = 180 * (2 * M_PI / 360);
const double shift = myOSystem.settings().getFloat("phase_pal") * (2 * M_PI / 360);
const double fixedShift = 22.5 * (2 * M_PI / 360);
// colors 0, 1, 14 and 15 are grayscale
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
{
int idx = NUM_CHROMA - 1 - chroma;
color[idx][0] = SATURATION * sin(offset - fixedShift * chroma);
if ((idx & 1) == 0)
color[idx][1] = SATURATION * sin(offset - shift * (chroma - 3.5) / 2.F);
else
color[idx][1] = SATURATION * -sin(offset - shift * chroma / 2.F);
}
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{
const double U = color[chroma][0];
const double V = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++)
{
const double Y = 0.05 + luma / 8.24; // 0.05..~0.90
// Most sources
double R = Y + 1.403 * V;
double G = Y - 0.344 * U - 0.714 * V;
double B = Y + 1.770 * U;
// German Wikipedia, huh???
//double B = Y + 1 / 0.493 * U;
//double R = Y + 1 / 0.877 * V;
//double G = 1.704 * Y - 0.590 * R - 0.194 * B;
if(R < 0) R = 0.0;
if(G < 0) G = 0.0;
if(B < 0) B = 0.0;
R = pow(R, 1.2);
G = pow(G, 1.2);
B = pow(B, 1.2);
if(R > 1) R = 1;
if(G > 1) G = 1;
if(B > 1) B = 1;
int r = R * 255.F;
int g = G * 255.F;
int b = B * 255.F;
ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::generateColorLossPalette()
{
// Look at all the palettes, since we don't know which one is
// currently active
std::array<uInt32*, 3 * PaletteType::NumTypes> palette = {
ourNTSCPalette.data(), ourPALPalette.data(), ourSECAMPalette.data(),
ourNTSCPaletteZ26.data(), ourPALPaletteZ26.data(), ourSECAMPaletteZ26.data(),
nullptr, nullptr, nullptr,
ourCustomNTSCPalette.data(), ourCustomPALPalette.data(), ourSECAMPalette.data(),
};
if(myUserPaletteDefined)
{
palette[6] = ourUserNTSCPalette.data();
palette[7] = ourUserPALPalette.data();
palette[8] = ourUserSECAMPalette.data();
}
for(int i = 0; i < 3 * PaletteType::NumTypes; ++i)
{
if(palette[i] == nullptr)
continue;
// Fill the odd numbered palette entries with gray values (calculated
// using the standard RGB -> grayscale conversion formula)
for(int j = 0; j < 128; ++j)
{
const uInt32 pixel = palette[i][(j<<1)];
const uInt8 r = (pixel >> 16) & 0xff;
const uInt8 g = (pixel >> 8) & 0xff;
const uInt8 b = (pixel >> 0) & 0xff;
const uInt8 sum = static_cast<uInt8>((r * 0.2989) + (g * 0.5870) + (b * 0.1140));
palette[i][(j<<1)+1] = (sum << 16) + (sum << 8) + sum;
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float Console::getFramerate() const
{
@ -1338,234 +938,3 @@ void Console::stateChanged(EventHandlerState state)
{
// only the CompuMate used to care about state changes
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourNTSCPalette = {
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0,
0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0,
0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0,
0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0,
0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0,
0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0,
0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0,
0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0,
0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0,
0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0,
0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0,
0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0,
0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0,
0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0,
0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0,
0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0,
0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0,
0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0,
0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0,
0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0,
0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0,
0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0,
0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0,
0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0,
0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0,
0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0,
0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0,
0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0,
0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourPALPalette = {
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2
0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389
0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3
0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0,
0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4
0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac
0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5
0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0,
0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6
0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd
0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7
0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff
0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8
0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff
0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9
0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0,
0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a
0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff
0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b
0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0,
0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c
0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff,
0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d
0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0,
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourSECAMPalette = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourNTSCPaletteZ26 = {
0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0,
0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0,
0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0,
0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0,
0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0,
0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0,
0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0,
0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0,
0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0,
0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0,
0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0,
0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0,
0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0,
0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0,
0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0,
0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0,
0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0,
0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0,
0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0,
0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0,
0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0,
0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0,
0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0,
0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0,
0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0,
0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0,
0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0,
0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0,
0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourPALPaletteZ26 = {
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0,
0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0,
0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0,
0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0,
0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0,
0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0,
0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0,
0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0,
0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0,
0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0,
0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0,
0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0,
0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0,
0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0,
0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0,
0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0,
0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0,
0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0,
0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0,
0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0,
0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0,
0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0,
0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0,
0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourSECAMPaletteZ26 = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourUserNTSCPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourUserPALPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourUserSECAMPalette = { 0 }; // filled from external file
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourCustomNTSCPalette = { 0 }; // filled by function
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray Console::ourCustomPALPalette = { 0 }; // filled by function

View File

@ -39,7 +39,6 @@ class AudioSettings;
#include "FrameBufferConstants.hxx"
#include "Serializable.hxx"
#include "EventHandlerConstants.hxx"
#include "NTSCFilter.hxx"
#include "EmulationTiming.hxx"
#include "ConsoleTiming.hxx"
#include "frame-manager/AbstractFrameManager.hxx"
@ -190,41 +189,24 @@ class Console : public Serializable, public ConsoleIO
/**
Toggle between NTSC/PAL/SECAM (and variants) display format.
@param direction +1 indicates increase, -1 indicates decrease.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void toggleFormat(int direction = 1);
void selectFormat(int direction = +1);
/**
Set NTSC/PAL/SECAM (and variants) display format.
*/
void setFormat(uInt32 format);
void setFormat(uInt32 format, bool force = false);
/**
Get NTSC/PAL/SECAM (and variants) display format name
*/
string getFormatString() const { return myDisplayFormat; }
/**
Toggle between the available palettes.
*/
void togglePalette();
/**
Generates a custom palette, based on user defined phase shifts.
*/
void generateCustomPalette(int type);
/**
Sets the palette according to the given palette name.
@param palette The palette to switch to.
*/
void setPalette(const string& palette);
/**
Toggle interpolation on/off
*/
void toggleInter();
void toggleInter(bool toggle = true);
/**
Toggle turbo mode on/off
@ -240,9 +222,9 @@ class Console : public Serializable, public ConsoleIO
/**
Change the "Display.PPBlend" variable.
@param direction +1 indicates increase, -1 indicates decrease.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changePhosphor(int direction);
void changePhosphor(int direction = +1);
/**
Toggles the PAL color-loss effect.
@ -275,28 +257,18 @@ class Console : public Serializable, public ConsoleIO
/**
Change the "Display.VCenter" variable.
@param direction +1 indicates increase, -1 indicates decrease.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeVerticalCenter(int direction);
void changeVerticalCenter(int direction = +1);
/**
Change the "TIA scanline adjust" variable.
Note that there are currently two of these (NTSC and PAL). The currently
active mode will determine which one is used.
@param direction +1 indicates increase, -1 indicates decrease.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeScanlineAdjust(int direction);
/**
Change the "phase shift" variable.
Note that there are two of these (NTSC and PAL). The currently
active mode will determine which one is used.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeColorPhaseShift(int direction);
void changeVSizeAdjust(int direction = +1);
/**
Returns the current framerate.
@ -379,35 +351,10 @@ class Console : public Serializable, public ConsoleIO
unique_ptr<Controller> getControllerPort(const Controller::Type type,
const Controller::Jack port, const string& romMd5);
/**
Loads a user-defined palette file (from OSystem::paletteFile), filling the
appropriate user-defined palette arrays.
*/
void loadUserPalette();
/**
Loads all defined palettes with PAL color-loss data, even those that
normally can't have it enabled (NTSC), since it's also used for
'greying out' the frame in the debugger.
*/
void generateColorLossPalette();
int getPaletteNum(const string& name) const;
void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const;
void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const;
private:
enum PaletteType {
Standard,
Z26,
User,
Custom,
NumTypes
};
// Reference to the osystem object
OSystem& myOSystem;
@ -457,10 +404,6 @@ class Console : public Serializable, public ConsoleIO
// Is the TV format autodetected?
bool myFormatAutodetected{false};
// Indicates whether an external palette was found and
// successfully loaded
bool myUserPaletteDefined{false};
// Contains detailed info about this console
ConsoleInfo myConsoleInfo;
@ -474,25 +417,6 @@ class Console : public Serializable, public ConsoleIO
// The audio settings
AudioSettings& myAudioSettings;
// Table of RGB values for NTSC, PAL and SECAM
static PaletteArray ourNTSCPalette;
static PaletteArray ourPALPalette;
static PaletteArray ourSECAMPalette;
// Table of RGB values for NTSC, PAL and SECAM - Z26 version
static PaletteArray ourNTSCPaletteZ26;
static PaletteArray ourPALPaletteZ26;
static PaletteArray ourSECAMPaletteZ26;
// Table of RGB values for NTSC, PAL and SECAM - user-defined
static PaletteArray ourUserNTSCPalette;
static PaletteArray ourUserPALPalette;
static PaletteArray ourUserSECAMPalette;
// Table of RGB values for NTSC, PAL - custom-defined
static PaletteArray ourCustomNTSCPalette;
static PaletteArray ourCustomPALPalette;
private:
// Following constructors and assignment operators not supported
Console() = delete;

View File

@ -15,12 +15,12 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Control.hxx"
#include "Switches.hxx"
#ifndef CONSOLE_IO_HXX
#define CONSOLE_IO_HXX
class Controller;
class Switches;
class ConsoleIO
{
public:

View File

@ -25,7 +25,8 @@ enum class ConsoleTiming
{
ntsc, // console with CPU running at 1.193182 MHz, NTSC colours
pal, // console with CPU running at 1.182298 MHz, PAL colours
secam // console with CPU running at 1.187500 MHz, SECAM colours
secam, // console with CPU running at 1.187500 MHz, SECAM colours
numTimings
};
#endif // CONSOLE_TIMING_HXX

View File

@ -25,8 +25,8 @@ class System;
#include <functional>
#include "Serializable.hxx"
#include "bspf.hxx"
#include "Serializable.hxx"
/**
A controller is a device that plugs into either the left or right

View File

@ -18,6 +18,8 @@
#ifndef CONTROLLER_DETECTOR_HXX
#define CONTROLLER_DETECTOR_HXX
class Settings;
#include "Control.hxx"
/**

View File

@ -20,9 +20,9 @@
class System;
#include "Console.hxx"
#include "Serializable.hxx"
#include "bspf.hxx"
#include "ConsoleTiming.hxx"
#include "Serializable.hxx"
/**
Abstract base class for devices which can be attached to a 6502

View File

@ -22,7 +22,6 @@
#include <set>
#include "bspf.hxx"
#include "StellaKeys.hxx"
/**
@author Stephen Anthony, Christian Speckner, Thomas Jentzsch
@ -92,6 +91,7 @@ class Event
TogglePauseMode, StartPauseMode,
OptionsMenuMode, CmdMenuMode, DebuggerMode, ExitMode,
TakeSnapshot, ToggleContSnapshots, ToggleContSnapshotsFrame,
ToggleTurbo,
NextState, PreviousState, LoadState, SaveState,
SaveAllStates, LoadAllStates,
@ -100,12 +100,15 @@ class Event
Unwind1Menu, Unwind10Menu, UnwindAllMenu,
RewindPause, UnwindPause,
FormatDecrease, FormatIncrease, TogglePalette, ToggleColorLoss,
FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss,
PreviousPaletteAttribute, NextPaletteAttribute,
PaletteAttributeDecrease, PaletteAttributeIncrease,
ToggleFullScreen, VidmodeDecrease, VidmodeIncrease,
VCenterDecrease, VCenterIncrease, ScanlineAdjustDecrease, ScanlineAdjustIncrease,
VCenterDecrease, VCenterIncrease, VSizeAdjustDecrease, VSizeAdjustIncrease,
OverscanDecrease, OverscanIncrease,
VidmodeStd, VidmodeRGB, VidmodeSVideo, VidModeComposite, VidModeBad, VidModeCustom,
PreviousVideoMode, NextVideoMode,
PreviousAttribute, NextAttribute, DecreaseAttribute, IncreaseAttribute,
ScanlinesDecrease, ScanlinesIncrease,
PhosphorDecrease, PhosphorIncrease, TogglePhosphor, ToggleInter, ToggleJitter,
@ -118,10 +121,8 @@ class Event
ToggleCollisions, ToggleBits, ToggleFixedColors,
ToggleFrameStats, ToggleSAPortOrder, ExitGame,
// add new events from here to avoid that user remapped events get overwritten
ToggleTurbo,
ColorShiftDecrease, ColorShiftIncrease,
SettingDecrease, SettingIncrease, PreviousSetting, NextSetting,
LastType
};
@ -136,7 +137,7 @@ class Event
};
// Event list version, update only if the id of existing(!) event types changed
static constexpr Int32 VERSION = 3;
static constexpr Int32 VERSION = 4;
using EventSet = std::set<Event::Type>;

View File

@ -22,6 +22,7 @@
#include "Base.hxx"
#include "Console.hxx"
#include "PaletteHandler.hxx"
#include "FrameBuffer.hxx"
#include "FSNode.hxx"
#include "OSystem.hxx"
@ -62,6 +63,8 @@
#include "ScrollBarWidget.hxx"
#endif
using namespace std::placeholders;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::EventHandler(OSystem& osystem)
: myOSystem(osystem)
@ -339,15 +342,149 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AdjustFunction EventHandler::cycleAdjustSetting(int direction)
{
const bool isFullScreen = myOSystem.frameBuffer().fullScreen();
const bool isCustomPalette =
myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM;
const bool isCustomFilter =
myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM);
do
{
myAdjustSetting =
AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction, 0, int(AdjustSetting::MAX_ADJ)));
// skip currently non-relevant adjustments
} while((myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen)
|| (myAdjustSetting == AdjustSetting::PALETTE_PHASE && !isCustomPalette)
|| (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS
&& myAdjustSetting <= AdjustSetting::NTSC_BLEEDING
&& !isCustomFilter));
return getAdjustSetting(myAdjustSetting);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
{
// Notes:
// - All methods MUST show a message
// - This array MUST have the same order as AdjustSetting
const AdjustFunction ADJUST_FUNCTIONS[int(AdjustSetting::NUM_ADJ)] =
{
std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1),
std::bind(&FrameBuffer::selectVidMode, &myOSystem.frameBuffer(), _1),
std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1),
std::bind(&FrameBuffer::changeOverscan, &myOSystem.frameBuffer(), _1),
std::bind(&Console::selectFormat, &myOSystem.console(), _1),
std::bind(&Console::changeVerticalCenter, &myOSystem.console(), _1),
std::bind(&Console::changeVSizeAdjust, &myOSystem.console(), _1),
// Palette adjustables
std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::PHASE_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::HUE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::SATURATION, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::CONTRAST, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BRIGHTNESS, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GAMMA, _1),
// NTSC filter adjustables
std::bind(&TIASurface::changeNTSC, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::SHARPNESS), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::RESOLUTION), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::ARTIFACTS), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::FRINGING), _1),
std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
int(NTSCFilter::Adjustables::BLEEDING), _1),
std::bind(&Console::changePhosphor, &myOSystem.console(), _1),
std::bind(&TIASurface::setScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&Console::toggleInter, &myOSystem.console(), _1),
// Following functions are not used when cycling settings but for "direct only" hotkeys
std::bind(&StateManager::changeState, &myOSystem.state(), _1),
std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
std::bind(&TIASurface::changeCurrentNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), _1),
};
return ADJUST_FUNCTIONS[int(setting)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
{
// Take care of special events that aren't part of the emulation core
// or need to be preprocessed before passing them on
bool pressed = (value != 0);
const bool pressed = (value != 0);
// The global settings keys change settings or values as long as the setting
// message from the previous settings event is still displayed.
// Therefore, do not change global settings/values or direct values if
// a) the setting message is no longer shown
// b) other keys have been pressed
if(!myOSystem.frameBuffer().messageShown())
{
myAdjustActive = false;
myAdjustDirect = AdjustSetting::NONE;
}
const bool adjustActive = myAdjustActive;
const AdjustSetting adjustDirect = myAdjustDirect;
if(pressed)
{
myAdjustActive = false;
myAdjustDirect = AdjustSetting::NONE;
}
switch(event)
{
////////////////////////////////////////////////////////////////////////
// Allow adjusting several (mostly repeated) settings using the same four hotkeys
case Event::PreviousSetting:
case Event::NextSetting:
if(pressed && !repeated)
{
const int direction = event == Event::PreviousSetting ? -1 : +1;
// Get (and display) the previous|next adjustment function,
// but do not change its value
cycleAdjustSetting(adjustActive ? direction : 0)(0);
// Fallback message when no message is displayed by method
//if(!myOSystem.frameBuffer().messageShown())
// myOSystem.frameBuffer().showMessage("Message " + std::to_string(int(myAdjustSetting)));
myAdjustActive = true;
}
break;
case Event::SettingDecrease:
case Event::SettingIncrease:
if(pressed)
{
const int direction = event == Event::SettingDecrease ? -1 : +1;
// if a "direct only" hotkey was pressed last, use this one
if(adjustDirect != AdjustSetting::NONE)
{
myAdjustDirect = adjustDirect;
getAdjustSetting(myAdjustDirect)(direction);
}
else
{
// Get (and display) the current adjustment function,
// but only change its value if the function was already active before
getAdjustSetting(myAdjustSetting)(adjustActive ? direction : 0);
myAdjustActive = true;
}
}
return;
////////////////////////////////////////////////////////////////////////
// If enabled, make sure 'impossible' joystick directions aren't allowed
case Event::JoystickZeroUp:
@ -392,67 +529,169 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
////////////////////////////////////////////////////////////////////////
case Event::Fry:
if (!repeated) myFryingFlag = pressed;
if(!repeated) myFryingFlag = pressed;
return;
case Event::ReloadConsole:
if (pressed && !repeated) myOSystem.reloadConsole();
if(pressed && !repeated) myOSystem.reloadConsole();
return;
case Event::VolumeDecrease:
if(pressed) myOSystem.sound().adjustVolume(-1);
if(pressed)
{
myOSystem.sound().adjustVolume(-1);
myAdjustSetting = AdjustSetting::VOLUME;
myAdjustActive = true;
}
return;
case Event::VolumeIncrease:
if(pressed) myOSystem.sound().adjustVolume(+1);
if(pressed)
{
myOSystem.sound().adjustVolume(+1);
myAdjustSetting = AdjustSetting::VOLUME;
myAdjustActive = true;
}
return;
case Event::SoundToggle:
if(pressed && !repeated) myOSystem.sound().toggleMute();
if(pressed && !repeated)
{
myOSystem.sound().toggleMute();
myAdjustSetting = AdjustSetting::VOLUME;
myAdjustActive = true;
}
return;
case Event::VidmodeDecrease:
if(pressed) myOSystem.frameBuffer().changeVidMode(-1);
if(pressed)
{
myOSystem.frameBuffer().selectVidMode(-1);
myAdjustSetting = AdjustSetting::ZOOM;
myAdjustActive = true;
}
return;
case Event::VidmodeIncrease:
if(pressed) myOSystem.frameBuffer().changeVidMode(+1);
if(pressed)
{
myOSystem.frameBuffer().selectVidMode(+1);
myAdjustSetting = AdjustSetting::ZOOM;
myAdjustActive = true;
}
return;
case Event::VCenterDecrease:
if (pressed) myOSystem.console().changeVerticalCenter(-1);
if(pressed)
{
myOSystem.console().changeVerticalCenter(-1);
myAdjustSetting = AdjustSetting::VCENTER;
myAdjustActive = true;
}
return;
case Event::VCenterIncrease:
if (pressed) myOSystem.console().changeVerticalCenter(+1);
if(pressed)
{
myOSystem.console().changeVerticalCenter(+1);
myAdjustSetting = AdjustSetting::VCENTER;
myAdjustActive = true;
}
return;
case Event::ScanlineAdjustDecrease:
if (pressed) myOSystem.console().changeScanlineAdjust(-1);
case Event::VSizeAdjustDecrease:
if(pressed)
{
myOSystem.console().changeVSizeAdjust(-1);
myAdjustSetting = AdjustSetting::VSIZE;
myAdjustActive = true;
}
return;
case Event::ScanlineAdjustIncrease:
if (pressed) myOSystem.console().changeScanlineAdjust(+1);
case Event::VSizeAdjustIncrease:
if(pressed)
{
myOSystem.console().changeVSizeAdjust(+1);
myAdjustSetting = AdjustSetting::VSIZE;
myAdjustActive = true;
}
return;
case Event::ColorShiftDecrease:
if (pressed) myOSystem.console().changeColorPhaseShift(-1);
case Event::PreviousPaletteAttribute:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(-1);
myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
}
return;
case Event::ColorShiftIncrease:
if (pressed) myOSystem.console().changeColorPhaseShift(+1);
case Event::NextPaletteAttribute:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(+1);
myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
}
return;
case Event::PaletteAttributeDecrease:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(-1);
myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
}
return;
case Event::PaletteAttributeIncrease:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(+1);
myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
}
return;
case Event::ToggleFullScreen:
if (pressed && !repeated) myOSystem.frameBuffer().toggleFullscreen();
if(pressed && !repeated)
{
myOSystem.frameBuffer().toggleFullscreen();
myAdjustSetting = AdjustSetting::FULLSCREEN;
myAdjustActive = true;
}
return;
case Event::OverscanDecrease:
if (pressed) myOSystem.frameBuffer().changeOverscan(-1);
if(pressed)
{
myOSystem.frameBuffer().changeOverscan(-1);
myAdjustSetting = AdjustSetting::OVERSCAN;
myAdjustActive = true;
}
return;
case Event::OverscanIncrease:
if (pressed) myOSystem.frameBuffer().changeOverscan(1);
if(pressed)
{
myOSystem.frameBuffer().changeOverscan(+1);
myAdjustSetting = AdjustSetting::OVERSCAN;
myAdjustActive = true;
}
return;
case Event::PreviousVideoMode:
if(pressed && !repeated)
{
myOSystem.frameBuffer().tiaSurface().changeNTSC(-1);
myAdjustSetting = AdjustSetting::NTSC_PRESET;
myAdjustActive = true;
}
return;
case Event::NextVideoMode:
if(pressed && !repeated)
{
myOSystem.frameBuffer().tiaSurface().changeNTSC(+1);
myAdjustSetting = AdjustSetting::NTSC_PRESET;
myAdjustActive = true;
}
return;
case Event::VidmodeStd:
@ -479,72 +718,113 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
return;
case Event::ScanlinesDecrease:
if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-2);
return;
case Event::ScanlinesIncrease:
if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+2);
return;
case Event::PreviousAttribute:
if (pressed)
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().setPreviousAdjustable());
myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(-1);
myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::NextAttribute:
if (pressed)
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().setNextAdjustable());
myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(+1);
myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::DecreaseAttribute:
if (pressed)
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().decreaseAdjustable());
myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(-1);
myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::IncreaseAttribute:
if (pressed)
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
myOSystem.frameBuffer().showMessage(
myOSystem.frameBuffer().tiaSurface().ntsc().increaseAdjustable());
myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(+1);
myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::ScanlinesDecrease:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-1);
myAdjustSetting = AdjustSetting::SCANLINES;
myAdjustActive = true;
}
return;
case Event::ScanlinesIncrease:
if(pressed)
{
myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+1);
myAdjustSetting = AdjustSetting::SCANLINES;
myAdjustActive = true;
}
return;
case Event::PhosphorDecrease:
if (pressed) myOSystem.console().changePhosphor(-1);
if(pressed)
{
myOSystem.console().changePhosphor(-1);
myAdjustSetting = AdjustSetting::PHOSPHOR;
myAdjustActive = true;
}
return;
case Event::PhosphorIncrease:
if (pressed) myOSystem.console().changePhosphor(1);
if(pressed)
{
myOSystem.console().changePhosphor(+1);
myAdjustSetting = AdjustSetting::PHOSPHOR;
myAdjustActive = true;
}
return;
case Event::TogglePhosphor:
if (pressed && !repeated) myOSystem.console().togglePhosphor();
if(pressed && !repeated)
{
myOSystem.console().togglePhosphor();
myAdjustSetting = AdjustSetting::PHOSPHOR;
myAdjustActive = true;
}
return;
case Event::ToggleColorLoss:
if (pressed && !repeated) myOSystem.console().toggleColorLoss();
return;
case Event::TogglePalette:
if (pressed && !repeated) myOSystem.console().togglePalette();
case Event::PaletteDecrease:
if(pressed && !repeated)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(-1);
myAdjustSetting = AdjustSetting::PALETTE;
myAdjustActive = true;
}
return;
case Event::PaletteIncrease:
if(pressed && !repeated)
{
myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(+1);
myAdjustSetting = AdjustSetting::PALETTE;
myAdjustActive = true;
}
return;
case Event::ToggleInter:
if (pressed && !repeated) myOSystem.console().toggleInter();
if(pressed && !repeated)
{
myOSystem.console().toggleInter();
myAdjustSetting = AdjustSetting::INTERPOLATION;
myAdjustActive = true;
}
return;
case Event::ToggleTurbo:
@ -582,23 +862,26 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::FormatDecrease:
if (pressed) myOSystem.console().toggleFormat(-1);
if(pressed && !repeated)
{
myOSystem.console().selectFormat(-1);
myAdjustSetting = AdjustSetting::TVFORMAT;
myAdjustActive = true;
}
return;
case Event::FormatIncrease:
if (pressed) myOSystem.console().toggleFormat(1);
if(pressed && !repeated)
{
myOSystem.console().selectFormat(+1);
myAdjustSetting = AdjustSetting::TVFORMAT;
myAdjustActive = true;
}
return;
case Event::ToggleGrabMouse:
if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen())
{
bool oldState = myOSystem.frameBuffer().grabMouseEnabled();
myOSystem.frameBuffer().toggleGrabMouse();
bool newState = myOSystem.frameBuffer().grabMouseEnabled();
myOSystem.frameBuffer().showMessage(oldState != newState ? myOSystem.frameBuffer().grabMouseEnabled()
? "Grab mouse enabled" : "Grab mouse disabled"
: "Grab mouse not allowed while cursor shown");
}
return;
case Event::ToggleP0Collision:
@ -662,7 +945,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::SaveState:
if(pressed && !repeated) myOSystem.state().saveState();
if(pressed && !repeated)
{
myOSystem.state().saveState();
myAdjustDirect = AdjustSetting::STATE;
}
return;
case Event::SaveAllStates:
@ -670,12 +957,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
myOSystem.frameBuffer().showMessage(myOSystem.state().rewindManager().saveAllStates());
return;
case Event::NextState:
if(pressed) myOSystem.state().changeState(1);
case Event::PreviousState:
if(pressed)
{
myOSystem.state().changeState(-1);
myAdjustDirect = AdjustSetting::STATE;
}
return;
case Event::PreviousState:
if (pressed) myOSystem.state().changeState(-1);
case Event::NextState:
if(pressed)
{
myOSystem.state().changeState(+1);
myAdjustDirect = AdjustSetting::STATE;
}
return;
case Event::ToggleAutoSlot:
@ -683,7 +978,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::LoadState:
if(pressed && !repeated) myOSystem.state().loadState();
if(pressed && !repeated)
{
myOSystem.state().loadState();
myAdjustDirect = AdjustSetting::STATE;
}
return;
case Event::LoadAllStates:
@ -759,7 +1058,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if (myOSystem.settings().getBool("confirmexit"))
{
StringList msg;
string saveOnExit = myOSystem.settings().getString("saveonexit");
const string saveOnExit = myOSystem.settings().getString("saveonexit");
bool activeTM = myOSystem.settings().getBool(
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
@ -1084,12 +1383,12 @@ void EventHandler::setActionMappings(EventMode mode)
// Fill the EmulActionList with the current key and joystick mappings
for(auto& item: ourEmulActionList)
{
Event::Type event = item.event;
const Event::Type event = item.event;
item.key = "None";
string key = myPKeyHandler->getMappingDesc(event, mode);
#ifdef JOYSTICK_SUPPORT
string joydesc = myPJoyHandler->getMappingDesc(event, mode);
const string joydesc = myPJoyHandler->getMappingDesc(event, mode);
if(joydesc != "")
{
if(key != "")
@ -1106,12 +1405,12 @@ void EventHandler::setActionMappings(EventMode mode)
// Fill the MenuActionList with the current key and joystick mappings
for(auto& item: ourMenuActionList)
{
Event::Type event = item.event;
const Event::Type event = item.event;
item.key = "None";
string key = myPKeyHandler->getMappingDesc(event, mode);
#ifdef JOYSTICK_SUPPORT
string joydesc = myPJoyHandler->getMappingDesc(event, mode);
const string joydesc = myPJoyHandler->getMappingDesc(event, mode);
if(joydesc != "")
{
if(key != "")
@ -1137,7 +1436,7 @@ void EventHandler::setComboMap()
string list = myOSystem.settings().getString("combomap");
replace(list.begin(), list.end(), ':', ' ');
istringstream buf(list);
Int32 version = myOSystem.settings().getInt("event_ver");
const Int32 version = myOSystem.settings().getInt("event_ver");
// Erase the 'combo' array
auto ERASE_ALL = [&]() {
@ -1199,7 +1498,7 @@ void EventHandler::removePhysicalJoystickFromDatabase(const string& name)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod)
{
bool mapped = myPKeyHandler->addMapping(event, mode, key, mod);
const bool mapped = myPKeyHandler->addMapping(event, mode, key, mod);
if(mapped)
setActionMappings(mode);
@ -1212,7 +1511,7 @@ bool EventHandler::addJoyMapping(Event::Type event, EventMode mode,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir);
const bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir);
if (mapped && updateMenus)
setActionMappings(mode);
@ -1410,7 +1709,7 @@ VariantList EventHandler::getComboList(EventMode /**/) const
VarList::push_back(l, "None", "-1");
for(uInt32 i = 0; i < ourEmulActionList.size(); ++i)
{
Event::Type event = EventHandler::ourEmulActionList[i].event;
const Event::Type event = EventHandler::ourEmulActionList[i].event;
// exclude combos events
if(!(event >= Event::Combo1 && event <= Event::Combo16))
{
@ -1432,7 +1731,7 @@ StringList EventHandler::getComboListForEvent(Event::Type event) const
int combo = event - Event::Combo1;
for(uInt32 i = 0; i < EVENTS_PER_COMBO; ++i)
{
Event::Type e = myComboTable[combo][i];
const Event::Type e = myComboTable[combo][i];
for(uInt32 j = 0; j < ourEmulActionList.size(); ++j)
{
if(EventHandler::ourEmulActionList[j].event == e)
@ -1456,7 +1755,7 @@ void EventHandler::setComboListForEvent(Event::Type event, const StringList& eve
if(event >= Event::Combo1 && event <= Event::Combo16)
{
assert(events.size() == 8);
int combo = event - Event::Combo1;
const int combo = event - Event::Combo1;
for(uInt32 i = 0; i < 8; ++i)
{
uInt32 idx = BSPF::stringToInt(events[i]);
@ -1543,7 +1842,7 @@ int EventHandler::getActionListIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const
{
int index = getActionListIndex(idx, group);
const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@ -1564,7 +1863,7 @@ Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::actionAtIndex(int idx, Event::Group group) const
{
int index = getActionListIndex(idx, group);
const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@ -1585,7 +1884,7 @@ string EventHandler::actionAtIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::keyAtIndex(int idx, Event::Group group) const
{
int index = getActionListIndex(idx, group);
const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@ -1796,8 +2095,8 @@ void EventHandler::setState(EventHandlerState state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::exitEmulation(bool checkLauncher)
{
string saveOnExit = myOSystem.settings().getString("saveonexit");
bool activeTM = myOSystem.settings().getBool(
const string saveOnExit = myOSystem.settings().getString("saveonexit");
const bool activeTM = myOSystem.settings().getBool(
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
@ -1923,32 +2222,45 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::OverscanIncrease, "Increase overscan in fullscreen mode", "" },
{ Event::VidmodeDecrease, "Previous zoom level", "" },
{ Event::VidmodeIncrease, "Next zoom level", "" },
{ Event::ScanlineAdjustDecrease, "Decrease vertical display size", "" },
{ Event::ScanlineAdjustIncrease, "Increase vertical display size", "" },
{ Event::VSizeAdjustDecrease, "Decrease vertical display size", "" },
{ Event::VSizeAdjustIncrease, "Increase vertical display size", "" },
{ Event::VCenterDecrease, "Move display up", "" },
{ Event::VCenterIncrease, "Move display down", "" },
{ Event::FormatDecrease, "Decrease display format", "" },
{ Event::FormatIncrease, "Increase display format", "" },
{ Event::TogglePalette, "Switch palette (Std./Z26/User/Cust.)", "" },
{ Event::ColorShiftDecrease, "Decrease custom palette phase shift", "" },
{ Event::ColorShiftIncrease, "Increase custom palette phase shift", "" },
// Palette settings
{ Event::PaletteDecrease, "Switch to previous palette", "" },
{ Event::PaletteIncrease, "Switch to next palette", "" },
{ Event::PreviousPaletteAttribute,"Select previous palette attribute", "" },
{ Event::NextPaletteAttribute, "Select next palette attribute", "" },
{ Event::PaletteAttributeDecrease,"Decrease selected palette attribute", "" },
{ Event::PaletteAttributeIncrease,"Increase selected palette attribute", "" },
{ Event::ToggleInter, "Toggle display interpolation", "" },
// TV effects:
// Blargg TV effects:
{ Event::VidmodeStd, "Disable TV effects", "" },
{ Event::VidmodeRGB, "Select 'RGB' preset", "" },
{ Event::VidmodeSVideo, "Select 'S-Video' preset", "" },
{ Event::VidModeComposite, "Select 'Composite' preset", "" },
{ Event::VidModeBad, "Select 'Badly adjusted' preset", "" },
{ Event::VidModeCustom, "Select 'Custom' preset", "" },
{ Event::PreviousVideoMode, "Select previous TV effect mode preset", "" },
{ Event::NextVideoMode, "Select next TV effect mode preset", "" },
{ Event::PreviousAttribute, "Select previous 'Custom' attribute", "" },
{ Event::NextAttribute, "Select next 'Custom' attribute", "" },
{ Event::DecreaseAttribute, "Decrease selected 'Custom' attribute", "" },
{ Event::IncreaseAttribute, "Increase selected 'Custom' attribute", "" },
// Other TV effects
{ Event::TogglePhosphor, "Toggle 'phosphor' effect", "" },
{ Event::PhosphorDecrease, "Decrease 'phosphor' blend", "" },
{ Event::PhosphorIncrease, "Increase 'phosphor' blend", "" },
{ Event::ScanlinesDecrease, "Decrease scanlines", "" },
{ Event::ScanlinesIncrease, "Increase scanlines", "" },
{ Event::PreviousSetting, "Select previous setting", "" },
{ Event::NextSetting, "Select next setting", "" },
{ Event::SettingDecrease, "Decrease current setting", "" },
{ Event::SettingIncrease, "Increase current setting", "" },
// Developer keys:
{ Event::ToggleFrameStats, "Toggle frame stats", "" },
{ Event::ToggleP0Bit, "Toggle TIA Player0 object", "" },
@ -2050,16 +2362,21 @@ const Event::EventSet EventHandler::AudioVideoEvents = {
Event::VolumeDecrease, Event::VolumeIncrease, Event::SoundToggle,
Event::VidmodeDecrease, Event::VidmodeIncrease,
Event::ToggleFullScreen,
Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom,
Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute,
Event::ScanlinesDecrease, Event::ScanlinesIncrease,
Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor,
Event::OverscanDecrease, Event::OverscanIncrease,
Event::FormatDecrease, Event::FormatIncrease,
Event::VCenterDecrease, Event::VCenterIncrease,
Event::ScanlineAdjustDecrease, Event::ScanlineAdjustIncrease,
Event::OverscanDecrease, Event::OverscanIncrease,
Event::TogglePalette, Event::ColorShiftDecrease, Event::ColorShiftIncrease,
Event::ToggleInter
Event::VSizeAdjustDecrease, Event::VSizeAdjustIncrease,
Event::PaletteDecrease, Event::PaletteIncrease,
Event::PreviousPaletteAttribute, Event::NextPaletteAttribute,
Event::PaletteAttributeDecrease, Event::PaletteAttributeIncrease,
Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom,
Event::PreviousVideoMode, Event::NextVideoMode,
Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute,
Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor,
Event::ScanlinesDecrease, Event::ScanlinesIncrease,
Event::ToggleInter,
Event::PreviousSetting, Event::NextSetting,
Event::SettingDecrease, Event::SettingIncrease,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -25,6 +25,7 @@ class OSystem;
class MouseControl;
class DialogContainer;
class PhysicalJoystick;
class Variant;
namespace GUI {
class Font;
@ -36,7 +37,6 @@ namespace GUI {
#include "StellaKeys.hxx"
#include "PKeyboardHandler.hxx"
#include "PJoystickHandler.hxx"
#include "Variant.hxx"
#include "bspf.hxx"
/**
@ -391,6 +391,43 @@ class EventHandler
*/
void removePhysicalJoystick(int index);
private:
enum class AdjustSetting
{
NONE = -1,
VOLUME,
ZOOM,
FULLSCREEN,
OVERSCAN,
TVFORMAT,
VCENTER,
VSIZE,
// Palette adjustables
PALETTE,
PALETTE_PHASE,
PALETTE_HUE,
PALETTE_SATURATION,
PALETTE_CONTRAST,
PALETTE_BRIGHTNESS,
PALETTE_GAMMA,
// NTSC filter adjustables
NTSC_PRESET,
NTSC_SHARPNESS,
NTSC_RESOLUTION,
NTSC_ARTIFACTS,
NTSC_FRINGING,
NTSC_BLEEDING,
PHOSPHOR,
SCANLINES,
INTERPOLATION,
MAX_ADJ = INTERPOLATION,
// Only used via direct hotkeys
STATE,
PALETTE_CHANGE_ATTRIBUTE,
NTSC_CHANGE_ATTRIBUTE,
NUM_ADJ
};
private:
// Define event groups
static const Event::EventSet MiscEvents;
@ -417,6 +454,11 @@ class EventHandler
int getEmulActionListIndex(int idx, const Event::EventSet& events) const;
int getActionListIndex(int idx, Event::Group group) const;
// The following two methods are used for adjusting several settings using global hotkeys
// They return the function used to adjust the currenly selected setting
AdjustFunction cycleAdjustSetting(int direction);
AdjustFunction getAdjustSetting(AdjustSetting setting);
private:
// Structure used for action menu items
struct ActionList {
@ -425,6 +467,13 @@ class EventHandler
string key;
};
// ID of the currently selected global setting
AdjustSetting myAdjustSetting{AdjustSetting::VOLUME};
// If true, the setting is visible and its value can be changed
bool myAdjustActive{false};
// ID of the currently selected direct hotkey setting (0 if none)
AdjustSetting myAdjustDirect{AdjustSetting::NONE};
// Global Event object
Event myEvent;
@ -468,7 +517,7 @@ class EventHandler
#else
PNG_SIZE = 0,
#endif
EMUL_ACTIONLIST_SIZE = 149 + PNG_SIZE + COMBO_SIZE,
EMUL_ACTIONLIST_SIZE = 156 + PNG_SIZE + COMBO_SIZE,
MENU_ACTIONLIST_SIZE = 18
;

View File

@ -171,10 +171,9 @@ void FrameBuffer::setupFonts()
// However, we have to make sure all Dialogs are sized using the fontsize.
int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height;
int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth;
myTIAMinZoom = std::max(zoom_w, zoom_h) / 4.F; // round to 25% steps
myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F); // round to 25% steps, >= 200%
}
// The font used by the ROM launcher
const string& lf = myOSystem.settings().getString("launcherfont");
@ -310,7 +309,12 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
}
if(!myMsg.surface)
myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight() * 1.5);
{
const int fontWidth = font().getMaxCharWidth(),
HBORDER = fontWidth * 1.25 / 2.0;
myMsg.surface = allocateSurface(fontWidth * MESSAGE_WIDTH + HBORDER * 2,
font().getFontHeight() * 1.5);
}
#endif
// Print initial usage message, but only print it later if the status has changed
@ -501,19 +505,72 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
// Precompute the message coordinates
myMsg.text = message;
myMsg.counter = uInt32(myOSystem.frameRate()) << 1; // Show message for 2 seconds
if(myMsg.counter == 0) myMsg.counter = 60;
myMsg.color = kBtnTextColor;
myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds
if(myMsg.counter == 0)
myMsg.counter = 120;
myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
myMsg.h = fontHeight + VBORDER * 2;
// Precompute the message coordinates
myMsg.text = message;
myMsg.color = kBtnTextColor;
myMsg.showGauge = false;
myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
myMsg.h = fontHeight + VBORDER * 2;
myMsg.position = position;
myMsg.enabled = true;
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
myMsg.position = position;
myMsg.enabled = true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showMessage(const string& message, const string& valueText,
float value, float minValue, float maxValue)
{
#ifdef GUI_SUPPORT
// Only show messages if they've been enabled
if(myMsg.surface == nullptr || !myOSystem.settings().getBool("uimessages"))
return;
const int fontWidth = font().getMaxCharWidth(),
fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds
if(myMsg.counter == 0)
myMsg.counter = 120;
// Precompute the message coordinates
myMsg.text = message;
myMsg.color = kBtnTextColor;
myMsg.showGauge = true;
if(maxValue - minValue != 0)
myMsg.value = (value - minValue) / (maxValue - minValue) * 100.F;
else
myMsg.value = 100.F;
myMsg.valueText = valueText;
myMsg.w = std::min(fontWidth * MESSAGE_WIDTH,
font().getStringWidth(myMsg.text)
+ fontWidth * (GAUGEBAR_WIDTH + 2)
+ font().getStringWidth(myMsg.valueText))
+ HBORDER * 2;
myMsg.h = fontHeight + VBORDER * 2;
myMsg.position = MessagePosition::BottomCenter;
myMsg.enabled = true;
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::messageShown()
{
#ifdef GUI_SUPPORT
return myMsg.enabled;
#else
return false;
#endif
}
@ -632,6 +689,7 @@ inline bool FrameBuffer::drawMessage()
fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
constexpr int BORDER = 1;
switch(myMsg.position)
{
@ -682,10 +740,44 @@ inline bool FrameBuffer::drawMessage()
}
myMsg.surface->setDstPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y());
myMsg.surface->fillRect(1, 1, myMsg.w - 2, myMsg.h - 2, kBtnColor);
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
myMsg.surface->fillRect(0, 0, myMsg.w, myMsg.h, kColor);
myMsg.surface->fillRect(BORDER, BORDER, myMsg.w - BORDER * 2, myMsg.h - BORDER * 2, kBtnColor);
myMsg.surface->drawString(font(), myMsg.text, HBORDER, VBORDER,
myMsg.w, myMsg.color);
if(myMsg.showGauge)
{
constexpr int NUM_TICKMARKS = 4;
// limit gauge bar width if texts are too long
const int swidth = std::min(fontWidth * GAUGEBAR_WIDTH,
fontWidth * (MESSAGE_WIDTH - 2)
- font().getStringWidth(myMsg.text)
- font().getStringWidth(myMsg.valueText));
const int bwidth = swidth * myMsg.value / 100.F;
const int bheight = fontHeight >> 1;
const int x = HBORDER + font().getStringWidth(myMsg.text) + fontWidth;
// align bar with bottom of text
const int y = VBORDER + font().desc().ascent - bheight;
// draw gauge bar
myMsg.surface->fillRect(x - BORDER, y, swidth + BORDER * 2, bheight, kSliderBGColor);
myMsg.surface->fillRect(x, y + BORDER, bwidth, bheight - BORDER * 2, kSliderColor);
// draw tickmark in the middle of the bar
for(int i = 1; i < NUM_TICKMARKS; ++i)
{
ColorId color;
int xt = x + swidth * i / NUM_TICKMARKS;
if(bwidth < xt - x)
color = kCheckColor; // kSliderColor;
else
color = kSliderBGColor;
myMsg.surface->vLine(xt, y + bheight / 2, y + bheight - 1, color);
}
// draw value text
myMsg.surface->drawString(font(), myMsg.valueText,
x + swidth + fontWidth, VBORDER,
myMsg.w, myMsg.color);
}
myMsg.surface->render();
myMsg.counter--;
#endif
@ -895,9 +987,13 @@ void FrameBuffer::setFullscreen(bool enable)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFullscreen()
void FrameBuffer::toggleFullscreen(bool toggle)
{
setFullscreen(!fullScreen());
const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
setFullscreen(isFullscreen);
showMessage(string("Fullscreen ") + (isFullscreen ? "enabled" : "disabled"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -915,14 +1011,18 @@ void FrameBuffer::changeOverscan(int direction)
// issue a complete framebuffer re-initialization
myOSystem.createFrameBuffer();
}
ostringstream msg;
msg << "Overscan at " << overscan << "%";
showMessage(msg.str());
ostringstream val;
if(overscan)
val << (overscan > 0 ? "+" : "" ) << overscan << "%";
else
val << "Off";
myOSystem.frameBuffer().showMessage("Overscan", val.str(), overscan, 0, 10);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::changeVidMode(int direction)
void FrameBuffer::selectVidMode(int direction)
{
EventHandlerState state = myOSystem.eventHandler().state();
bool tiaMode = (state != EventHandlerState::DEBUGGER &&
@ -930,14 +1030,14 @@ bool FrameBuffer::changeVidMode(int direction)
// Only applicable when in TIA/emulation mode
if(!tiaMode)
return false;
return;
if(direction == +1)
myCurrentModeList->next();
else if(direction == -1)
myCurrentModeList->previous();
else
return false;
saveCurrentWindowPosition();
// Changing the video mode can take some time, during which the last
// sound played may get 'stuck'
@ -955,7 +1055,10 @@ bool FrameBuffer::changeVidMode(int direction)
myTIASurface->initialize(myOSystem.console(), mode);
resetSurfaces();
showMessage(mode.description);
if(fullScreen())
showMessage(mode.description);
else
showMessage("Zoom", mode.description, mode.zoom, supportedTIAMinZoom(), myTIAMaxZoom);
myOSystem.sound().mute(oldMuteState);
if(fullScreen())
@ -964,11 +1067,9 @@ bool FrameBuffer::changeVidMode(int direction)
else
myOSystem.settings().setValue("tia.zoom", mode.zoom);
return true;
return;
}
myOSystem.sound().mute(oldMuteState);
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1023,9 +1124,14 @@ void FrameBuffer::enableGrabMouse(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleGrabMouse()
{
const bool oldState = myGrabMouse;
myGrabMouse = !myGrabMouse;
setCursorState();
myOSystem.settings().setValue("grabmouse", myGrabMouse);
myOSystem.frameBuffer().showMessage(oldState != myGrabMouse ? myGrabMouse
? "Grab mouse enabled" : "Grab mouse disabled"
: "Grab mouse not allowed while cursor shown");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1076,7 +1182,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
for(float zoom = minZoom; zoom <= myTIAMaxZoom; zoom += ZOOM_STEPS)
{
ostringstream desc;
desc << "Zoom " << zoom << "x";
desc << (zoom * 100) << "%";
VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom,
VideoMode::Stretch::Fill, 1.0, desc.str(), zoom);
@ -1096,12 +1202,12 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
VideoMode mode1(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
VideoMode::Stretch::Preserve, overscan,
"Preserve aspect, no stretch", myTIAMaxZoom, i);
"Fullscreen: Preserve aspect, no stretch", myTIAMaxZoom, i);
myFullscreenModeLists[i].add(mode1);
VideoMode mode2(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
VideoMode::Stretch::Fill, overscan,
"Ignore aspect, full stretch", myTIAMaxZoom, i);
"Fullscreen: Ignore aspect, full stretch", myTIAMaxZoom, i);
myFullscreenModeLists[i].add(mode2);
}
}

View File

@ -147,6 +147,19 @@ class FrameBuffer
void showMessage(const string& message,
MessagePosition position = MessagePosition::BottomCenter,
bool force = false);
/**
Shows a message with a gauge bar onscreen.
@param message The message to be shown
@param valueText The value of the gauge bar as text
@param value The gauge bar percentage
@param minValue The minimal value of the gauge bar
@param maxValue The maximal value of the gauge bar
*/
void showMessage(const string& message, const string& valueText,
float value, float minValue = 0.F, float maxValue = 100.F);
bool messageShown();
/**
Toggles showing or hiding framerate statistics.
@ -247,14 +260,14 @@ class FrameBuffer
/**
Toggles between fullscreen and window mode.
*/
void toggleFullscreen();
void toggleFullscreen(bool toggle = true);
/**
Changes the fullscreen overscan.
direction = -1 means less overscan
direction = +1 means more overscan
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeOverscan(int direction);
void changeOverscan(int direction = +1);
/**
This method is called when the user wants to switch to the next
@ -264,9 +277,9 @@ class FrameBuffer
direction = -1 means go to the next lower video mode
direction = +1 means go to the next higher video mode
@param direction Described above
@param direction +1 indicates increase, -1 indicates decrease.
*/
bool changeVidMode(int direction);
void selectVidMode(int direction = +1);
/**
Sets the state of the cursor (hidden or grabbed) based on the
@ -502,6 +515,11 @@ class FrameBuffer
OSystem& myOSystem;
private:
// Maximum message width [chars]
static constexpr int MESSAGE_WIDTH = 56;
// Maximum gauge bar width [chars]
static constexpr int GAUGEBAR_WIDTH = 30;
/**
Draw pending messages.
@ -648,6 +666,9 @@ class FrameBuffer
ColorId color{kNone};
shared_ptr<FBSurface> surface;
bool enabled{false};
bool showGauge{false};
float value{0.0F};
string valueText;
};
Message myMsg;
Message myStatsMsg;

View File

@ -19,8 +19,8 @@
#define JOYSTICK_HXX
#include "bspf.hxx"
#include "Control.hxx"
#include "Event.hxx"
#include "Control.hxx"
/**
The standard Atari 2600 joystick controller.

View File

@ -19,8 +19,8 @@
#define KEYBOARD_HXX
#include "bspf.hxx"
#include "Control.hxx"
#include "Event.hxx"
#include "Control.hxx"
/**
The standard Atari 2600 keyboard controller

View File

@ -18,6 +18,11 @@
#ifndef LIGHTGUN_HXX
#define LIGHTGUN_HXX
class FrameBuffer;
#include "bspf.hxx"
#include "Control.hxx"
/**
This class handles the lightgun controller

View File

@ -49,6 +49,7 @@
#include "CartDetector.hxx"
#include "FrameBuffer.hxx"
#include "TIASurface.hxx"
#include "PaletteHandler.hxx"
#include "TIAConstants.hxx"
#include "Settings.hxx"
#include "PropsSet.hxx"
@ -243,6 +244,8 @@ void OSystem::saveConfig()
Logger::debug("Saving TV effects options ...");
myFrameBuffer->tiaSurface().ntsc().saveConfig(settings());
Logger::debug("Saving palette settings...");
myFrameBuffer->tiaSurface().paletteHandler().saveConfig(settings());
}
Logger::debug("Saving config options ...");
@ -645,35 +648,8 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size
if(md5 == "")
md5 = MD5::hash(image, size);
// Handle ROM properties, do some error checking
// Only add to the database when necessary
bool toInsert = false;
// First, does this ROM have a per-ROM properties entry?
// If so, load it into the database
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
if(propsNode.exists() && propsNode.isFile())
{
Logger::info("Loading per-ROM properties: " + propsNode.getShortPath());
myPropSet->load(propsNode.getPath(), false);
}
// Next, make sure we have a valid md5 and name
Properties props;
if(!myPropSet->getMD5(md5, props))
{
props.set(PropType::Cart_MD5, md5);
toInsert = true;
}
if(toInsert || props.get(PropType::Cart_Name) == EmptyString)
{
props.set(PropType::Cart_Name, rom.getNameWithExt(""));
toInsert = true;
}
// Finally, insert properties if any info was missing
if(toInsert)
myPropSet->insert(props, false);
// Make sure to load a per-ROM properties entry, if one exists
myPropSet->loadPerROM(rom, md5);
return image;
}

View File

@ -41,7 +41,7 @@ class AudioSettings;
class Menu;
class MessageMenu;
class TimeMachine;
class VideoDialog;
class VideoAudioDialog;
#endif
#ifdef PNG_SUPPORT
class PNGLibrary;

View File

@ -15,6 +15,8 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include <cmath>
#include "Control.hxx"
#include "Event.hxx"
#include "System.hxx"

View File

@ -18,7 +18,6 @@
#ifndef POINTING_DEVICE_HXX
#define POINTING_DEVICE_HXX
class Controller;
class Event;
#include "Control.hxx"

View File

@ -54,7 +54,6 @@ namespace {
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProfilingRunner::ProfilingRunner(int argc, char* argv[])
: profilingRuns(std::max(argc - 2, 0))

View File

@ -18,10 +18,9 @@
#ifndef PROFILING_RUNNER
#define PROFILING_RUNNER
class Control;
class Switches;
#include "bspf.hxx"
#include "Control.hxx"
#include "Switches.hxx"
#include "Settings.hxx"
#include "ConsoleIO.hxx"
#include "Props.hxx"
@ -41,13 +40,13 @@ class ProfilingRunner {
};
struct IO: public ConsoleIO {
Controller& leftController() const override { return *myLeftControl; }
Controller& rightController() const override { return *myRightControl; }
Switches& switches() const override { return *mySwitches; }
Controller& leftController() const override { return *myLeftControl; }
Controller& rightController() const override { return *myRightControl; }
Switches& switches() const override { return *mySwitches; }
unique_ptr<Controller> myLeftControl;
unique_ptr<Controller> myRightControl;
unique_ptr<Switches> mySwitches;
unique_ptr<Controller> myLeftControl;
unique_ptr<Controller> myRightControl;
unique_ptr<Switches> mySwitches;
};
private:

View File

@ -156,6 +156,37 @@ void PropertiesSet::insert(const Properties& properties, bool save)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5)
{
// Handle ROM properties, do some error checking
// Only add to the database when necessary
bool toInsert = false;
// First, does this ROM have a per-ROM properties entry?
// If so, load it into the database
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
if(propsNode.exists() && propsNode.isFile())
load(propsNode.getPath(), false);
// Next, make sure we have a valid md5 and name
Properties props;
if(!getMD5(md5, props))
{
props.set(PropType::Cart_MD5, md5);
toInsert = true;
}
if(toInsert || props.get(PropType::Cart_Name) == EmptyString)
{
props.set(PropType::Cart_Name, rom.getNameWithExt(""));
toInsert = true;
}
// Finally, insert properties if any info was missing
if(toInsert)
insert(props, false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::print() const
{

View File

@ -42,7 +42,7 @@ class PropertiesSet
/**
Trivial constructor.
*/
PropertiesSet() = default;
PropertiesSet() = default;
/**
Load properties from the specified file, and create an internal
@ -90,6 +90,21 @@ class PropertiesSet
*/
void insert(const Properties& properties, bool save = true);
/**
Load properties for a specific ROM from a per-ROM properties file,
if it exists. In any event, also do some error checking, like making
sure that the properties have a valid name, etc.
NOTE: This method is meant to be called only when starting Stella
and loading a ROM for the first time. Currently, that means
only from the ROM launcher or when actually opening the ROM.
*** FOR ALL OTHER CASES, USE getMD5() ***
@param rom The node representing the rom file
@param md5 The md5 of the property to get
*/
void loadPerROM(const FilesystemNode& rom, const string& md5);
/**
Prints the contents of the PropertiesSet as a flat file.
*/

View File

@ -21,6 +21,7 @@
#include "Version.hxx"
#include "Logger.hxx"
#include "AudioSettings.hxx"
#include "PaletteHandler.hxx"
#include "Paddles.hxx"
#ifdef DEBUGGER_SUPPORT
@ -45,31 +46,30 @@ Settings::Settings()
setPermanent("center", "true");
setPermanent("windowedpos", Common::Point(50, 50));
setPermanent("display", 0);
setPermanent("palette", "standard");
setPermanent("phase_ntsc", "26.2");
setPermanent("phase_pal", "31.3");
setPermanent("uimessages", "true");
// TIA specific options
setPermanent("tia.zoom", "3");
setPermanent("tia.inter", "false");
setPermanent("tia.vsizeadjust", 0);
setPermanent("tia.zoom", "3");
setPermanent("fullscreen", "false");
setPermanent("tia.fs_stretch", "false");
setPermanent("tia.fs_overscan", "0");
setPermanent("tia.vsizeadjust", 0);
setPermanent("tia.dbgcolors", "roygpb");
// Palette options
setPermanent("palette", PaletteHandler::SETTING_STANDARD);
setPermanent("pal.phase_ntsc", "26.2");
setPermanent("pal.phase_pal", "31.3");
setPermanent("pal.contrast", "0.0");
setPermanent("pal.brightness", "0.0");
setPermanent("pal.hue", "0.0");
setPermanent("pal.saturation", "0.0");
setPermanent("pal.gamma", "0.0");
// TV filtering options
setPermanent("tv.filter", "0");
setPermanent("tv.phosphor", "byrom");
setPermanent("tv.phosblend", "50");
setPermanent("tv.scanlines", "25");
// TV options when using 'custom' mode
setPermanent("tv.contrast", "0.0");
setPermanent("tv.brightness", "0.0");
setPermanent("tv.hue", "0.0");
setPermanent("tv.saturation", "0.0");
setPermanent("tv.gamma", "0.0");
setPermanent("tv.sharpness", "0.0");
setPermanent("tv.resolution", "0.0");
setPermanent("tv.artifacts", "0.0");
@ -358,8 +358,11 @@ void Settings::validate()
else if(i > 10) setValue("ssinterval", "10");
s = getString("palette");
if(s != "standard" && s != "z26" && s != "user" && s != "custom")
setValue("palette", "standard");
if(s != PaletteHandler::SETTING_STANDARD
&& s != PaletteHandler::SETTING_Z26
&& s != PaletteHandler::SETTING_USER
&& s != PaletteHandler::SETTING_CUSTOM)
setValue("palette", PaletteHandler::SETTING_STANDARD);
s = getString("launcherfont");
if(s != "small" && s != "low_medium" && s != "medium" && s != "large"
@ -407,8 +410,13 @@ void Settings::usage() const
<< " -palette <standard| Use the specified color palette\n"
<< " z26|user|\n"
<< " custom>\n"
<< " -phase_ntsc <number> Phase shift for NTSC custom color palette\n"
<< " -phase_pal <number> Phase shift for PAL custom color palette\n"
<< " -pal.phase_ntsc <number> Phase shift for NTSC 'custom' palette\n"
<< " -pal.phase_pal <number> Phase shift for PAL 'custom' palette\n"
<< " -pal.hue <-1.0 - 1.0> Adjust hue for current palette\n"
<< " -pal.saturation <-1.0 - 1.0> Adjust saturation of current palette\n"
<< " -pal.contrast <-1.0 - 1.0> Adjust contrast of current palette\n"
<< " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n"
<< " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n"
<< " -speed <number> Run emulation at the given speed\n"
<< " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
@ -443,11 +451,6 @@ void Settings::usage() const
<< " -tv.phosblend <0-100> Set default blend level in phosphor mode\n"
<< " -tv.scanlines <0-100> Set scanline intensity to percentage\n"
<< " (0 disables completely)\n"
<< " -tv.contrast <-1.0 - 1.0> Set TV effects custom contrast\n"
<< " -tv.brightness <-1.0 - 1.0> Set TV effects custom brightness\n"
<< " -tv.hue <-1.0 - 1.0> Set TV effects custom hue\n"
<< " -tv.saturation <-1.0 - 1.0> Set TV effects custom saturation\n"
<< " -tv.gamma <-1.0 - 1.0> Set TV effects custom gamma\n"
<< " -tv.sharpness <-1.0 - 1.0> Set TV effects custom sharpness\n"
<< " -tv.resolution <-1.0 - 1.0> Set TV effects custom resolution\n"
<< " -tv.artifacts <-1.0 - 1.0> Set TV effects custom artifacts\n"

View File

@ -88,10 +88,9 @@ class Sound
/**
Adjusts the volume of the sound device based on the given direction.
@param direction Increase or decrease the current volume by a predefined
amount based on the direction (1 = increase, -1 =decrease)
@param direction +1 indicates increase, -1 indicates decrease.
*/
virtual void adjustVolume(Int8 direction) = 0;
virtual void adjustVolume(int direction = 1) = 0;
/**
This method is called to provide information about the sound device.

View File

@ -22,8 +22,8 @@ class Event;
class Properties;
class Settings;
#include "Serializable.hxx"
#include "bspf.hxx"
#include "Serializable.hxx"
/**
This class represents the console switches of the game console.

View File

@ -18,11 +18,10 @@
#ifndef SYSTEM_HXX
#define SYSTEM_HXX
class Device;
class M6502;
class M6532;
class TIA;
class NullDevice;
class Cartridge;
#include "bspf.hxx"
#include "Device.hxx"

View File

@ -23,6 +23,7 @@
#include "Console.hxx"
#include "TIA.hxx"
#include "PNGLibrary.hxx"
#include "PaletteHandler.hxx"
#include "TIASurface.hxx"
namespace {
@ -76,6 +77,14 @@ TIASurface::TIASurface(OSystem& system)
// Enable/disable threading in the NTSC TV effects renderer
myNTSCFilter.enableThreading(myOSystem.settings().getBool("threads"));
myPaletteHandler = make_unique<PaletteHandler>(myOSystem);
myPaletteHandler->loadConfig(myOSystem.settings());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TIASurface::~TIASurface()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -89,6 +98,8 @@ void TIASurface::initialize(const Console& console,
mySLineSurface->setDstPos(mode.image.x(), mode.image.y());
mySLineSurface->setDstSize(mode.image.w(), mode.image.h());
myPaletteHandler->setPalette();
// Phosphor mode can be enabled either globally or per-ROM
int p_blend = 0;
bool enable = false;
@ -189,37 +200,87 @@ void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::setScanlineIntensity(int amount)
void TIASurface::changeNTSC(int direction)
{
ostringstream buf;
uInt32 intensity = enableScanlines(amount);
constexpr NTSCFilter::Preset PRESETS[] = {
NTSCFilter::Preset::OFF, NTSCFilter::Preset::RGB, NTSCFilter::Preset::SVIDEO,
NTSCFilter::Preset::COMPOSITE, NTSCFilter::Preset::BAD, NTSCFilter::Preset::CUSTOM
};
int preset = myOSystem.settings().getInt("tv.filter");
if(intensity == 0)
buf << "Scanlines disabled";
else
if(direction == +1)
{
buf << "Scanline intensity at ";
if(intensity < 100)
buf << intensity << "%";
if(preset == int(NTSCFilter::Preset::CUSTOM))
preset = int(NTSCFilter::Preset::OFF);
else
buf << "maximum";
preset++;
}
myOSystem.settings().setValue("tv.scanlines", intensity);
enableNTSC(ntscEnabled());
myFB.showMessage(buf.str());
else if (direction == -1)
{
if(preset == int(NTSCFilter::Preset::OFF))
preset = int(NTSCFilter::Preset::CUSTOM);
else
preset--;
}
setNTSC(PRESETS[preset], true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::enableScanlines(int relative, int absolute)
void TIASurface::setNTSCAdjustable(int direction)
{
string text, valueText;
Int32 value;
setNTSC(NTSCFilter::Preset::CUSTOM);
ntsc().selectAdjustable(direction, text, valueText, value);
myOSystem.frameBuffer().showMessage(text, valueText, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::changeNTSCAdjustable(int adjustable, int direction)
{
string text, valueText;
Int32 newValue;
setNTSC(NTSCFilter::Preset::CUSTOM);
ntsc().changeAdjustable(adjustable, direction, text, valueText, newValue);
myOSystem.frameBuffer().showMessage(text, valueText, newValue);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::changeCurrentNTSCAdjustable(int direction)
{
string text, valueText;
Int32 newValue;
setNTSC(NTSCFilter::Preset::CUSTOM);
ntsc().changeCurrentAdjustable(direction, text, valueText, newValue);
myOSystem.frameBuffer().showMessage(text, valueText, newValue);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::setScanlineIntensity(int direction)
{
ostringstream buf;
uInt32 intensity = enableScanlines(direction * 2);
myOSystem.settings().setValue("tv.scanlines", intensity);
enableNTSC(ntscEnabled());
if(intensity)
buf << intensity << "%";
else
buf << "Off";
myFB.showMessage("Scanline intensity", buf.str(), intensity);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::enableScanlines(int change)
{
FBSurface::Attributes& attr = mySLineSurface->attributes();
if(relative == 0) attr.blendalpha = absolute;
else attr.blendalpha += relative;
attr.blendalpha = std::max(0, Int32(attr.blendalpha));
attr.blendalpha = std::min(100U, attr.blendalpha);
attr.blendalpha += change;
attr.blendalpha = BSPF::clamp(Int32(attr.blendalpha), 0, 100);
mySLineSurface->applyAttributes();
return attr.blendalpha;

View File

@ -22,6 +22,7 @@ class TIA;
class Console;
class OSystem;
class FBSurface;
class PaletteHandler;
#include <thread>
@ -48,6 +49,7 @@ class TIASurface
Creates a new TIASurface object
*/
explicit TIASurface(OSystem& system);
virtual ~TIASurface();
/**
Set the TIA object, which is needed for actually rendering the TIA image.
@ -88,19 +90,53 @@ class TIASurface
void setNTSC(NTSCFilter::Preset preset, bool show = true);
/**
Increase/decrease current scanline intensity by given relative amount.
Switch to next/previous NTSC filtering effect.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void setScanlineIntensity(int relative);
void changeNTSC(int direction = +1);
/**
Switch to next/previous NTSC filtering adjustable.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void setNTSCAdjustable(int direction = +1);
/**
Increase/decrease given NTSC filtering adjustable.
@param adjustable The adjustable to change
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeNTSCAdjustable(int adjustable, int direction);
/**
Increase/decrease current NTSC filtering adjustable.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void changeCurrentNTSCAdjustable(int direction = +1);
/**
Retrieve palette handler.
*/
PaletteHandler& paletteHandler() const { return *myPaletteHandler; }
/**
Increase/decrease current scanline intensity by given relative amount.
@param direction +1 indicates increase, -1 indicates decrease.
*/
void setScanlineIntensity(int direction = +1);
/**
Change scanline intensity and interpolation.
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@param change change current intensity by 'change'
@return New current intensity
*/
uInt32 enableScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
uInt32 enableScanlines(int change);
/**
Enable/disable/query phosphor effect.
@ -183,6 +219,9 @@ class TIASurface
// Flag for saving a snapshot
bool mySaveSnapFlag{false};
// The palette handler
unique_ptr<PaletteHandler>myPaletteHandler;
private:
// Following constructors and assignment operators not supported
TIASurface() = delete;

View File

@ -108,6 +108,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
case ConsoleTiming::ntsc: timing_factor = NTSC; break;
case ConsoleTiming::secam: timing_factor = SECAM; break;
case ConsoleTiming::pal: timing_factor = PAL; break;
default: break; // satisfy compiler
}
}

View File

@ -18,12 +18,12 @@
#ifndef TIA_AUDIO_HXX
#define TIA_AUDIO_HXX
class AudioQueue;
#include "bspf.hxx"
#include "AudioChannel.hxx"
#include "Serializable.hxx"
class AudioQueue;
class Audio : public Serializable
{
public:

View File

@ -18,11 +18,11 @@
#ifndef TIA_BACKGROUND
#define TIA_BACKGROUND
class TIA;
#include "Serializable.hxx"
#include "bspf.hxx"
class TIA;
class Background : public Serializable
{
public:

Some files were not shown because too many files have changed in this diff Show More