diff --git a/Changes.txt b/Changes.txt index f0c1b4acc..557157f25 100644 --- a/Changes.txt +++ b/Changes.txt @@ -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! diff --git a/docs/debugger.html b/docs/debugger.html index 91e71bd47..423a20aa1 100644 --- a/docs/debugger.html +++ b/docs/debugger.html @@ -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) diff --git a/docs/graphics/eventmapping.png b/docs/graphics/eventmapping.png index 86deacd4a..f9b089b6d 100644 Binary files a/docs/graphics/eventmapping.png and b/docs/graphics/eventmapping.png differ diff --git a/docs/graphics/eventmapping_devsports.png b/docs/graphics/eventmapping_devsports.png index d66197a72..ab187595e 100644 Binary files a/docs/graphics/eventmapping_devsports.png and b/docs/graphics/eventmapping_devsports.png differ diff --git a/docs/graphics/eventmapping_mouse.png b/docs/graphics/eventmapping_mouse.png new file mode 100644 index 000000000..daac75b09 Binary files /dev/null and b/docs/graphics/eventmapping_mouse.png differ diff --git a/docs/graphics/eventmapping_remap.png b/docs/graphics/eventmapping_remap.png index a2e3ce949..34df62937 100644 Binary files a/docs/graphics/eventmapping_remap.png and b/docs/graphics/eventmapping_remap.png differ diff --git a/docs/graphics/options.png b/docs/graphics/options.png index db86da3fb..9f8a95430 100644 Binary files a/docs/graphics/options.png and b/docs/graphics/options.png differ diff --git a/docs/graphics/options_audio.png b/docs/graphics/options_audio.png index e77d69a5e..f37f07c6f 100644 Binary files a/docs/graphics/options_audio.png and b/docs/graphics/options_audio.png differ diff --git a/docs/graphics/options_developer_timemachine.png b/docs/graphics/options_developer_timemachine.png index ddb58f28e..498f83c0f 100644 Binary files a/docs/graphics/options_developer_timemachine.png and b/docs/graphics/options_developer_timemachine.png differ diff --git a/docs/graphics/options_emulation.png b/docs/graphics/options_emulation.png new file mode 100644 index 000000000..99a1dfa4d Binary files /dev/null and b/docs/graphics/options_emulation.png differ diff --git a/docs/graphics/options_gameinfo_controller.png b/docs/graphics/options_gameinfo_controller.png index 9b9413ab2..04cc025db 100644 Binary files a/docs/graphics/options_gameinfo_controller.png and b/docs/graphics/options_gameinfo_controller.png differ diff --git a/docs/graphics/options_misc.png b/docs/graphics/options_misc.png index b1930b45d..1faa756b5 100644 Binary files a/docs/graphics/options_misc.png and b/docs/graphics/options_misc.png differ diff --git a/docs/graphics/options_video.png b/docs/graphics/options_video.png index be67fe065..deb857ca4 100644 Binary files a/docs/graphics/options_video.png and b/docs/graphics/options_video.png differ diff --git a/docs/graphics/options_video_palettes.png b/docs/graphics/options_video_palettes.png new file mode 100644 index 000000000..dae0cf7ee Binary files /dev/null and b/docs/graphics/options_video_palettes.png differ diff --git a/docs/graphics/options_video_tv.png b/docs/graphics/options_video_tv.png index e76d32ba6..5ce3c3f2a 100644 Binary files a/docs/graphics/options_video_tv.png and b/docs/graphics/options_video_tv.png differ diff --git a/docs/index.html b/docs/index.html index 851aea9dc..3bf9ee26a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -19,7 +19,7 @@

A multi-platform Atari 2600 VCS emulator

-

Release 6.1

+

Release 6.2



User's Guide

@@ -70,7 +70,7 @@


-
February 1999 - March 2020
+
February 1999 - ??? 2020
The Stella Team
Stella Homepage
@@ -1336,7 +1336,150 @@ -

TV effects (can be remapped, only active in TIA mode)

+

Audio & Video Keys (can be remapped)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionKey (Standard)Key (macOS)
Toggle soundControl + ]Control + ]
Decrease volumeAlt + [Cmd + [
Increase volumeAlt + ]Cmd + ]
Switch to next larger zoom level in windowed mode, +
toggle stretching in fullscreen mode
Alt + =Cmd + =
Switch to next smaller zoom level in windowed mode, +
toggle stretching in fullscreen mode
Alt + -Cmd + -
Toggle windowed/fullscreen modeAlt + EnterCmd + Enter
Decrease overscan in fullscreen modeShift + PageDownShift-Fn + Down arrow
Increase overscan in fullscreen modeShift + PageUpShift-Fn + Up arrow
Move display down (uses "Display.VCenter")Alt + PageDownCmd-Fn + Down arrow
Move display up (uses "Display.VCenter")Alt + PageUpCmd-Fn + Up arrow
Decrease vertical display sizeShift-Alt + PageUpShift-Cmd-Fn + Up arrow
Increase vertical display sizeShift-Alt + PageDownShift-Cmd-Fn + Down arrow
Switch to previous display format (NTSC/PAL/SECAM etc.)Shift-Control + fShift-Control + f
Switch to next display format (NTSC/PAL/SECAM etc.)Control + fControl + f
Toggle display interpolationControl + iControl + i
+ These settings can also be changed using Global Audio & Video Keys
+
+ +

Palettes Keys (can be remapped)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionKey (Standard)Key (macOS)
Select previous palette (Standard/z26/User/Custom)Shift-Control + pShift-Control + p
Select next palette (Standard/z26/User/Custom)Control + pControl + p
Select previous palette attributeShift-Alt + 9Shift-Cmd + 9
Select next palette attributeAlt + 9Cmd + 9
Decrease selected palette attributeShift-Alt + 0Shift-Cmd + 0
Increase selected palette attributeAlt + 0Cmd + 0
+ These settings can also be changed using Global Audio & Video Keys
+
+ +

TV effects Keys (can be remapped)

@@ -1345,93 +1488,112 @@ - + + + + + + - + + + + + + - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + + + + + + + + + + + + - + These settings can also be changed using Global Audio & Video Keys + + + +
Key (macOS)
Disable TV effectsSelect previous TV effects presetShift-Alt + 1Shift-Cmd + 1
Select next TV effects preset Alt + 1 Cmd + 1
Select 'RGB' presetSelect previous 'Custom' mode attribute (*)Shift-Alt + 2Shift-Cmd + 2
Select next 'Custom' mode attribute (*) Alt + 2 Cmd + 2
Select 'S-Video' presetDecrease 'Custom' selected attribute value (*)Shift-Alt + 3Shift-Cmd + 3
Increase 'Custom' selected attribute value (*) Alt + 3 Cmd + 3
Select 'Composite' presetAlt + 4Cmd + 4
Select 'Badly adjusted' presetAlt + 5Cmd + 5
Select 'Custom' presetAlt + 6Cmd + 6
Select previous 'Custom' mode attribute (*)Shift-Alt + 7Shift-Cmd + 7
Select next 'Custom' mode attribute (*)Alt + 7Cmd + 7
Decrease 'Custom' selected attribute value (*)Shift-Alt + 8Shift-Cmd + 8
Increase 'Custom' selected attribute value (*)Alt + 8Cmd + 8
Toggle 'phosphor' mode Alt + p Cmd + p
Decrease 'phosphor' blendShift-Alt + 9Shift-Cmd + 9
Increase 'phosphor' blendAlt + 9Cmd + 9
Decrease scanline intensityShift-Alt + 0Shift-Cmd + 0Decrease 'phosphor' blendShift-Alt + 4Shift-Cmd + 4
Increase scanline intensityAlt + 0Cmd + 0Increase 'phosphor' blendAlt + 4Cmd + 4
Decrease scanline intensityShift-Alt + 5Shift-Cmd + 5
Increase scanline intensityAlt + 5Cmd + 5
- Items marked as (*) will also switch to 'Custom' preset mode
+ Items marked as (*) will also switch to 'Custom' mode
+

Global Audio & Video Keys (can be remapped)

+

These keys allow selecting and changing audio & video settings without having to remember the + dedicated keys.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionKey (Standard)Key (macOS)
Select previous AV settingEndFn + Left arrow
Select next AV settingHomeFn + Right arrow
Decrease current AV settingPageDownFn + Down arrow
Increase current AV setting + PageUpFn + Up arrow
+

Notes: +

+


+ -

Developer Keys in TIA mode (can be remapped)

+

Developer Keys (can be remapped)

@@ -1549,7 +1711,7 @@
-

Other Keys (can be remapped)

+

Other Emulation Keys (can be remapped)

@@ -1557,111 +1719,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1761,7 +1823,7 @@
Key (Standard) Key (macOS)
Switch to next larger zoom level in windowed mode, -
toggle stretching in fullscreen mode
Alt + =Cmd + =
Switch to next smaller zoom level in windowed mode, -
toggle stretching in fullscreen mode
Alt + -Cmd + -
Toggle fullscreen/windowed modeAlt + EnterCmd + Enter
Decrease overscan in fullscreen modeShift + PageDownShift + PageDown
Increase overscan in fullscreen modeShift + PageUpShift + PageUp
Move display up (uses "Display.VCenter")Alt + PageUpCmd + PageUp
Move display down (uses "Display.VCenter")Alt + PageDownCmd + PageDown
Switch display format in decreasing order (NTSC/PAL/SECAM etc.)Shift-Control + fShift-Control + f
Switch display format in increasing order (NTSC/PAL/SECAM etc.)Control + fControl + f
Switch palette (Standard/Z26/User/Custom)Control + pControl + p
Decrease custom palette phase shift (switches to 'Custom' palette)Shift-Control + 9Shift-Control + 9
Increase custom palette phase shift (switches to 'Custom' palette)Control + 9Control + 9
Toggle display interpolationControl + iControl + i
Toggle 'Turbo' mode Control + t Control + t
Toggle sound on/offControl + ]Control + ]
Decrease volumeAlt + [Cmd + [
Increase volumeAlt + ]Cmd + ]
Switch mouse between controller emulation modes
(see Game Properties - Controller)
Control + 0
-

UI keys in Text Editing areas (cannot be remapped)

+

UI Keys in Text Editing areas (cannot be remapped)

@@ -2008,11 +2070,11 @@ - + - + @@ -2029,13 +2091,38 @@ - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2152,36 +2239,6 @@ and 'Custom' modes. - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + @@ -2566,7 +2630,7 @@ - + @@ -2703,6 +2767,16 @@ + + + + + + + + + +
KeyEditor Function
-center <1|0>
Centers game window (if possible).Centers all windows (if possible).
-windowedpos <WxH>
-windowedpos <XxY>
Sets the window position in windowed emulator mode.
-phase_ntsc <number>
Set phase shift for custom NTSC palette.
-pal.phase_ntsc <number>
Adjust phase shift of 'custom' NTSC palette.
-phase_pal <number>
Set phase shift for custom PAL palette.
-pal.phase_pal <number>
Adjust phase shift of 'custom' PAL palette.
-pal.hue <number>
Adjust hue of current palette (range -1.0 to 1.0).
-pal.saturation <number>
Adjust saturation of current palette (range -1.0 to 1.0).
-pal.contrast <number>
Adjust contrast of current palette (range -1.0 to 1.0).
-pal.brightness <number>
Adjust brightness of current palette (range -1.0 to 1.0).
-pal.gamma <number>
Adjust gamma of current palette (range -1.0 to 1.0).
-tv.contrast <number>
Blargg TV effects 'contrast' (only available in custom mode, - range -1.0 to 1.0).
-tv.brightness <number>
Blargg TV effects 'brightness' (only available in custom mode, - range -1.0 to 1.0).
-tv.hue <number>
Blargg TV effects 'hue' (only available in custom mode, - range -1.0 to 1.0).
-tv.saturation <number>
Blargg TV effects 'saturation' (only available in custom mode, - range -1.0 to 1.0).
-tv.gamma <number>
Blargg TV effects 'gamma' (only available in custom mode, - range -1.0 to 1.0).
-tv.sharpness <number>
Blargg TV effects 'sharpness' (only available in custom mode, @@ -2319,6 +2376,13 @@ faster movement.
-dcsense <number>
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.
-saport <lr|rl>
Determines how to enumerate the Stelladaptor/2600-daptor devices in the @@ -2410,7 +2474,7 @@
-launcherpos <WxH>
-launcherpos <XxY>
Sets the window position in windowed ROM launcher mode.
-dbg.pos <WxH>
-dbg.pos <XxY>
Sets the window position in windowed debugger mode.
Set "Controller.SwapPaddles" property.
-pxcenter <-10..30>
Set "Controller.PaddlesXCenter" property.
-pycenter <-10..30>
Set "Controller.PaddlesYCenter" property.
-ma <Auto|XY>
Set "Controller.MouseAxis" property. @@ -2860,7 +2934,7 @@

Options Menu dialog:



-

Video Settings dialog:

+

Video & Audio Settings dialog (Display):

@@ -2869,29 +2943,42 @@
- - - - - - - - + + - - - - +
ItemBrief descriptionFor more information,
see CommandLine
RendererUse specified rendering mode-video
PalettePalette for emulation mode-palette
NTSC phasePhase shift for custom NTSC palette-phase_ntsc
PAL phasePhase shift for custom PAL palette-phase_pal
InterpolationInterpolation for TIA image-tia.inter
ZoomZoom level for emulation mode -tia.zoom
V-Size adjustAdjust height of TIA image-tia.vsizeadjust
Emul. speedEmulation speed-speed
VSyncEnable vertical synced updates-vsync
InterpolationInterpolation of TIA image-tia.inter
ZoomZoom level of TIA image-tia.zoom
FullscreenSelf-explanatory - Note that colors may slightly change. This depends on the OS and renderer used.-fullscreen
StretchIn fullscreen mode, completely fill screen with TIA image-tia.fs_stretch
OverscanIn fullscreen mode, add overscan to the TIA image-tia.fs_overscan
Fast SuperCharger loadSkip progress loading bars for SuperCharger ROMs-fastscbios
Show UI messagesOverlay UI messages onscreen-uimessages
Center windowAttempt to center application windows, else position at last position-center
Multi-threadingEnable multi-threaded rendering-threads
V-Size adjustAdjust height of TIA image-tia.vsizeadjust

-

Video Settings dialog (TV Effects):

+

Video & Audio Settings dialog (Palettes):

+ + + + + + +
     + + + + + + + + + + +
ItemBrief descriptionFor more information,
see CommandLine
PalettePalette used for emulation mode-palette
NTSC phaseAdjust phase shift for 'Custom' NTSC palette-pal.phase_ntsc
PAL phaseAdjust phase shift for 'Custom' PAL palette-pal.phase_pal
HueAdjust hue of currently selected palette-pal.hue
SaturationAdjust saturation of currently selected palette-pal.saturation
ContrastAdjust contrast of currently selected palette-pal.contrast
BrightnessAdjust brightness of currently selected palette-pal.brightness
GammaAdjust gamma of currently selected palette-pal.gamma
+
+
+ +

Video & Audio Settings dialog (TV Effects):

@@ -2900,24 +2987,24 @@
- + - - - - - + + + + +
ItemBrief descriptionFor more information,
see CommandLine
TV modeDisable TV effects, or select TV preset-tv.filter
Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.contrast, -tv.hue, etc.
Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.sharpness, -tv.resolution, etc.
Phosphor for all ROMsEnable phosphor mode for all ROMs-tv.phosphor
Blend (phosphor)Blend level to use in phosphor mode for all ROMs (needs to be manually adjusted for your particular hardware)-tv.phosblend
Scanline intensitySets scanline black-level intensity.
Note: No scanlines in 1x mode snapshots.
-tv.scanlines
Clone CompositeCopy 'Composite' attributes to 'Custom' sliders 
Clone S-VideoCopy 'S-Video' attributes to 'Custom' sliders 
Clone RGBCopy 'RGB' attributes to 'Custom' sliders 
Clone Bad adjustCopy 'Bad Adjust' attributes to 'Custom' sliders 
RevertRevert attribute sliders to saved 'Custom' settings 
Clone RGBCopy 'RGB' attributes to 'Custom' TV mode sliders 
Clone S-VideoCopy 'S-Video' attributes to 'Custom' TV mode sliders 
Clone CompositeCopy 'Composite' attributes to 'Custom' TV mode sliders 
Clone Bad adjustCopy 'Bad Adjust' attributes to 'Custom' TV mode sliders 
RevertRevert attribute sliders to saved 'Custom' TV mode settings 

-

Audio Settings dialog:

+

Video & Audio Settings dialog (Audio):

@@ -2941,7 +3028,7 @@ - +
-audio.resampling_quality
HeadroomNumber of frames to buffer before playback starts. Higher values increase latency, but reduce the potential for dropouts.-audio.headroom
Buffer sizeMaximum size of the audio buffer. Higher values increase maximum latency, but reduce the potential for dropouts-audio.buffer_size
Stereo for all ROMsEnables stereo mode for all ROMs.-audio.stereo
Stereo for all ROMsEnable stereo mode for all ROMs.-audio.stereo
Pitfall II music pitchDefines the pitch of Pitfall II music (which may vary between carts).-audio.dpc_pitch

@@ -2960,6 +3047,44 @@
+ +

Emulation dialog:

+ + + + + + +
     + + + + + + + + + + + + + + + + + + +
ItemBrief descriptionFor more information,
see CommandLine
Emulation speedEmulation speed-speed
VSyncEnable vertical synced updates-vsync
TurboEnable 'Turbo' mode for maximum emulation speed. This overwrites 'Emulation speed' setting and disables 'VSync'.-turbo
Multi-threadingEnable multi-threaded rendering-threads
Fast SuperCharger loadSkip progress loading bars for SuperCharger ROMs-fastscbios
Show UI messagesOverlay UI messages onscreen-uimessages
Confirm exiting...Display a popup when emulation is exited-confirmexit
When entering/exiting emulation: + Automatically save no, current or all Time Machine states when exiting emulation.
+ 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! +
-saveonexit
Automatically change... + Automatically change to the next available save state slot after saving a ROM state file. + -autoslot
+
+
+

Input Settings dialog:

@@ -2980,9 +3105,9 @@ - + - + @@ -3129,16 +3254,12 @@
ItemBrief descriptionFor more information,
see CommandLine
ThemeTheme to use for UI elements (see examples)-uipalette
Dialogs fontThe font used in the dialogs-dialogfont
HiDPI modeScales the UI by a factor of two when enabled-hidpi
HiDPI modeScale the UI by a factor of two when enabled-hidpi
Dialogs positionPosition of dialogs with Stella window-dialogpos
Confirm exiting...Display a popup when emulation is exited-confirmexit
Center windowsAttempt to center application windows, else position at last position-center
List input delayMaximum delay between keypresses in filelist-widgets before a search string resets. -listdelay
Mouse wheel scrollNumber of lines a mouse scroll will move in list-widgets-mwheel
Double-click speedSpeed of mouse double-clicks-mdouble
- - - + + + - - - @@ -3148,6 +3269,27 @@
ItemBrief descriptionFor more information,
see CommandLine
Use mouse as ...Allow the mouse to emulate various controllers-usemouse
Mouse cursor visibilityShow/hide cursor depending on current state-cursor
Joystick deadzone sizeDeadzone area for axes on joysticks/gamepads-joydeadzone
Paddle dejitter strengthStrenght of paddle input averaging (base) and reaction to fast paddle movements (diff)-dejitter.base, -dejitter.diff
(Analog paddle) SensitivitySensitivity of an analog paddle-psense
Analog paddle) Dejitter averagingStrength of paddle input averaging, suppresses mouse jitter-dejitter.base
(Analog paddle) Dejitter reactionStrength of paddle reaction to fast paddle movements, suppresses mouse jitter-dejitter.diff
Digital paddle sensitivitySensitivity used when emulating a paddle using a digital device-dsense
Mouse paddle sensitivitySensitivity used when emulating a paddle using a mouse-msense
Trackball sensitivitySensitivity used when emulating a trackball device using a mouse-tsense
Allow all 4 directions ...Allow all 4 joystick directions to be pressed simultaneously-joyallow4
Grab mouse ...Keep mouse in window in emulation mode
(only when used as controller)
- Note: The sensitivity may greatly vary when the mouse is not grabbed.
-grabmouse
Use modifier key combosEnable using modifier keys in keyboard actions-modcombo
Swap Stelladaptor portsSwap the order of the detected Stelladaptors/2600-daptors (see Advanced Configuration - Stelladaptor/2600-daptor Support)-saport
Joystick databaseShow all joysticks that Stella knows about, with the option to remove them 
+ +

Mouse settings can be configured under the 'Mouse' tab, shown below:

+ + + + + + +
     + + + + + + + + +
ItemBrief descriptionFor more information,
see CommandLine
Use mouse as ...Allow the mouse to emulate various controllers-usemouse
(Sensitivity) PaddleSensitivity used when emulating a paddle using a mouse-msense
(Sensitivity) TrackballSensitivity used when emulating a trackball device using a mouse-tsense
(Sensitivity) Driving controllerSensitivity used when emulating a driving controller device using a mouse-dcsense
Mouse cursor visibilityShow/hide cursor depending on current state-cursor
Grab mouse ...Keep mouse in window in emulation mode
(only when used as controller)
+ Note: The sensitivity may greatly vary when the mouse is not grabbed.
-grabmouse
+
+

ROM Launcher

@@ -3233,8 +3375,6 @@
- -
  • Show only ROM files: Selecting this reloads the current listing, showing only files that have a valid ROM extension.
  • @@ -3518,21 +3658,6 @@ 'Buffer size'. -plr.tm.horizon
    -dev.tm.horizon - - When entering/exiting emulation: - - Automatically save no, current or all Time Machine states when exiting emulation.
    - 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! - - -saveonexit - - Automatically change... - - Automatically change to the next available save state slot after saving a ROM state file. - - -autoslot @@ -4032,6 +4157,16 @@ Ms Pac-Man (Stella extended codes): 'Console.SwapPorts'. The value must be Yes or No. + + Controller.PaddlesXCenter: + Defines the horizontal center of the paddles (range -10..30). + + + + Controller.PaddlesYCenter: + Defines the vertical center of the paddles (range -10..30). + + Controller.MouseAxis: Indicates how the mouse should emulate virtual controllers. diff --git a/src/common/JoyMap.hxx b/src/common/JoyMap.hxx index 6448de1ff..e3cc7ff7a 100644 --- a/src/common/JoyMap.hxx +++ b/src/common/JoyMap.hxx @@ -19,6 +19,7 @@ #define CONTROLLERMAP_HXX #include + #include "Event.hxx" #include "EventHandlerConstants.hxx" diff --git a/src/common/KeyMap.hxx b/src/common/KeyMap.hxx index 94d3b4242..0b7eff2fe 100644 --- a/src/common/KeyMap.hxx +++ b/src/common/KeyMap.hxx @@ -21,6 +21,7 @@ #include #include "Event.hxx" #include "EventHandlerConstants.hxx" +#include "StellaKeys.hxx" /** This class handles keyboard mappings in Stella. diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index f32600345..cf4a31831 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -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}, diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx new file mode 100644 index 000000000..d2a2a7768 --- /dev/null +++ b/src/common/PaletteHandler.cxx @@ -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 + +#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 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 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((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 pixbuf; // Temporary buffer for one 24-bit pixel + + for(int i = 0; i < 128; i++) // NTSC palette + { + in.read(reinterpret_cast(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(pixbuf.data()), 3); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + ourUserPALPalette[(i<<1)] = pixel; + } + + std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels + for(int i = 0; i < 8; i++) // SECAM palette + { + in.read(reinterpret_cast(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 diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx new file mode 100644 index 000000000..bd102d9f0 --- /dev/null +++ b/src/common/PaletteHandler.hxx @@ -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 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 diff --git a/src/common/RewindManager.cxx b/src/common/RewindManager.cxx index d16bbd6c3..6bafbeeaa 100644 --- a/src/common/RewindManager.cxx +++ b/src/common/RewindManager.cxx @@ -18,6 +18,7 @@ #include #include "OSystem.hxx" +#include "Console.hxx" #include "Serializer.hxx" #include "StateManager.hxx" #include "TIA.hxx" diff --git a/src/common/SoundNull.hxx b/src/common/SoundNull.hxx index 87ba7736a..8974e9834 100644 --- a/src/common/SoundNull.hxx +++ b/src/common/SoundNull.hxx @@ -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. diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx index 671e5f83c..928ebbc44 100644 --- a/src/common/SoundSDL2.cxx +++ b/src/common/SoundSDL2.cxx @@ -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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx index 85fb86031..398f1fa92 100644 --- a/src/common/SoundSDL2.hxx +++ b/src/common/SoundSDL2.hxx @@ -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. diff --git a/src/common/StateManager.cxx b/src/common/StateManager.cxx index 667665054..a4add0889 100644 --- a/src/common/StateManager.cxx +++ b/src/common/StateManager.cxx @@ -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()); } diff --git a/src/common/StateManager.hxx b/src/common/StateManager.hxx index 09de785fb..3da98499c 100644 --- a/src/common/StateManager.hxx +++ b/src/common/StateManager.hxx @@ -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. diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index 1484b21ed..f21a99a4c 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -43,6 +43,7 @@ using uInt64 = uint64_t; #include #include #include +#include #include #include #include @@ -86,6 +87,8 @@ using StringList = std::vector; using ByteBuffer = std::unique_ptr; // NOLINT using DWordBuffer = std::unique_ptr; // NOLINT +using AdjustFunction = std::function; + // 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 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) diff --git a/src/common/module.mk b/src/common/module.mk index f7a228189..1aae6cd0a 100644 --- a/src/common/module.mk +++ b/src/common/module.mk @@ -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 \ diff --git a/src/common/sdl_blitter/BilinearBlitter.cxx b/src/common/sdl_blitter/BilinearBlitter.cxx index bae05207c..295d8e8e2 100644 --- a/src/common/sdl_blitter/BilinearBlitter.cxx +++ b/src/common/sdl_blitter/BilinearBlitter.cxx @@ -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) diff --git a/src/common/sdl_blitter/BilinearBlitter.hxx b/src/common/sdl_blitter/BilinearBlitter.hxx index e18cba6bf..84c550ad1 100644 --- a/src/common/sdl_blitter/BilinearBlitter.hxx +++ b/src/common/sdl_blitter/BilinearBlitter.hxx @@ -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 { diff --git a/src/common/sdl_blitter/QisBlitter.cxx b/src/common/sdl_blitter/QisBlitter.cxx index 95d958565..c68c4bff9 100644 --- a/src/common/sdl_blitter/QisBlitter.cxx +++ b/src/common/sdl_blitter/QisBlitter.cxx @@ -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) diff --git a/src/common/sdl_blitter/QisBlitter.hxx b/src/common/sdl_blitter/QisBlitter.hxx index 77ab2b51d..14ee84fcc 100644 --- a/src/common/sdl_blitter/QisBlitter.hxx +++ b/src/common/sdl_blitter/QisBlitter.hxx @@ -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 { diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index a0b9ef169..ad57a12f8 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -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 }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 4ae7b666f..eb75bce3d 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -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 to_rgb{0.F}; + #ifdef BLARGG_PALETTE std::array to_float{0.F}; float contrast{0.F}; float brightness{0.F}; + #endif float artifacts{0.F}; float fringing{0.F}; std::array kernel{0.F}; init_t() { to_rgb.fill(0.0); + #ifdef BLARGG_PALETTE to_float.fill(0.0); + #endif kernel.fill(0.0); } }; diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 6ec1afc8c..9764f1ac3 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -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::ourCustomAdjustables = { { { "contrast", &myCustomSetup.contrast }, { "brightness", &myCustomSetup.brightness }, { "hue", &myCustomSetup.hue }, { "saturation", &myCustomSetup.saturation }, { "gamma", &myCustomSetup.gamma }, +#else +const std::array NTSCFilter::ourCustomAdjustables = { { +#endif { "sharpness", &myCustomSetup.sharpness }, { "resolution", &myCustomSetup.resolution }, { "artifacts", &myCustomSetup.artifacts }, diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index b4a5e0e3d..b4b3aa713 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -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 ourCustomAdjustables; + #else + static const std::array ourCustomAdjustables; + #endif private: // Following constructors and assignment operators not supported diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index b46570a6a..cdb039491 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -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); } diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index d063f2e90..6083d556a 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -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); diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index da3b0bc5f..49692ef8a 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -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"; } diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index 8aff0b568..c77d1eabf 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -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 << " " diff --git a/src/debugger/gui/CartARWidget.cxx b/src/debugger/gui/CartARWidget.cxx index 6037849f6..ec4c4037a 100644 --- a/src/debugger/gui/CartARWidget.cxx +++ b/src/debugger/gui/CartARWidget.cxx @@ -16,6 +16,9 @@ //============================================================================ #include "CartAR.hxx" +#include "OSystem.hxx" +#include "Debugger.hxx" +#include "CartDebug.hxx" #include "PopUpWidget.hxx" #include "CartARWidget.hxx" diff --git a/src/debugger/gui/CartCMWidget.cxx b/src/debugger/gui/CartCMWidget.cxx index 8fa72f0bb..e4d11ba55 100644 --- a/src/debugger/gui/CartCMWidget.cxx +++ b/src/debugger/gui/CartCMWidget.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "CartCM.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" #include "RiotDebug.hxx" diff --git a/src/debugger/gui/CartCTYWidget.cxx b/src/debugger/gui/CartCTYWidget.cxx index 76230fa21..659fb9bea 100644 --- a/src/debugger/gui/CartCTYWidget.cxx +++ b/src/debugger/gui/CartCTYWidget.cxx @@ -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" diff --git a/src/debugger/gui/CartDebugWidget.hxx b/src/debugger/gui/CartDebugWidget.hxx index 7bdcbf472..27c3befa5 100644 --- a/src/debugger/gui/CartDebugWidget.hxx +++ b/src/debugger/gui/CartDebugWidget.hxx @@ -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 { diff --git a/src/debugger/gui/CartE0Widget.cxx b/src/debugger/gui/CartE0Widget.cxx index 12205c463..08ccc802a 100644 --- a/src/debugger/gui/CartE0Widget.cxx +++ b/src/debugger/gui/CartE0Widget.cxx @@ -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 diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx index f864a21c0..0bf38f529 100644 --- a/src/debugger/gui/CartEnhancedWidget.cxx +++ b/src/debugger/gui/CartEnhancedWidget.cxx @@ -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" diff --git a/src/debugger/gui/CartEnhancedWidget.hxx b/src/debugger/gui/CartEnhancedWidget.hxx index 968a4bbf0..a367e8def 100644 --- a/src/debugger/gui/CartEnhancedWidget.hxx +++ b/src/debugger/gui/CartEnhancedWidget.hxx @@ -25,6 +25,7 @@ namespace GUI { class Font; } +#include "Variant.hxx" #include "CartDebugWidget.hxx" class CartridgeEnhancedWidget : public CartDebugWidget diff --git a/src/debugger/gui/ControllerWidget.hxx b/src/debugger/gui/ControllerWidget.hxx index e552be284..d14c1ba69 100644 --- a/src/debugger/gui/ControllerWidget.hxx +++ b/src/debugger/gui/ControllerWidget.hxx @@ -23,6 +23,7 @@ class ButtonWidget; #include "Font.hxx" #include "Widget.hxx" +#include "OSystem.hxx" #include "Console.hxx" #include "Command.hxx" #include "ControlLowLevel.hxx" diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index 6b663609c..719eebef2 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -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" diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 5d8404d06..6674311f6 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -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() { diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index b66ae37a6..f38e8b2dc 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -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; } diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index b803adc17..eb27f5258 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -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" diff --git a/src/debugger/gui/RiotRamWidget.cxx b/src/debugger/gui/RiotRamWidget.cxx index 2666182ec..5f3d5c0ab 100644 --- a/src/debugger/gui/RiotRamWidget.cxx +++ b/src/debugger/gui/RiotRamWidget.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 64ca2df9d..6e450e334 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "bspf.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "DiStella.hxx" #include "Widget.hxx" diff --git a/src/debugger/gui/RomWidget.cxx b/src/debugger/gui/RomWidget.cxx index 3279ca5d9..010ae5f0b 100644 --- a/src/debugger/gui/RomWidget.cxx +++ b/src/debugger/gui/RomWidget.cxx @@ -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); } } diff --git a/src/emucore/AtariVox.cxx b/src/emucore/AtariVox.cxx index 3314ac08c..700789352 100644 --- a/src/emucore/AtariVox.cxx +++ b/src/emucore/AtariVox.cxx @@ -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) { diff --git a/src/emucore/AtariVox.hxx b/src/emucore/AtariVox.hxx index b21ec38b0..e0c2e72c7 100644 --- a/src/emucore/AtariVox.hxx +++ b/src/emucore/AtariVox.hxx @@ -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; diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index 6fbf1a68d..b04a95f10 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -23,15 +23,18 @@ class Properties; class CartDebugWidget; class CartRamWidget; class GuiObject; +class Settings; + +#include #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. diff --git a/src/emucore/Cart3EPlus.hxx b/src/emucore/Cart3EPlus.hxx index c2ce64cd8..fe6a0a263 100644 --- a/src/emucore/Cart3EPlus.hxx +++ b/src/emucore/Cart3EPlus.hxx @@ -24,7 +24,6 @@ class System; #include "Cart3E.hxx" #ifdef DEBUGGER_SUPPORT -class Cartridge3EPlusWidget; #include "Cart3EPlusWidget.hxx" #endif diff --git a/src/emucore/Cart3EX.hxx b/src/emucore/Cart3EX.hxx index 7df53593e..c949a0c9c 100644 --- a/src/emucore/Cart3EX.hxx +++ b/src/emucore/Cart3EX.hxx @@ -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 diff --git a/src/emucore/CartAR.cxx b/src/emucore/CartAR.cxx index 2d8b204b6..a0eea7486 100644 --- a/src/emucore/CartAR.cxx +++ b/src/emucore/CartAR.cxx @@ -17,6 +17,7 @@ #include "M6502.hxx" #include "System.hxx" +#include "Settings.hxx" #include "CartAR.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartDPC.cxx b/src/emucore/CartDPC.cxx index 481e385be..bc8962b1b 100644 --- a/src/emucore/CartDPC.cxx +++ b/src/emucore/CartDPC.cxx @@ -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" diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 6c68bf6e4..976d56579 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -62,6 +62,7 @@ #include "MD5.hxx" #include "Props.hxx" #include "Logger.hxx" +#include "OSystem.hxx" #include "CartDetector.hxx" diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index 706731b0f..9ff193c87 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -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, diff --git a/src/emucore/CartEnhanced.cxx b/src/emucore/CartEnhanced.cxx index f5c38c9a3..27fa425b5 100644 --- a/src/emucore/CartEnhanced.cxx +++ b/src/emucore/CartEnhanced.cxx @@ -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(myBankSegs); // Allocate array for the RAM area - myRAM = make_unique(myRamSize); + if(myRamSize > 0) + myRAM = make_unique(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]; diff --git a/src/emucore/CompuMate.cxx b/src/emucore/CompuMate.cxx index b39e46ab4..a3a0367cc 100644 --- a/src/emucore/CompuMate.cxx +++ b/src/emucore/CompuMate.cxx @@ -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" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CompuMate.hxx b/src/emucore/CompuMate.hxx index ff0e0f781..8b8d772e8 100644 --- a/src/emucore/CompuMate.hxx +++ b/src/emucore/CompuMate.hxx @@ -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. diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 29fe2bfac..1e796a0bd 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -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& 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(myOSystem.settings()); myRiot = make_unique(*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 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 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 pixbuf; // Temporary buffer for one 24-bit pixel - - for(int i = 0; i < 128; i++) // NTSC palette - { - in.read(reinterpret_cast(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(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - ourUserPALPalette[(i<<1)] = pixel; - } - - std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels - for(int i = 0; i < 8; i++) // SECAM palette - { - in.read(reinterpret_cast(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 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((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 diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 9ff4b002c..d13588b07 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -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 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; diff --git a/src/emucore/ConsoleIO.hxx b/src/emucore/ConsoleIO.hxx index d8ae106a6..2fde50ed8 100644 --- a/src/emucore/ConsoleIO.hxx +++ b/src/emucore/ConsoleIO.hxx @@ -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: diff --git a/src/emucore/ConsoleTiming.hxx b/src/emucore/ConsoleTiming.hxx index 1f75db469..fd43caa98 100644 --- a/src/emucore/ConsoleTiming.hxx +++ b/src/emucore/ConsoleTiming.hxx @@ -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 diff --git a/src/emucore/Control.hxx b/src/emucore/Control.hxx index 3647d1bc0..a670f39f6 100644 --- a/src/emucore/Control.hxx +++ b/src/emucore/Control.hxx @@ -25,8 +25,8 @@ class System; #include -#include "Serializable.hxx" #include "bspf.hxx" +#include "Serializable.hxx" /** A controller is a device that plugs into either the left or right diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx index 737ea36f2..d37076eb1 100644 --- a/src/emucore/ControllerDetector.hxx +++ b/src/emucore/ControllerDetector.hxx @@ -18,6 +18,8 @@ #ifndef CONTROLLER_DETECTOR_HXX #define CONTROLLER_DETECTOR_HXX +class Settings; + #include "Control.hxx" /** diff --git a/src/emucore/Device.hxx b/src/emucore/Device.hxx index 7c175852b..fb2423a35 100644 --- a/src/emucore/Device.hxx +++ b/src/emucore/Device.hxx @@ -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 diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 915461e97..fa8a4d04d 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -22,7 +22,6 @@ #include #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; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index c9fa85835..fa87be91d 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -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, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 8fe4c7821..0ab40c7cd 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -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 ; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 250a895cf..4599a3860 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -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); } } diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index a73b01ffb..3912f38cd 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -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 surface; bool enabled{false}; + bool showGauge{false}; + float value{0.0F}; + string valueText; }; Message myMsg; Message myStatsMsg; diff --git a/src/emucore/Joystick.hxx b/src/emucore/Joystick.hxx index 7acd631bc..505294456 100644 --- a/src/emucore/Joystick.hxx +++ b/src/emucore/Joystick.hxx @@ -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. diff --git a/src/emucore/Keyboard.hxx b/src/emucore/Keyboard.hxx index a241cbc37..9ec176d71 100644 --- a/src/emucore/Keyboard.hxx +++ b/src/emucore/Keyboard.hxx @@ -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 diff --git a/src/emucore/Lightgun.hxx b/src/emucore/Lightgun.hxx index 7bec4f4e2..facdffe1e 100644 --- a/src/emucore/Lightgun.hxx +++ b/src/emucore/Lightgun.hxx @@ -18,6 +18,11 @@ #ifndef LIGHTGUN_HXX #define LIGHTGUN_HXX +class FrameBuffer; + +#include "bspf.hxx" +#include "Control.hxx" + /** This class handles the lightgun controller diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index ccf6838cb..9c84b4165 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -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; } diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index b23cbdb83..2bc5368c6 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -41,7 +41,7 @@ class AudioSettings; class Menu; class MessageMenu; class TimeMachine; - class VideoDialog; + class VideoAudioDialog; #endif #ifdef PNG_SUPPORT class PNGLibrary; diff --git a/src/emucore/PointingDevice.cxx b/src/emucore/PointingDevice.cxx index 1a2c781b4..4d91d010c 100644 --- a/src/emucore/PointingDevice.cxx +++ b/src/emucore/PointingDevice.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + #include "Control.hxx" #include "Event.hxx" #include "System.hxx" diff --git a/src/emucore/PointingDevice.hxx b/src/emucore/PointingDevice.hxx index 4f0a007b5..11b9fcd2d 100644 --- a/src/emucore/PointingDevice.hxx +++ b/src/emucore/PointingDevice.hxx @@ -18,7 +18,6 @@ #ifndef POINTING_DEVICE_HXX #define POINTING_DEVICE_HXX -class Controller; class Event; #include "Control.hxx" diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx index f561dc7a1..e7d81b997 100644 --- a/src/emucore/ProfilingRunner.cxx +++ b/src/emucore/ProfilingRunner.cxx @@ -54,7 +54,6 @@ namespace { } } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ProfilingRunner::ProfilingRunner(int argc, char* argv[]) : profilingRuns(std::max(argc - 2, 0)) diff --git a/src/emucore/ProfilingRunner.hxx b/src/emucore/ProfilingRunner.hxx index 1194cfdda..a3523b98f 100644 --- a/src/emucore/ProfilingRunner.hxx +++ b/src/emucore/ProfilingRunner.hxx @@ -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 myLeftControl; - unique_ptr myRightControl; - unique_ptr mySwitches; + unique_ptr myLeftControl; + unique_ptr myRightControl; + unique_ptr mySwitches; }; private: diff --git a/src/emucore/PropsSet.cxx b/src/emucore/PropsSet.cxx index a13a9c759..a74a999e7 100644 --- a/src/emucore/PropsSet.cxx +++ b/src/emucore/PropsSet.cxx @@ -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 { diff --git a/src/emucore/PropsSet.hxx b/src/emucore/PropsSet.hxx index 71924749a..f5a763ef8 100644 --- a/src/emucore/PropsSet.hxx +++ b/src/emucore/PropsSet.hxx @@ -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. */ diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index c1c64dd20..f5e120408 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -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 \n" - << " -phase_ntsc Phase shift for NTSC custom color palette\n" - << " -phase_pal Phase shift for PAL custom color palette\n" + << " -pal.phase_ntsc Phase shift for NTSC 'custom' palette\n" + << " -pal.phase_pal 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 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" diff --git a/src/emucore/Sound.hxx b/src/emucore/Sound.hxx index f74705489..4e1fda0d5 100644 --- a/src/emucore/Sound.hxx +++ b/src/emucore/Sound.hxx @@ -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. diff --git a/src/emucore/Switches.hxx b/src/emucore/Switches.hxx index fb7ae4539..16c4dba74 100644 --- a/src/emucore/Switches.hxx +++ b/src/emucore/Switches.hxx @@ -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. diff --git a/src/emucore/System.hxx b/src/emucore/System.hxx index 1c36acf53..dab87b28a 100644 --- a/src/emucore/System.hxx +++ b/src/emucore/System.hxx @@ -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" diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index a13a9fd83..afaad7855 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -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(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; diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx index c87ddc881..826ff75d9 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -22,6 +22,7 @@ class TIA; class Console; class OSystem; class FBSurface; +class PaletteHandler; #include @@ -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_ptrmyPaletteHandler; + private: // Following constructors and assignment operators not supported TIASurface() = delete; diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index c5bd3e637..2984159cd 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -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 } } diff --git a/src/emucore/tia/Audio.hxx b/src/emucore/tia/Audio.hxx index 92e854a0d..5ab53ecae 100644 --- a/src/emucore/tia/Audio.hxx +++ b/src/emucore/tia/Audio.hxx @@ -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: diff --git a/src/emucore/tia/Background.hxx b/src/emucore/tia/Background.hxx index 3004c7978..ea84aed96 100644 --- a/src/emucore/tia/Background.hxx +++ b/src/emucore/tia/Background.hxx @@ -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: diff --git a/src/emucore/tia/Ball.hxx b/src/emucore/tia/Ball.hxx index 5b9b3a604..0a40250e2 100644 --- a/src/emucore/tia/Ball.hxx +++ b/src/emucore/tia/Ball.hxx @@ -18,11 +18,11 @@ #ifndef TIA_BALL #define TIA_BALL -#include "Serializable.hxx" +class TIA; + #include "bspf.hxx" #include "TIAConstants.hxx" - -class TIA; +#include "Serializable.hxx" class Ball : public Serializable { diff --git a/src/emucore/tia/DelayQueueIterator.hxx b/src/emucore/tia/DelayQueueIterator.hxx index 31e5251e8..3b615e3d4 100644 --- a/src/emucore/tia/DelayQueueIterator.hxx +++ b/src/emucore/tia/DelayQueueIterator.hxx @@ -19,8 +19,6 @@ #define TIA_DELAY_QUEUE_ITERATOR #include "bspf.hxx" -#include "DelayQueue.hxx" -#include "DelayQueueMember.hxx" class DelayQueueIterator { diff --git a/src/emucore/tia/DelayQueueIteratorImpl.hxx b/src/emucore/tia/DelayQueueIteratorImpl.hxx index b556cb279..9f9e4d4c7 100644 --- a/src/emucore/tia/DelayQueueIteratorImpl.hxx +++ b/src/emucore/tia/DelayQueueIteratorImpl.hxx @@ -20,7 +20,6 @@ #include "bspf.hxx" #include "DelayQueue.hxx" -#include "DelayQueueMember.hxx" #include "DelayQueueIterator.hxx" template diff --git a/src/emucore/tia/DelayQueueMember.hxx b/src/emucore/tia/DelayQueueMember.hxx index f87c9b459..653167b6f 100644 --- a/src/emucore/tia/DelayQueueMember.hxx +++ b/src/emucore/tia/DelayQueueMember.hxx @@ -18,8 +18,8 @@ #ifndef TIA_DELAY_QUEUE_MEMBER #define TIA_DELAY_QUEUE_MEMBER -#include "Serializable.hxx" #include "bspf.hxx" +#include "Serializable.hxx" template class DelayQueueMember : public Serializable { diff --git a/src/emucore/tia/Missile.hxx b/src/emucore/tia/Missile.hxx index dda9b493c..cd5cce582 100644 --- a/src/emucore/tia/Missile.hxx +++ b/src/emucore/tia/Missile.hxx @@ -18,13 +18,13 @@ #ifndef TIA_MISSILE #define TIA_MISSILE +class TIA; +class Player; + #include "Serializable.hxx" #include "bspf.hxx" -#include "Player.hxx" #include "TIAConstants.hxx" -class TIA; - class Missile : public Serializable { public: diff --git a/src/emucore/tia/PaddleReader.hxx b/src/emucore/tia/PaddleReader.hxx index abbc013c6..8071617c6 100644 --- a/src/emucore/tia/PaddleReader.hxx +++ b/src/emucore/tia/PaddleReader.hxx @@ -20,7 +20,7 @@ #include "bspf.hxx" #include "Serializable.hxx" -#include "Console.hxx" +#include "ConsoleTiming.hxx" class PaddleReader : public Serializable { diff --git a/src/emucore/tia/Player.hxx b/src/emucore/tia/Player.hxx index 454bfcd9f..60dfbe3c5 100644 --- a/src/emucore/tia/Player.hxx +++ b/src/emucore/tia/Player.hxx @@ -18,12 +18,12 @@ #ifndef TIA_PLAYER #define TIA_PLAYER +class TIA; + #include "bspf.hxx" #include "Serializable.hxx" #include "TIAConstants.hxx" -class TIA; - class Player : public Serializable { public: diff --git a/src/emucore/tia/Playfield.hxx b/src/emucore/tia/Playfield.hxx index fe811d53a..4a1376991 100644 --- a/src/emucore/tia/Playfield.hxx +++ b/src/emucore/tia/Playfield.hxx @@ -18,11 +18,11 @@ #ifndef TIA_PLAYFIELD #define TIA_PLAYFIELD -#include "Serializable.hxx" +class TIA; + #include "bspf.hxx" #include "TIAConstants.hxx" - -class TIA; +#include "Serializable.hxx" class Playfield : public Serializable { diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx index fa7e50308..443b9c20c 100644 --- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx +++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx @@ -18,8 +18,8 @@ #ifndef TIA_FRAME_LAYOUT_DETECTOR #define TIA_FRAME_LAYOUT_DETECTOR -#include "AbstractFrameManager.hxx" #include "FrameLayout.hxx" +#include "AbstractFrameManager.hxx" /** * This frame manager performs frame layout autodetection. It counts the scanlines diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx deleted file mode 100644 index 1f97c2f8b..000000000 --- a/src/gui/AudioDialog.cxx +++ /dev/null @@ -1,353 +0,0 @@ -//============================================================================ -// -// 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 - -#include "bspf.hxx" - -#include "Console.hxx" -#include "Cart.hxx" -#include "CartDPC.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Font.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "PopUpWidget.hxx" -#include "Settings.hxx" -#include "Sound.hxx" -#include "Widget.hxx" -#include "AudioSettings.hxx" - -#include "AudioDialog.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font) - : Dialog(osystem, parent, font, "Audio settings") -{ - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - - int xpos, ypos; - int lwidth = font.getStringWidth("Volume "), - pwidth; - - WidgetArray wid; - VariantList items; - - // Set real dimensions - _w = 48 * fontWidth + HBORDER * 2; - _h = 12 * (lineHeight + VGAP) + VBORDER + _th; - - xpos = HBORDER; ypos = VBORDER + _th; - - // Enable sound - mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Enable sound", kSoundEnableChanged); - wid.push_back(mySoundEnableCheckbox); - ypos += lineHeight + VGAP; - xpos += CheckboxWidget::prefixSize(font); - - // Volume - myVolumeSlider = new SliderWidget(this, font, xpos, ypos, - "Volume", lwidth, 0, 4 * fontWidth, "%"); - myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); - myVolumeSlider->setTickmarkIntervals(4); - wid.push_back(myVolumeSlider); - ypos += lineHeight + VGAP; - - // Mode - items.clear(); - VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); - VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); - VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); - VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); - VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); - myModePopup = new PopUpWidget(this, font, xpos, ypos, - font.getStringWidth("Ultry quality, minimal lag"), lineHeight, - items, "Mode", lwidth, kModeChanged); - wid.push_back(myModePopup); - ypos += lineHeight + VGAP; - xpos += INDENT; - - // Fragment size - pwidth = font.getStringWidth("512 samples") + 7; - lwidth = font.getStringWidth("Resampling quality "); - items.clear(); - VarList::push_back(items, "128 samples", 128); - VarList::push_back(items, "256 samples", 256); - VarList::push_back(items, "512 samples", 512); - VarList::push_back(items, "1k samples", 1024); - VarList::push_back(items, "2k samples", 2048); - VarList::push_back(items, "4K samples", 4096); - myFragsizePopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Fragment size", lwidth); - wid.push_back(myFragsizePopup); - ypos += lineHeight + VGAP; - - // Output frequency - items.clear(); - VarList::push_back(items, "44100 Hz", 44100); - VarList::push_back(items, "48000 Hz", 48000); - VarList::push_back(items, "96000 Hz", 96000); - myFreqPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Sample rate", lwidth); - wid.push_back(myFreqPopup); - ypos += lineHeight + VGAP; - - // Resampling quality - items.clear(); - VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); - VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); - VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); - myResamplingPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Resampling quality ", lwidth); - wid.push_back(myResamplingPopup); - ypos += lineHeight + VGAP; - - // Param 1 - int swidth = pwidth+23; - myHeadroomSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); - myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); - myHeadroomSlider->setTickmarkIntervals(5); - wid.push_back(myHeadroomSlider); - ypos += lineHeight + VGAP; - - // Param 2 - myBufferSizeSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); - myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); - myBufferSizeSlider->setTickmarkIntervals(5); - wid.push_back(myBufferSizeSlider); - ypos += lineHeight + VGAP; - - // Stereo sound - xpos -= INDENT; - myStereoSoundCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Stereo for all ROMs"); - wid.push_back(myStereoSoundCheckbox); - ypos += lineHeight + VGAP; - - myDpcPitch = new SliderWidget(this, font, xpos, ypos, swidth - 16, lineHeight, - "Pitfall II music pitch ", 0, 0, 5 * fontWidth); - myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); - myDpcPitch->setStepValue(100); - myDpcPitch->setTickmarkIntervals(2); - wid.push_back(myDpcPitch); - - // Add Defaults, OK and Cancel buttons - addDefaultsOKCancelBGroup(wid, font); - - addToFocusList(wid); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::loadConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enable sound - mySoundEnableCheckbox->setState(audioSettings.enabled()); - - // Volume - myVolumeSlider->setValue(audioSettings.volume()); - - // Stereo - myStereoSoundCheckbox->setState(audioSettings.stereo()); - - // DPC Pitch - myDpcPitch->setValue(audioSettings.dpcPitch()); - - // Preset / mode - myModePopup->setSelected(static_cast(audioSettings.preset())); - - updateSettingsWithPreset(instance().audioSettings()); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) -{ - // Fragsize - myFragsizePopup->setSelected(audioSettings.fragmentSize()); - - // Output frequency - myFreqPopup->setSelected(audioSettings.sampleRate()); - - // Headroom - myHeadroomSlider->setValue(audioSettings.headroom()); - - // Buffer size - myBufferSizeSlider->setValue(audioSettings.bufferSize()); - - // Resampling quality - myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::saveConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enabled - audioSettings.setEnabled(mySoundEnableCheckbox->getState()); - instance().sound().setEnabled(mySoundEnableCheckbox->getState()); - - // Volume - audioSettings.setVolume(myVolumeSlider->getValue()); - instance().sound().setVolume(myVolumeSlider->getValue()); - - // Stereo - audioSettings.setStereo(myStereoSoundCheckbox->getState()); - - // DPC Pitch - audioSettings.setDpcPitch(myDpcPitch->getValue()); - // update if current cart is Pitfall II - if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") - { - CartridgeDPC& cart = static_cast(instance().console().cartridge()); - cart.setDpcPitch(myDpcPitch->getValue()); - } - - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - audioSettings.setPreset(preset); - - if (preset == AudioSettings::Preset::custom) { - // Fragsize - audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); - audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); - audioSettings.setHeadroom(myHeadroomSlider->getValue()); - audioSettings.setBufferSize(myBufferSizeSlider->getValue()); - audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); - } - - // Only force a re-initialization when necessary, since it can - // be a time-consuming operation - if(instance().hasConsole()) - instance().console().initializeAudio(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::setDefaults() -{ - mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); - myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); - myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); - myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); - myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); - - if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { - myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); - myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); - myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); - myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); - myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); - } - else updatePreset(); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateEnabledState() -{ - bool active = mySoundEnableCheckbox->getState(); - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - bool userMode = preset == AudioSettings::Preset::custom; - - myVolumeSlider->setEnabled(active); - myStereoSoundCheckbox->setEnabled(active); - myModePopup->setEnabled(active); - // enable only for Pitfall II cart - myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); - - myFragsizePopup->setEnabled(active && userMode); - myFreqPopup->setEnabled(active && userMode); - myResamplingPopup->setEnabled(active && userMode); - myHeadroomSlider->setEnabled(active && userMode); - myBufferSizeSlider->setEnabled(active && userMode); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updatePreset() -{ - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - - // Make a copy that does not affect the actual settings... - AudioSettings audioSettings = instance().audioSettings(); - audioSettings.setPersistent(false); - // ... and set the requested preset - audioSettings.setPreset(preset); - - updateSettingsWithPreset(audioSettings); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch(cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kSoundEnableChanged: - updateEnabledState(); - break; - - case kModeChanged: - updatePreset(); - updateEnabledState(); - break; - - case kHeadroomChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; - myHeadroomSlider->setValueLabel(ss.str()); - break; - } - case kBufferSizeChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; - myBufferSizeSlider->setValueLabel(ss.str()); - break; - } - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/AudioDialog.hxx b/src/gui/AudioDialog.hxx deleted file mode 100644 index b7aa35c65..000000000 --- a/src/gui/AudioDialog.hxx +++ /dev/null @@ -1,77 +0,0 @@ -//============================================================================ -// -// 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 AUDIO_DIALOG_HXX -#define AUDIO_DIALOG_HXX - -class CommandSender; -class Dialog; -class DialogContainer; -class PopUpWidget; -class SliderWidget; -class StaticTextWidget; -class CheckboxWidget; -class OSystem; -class AudioSettings; - -#include "bspf.hxx" - -class AudioDialog : public Dialog -{ - public: - AudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font); - virtual ~AudioDialog() = default; - - private: - void loadConfig() override; - void saveConfig() override; - void setDefaults() override; - - void updatePreset(); - void updateEnabledState(); - void updateSettingsWithPreset(AudioSettings&); - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - private: - enum { - kSoundEnableChanged = 'ADse', - kModeChanged = 'ADmc', - kHeadroomChanged = 'ADhc', - kBufferSizeChanged = 'ADbc' - }; - - CheckboxWidget* mySoundEnableCheckbox{nullptr}; - SliderWidget* myVolumeSlider{nullptr}; - CheckboxWidget* myStereoSoundCheckbox{nullptr}; - PopUpWidget* myModePopup{nullptr}; - PopUpWidget* myFragsizePopup{nullptr}; - PopUpWidget* myFreqPopup{nullptr}; - PopUpWidget* myResamplingPopup{nullptr}; - SliderWidget* myHeadroomSlider{nullptr}; - SliderWidget* myBufferSizeSlider{nullptr}; - SliderWidget* myDpcPitch{nullptr}; - - private: - // Following constructors and assignment operators not supported - AudioDialog() = delete; - AudioDialog(const AudioDialog&) = delete; - AudioDialog(AudioDialog&&) = delete; - AudioDialog& operator=(const AudioDialog&) = delete; - AudioDialog& operator=(AudioDialog&&) = delete; -}; - -#endif diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 6aa58a049..27f4bc3cf 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -25,9 +25,10 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, int cmd) + int x, int y, int w, int h, int cmd, bool framed) : Widget(boss, font, x, y, w, h), CommandSender(boss), + _framed(framed), _cmd(cmd) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; @@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite) FBSurface& s = dialog().surface(); bool onTop = _boss->dialog().isOnTop(); + if(_framed) + { // Draw a thin frame around us. - s.frameRect(_x, _y, _w, _h + 1, kColor); + s.frameRect(_x, _y, _w, _h + 1, kColor); - // Show the currently selected color - s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + // Show the currently selected color + s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } + else + { + s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } // Cross out the grid? if(_crossGrid) diff --git a/src/gui/ColorWidget.hxx b/src/gui/ColorWidget.hxx index 7691ff6ad..9169c2153 100644 --- a/src/gui/ColorWidget.hxx +++ b/src/gui/ColorWidget.hxx @@ -36,7 +36,7 @@ class ColorWidget : public Widget, public CommandSender public: ColorWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, int cmd = 0); + int x, int y, int w, int h, int cmd = 0, bool framed = true); virtual ~ColorWidget() = default; void setColor(ColorId color); @@ -49,6 +49,7 @@ class ColorWidget : public Widget, public CommandSender protected: ColorId _color{kNone}; + bool _framed{true}; int _cmd{0}; bool _crossGrid{false}; diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 5c734a52e..e4c5f610a 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Console.hxx" +#include "PaletteHandler.hxx" #include "TIA.hxx" #include "Switches.hxx" #include "Dialog.hxx" @@ -198,12 +199,12 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, // Column 3 case kFormatCmd: - instance().console().toggleFormat(); + instance().console().selectFormat(); updateTVFormat(); break; case kPaletteCmd: - instance().console().togglePalette(); + instance().frameBuffer().tiaSurface().paletteHandler().cyclePalette(); updatePalette(); break; @@ -269,11 +270,11 @@ void CommandDialog::updatePalette() string palette, label; palette = instance().settings().getString("palette"); - if(BSPF::equalsIgnoreCase(palette, "standard")) + if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_STANDARD)) label = "Stella Palette"; - else if(BSPF::equalsIgnoreCase(palette, "z26")) + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_Z26)) label = "Z26 Palette"; - else if(BSPF::equalsIgnoreCase(palette, "user")) + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_USER)) label = "User Palette"; else label = "Custom Palette"; diff --git a/src/gui/CommandMenu.cxx b/src/gui/CommandMenu.cxx index 68e9a0fef..1a6708f71 100644 --- a/src/gui/CommandMenu.cxx +++ b/src/gui/CommandMenu.cxx @@ -16,6 +16,8 @@ //============================================================================ #include "Dialog.hxx" +#include "OSystem.hxx" +#include "Settings.hxx" #include "CommandDialog.hxx" #include "MinUICommandDialog.hxx" #include "CommandMenu.hxx" diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 5badbc513..288fb6a40 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -499,31 +499,6 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) lineHeight, items, "Horizon ~ ", 0, kHorizonChanged); wid.push_back(myStateHorizonWidget); - xpos = HBORDER + INDENT; - ypos += lineHeight + VGAP * 2; - new StaticTextWidget(myTab, font, HBORDER, ypos + 1, - "When entering/exiting emulation:"); - ypos += lineHeight + VGAP; - mySaveOnExitGroup = new RadioButtonGroup(); - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Do nothing", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Save current state in current slot", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Load/save all Time Machine states", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - xpos = HBORDER; - - - myAutoSlotWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Automatically change save state slots"); - wid.push_back(myAutoSlotWidget); - ypos += lineHeight + VGAP; - // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; @@ -678,8 +653,6 @@ void DeveloperDialog::loadSettings(SettingsSet set) myUncompressed[set] = instance().settings().getInt(prefix + "tm.uncompressed"); myStateInterval[set] = instance().settings().getString(prefix + "tm.interval"); myStateHorizon[set] = instance().settings().getString(prefix + "tm.horizon"); - - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -871,12 +844,6 @@ void DeveloperDialog::loadConfig() // Debug colours handleDebugColours(instance().settings().getString("tia.dbgcolors")); - // Save on exit - string saveOnExit = instance().settings().getString("saveonexit"); - mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); - // Automatically change save state slots - myAutoSlotWidget->setState(instance().settings().getBool("autoslot")); - #ifdef DEBUGGER_SUPPORT uInt32 w, h; @@ -953,13 +920,6 @@ void DeveloperDialog::saveConfig() instance().state().setRewindMode(myTimeMachineWidget->getState() ? StateManager::Mode::TimeMachine : StateManager::Mode::Off); - // Save on exit - int saveOnExit = mySaveOnExitGroup->getSelected(); - instance().settings().setValue("saveonexit", - saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); - // Automatically change save state slots - instance().settings().setValue("autoslot", myAutoSlotWidget->getState()); - #ifdef DEBUGGER_SUPPORT // Debugger font style instance().settings().setValue("dbg.fontstyle", @@ -1050,8 +1010,6 @@ void DeveloperDialog::setDefaults() myStateHorizon[set] = devSettings ? "30s" : "10m"; setWidgetStates(set); - mySaveOnExitGroup->setSelected(0); - myAutoSlotWidget->setState(false); break; case 4: // Debugger options diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx index ddee5468d..8bd84ab91 100644 --- a/src/gui/DeveloperDialog.hxx +++ b/src/gui/DeveloperDialog.hxx @@ -135,8 +135,6 @@ class DeveloperDialog : public Dialog SliderWidget* myUncompressedWidget{nullptr}; PopUpWidget* myStateIntervalWidget{nullptr}; PopUpWidget* myStateHorizonWidget{nullptr}; - RadioButtonGroup* mySaveOnExitGroup{nullptr}; - CheckboxWidget* myAutoSlotWidget{nullptr}; #ifdef DEBUGGER_SUPPORT // Debugger UI widgets diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index b60faf6d4..950d71c06 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -384,4 +384,3 @@ void DialogContainer::reset() uInt64 DialogContainer::_DOUBLE_CLICK_DELAY = 500; uInt64 DialogContainer::_REPEAT_INITIAL_DELAY = 400; uInt64 DialogContainer::_REPEAT_SUSTAIN_DELAY = 50; - diff --git a/src/gui/EditTextWidget.hxx b/src/gui/EditTextWidget.hxx index f752ae385..c7a346804 100644 --- a/src/gui/EditTextWidget.hxx +++ b/src/gui/EditTextWidget.hxx @@ -21,7 +21,6 @@ #include "Rect.hxx" #include "EditableWidget.hxx" - /* EditTextWidget */ class EditTextWidget : public EditableWidget { diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx new file mode 100644 index 000000000..e9bb3804a --- /dev/null +++ b/src/gui/EmulationDialog.cxx @@ -0,0 +1,284 @@ +//============================================================================ +// +// 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 "OSystem.hxx" +#include "Console.hxx" +#include "FrameBuffer.hxx" +#include "RadioButtonWidget.hxx" +#include "TIASurface.hxx" + +#include "EmulationDialog.hxx" + +namespace { + // Emulation speed is a positive float that multiplies the framerate. However, the UI controls + // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following + // mapping and formatting functions implement this conversion. The speedup factor is represented + // by an integer value between -900 and 900 (0 means no speedup). + + constexpr int MAX_SPEED = 900; + constexpr int MIN_SPEED = -900; + constexpr int SPEED_STEP = 10; + + int mapSpeed(float speed) + { + speed = std::abs(speed); + + return BSPF::clamp( + static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), + MIN_SPEED, MAX_SPEED + ); + } + + float unmapSpeed(int speed) + { + float f_speed = static_cast(speed) / 100; + + return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; + } + + string formatSpeed(int speed) { + stringstream ss; + + ss + << std::setw(3) << std::fixed << std::setprecision(0) + << (unmapSpeed(speed) * 100); + + return ss.str(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Emulation settings") +{ + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = font.getStringWidth("Emulation speed "); + WidgetArray wid; + VariantList items; + const int swidth = fontWidth * 10; + + // Set real dimensions + _w = 37 * fontWidth + HBORDER * 2 + CheckboxWidget::prefixSize(_font); + _h = 12 * (lineHeight + VGAP) + VGAP * 7 + VBORDER * 3 + _th + buttonHeight; + + xpos = HBORDER; ypos = VBORDER + _th; + + // Speed + mySpeed = + new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight, + "Emulation speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); + mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); + mySpeed->setStepValue(SPEED_STEP); + mySpeed->setTickmarkIntervals(2); + wid.push_back(mySpeed); + ypos += lineHeight + VGAP; + + // Use sync to vblank + myUseVSync = new CheckboxWidget(this, _font, xpos, ypos + 1, "VSync"); + wid.push_back(myUseVSync); + ypos += lineHeight + VGAP; + + + myTurbo = new CheckboxWidget(this, _font, xpos, ypos + 1, "Turbo mode"); + wid.push_back(myTurbo); + ypos += lineHeight + VGAP * 3; + + // Use multi-threading + myUseThreads = new CheckboxWidget(this, _font, xpos, ypos + 1, "Multi-threading"); + wid.push_back(myUseThreads); + ypos += lineHeight + VGAP; + + // Skip progress load bars for SuperCharger ROMs + // Doesn't really belong here, but I couldn't find a better place for it + myFastSCBios = new CheckboxWidget(this, _font, xpos, ypos + 1, "Fast SuperCharger load"); + wid.push_back(myFastSCBios); + ypos += lineHeight + VGAP; + + // Show UI messages onscreen + myUIMessages = new CheckboxWidget(this, _font, xpos, ypos + 1, "Show UI messages"); + wid.push_back(myUIMessages); + ypos += lineHeight + VGAP; + + // Confirm dialog when exiting emulation + xpos = HBORDER; ypos += VGAP * 3; + myConfirmExitWidget = new CheckboxWidget(this, _font, xpos, ypos, "Confirm exiting emulation"); + wid.push_back(myConfirmExitWidget); + + xpos = HBORDER + INDENT; + ypos += lineHeight + VGAP * 3; + new StaticTextWidget(this, font, HBORDER, ypos + 1, + "When entering/exiting emulation:"); + ypos += lineHeight + VGAP; + mySaveOnExitGroup = new RadioButtonGroup(); + RadioButtonWidget* r; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Do nothing", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Save current state in current slot", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Load/save all Time Machine states", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + xpos = HBORDER; + + + myAutoSlotWidget = new CheckboxWidget(this, font, xpos, ypos + 1, "Automatically change save state slots"); + wid.push_back(myAutoSlotWidget); + ypos += lineHeight + VGAP; + + // Add Defaults, OK and Cancel buttons + addDefaultsOKCancelBGroup(wid, font); + + addToFocusList(wid); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::loadConfig() +{ + Settings& settings = instance().settings(); + + // Emulation speed + int speed = mapSpeed(settings.getFloat("speed")); + mySpeed->setValue(speed); + mySpeed->setValueLabel(formatSpeed(speed)); + + // Use sync to vertical blank + myUseVSync->setState(settings.getBool("vsync")); + + // Enable 'Turbo' mode + myTurbo->setState(settings.getBool("turbo")); + + // Show UI messages + myUIMessages->setState(settings.getBool("uimessages")); + + // Fast loading of Supercharger BIOS + myFastSCBios->setState(settings.getBool("fastscbios")); + + // Multi-threaded rendering + myUseThreads->setState(settings.getBool("threads")); + + // Confirm dialog when exiting emulation + myConfirmExitWidget->setState(settings.getBool("confirmexit")); + + // Save on exit + string saveOnExit = settings.getString("saveonexit"); + mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); + // Automatically change save state slots + myAutoSlotWidget->setState(settings.getBool("autoslot")); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::saveConfig() +{ + Settings& settings = instance().settings(); + + // Speed + const int speedup = mySpeed->getValue(); + settings.setValue("speed", unmapSpeed(speedup)); + if(instance().hasConsole()) + instance().console().initializeAudio(); + + // Use sync to vertical blank + settings.setValue("vsync", myUseVSync->getState()); + + // Enable 'Turbo' mode + settings.setValue("turbo", myTurbo->getState()); + + // Show UI messages + settings.setValue("uimessages", myUIMessages->getState()); + + // Fast loading of Supercharger BIOS + settings.setValue("fastscbios", myFastSCBios->getState()); + + // Multi-threaded rendering + settings.setValue("threads", myUseThreads->getState()); + + // Confirm dialog when exiting emulation + settings.setValue("confirmexit", myConfirmExitWidget->getState()); + + // Save on exit + int saveOnExit = mySaveOnExitGroup->getSelected(); + settings.setValue("saveonexit", + saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); + // Automatically change save state slots + settings.setValue("autoslot", myAutoSlotWidget->getState()); + + if(instance().hasConsole()) + { + // update speed + instance().console().initializeAudio(); + // update VSync + instance().console().initializeVideo(); + + instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::setDefaults() +{ + // speed + mySpeed->setValue(0); + myUseVSync->setState(true); + // misc + myUIMessages->setState(true); + myFastSCBios->setState(true); + myUseThreads->setState(false); + myConfirmExitWidget->setState(false); + + mySaveOnExitGroup->setSelected(0); + myAutoSlotWidget->setState(false); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch(cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + close(); + break; + + case GuiObject::kDefaultsCmd: + setDefaults(); + break; + + case kSpeedupChanged: + mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); + break; + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} diff --git a/src/gui/EmulationDialog.hxx b/src/gui/EmulationDialog.hxx new file mode 100644 index 000000000..f1470d7bb --- /dev/null +++ b/src/gui/EmulationDialog.hxx @@ -0,0 +1,63 @@ +//============================================================================ +// +// 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 EMULATION_DIALOG_HXX +#define EMULATION_DIALOG_HXX + +class RadioButtonGroup; + +#include "Dialog.hxx" + +class EmulationDialog : public Dialog +{ +public: + EmulationDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + int max_w, int max_h); + virtual ~EmulationDialog() = default; + +private: + void loadConfig() override; + void saveConfig() override; + void setDefaults() override; + + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + +private: + SliderWidget* mySpeed{nullptr}; + CheckboxWidget* myUseVSync{nullptr}; + CheckboxWidget* myTurbo{nullptr}; + CheckboxWidget* myUIMessages{nullptr}; + CheckboxWidget* myFastSCBios{nullptr}; + CheckboxWidget* myUseThreads{nullptr}; + CheckboxWidget* myConfirmExitWidget{nullptr}; + RadioButtonGroup* mySaveOnExitGroup{nullptr}; + CheckboxWidget* myAutoSlotWidget{nullptr}; + + enum { + kSpeedupChanged = 'EDSp', + }; + +private: + // Following constructors and assignment operators not supported + EmulationDialog() = delete; + EmulationDialog(const EmulationDialog&) = delete; + EmulationDialog(EmulationDialog&&) = delete; + EmulationDialog& operator=(const EmulationDialog&) = delete; + EmulationDialog& operator=(EmulationDialog&&) = delete; +}; + +#endif diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx index 3f473867b..fc8f77285 100644 --- a/src/gui/GuiObject.hxx +++ b/src/gui/GuiObject.hxx @@ -27,7 +27,6 @@ class Widget; class OSystem; #include "Command.hxx" -#include "OSystem.hxx" #include "Vec.hxx" using WidgetArray = vector; diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index 5c9a6b1d3..77c01f174 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -121,7 +121,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) case 2: title = "Special commands"; ADD_EVENT(Event::FormatIncrease, "Switch between NTSC/PAL/SECAM"); - ADD_EVENT(Event::TogglePalette, "Switch palette"); + ADD_EVENT(Event::PaletteIncrease, "Switch to next palette"); ADD_EVENT(Event::TogglePhosphor, "Toggle 'phosphor' effect"); ADD_LINE(); ADD_EVENT(Event::ToggleGrabMouse, "Grab mouse (keep in window)"); diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 03cedb644..3cced561b 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -53,7 +53,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, int xpos, ypos, tabID; // Set real dimensions - setSize(50 * fontWidth + HBORDER * 2, + setSize(48 * fontWidth + PopUpWidget::dropDownWidth(_font) + HBORDER * 2, _th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + VGAP * 8 + buttonHeight + VBORDER * 3, max_w, max_h); @@ -127,10 +127,9 @@ void InputDialog::addDevicePortTab() "Joystick deadzone size", lwidth, kDeadzoneChanged, 5 * fontWidth); myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29); myDeadzone->setTickmarkIntervals(4); - xpos = HBORDER + myDeadzone->getWidth() + 5; wid.push_back(myDeadzone); - xpos = HBORDER; ypos += lineHeight + VGAP * 2; + xpos = HBORDER; ypos += lineHeight + VGAP * 4; new StaticTextWidget(myTab, _font, xpos, ypos+1, "Analog paddle:"); xpos += fontWidth * 2; @@ -165,7 +164,7 @@ void InputDialog::addDevicePortTab() wid.push_back(myDejitterDiff); // Add paddle speed (digital emulation) - ypos += lineHeight + VGAP * 3; + ypos += lineHeight + VGAP * 4; myDPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, "Digital paddle sensitivity", lwidth, kDPSpeedChanged, 4 * fontWidth, "%"); @@ -173,26 +172,8 @@ void InputDialog::addDevicePortTab() myDPaddleSpeed->setTickmarkIntervals(4); wid.push_back(myDPaddleSpeed); - // Add trackball speed - ypos += lineHeight + VGAP; - myTrackBallSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Trackball sensitivity", - lwidth, kTBSpeedChanged, 4 * fontWidth, "%"); - myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); - myTrackBallSpeed->setTickmarkIntervals(4); - wid.push_back(myTrackBallSpeed); - - // Add driving controller speed - ypos += lineHeight + VGAP; - myDrivingSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Driving contr. sensitivity", - lwidth, kDCSpeedChanged, 4 * fontWidth, "%"); - myDrivingSpeed->setMinValue(1); myDrivingSpeed->setMaxValue(20); - myDrivingSpeed->setTickmarkIntervals(4); - wid.push_back(myDrivingSpeed); - // Add 'allow all 4 directions' for joystick - ypos += lineHeight + VGAP * 3; + ypos += lineHeight + VGAP * 4; myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos, "Allow all 4 directions on joystick"); wid.push_back(myAllowAll4); @@ -231,7 +212,7 @@ void InputDialog::addDevicePortTab() wid.push_back(myEraseEEPROMButton); // Add AtariVox serial port - ypos += lineHeight + VGAP * 2; + ypos += lineHeight + VGAP * 3; lwidth = _font.getStringWidth("AVox serial port "); fwidth = _w - HBORDER * 2 - 2 - lwidth; new StaticTextWidget(myTab, _font, HBORDER, ypos + 2, "AVox serial port "); @@ -252,7 +233,8 @@ void InputDialog::addMouseTab() const int VGAP = fontHeight / 4; const int VBORDER = fontHeight / 2; const int HBORDER = fontWidth * 1.25; - int ypos, lwidth, pwidth, tabID; + const int INDENT = fontWidth * 2; + int xpos = HBORDER, ypos, lwidth, pwidth, tabID; WidgetArray wid; VariantList items; @@ -267,21 +249,43 @@ void InputDialog::addMouseTab() VarList::push_back(items, "Always", "always"); VarList::push_back(items, "Analog devices", "analog"); VarList::push_back(items, "Never", "never"); - myMouseControl = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items, + myMouseControl = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, items, "Use mouse as a controller ", lwidth, kMouseCtrlChanged); wid.push_back(myMouseControl); - // Add paddle speed (mouse emulation) ypos += lineHeight + VGAP; - myMPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Mouse paddle sensitivity ", + myMouseSensitivity = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Sensitivity:"); + + // Add paddle speed (mouse emulation) + xpos += INDENT; ypos += lineHeight + VGAP; + lwidth -= INDENT; + myMPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Paddle", lwidth, kMPSpeedChanged, 4 * fontWidth, "%"); myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); myMPaddleSpeed->setTickmarkIntervals(4); wid.push_back(myMPaddleSpeed); + // Add trackball speed + ypos += lineHeight + VGAP; + myTrackBallSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Trackball", + lwidth, kTBSpeedChanged, 4 * fontWidth, "%"); + myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); + myTrackBallSpeed->setTickmarkIntervals(4); + wid.push_back(myTrackBallSpeed); + + // Add driving controller speed + ypos += lineHeight + VGAP; + myDrivingSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Driving controller", + lwidth, kDCSpeedChanged, 4 * fontWidth, "%"); + myDrivingSpeed->setMinValue(1); myDrivingSpeed->setMaxValue(20); + myDrivingSpeed->setTickmarkIntervals(4); + wid.push_back(myDrivingSpeed); // Mouse cursor state + lwidth += INDENT; ypos += lineHeight + VGAP * 4; items.clear(); VarList::push_back(items, "-UI, -Emulation", "0"); @@ -473,9 +477,6 @@ void InputDialog::setDefaults() myDejitterBase->setValue(0); myDejitterDiff->setValue(0); #endif - myDrivingSpeed->setValue(10); - myTrackBallSpeed->setValue(10); - // AtariVox serial port myAVoxPort->setText(""); @@ -491,15 +492,17 @@ void InputDialog::setDefaults() // Use mouse as a controller myMouseControl->setSelected("analog"); + // Paddle speed (mouse) + myMPaddleSpeed->setValue(10); + myTrackBallSpeed->setValue(10); + myDrivingSpeed->setValue(10); + // Mouse cursor state myCursorState->setSelected("2"); // Grab mouse myGrabMouse->setState(true); - // Paddle speed (mouse) - myMPaddleSpeed->setValue(10); - handleMouseControlState(); handleCursorState(); break; @@ -691,6 +694,7 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, case kMouseCtrlChanged: handleMouseControlState(); + handleCursorState(); break; case kCursorStateChanged: @@ -725,14 +729,19 @@ void InputDialog::updateDejitterReaction() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::handleMouseControlState() { - myMPaddleSpeed->setEnabled(myMouseControl->getSelected() != 2); + bool enable = myMouseControl->getSelected() != 2; + + myMouseSensitivity->setEnabled(enable); + myMPaddleSpeed->setEnabled(enable); + myTrackBallSpeed->setEnabled(enable); + myDrivingSpeed->setEnabled(enable); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::handleCursorState() { int state = myCursorState->getSelected(); - bool enableGrab = state != 1 && state != 3; + bool enableGrab = state != 1 && state != 3 && myMouseControl->getSelected() != 2; myGrabMouse->setEnabled(enableGrab); } diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 54fde4a91..48e1629a3 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -62,7 +62,6 @@ class InputDialog : public Dialog void addDevicePortTab(); void addMouseTab(); - void handleMouseControlState(); void handleCursorState(); void updateDejitterAveraging(); @@ -91,9 +90,7 @@ class InputDialog : public Dialog EventMappingWidget* myEmulEventMapper{nullptr}; EventMappingWidget* myMenuEventMapper{nullptr}; - CheckboxWidget* mySAPort{nullptr}; - PopUpWidget* myMouseControl{nullptr}; - PopUpWidget* myCursorState{nullptr}; + CheckboxWidget* mySAPort{nullptr}; EditTextWidget* myAVoxPort{nullptr}; @@ -102,16 +99,20 @@ class InputDialog : public Dialog SliderWidget* myDejitterBase{nullptr}; SliderWidget* myDejitterDiff{nullptr}; SliderWidget* myDPaddleSpeed{nullptr}; - SliderWidget* myMPaddleSpeed{nullptr}; - SliderWidget* myTrackBallSpeed{nullptr}; - SliderWidget* myDrivingSpeed{nullptr}; CheckboxWidget* myAllowAll4{nullptr}; - CheckboxWidget* myGrabMouse{nullptr}; CheckboxWidget* myModCombo{nullptr}; ButtonWidget* myJoyDlgButton{nullptr}; ButtonWidget* myEraseEEPROMButton{nullptr}; + PopUpWidget* myMouseControl{nullptr}; + StaticTextWidget* myMouseSensitivity{nullptr}; + SliderWidget* myMPaddleSpeed{nullptr}; + SliderWidget* myTrackBallSpeed{nullptr}; + SliderWidget* myDrivingSpeed{nullptr}; + PopUpWidget* myCursorState{nullptr}; + CheckboxWidget* myGrabMouse{nullptr}; + // Show the list of joysticks that the eventhandler knows about unique_ptr myJoyDialog; diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index bfa0cecba..faeea2598 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -32,6 +32,9 @@ class EditTextWidget; class FileListWidget; class RomInfoWidget; class StaticTextWidget; +namespace Common { + struct Size; +} namespace GUI { class MessageBox; } @@ -41,7 +44,6 @@ namespace GUI { #include "bspf.hxx" #include "Dialog.hxx" #include "FSNode.hxx" -#include "Stack.hxx" class LauncherDialog : public Dialog { diff --git a/src/gui/Menu.cxx b/src/gui/Menu.cxx index c2976857f..547f8e2ac 100644 --- a/src/gui/Menu.cxx +++ b/src/gui/Menu.cxx @@ -19,6 +19,7 @@ #include "FrameBufferConstants.hxx" #include "OptionsDialog.hxx" #include "StellaSettingsDialog.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "bspf.hxx" #include "Menu.hxx" diff --git a/src/gui/MessageDialog.cxx b/src/gui/MessageDialog.cxx index d00acc5a5..ca52c99e6 100644 --- a/src/gui/MessageDialog.cxx +++ b/src/gui/MessageDialog.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Console.hxx" #include "EventHandler.hxx" #include "Font.hxx" diff --git a/src/gui/MessageMenu.cxx b/src/gui/MessageMenu.cxx index f7c7f0faa..19b700ae7 100644 --- a/src/gui/MessageMenu.cxx +++ b/src/gui/MessageMenu.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Dialog.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "MessageDialog.hxx" #include "MessageMenu.hxx" diff --git a/src/gui/MinUICommandDialog.cxx b/src/gui/MinUICommandDialog.cxx index b93b95890..080316005 100644 --- a/src/gui/MinUICommandDialog.cxx +++ b/src/gui/MinUICommandDialog.cxx @@ -217,7 +217,7 @@ void MinUICommandDialog::handleCommand(CommandSender* sender, int cmd, // Column 3 case kFormatCmd: - instance().console().toggleFormat(); + instance().console().selectFormat(); updateTVFormat(); break; diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index 84ea9f605..865103822 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -23,8 +23,8 @@ #include "Widget.hxx" #include "Font.hxx" #include "Control.hxx" -#include "VideoDialog.hxx" -#include "AudioDialog.hxx" +#include "EmulationDialog.hxx" +#include "VideoAudioDialog.hxx" #include "InputDialog.hxx" #include "UIDialog.hxx" #include "SnapshotDialog.hxx" @@ -89,13 +89,10 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, return bw; }; - b = ADD_OD_BUTTON("Video" + ELLIPSIS, kVidCmd); + b = ADD_OD_BUTTON("Video & Audio" + ELLIPSIS, kVidCmd); wid.push_back(b); - b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd); -#ifndef SOUND_SUPPORT - b->clearFlags(Widget::FLAG_ENABLED); -#endif + b = ADD_OD_BUTTON("Emulation" + ELLIPSIS, kEmuCmd); wid.push_back(b); b = ADD_OD_BUTTON("Input" + ELLIPSIS, kInptCmd); @@ -143,8 +140,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, addCancelWidget(b); // Now create all the dialogs attached to each menu button - myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); - myAudioDialog = make_unique(osystem, parent, _font); + myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); + myEmulationDialog= make_unique(osystem, parent, _font, max_w, max_h); myInputDialog = make_unique(osystem, parent, _font, max_w, max_h); myUIDialog = make_unique(osystem, parent, _font, boss, max_w, max_h); mySnapshotDialog = make_unique(osystem, parent, _font, max_w, max_h); @@ -212,6 +209,10 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, instance().eventHandler().leaveMenuMode(); break; + case kEmuCmd: + myEmulationDialog->open(); + break; + case kVidCmd: { // This dialog is resizable under certain conditions, so we need @@ -220,17 +221,12 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, if(myVideoDialog == nullptr || myVideoDialog->shouldResize(w, h)) { - myVideoDialog = make_unique(instance(), parent(), + myVideoDialog = make_unique(instance(), parent(), instance().frameBuffer().font(), w, h); } myVideoDialog->open(); break; } - - case kAudCmd: - myAudioDialog->open(); - break; - case kInptCmd: { // This dialog is resizable under certain conditions, so we need diff --git a/src/gui/OptionsDialog.hxx b/src/gui/OptionsDialog.hxx index 3b5598693..001fad73b 100644 --- a/src/gui/OptionsDialog.hxx +++ b/src/gui/OptionsDialog.hxx @@ -22,8 +22,8 @@ class CommandSender; class DialogContainer; class GuiObject; class OSystem; -class VideoDialog; -class AudioDialog; +class EmulationDialog; +class VideoAudioDialog; class InputDialog; class UIDialog; class SnapshotDialog; @@ -52,8 +52,8 @@ class OptionsDialog : public Dialog void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: - unique_ptr myVideoDialog; - unique_ptr myAudioDialog; + unique_ptr myVideoDialog; + unique_ptr myEmulationDialog; unique_ptr myInputDialog; unique_ptr myUIDialog; unique_ptr mySnapshotDialog; @@ -78,7 +78,7 @@ class OptionsDialog : public Dialog enum { kBasSetCmd = 'BAST', kVidCmd = 'VIDO', - kAudCmd = 'AUDO', + kEmuCmd = 'EMUO', kInptCmd = 'INPT', kUsrIfaceCmd = 'URIF', kSnapCmd = 'SNAP', diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 890da7e95..58b9acaba 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -25,6 +25,7 @@ #include "FSNode.hxx" #include "Font.hxx" #include "MessageBox.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "MD5.hxx" #include "Props.hxx" diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index 8b1852528..3cfa43185 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -48,6 +48,11 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, void RomInfoWidget::setProperties(const FilesystemNode& node, const string& md5) { myHaveProperties = true; + + // Make sure to load a per-ROM properties entry, if one exists + instance().propSet().loadPerROM(node, md5); + + // And now get the properties for this ROM instance().propSet().getMD5(md5, myProperties); // Decide whether the information should be shown immediately diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index 2c0534ffa..870a82b54 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -21,6 +21,7 @@ #include "FSNode.hxx" #include "Font.hxx" #include "LauncherDialog.hxx" +#include "OSystem.hxx" #include "Settings.hxx" #include "SnapshotDialog.hxx" diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx index fbd93dc7d..b5c1e5106 100644 --- a/src/gui/StellaSettingsDialog.cxx +++ b/src/gui/StellaSettingsDialog.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Console.hxx" #include "EventHandler.hxx" #include "Launcher.hxx" @@ -88,6 +89,11 @@ StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& pa addToFocusList(wid); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StellaSettingsDialog::~StellaSettingsDialog() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos) { diff --git a/src/gui/StellaSettingsDialog.hxx b/src/gui/StellaSettingsDialog.hxx index 791db381c..6f7cfe8a8 100644 --- a/src/gui/StellaSettingsDialog.hxx +++ b/src/gui/StellaSettingsDialog.hxx @@ -23,7 +23,6 @@ class PopUpWidget; #include "Props.hxx" #include "Menu.hxx" #include "Dialog.hxx" -#include "MessageBox.hxx" #if defined(RETRON77) #include "R77HelpDialog.hxx" @@ -33,6 +32,7 @@ class PopUpWidget; namespace GUI { class Font; + class MessageBox; } class StellaSettingsDialog : public Dialog @@ -40,7 +40,7 @@ class StellaSettingsDialog : public Dialog public: StellaSettingsDialog(OSystem& osystem, DialogContainer& parent, int max_w, int max_h, Menu::AppMode mode); - virtual ~StellaSettingsDialog() = default; + virtual ~StellaSettingsDialog(); private: void loadConfig() override; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 099886b9b..eafc2e00b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -105,12 +105,13 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myDialogFontPopup); // Enable HiDPI mode - myHidpiWidget = new CheckboxWidget(myTab, font, myDialogFontPopup->getRight() + fontWidth * 5, + xpos = myDialogFontPopup->getRight() + fontWidth * 5; + myHidpiWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "HiDPI mode (*)"); wid.push_back(myHidpiWidget); - ypos += lineHeight + VGAP; // Dialog position + xpos = HBORDER; ypos += lineHeight + VGAP; items.clear(); VarList::push_back(items, "Centered", 0); VarList::push_back(items, "Left top", 1); @@ -120,14 +121,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Dialogs position", lwidth); wid.push_back(myPositionPopup); - ypos += lineHeight + VGAP * 2; - // Confirm dialog when exiting emulation - myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation"); - wid.push_back(myConfirmExitWidget); - ypos += lineHeight + VGAP * 3; + // Center window (in windowed mode) + xpos = myHidpiWidget->getLeft(); + myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows"); + wid.push_back(myCenter); // Delay between quick-selecting characters in ListWidget + xpos = HBORDER; ypos += lineHeight + VGAP * 4; int swidth = myPalettePopup->getWidth() - lwidth; myListDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, "List input delay ", 0, kListDelay, @@ -303,6 +304,10 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.clear(); addDefaultsOKCancelBGroup(wid, font); addBGroupToFocusList(wid); + +#ifndef WINDOWED_SUPPORT + myCenter->clearFlags(Widget::FLAG_ENABLED); +#endif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -353,6 +358,10 @@ void UIDialog::loadConfig() const string& pal = settings.getString("uipalette"); myPalettePopup->setSelected(pal, "standard"); + // Dialog font + const string& dialogFont = settings.getString("dialogfont"); + myDialogFontPopup->setSelected(dialogFont, "medium"); + // Enable HiDPI mode if (!instance().frameBuffer().hidpiAllowed()) { @@ -364,16 +373,12 @@ void UIDialog::loadConfig() myHidpiWidget->setState(settings.getBool("hidpi")); } - // Confirm dialog when exiting emulation - myConfirmExitWidget->setState(settings.getBool("confirmexit")); - - // Dialog font - const string& dialogFont = settings.getString("dialogfont"); - myDialogFontPopup->setSelected(dialogFont, "medium"); - // Dialog position myPositionPopup->setSelected(settings.getString("dialogpos"), "0"); + // Center window + myCenter->setState(settings.getBool("center")); + // Listwidget quick delay int delay = settings.getInt("listdelay"); myListDelaySlider->setValue(delay); @@ -436,18 +441,18 @@ void UIDialog::saveConfig() myPalettePopup->getSelectedTag().toString()); instance().frameBuffer().setUIPalette(); - // Enable HiDPI mode - settings.setValue("hidpi", myHidpiWidget->getState()); - // Dialog font settings.setValue("dialogfont", myDialogFontPopup->getSelectedTag().toString()); + // Enable HiDPI mode + settings.setValue("hidpi", myHidpiWidget->getState()); + // Dialog position settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString()); - // Confirm dialog when exiting emulation - settings.setValue("confirmexit", myConfirmExitWidget->getState()); + // Center window + settings.setValue("center", myCenter->getState()); // Listwidget quick delay settings.setValue("listdelay", myListDelaySlider->getValue()); @@ -481,10 +486,10 @@ void UIDialog::setDefaults() { case 0: // Misc. options myPalettePopup->setSelected("standard"); - myHidpiWidget->setState(false); myDialogFontPopup->setSelected("medium", ""); + myHidpiWidget->setState(false); myPositionPopup->setSelected("0"); - myConfirmExitWidget->setState(false); + myCenter->setState(false); myListDelaySlider->setValue(300); myWheelLinesSlider->setValue(4); myDoubleClickSlider->setValue(500); diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 83851e971..6ed1c655f 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -66,10 +66,10 @@ class UIDialog : public Dialog, public CommandSender // Misc options PopUpWidget* myPalettePopup{nullptr}; - CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myDialogFontPopup{nullptr}; + CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myPositionPopup{nullptr}; - CheckboxWidget* myConfirmExitWidget{nullptr}; + CheckboxWidget* myCenter{nullptr}; SliderWidget* myListDelaySlider{nullptr}; SliderWidget* myWheelLinesSlider{nullptr}; SliderWidget* myControllerRateSlider{nullptr}; diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx new file mode 100644 index 000000000..48fdcc8de --- /dev/null +++ b/src/gui/VideoAudioDialog.cxx @@ -0,0 +1,1084 @@ +//============================================================================ +// +// 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 + +#include "bspf.hxx" +#include "Base.hxx" +#include "Control.hxx" +#include "Cart.hxx" +#include "CartDPC.hxx" +#include "Dialog.hxx" +#include "Menu.hxx" +#include "OSystem.hxx" +#include "EditTextWidget.hxx" +#include "PopUpWidget.hxx" +#include "ColorWidget.hxx" +#include "Console.hxx" +#include "PaletteHandler.hxx" +#include "TIA.hxx" +#include "Settings.hxx" +#include "Sound.hxx" +#include "AudioSettings.hxx" +#include "Widget.hxx" +#include "Font.hxx" +#include "TabWidget.hxx" +#include "NTSCFilter.hxx" +#include "TIASurface.hxx" + +#include "VideoAudioDialog.hxx" + +#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ + myTV ## obj = \ + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, \ + desc, lwidth, cmd, fontWidth*4, "%"); \ + myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ + myTV ## obj->setStepValue(2); \ + myTV ## obj->setTickmarkIntervals(2); \ + wid.push_back(myTV ## obj); \ + ypos += lineHeight + VGAP; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Video & Audio settings") +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos; + + // Set real dimensions + setSize(44 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, + _th + VGAP * 6 + lineHeight + 10 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, + max_w, max_h); + + // The tab widget + xpos = 2; ypos = VGAP; + myTab = new TabWidget(this, font, xpos, ypos + _th, + _w - 2*xpos, + _h - _th - VGAP - buttonHeight - VBORDER * 2); + addTabWidget(myTab); + + addDisplayTab(); + addPaletteTab(); + addTVEffectsTab(); + addAudioTab(); + + //const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1; + //const int req_h = _th + VGAP * 3 + // + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom()) + // + buttonHeight + VBORDER * 2; + //// Set real dimensions + //setSize(req_w, req_h, max_w, max_h); + + + // Add Defaults, OK and Cancel buttons + WidgetArray wid; + addDefaultsOKCancelBGroup(wid, _font); + addBGroupToFocusList(wid); + + // Activate the first tab + myTab->setActiveTab(0); + + // Disable certain functions when we know they aren't present +#ifndef WINDOWED_SUPPORT + myFullscreen->clearFlags(Widget::FLAG_ENABLED); + myUseStretch->clearFlags(Widget::FLAG_ENABLED); + myTVOverscan->clearFlags(Widget::FLAG_ENABLED); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addDisplayTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int lwidth = _font.getStringWidth("V-Size adjust "), + pwidth = _font.getStringWidth("OpenGLES2"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Display ", TabWidget::AUTO_WIDTH); + + // Video renderer + myRenderer = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedRenderers(), + "Renderer ", lwidth); + wid.push_back(myRenderer); + const int swidth = myRenderer->getWidth() - lwidth; + ypos += lineHeight + VGAP; + + // TIA interpolation + myTIAInterpolate = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Interpolation "); + wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP * 4; + + // TIA zoom levels (will be dynamically filled later) + myTIAZoom = new SliderWidget(myTab, _font, xpos, ypos - 1, swidth, lineHeight, + "Zoom ", lwidth, 0, fontWidth * 4, "%"); + myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); + wid.push_back(myTIAZoom); + ypos += lineHeight + VGAP; + + // Fullscreen + myFullscreen = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); + wid.push_back(myFullscreen); + ypos += lineHeight + VGAP; + + /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); + myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedScreenModes(), "Mode "); + wid.push_back(myFullScreenMode); + ypos += lineHeight + VGAP;*/ + + // FS stretch + myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch"); + wid.push_back(myUseStretch); + ypos += lineHeight + VGAP; + + // FS overscan + myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight, + "Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%"); + myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); + myTVOverscan->setTickmarkIntervals(2); + wid.push_back(myTVOverscan); + ypos += lineHeight + VGAP; + + // Vertical size + myVSizeAdjust = + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, + "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); + myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); + myVSizeAdjust->setTickmarkIntervals(2); + wid.push_back(myVSizeAdjust); + + // Add items for tab 0 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addPaletteTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + const int lwidth = _font.getStringWidth(" NTSC phase "); + const int pwidth = _font.getStringWidth("Standard"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Palettes ", TabWidget::AUTO_WIDTH); + + // TIA Palette + items.clear(); + VarList::push_back(items, "Standard", PaletteHandler::SETTING_STANDARD); + VarList::push_back(items, "z26", PaletteHandler::SETTING_Z26); + if (instance().checkUserPalette()) + VarList::push_back(items, "User", PaletteHandler::SETTING_USER); + VarList::push_back(items, "Custom", PaletteHandler::SETTING_CUSTOM); + myTIAPalette = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, + lineHeight, items, "Palette ", lwidth, kPaletteChanged); + wid.push_back(myTIAPalette); + ypos += lineHeight + VGAP; + + const int swidth = myTIAPalette->getWidth() - lwidth; + const int plWidth = _font.getStringWidth("NTSC phase "); + const int pswidth = swidth - INDENT + lwidth - plWidth; + + myPhaseShiftNtsc = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); + myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftNtsc->setTickmarkIntervals(4); + wid.push_back(myPhaseShiftNtsc); + ypos += lineHeight + VGAP; + + myPhaseShiftPal = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); + myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftPal->setTickmarkIntervals(4); + wid.push_back(myPhaseShiftPal); + ypos += lineHeight + VGAP; + + CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated) + + // The resulting palette + xpos = myPhaseShiftNtsc->getRight() + fontWidth * 2; + addPalette(xpos, VBORDER, _w - 2 * 2 - HBORDER - xpos, + myTVGamma->getBottom() - myTIAPalette->getTop()); + + // Add items for tab 2 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addTVEffectsTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2; + const int VGAP = fontHeight / 4; + int xpos = HBORDER, + ypos = VBORDER; + const int lwidth = _font.getStringWidth("Saturation "); + const int pwidth = _font.getStringWidth("Bad adjust "); + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" TV Effects ", TabWidget::AUTO_WIDTH); + + items.clear(); + VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); + VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); + VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); + VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); + VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); + VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); + myTVMode = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + items, "TV mode ", 0, kTVModeChanged); + wid.push_back(myTVMode); + ypos += lineHeight + VGAP; + + // Custom adjustables (using macro voodoo) + const int swidth = myTVMode->getWidth() - INDENT - lwidth; + xpos += INDENT; + + CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) + CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) + CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) + CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) + CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) + + ypos += VGAP * 3; + + xpos = HBORDER; + + // TV Phosphor effect + myTVPhosphor = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); + wid.push_back(myTVPhosphor); + ypos += lineHeight + VGAP / 2; + + // TV Phosphor blend level + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend", kPhosBlendChanged) + ypos += VGAP; + + // Scanline intensity and interpolation + xpos -= INDENT; + myTVScanLabel = new StaticTextWidget(myTab, _font, xpos, ypos, "Scanlines:"); + ypos += lineHeight + VGAP / 2; + + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged) + + // Create buttons in 2nd column + int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5; + xpos = _w - HBORDER - 2 * 2 - cloneWidth; + ypos = VBORDER - VGAP / 2; + + // Adjustable presets +#define CREATE_CLONE_BUTTON(obj, desc) \ + myClone ## obj = \ + new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\ + desc, kClone ## obj ##Cmd); \ + wid.push_back(myClone ## obj); \ + ypos += buttonHeight + VGAP; + + ypos += VGAP; + CREATE_CLONE_BUTTON(RGB, "Clone RGB") + CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") + CREATE_CLONE_BUTTON(Composite, "Clone Composite") + CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") + CREATE_CLONE_BUTTON(Custom, "Revert") + + // Add items for tab 3 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addAudioTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = _font.getStringWidth("Volume "), + pwidth; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Audio ", TabWidget::AUTO_WIDTH); + + xpos = HBORDER; ypos = VBORDER; + + // Enable sound + mySoundEnableCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Enable sound", kSoundEnableChanged); + wid.push_back(mySoundEnableCheckbox); + ypos += lineHeight + VGAP; + xpos += CheckboxWidget::prefixSize(_font); + + // Volume + myVolumeSlider = new SliderWidget(myTab, _font, xpos, ypos, + "Volume", lwidth, 0, 4 * fontWidth, "%"); + myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); + myVolumeSlider->setTickmarkIntervals(4); + wid.push_back(myVolumeSlider); + ypos += lineHeight + VGAP; + + // Mode + items.clear(); + VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); + VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); + VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); + VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); + VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); + myModePopup = new PopUpWidget(myTab, _font, xpos, ypos, + _font.getStringWidth("Ultry quality, minimal lag"), lineHeight, + items, "Mode", lwidth, kModeChanged); + wid.push_back(myModePopup); + ypos += lineHeight + VGAP; + xpos += INDENT; + + // Fragment size + lwidth = _font.getStringWidth("Resampling quality "); + pwidth = myModePopup->getRight() - xpos - lwidth - PopUpWidget::dropDownWidth(_font); + items.clear(); + VarList::push_back(items, "128 samples", 128); + VarList::push_back(items, "256 samples", 256); + VarList::push_back(items, "512 samples", 512); + VarList::push_back(items, "1k samples", 1024); + VarList::push_back(items, "2k samples", 2048); + VarList::push_back(items, "4K samples", 4096); + myFragsizePopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Fragment size", lwidth); + wid.push_back(myFragsizePopup); + ypos += lineHeight + VGAP; + + // Output frequency + items.clear(); + VarList::push_back(items, "44100 Hz", 44100); + VarList::push_back(items, "48000 Hz", 48000); + VarList::push_back(items, "96000 Hz", 96000); + myFreqPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Sample rate", lwidth); + wid.push_back(myFreqPopup); + ypos += lineHeight + VGAP; + + // Resampling quality + items.clear(); + VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); + VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); + VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); + myResamplingPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Resampling quality ", lwidth); + wid.push_back(myResamplingPopup); + ypos += lineHeight + VGAP; + + // Param 1 + int swidth = pwidth + PopUpWidget::dropDownWidth(_font); + myHeadroomSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); + myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); + myHeadroomSlider->setTickmarkIntervals(5); + wid.push_back(myHeadroomSlider); + ypos += lineHeight + VGAP; + + // Param 2 + myBufferSizeSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); + myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); + myBufferSizeSlider->setTickmarkIntervals(5); + wid.push_back(myBufferSizeSlider); + ypos += lineHeight + VGAP; + + // Stereo sound + xpos -= INDENT; + myStereoSoundCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Stereo for all ROMs"); + wid.push_back(myStereoSoundCheckbox); + ypos += lineHeight + VGAP; + + swidth += INDENT - fontWidth * 4; + myDpcPitch = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Pitfall II music pitch ", 0, 0, 5 * fontWidth); + myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); + myDpcPitch->setStepValue(100); + myDpcPitch->setTickmarkIntervals(2); + wid.push_back(myDpcPitch); + + // Add items for tab 4 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadConfig() +{ + // Display tab + // Renderer settings + myRenderer->setSelected(instance().settings().getString("video"), "default"); + + // TIA interpolation + myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); + + // TIA zoom levels + // These are dynamically loaded, since they depend on the size of + // the desktop and which renderer we're using + float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values + float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); + + myTIAZoom->setMinValue(minZoom * 100); + myTIAZoom->setMaxValue(maxZoom * 100); + myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% + myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); + + // Fullscreen + myFullscreen->setState(instance().settings().getBool("fullscreen")); + /*string mode = instance().settings().getString("fullscreenmode"); + myFullScreenMode->setSelected(mode);*/ + // Fullscreen stretch setting + myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); + // Fullscreen overscan setting + myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); + handleFullScreenChange(); + + // Aspect ratio setting (NTSC and PAL) + myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); + + ///////////////////////////////////////////////////////////////////////////// + // Palettes tab + // TIA Palette + myPalette = instance().settings().getString("palette"); + myTIAPalette->setSelected(myPalette, PaletteHandler::SETTING_STANDARD); + + // Palette adjustables + instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj); + myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc); + myPhaseShiftPal->setValue(myPaletteAdj.phasePal); + myTVHue->setValue(myPaletteAdj.hue); + myTVBright->setValue(myPaletteAdj.brightness); + myTVContrast->setValue(myPaletteAdj.contrast); + myTVSatur->setValue(myPaletteAdj.saturation); + myTVGamma->setValue(myPaletteAdj.gamma); + handlePaletteChange(); + colorPalette(); + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + myTVMode->setSelected( + instance().settings().getString("tv.filter"), "0"); + int preset = instance().settings().getInt("tv.filter"); + handleTVModeChange(NTSCFilter::Preset(preset)); + + // TV Custom adjustables + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + + // TV phosphor mode + myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); + + // TV phosphor blend + myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); + handlePhosphorChange(); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enable sound +#ifdef SOUND_SUPPORT + mySoundEnableCheckbox->setState(audioSettings.enabled()); +#else + mySoundEnableCheckbox->setState(false); +#endif + + // Volume + myVolumeSlider->setValue(audioSettings.volume()); + + // Stereo + myStereoSoundCheckbox->setState(audioSettings.stereo()); + + // DPC Pitch + myDpcPitch->setValue(audioSettings.dpcPitch()); + + // Preset / mode + myModePopup->setSelected(static_cast(audioSettings.preset())); + + updateSettingsWithPreset(instance().audioSettings()); + + updateEnabledState(); + + myTab->loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) +{ + // Fragsize + myFragsizePopup->setSelected(audioSettings.fragmentSize()); + + // Output frequency + myFreqPopup->setSelected(audioSettings.sampleRate()); + + // Headroom + myHeadroomSlider->setValue(audioSettings.headroom()); + + // Buffer size + myBufferSizeSlider->setValue(audioSettings.bufferSize()); + + // Resampling quality + myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::saveConfig() +{ + ///////////////////////////////////////////////////////////////////////////// + // Display tab + // Renderer setting + instance().settings().setValue("video", + myRenderer->getSelectedTag().toString()); + + // TIA interpolation + instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); + + // Fullscreen + instance().settings().setValue("fullscreen", myFullscreen->getState()); + // Fullscreen stretch setting + instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); + // Fullscreen overscan + instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); + + // TIA zoom levels + instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); + + // Aspect ratio setting (NTSC and PAL) + const int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); + const int newAdjust = myVSizeAdjust->getValue(); + const bool vsizeChanged = oldAdjust != newAdjust; + + instance().settings().setValue("tia.vsizeadjust", newAdjust); + + + // Note: Palette values are saved directly when changed! + + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + instance().settings().setValue("tv.filter", + myTVMode->getSelectedTag().toString()); + // TV Custom adjustables + NTSCFilter::Adjustable ntscAdj; + ntscAdj.sharpness = myTVSharp->getValue(); + ntscAdj.resolution = myTVRes->getValue(); + ntscAdj.artifacts = myTVArtifacts->getValue(); + ntscAdj.fringing = myTVFringe->getValue(); + ntscAdj.bleed = myTVBleed->getValue(); + instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(ntscAdj); + + // TV phosphor mode + instance().settings().setValue("tv.phosphor", + myTVPhosphor->getState() ? "always" : "byrom"); + // TV phosphor blend + instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" + ? "0" : myTVPhosLevel->getValueLabel()); + + // TV scanline intensity + instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); + + if(instance().hasConsole()) + { + instance().console().setTIAProperties(); + + if(vsizeChanged) + { + instance().console().tia().clearFrameBuffer(); + instance().console().initializeVideo(); + } + } + + // Finally, issue a complete framebuffer re-initialization... + instance().createFrameBuffer(); + + // ... and apply potential setting changes to the TIA surface + instance().frameBuffer().tiaSurface().updateSurfaceSettings(); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enabled + audioSettings.setEnabled(mySoundEnableCheckbox->getState()); + instance().sound().setEnabled(mySoundEnableCheckbox->getState()); + + // Volume + audioSettings.setVolume(myVolumeSlider->getValue()); + instance().sound().setVolume(myVolumeSlider->getValue()); + + // Stereo + audioSettings.setStereo(myStereoSoundCheckbox->getState()); + + // DPC Pitch + audioSettings.setDpcPitch(myDpcPitch->getValue()); + // update if current cart is Pitfall II + if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") + { + CartridgeDPC& cart = static_cast(instance().console().cartridge()); + cart.setDpcPitch(myDpcPitch->getValue()); + } + + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + audioSettings.setPreset(preset); + + if (preset == AudioSettings::Preset::custom) { + // Fragsize + audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); + audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); + audioSettings.setHeadroom(myHeadroomSlider->getValue()); + audioSettings.setBufferSize(myBufferSizeSlider->getValue()); + audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); + } + + // Only force a re-initialization when necessary, since it can + // be a time-consuming operation + if(instance().hasConsole()) + instance().console().initializeAudio(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::setDefaults() +{ + switch(myTab->getActiveTab()) + { + case 0: // General + { + myRenderer->setSelectedIndex(0); + myTIAInterpolate->setState(false); + // screen size + myFullscreen->setState(false); + //myFullScreenMode->setSelectedIndex(0); + myUseStretch->setState(false); + myTVOverscan->setValue(0); + myTIAZoom->setValue(300); + myVSizeAdjust->setValue(0); + + handleFullScreenChange(); + break; + } + + case 1: // Palettes + myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD); + myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10); + myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10); + myTVHue->setValue(50); + myTVSatur->setValue(50); + myTVContrast->setValue(50); + myTVBright->setValue(50); + myTVGamma->setValue(50); + handlePaletteChange(); + break; + + case 2: // TV effects + { + myTVMode->setSelected("0", "0"); + + // TV phosphor mode + myTVPhosphor->setState(false); + + // TV phosphor blend + myTVPhosLevel->setValue(50); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(25); + + // Make sure that mutually-exclusive items are not enabled at the same time + handleTVModeChange(NTSCFilter::Preset::OFF); + handlePhosphorChange(); + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + } + case 3: // Audio + mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); + myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); + myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); + myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); + myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); + + if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { + myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); + myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); + myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); + myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); + myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); + } + else updatePreset(); + + updateEnabledState(); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleTVModeChange(NTSCFilter::Preset preset) +{ + bool enable = preset == NTSCFilter::Preset::CUSTOM; + + myTVSharp->setEnabled(enable); + myTVRes->setEnabled(enable); + myTVArtifacts->setEnabled(enable); + myTVFringe->setEnabled(enable); + myTVBleed->setEnabled(enable); + myCloneComposite->setEnabled(enable); + myCloneSvideo->setEnabled(enable); + myCloneRGB->setEnabled(enable); + myCloneBad->setEnabled(enable); + myCloneCustom->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadTVAdjustables(NTSCFilter::Preset preset) +{ + NTSCFilter::Adjustable adj; + instance().frameBuffer().tiaSurface().ntsc().getAdjustables( + adj, NTSCFilter::Preset(preset)); + myTVSharp->setValue(adj.sharpness); + myTVRes->setValue(adj.resolution); + myTVArtifacts->setValue(adj.artifacts); + myTVFringe->setValue(adj.fringing); + myTVBleed->setValue(adj.bleed); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePaletteChange() +{ + bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; + + myPhaseShiftNtsc->setEnabled(enable); + myPhaseShiftPal->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePaletteUpdate() +{ + // TIA Palette + instance().settings().setValue("palette", + myTIAPalette->getSelectedTag().toString()); + // Palette adjustables + PaletteHandler::Adjustable paletteAdj; + paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue(); + paletteAdj.phasePal = myPhaseShiftPal->getValue(); + paletteAdj.hue = myTVHue->getValue(); + paletteAdj.saturation = myTVSatur->getValue(); + paletteAdj.contrast = myTVContrast->getValue(); + paletteAdj.brightness = myTVBright->getValue(); + paletteAdj.gamma = myTVGamma->getValue(); + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj); + + if(instance().hasConsole()) + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleFullScreenChange() +{ + bool enable = myFullscreen->getState(); + myUseStretch->setEnabled(enable); + myTVOverscan->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleOverscanChange() +{ + if (myTVOverscan->getValue() == 0) + { + myTVOverscan->setValueLabel("Off"); + myTVOverscan->setValueUnit(""); + } + else + myTVOverscan->setValueUnit("%"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePhosphorChange() +{ + myTVPhosLevel->setEnabled(myTVPhosphor->getState()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch (cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + close(); + break; + + case GuiObject::kCloseCmd: + // restore palette settings + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj); + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette); + Dialog::handleCommand(sender, cmd, data, 0); + break; + + case GuiObject::kDefaultsCmd: + setDefaults(); + break; + + case kPaletteChanged: + handlePaletteChange(); + handlePaletteUpdate(); + break; + + case kPaletteUpdated: + handlePaletteUpdate(); + break; + + case kNtscShiftChanged: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; + myPhaseShiftNtsc->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kPalShiftChanged: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; + myPhaseShiftPal->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kVSizeChanged: + { + int adjust = myVSizeAdjust->getValue(); + + if (!adjust) + { + myVSizeAdjust->setValueLabel("Default"); + myVSizeAdjust->setValueUnit(""); + } + else + myVSizeAdjust->setValueUnit("%"); + break; + } + case kFullScreenChanged: + handleFullScreenChange(); + break; + + case kOverscanChanged: + handleOverscanChange(); + break; + + case kTVModeChanged: + handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); + break; + + case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); + break; + case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); + break; + case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); + break; + case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); + break; + case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + + case kScanlinesChanged: + if (myTVScanIntense->getValue() == 0) + { + myTVScanIntense->setValueLabel("Off"); + myTVScanIntense->setValueUnit(""); + } + else + myTVScanIntense->setValueUnit("%"); + break; + + case kPhosphorChanged: + handlePhosphorChange(); + break; + + case kPhosBlendChanged: + if (myTVPhosLevel->getValue() == 0) + { + myTVPhosLevel->setValueLabel("Off"); + myTVPhosLevel->setValueUnit(""); + } + else + myTVPhosLevel->setValueUnit("%"); + break; + + case kSoundEnableChanged: + updateEnabledState(); + break; + + case kModeChanged: + updatePreset(); + updateEnabledState(); + break; + + case kHeadroomChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; + myHeadroomSlider->setValueLabel(ss.str()); + break; + } + case kBufferSizeChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; + myBufferSizeSlider->setValueLabel(ss.str()); + break; + } + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addPalette(int x, int y, int w, int h) +{ + if(instance().hasConsole()) + { + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const GUI::Font& ifont = instance().frameBuffer().infoFont(); + const int lwidth = ifont.getMaxCharWidth() * 1.5; + const float COLW = float(w - lwidth) / NUM_LUMA; + const float COLH = float(h) / NUM_CHROMA; + const int yofs = (COLH - ifont.getFontHeight() + 1) / 2; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " "); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH, + COLW + 1, COLH + 1, 0, false); + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::colorPalette() +{ + if(instance().hasConsole()) + { + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const int order[2][NUM_CHROMA] = + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15} + }; + const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + ostringstream ss; + const int color = order[type][idx]; + + ss << Common::Base::HEX1 << std::uppercase << color; + myColorLbl[idx]->setLabel(ss.str()); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateEnabledState() +{ + bool active = mySoundEnableCheckbox->getState(); + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + bool userMode = preset == AudioSettings::Preset::custom; + + myVolumeSlider->setEnabled(active); + myStereoSoundCheckbox->setEnabled(active); + myModePopup->setEnabled(active); + // enable only for Pitfall II cart + myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); + + myFragsizePopup->setEnabled(active && userMode); + myFreqPopup->setEnabled(active && userMode); + myResamplingPopup->setEnabled(active && userMode); + myHeadroomSlider->setEnabled(active && userMode); + myBufferSizeSlider->setEnabled(active && userMode); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updatePreset() +{ + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + + // Make a copy that does not affect the actual settings... + AudioSettings audioSettings = instance().audioSettings(); + audioSettings.setPersistent(false); + // ... and set the requested preset + audioSettings.setPreset(preset); + + updateSettingsWithPreset(audioSettings); +} diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoAudioDialog.hxx similarity index 66% rename from src/gui/VideoDialog.hxx rename to src/gui/VideoAudioDialog.hxx index 429290082..f46740ae6 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -15,77 +15,75 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#ifndef VIDEO_DIALOG_HXX -#define VIDEO_DIALOG_HXX +#ifndef VIDEOAUDIO_DIALOG_HXX +#define VIDEOAUDIO_DIALOG_HXX class CommandSender; class CheckboxWidget; +class ColorWidget; class DialogContainer; class PopUpWidget; +class RadioButtonGroup; class SliderWidget; class StaticTextWidget; class TabWidget; class OSystem; #include "Dialog.hxx" +#include "PaletteHandler.hxx" #include "NTSCFilter.hxx" #include "bspf.hxx" -class VideoDialog : public Dialog +class VideoAudioDialog : public Dialog { public: - VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h); - virtual ~VideoDialog() = default; + virtual ~VideoAudioDialog() = default; private: void loadConfig() override; void saveConfig() override; void setDefaults() override; + void addDisplayTab(); + void addPaletteTab(); + void addTVEffectsTab(); + void addAudioTab(); void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); void handlePaletteChange(); + void handlePaletteUpdate(); void handleFullScreenChange(); void handleOverscanChange(); void handlePhosphorChange(); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void addPalette(int x, int y, int h, int w); + void colorPalette(); + void updatePreset(); + void updateEnabledState(); + void updateSettingsWithPreset(AudioSettings&); private: TabWidget* myTab; // General options PopUpWidget* myRenderer{nullptr}; - SliderWidget* myTIAZoom{nullptr}; - PopUpWidget* myTIAPalette{nullptr}; - SliderWidget* myPhaseShiftNtsc{nullptr}; - SliderWidget* myPhaseShiftPal{nullptr}; CheckboxWidget* myTIAInterpolate{nullptr}; - SliderWidget* myVSizeAdjust{nullptr}; - SliderWidget* mySpeed{nullptr}; - CheckboxWidget* myFullscreen{nullptr}; //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch{nullptr}; SliderWidget* myTVOverscan{nullptr}; - CheckboxWidget* myUseVSync{nullptr}; - CheckboxWidget* myUIMessages{nullptr}; - CheckboxWidget* myCenter{nullptr}; - CheckboxWidget* myFastSCBios{nullptr}; - CheckboxWidget* myUseThreads{nullptr}; + SliderWidget* myTIAZoom{nullptr}; + SliderWidget* myVSizeAdjust{nullptr}; // TV effects adjustables (custom mode) PopUpWidget* myTVMode{nullptr}; SliderWidget* myTVSharp{nullptr}; - SliderWidget* myTVHue{nullptr}; SliderWidget* myTVRes{nullptr}; SliderWidget* myTVArtifacts{nullptr}; SliderWidget* myTVFringe{nullptr}; SliderWidget* myTVBleed{nullptr}; - SliderWidget* myTVBright{nullptr}; - SliderWidget* myTVContrast{nullptr}; - SliderWidget* myTVSatur{nullptr}; - SliderWidget* myTVGamma{nullptr}; // TV phosphor effect CheckboxWidget* myTVPhosphor{nullptr}; @@ -102,15 +100,44 @@ class VideoDialog : public Dialog ButtonWidget* myCloneBad{nullptr}; ButtonWidget* myCloneCustom{nullptr}; + // Palettes + PopUpWidget* myTIAPalette{nullptr}; + SliderWidget* myPhaseShiftNtsc{nullptr}; + SliderWidget* myPhaseShiftPal{nullptr}; + SliderWidget* myTVHue{nullptr}; + SliderWidget* myTVSatur{nullptr}; + SliderWidget* myTVBright{nullptr}; + SliderWidget* myTVContrast{nullptr}; + SliderWidget* myTVGamma{nullptr}; + std::array myColorLbl{nullptr}; + ColorWidget* myColor[16][8]{{nullptr}}; + + // Audio + CheckboxWidget* mySoundEnableCheckbox{nullptr}; + SliderWidget* myVolumeSlider{nullptr}; + CheckboxWidget* myStereoSoundCheckbox{nullptr}; + PopUpWidget* myModePopup{nullptr}; + PopUpWidget* myFragsizePopup{nullptr}; + PopUpWidget* myFreqPopup{nullptr}; + PopUpWidget* myResamplingPopup{nullptr}; + SliderWidget* myHeadroomSlider{nullptr}; + SliderWidget* myBufferSizeSlider{nullptr}; + SliderWidget* myDpcPitch{nullptr}; + + string myPalette; + PaletteHandler::Adjustable myPaletteAdj; + enum { - kPaletteChanged = 'VDpl', - kNtscShiftChanged = 'VDns', - kPalShiftChanged = 'VDps', - kSpeedupChanged = 'VDSp', + kZoomChanged = 'VDZo', kVSizeChanged = 'VDVs', kFullScreenChanged = 'VDFs', kOverscanChanged = 'VDOv', + kPaletteChanged = 'VDpl', + kNtscShiftChanged = 'VDns', + kPalShiftChanged = 'VDps', + kPaletteUpdated = 'VDpu', + kTVModeChanged = 'VDtv', kCloneCompositeCmd = 'CLcp', kCloneSvideoCmd = 'CLsv', @@ -119,16 +146,21 @@ class VideoDialog : public Dialog kCloneCustomCmd = 'CLcu', kPhosphorChanged = 'VDph', kPhosBlendChanged = 'VDbl', - kScanlinesChanged = 'VDsc' + kScanlinesChanged = 'VDsc', + + kSoundEnableChanged = 'ADse', + kModeChanged = 'ADmc', + kHeadroomChanged = 'ADhc', + kBufferSizeChanged = 'ADbc' }; private: // Following constructors and assignment operators not supported - VideoDialog() = delete; - VideoDialog(const VideoDialog&) = delete; - VideoDialog(VideoDialog&&) = delete; - VideoDialog& operator=(const VideoDialog&) = delete; - VideoDialog& operator=(VideoDialog&&) = delete; + VideoAudioDialog() = delete; + VideoAudioDialog(const VideoAudioDialog&) = delete; + VideoAudioDialog(VideoAudioDialog&&) = delete; + VideoAudioDialog& operator=(const VideoAudioDialog&) = delete; + VideoAudioDialog& operator=(VideoAudioDialog&&) = delete; }; #endif diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx deleted file mode 100644 index 30b7a6ccc..000000000 --- a/src/gui/VideoDialog.cxx +++ /dev/null @@ -1,772 +0,0 @@ -//============================================================================ -// -// 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 - -#include "bspf.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "EditTextWidget.hxx" -#include "PopUpWidget.hxx" -#include "Console.hxx" -#include "TIA.hxx" -#include "Settings.hxx" -#include "Widget.hxx" -#include "Font.hxx" -#include "TabWidget.hxx" -#include "NTSCFilter.hxx" -#include "TIASurface.hxx" - -#include "VideoDialog.hxx" - -namespace { - // Emulation speed is a positive float that multiplies the framerate. However, the UI controls - // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following - // mapping and formatting functions implement this conversion. The speedup factor is represented - // by an integer value between -900 and 900 (0 means no speedup). - - constexpr int MAX_SPEED = 900; - constexpr int MIN_SPEED = -900; - constexpr int SPEED_STEP = 10; - - int mapSpeed(float speed) - { - speed = std::abs(speed); - - return BSPF::clamp( - static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), - MIN_SPEED, MAX_SPEED - ); - } - - float unmapSpeed(int speed) - { - float f_speed = static_cast(speed) / 100; - - return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; - } - - string formatSpeed(int speed) { - stringstream ss; - - ss - << std::setw(3) << std::fixed << std::setprecision(0) - << (unmapSpeed(speed) * 100); - - return ss.str(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Video settings") -{ - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() * 1.25; - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - - int xpos, ypos, tabID; - int lwidth = font.getStringWidth("V-Size adjust "), - pwidth = font.getStringWidth("XXXXxXXXX"); - - WidgetArray wid; - VariantList items; - - // Set real dimensions - setSize(57 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, - _th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, - max_w, max_h); - - // The tab widget - xpos = 2; ypos = VGAP; - myTab = new TabWidget(this, font, xpos, ypos + _th, - _w - 2*xpos, - _h - _th - VGAP - buttonHeight - VBORDER * 2); - addTabWidget(myTab); - - xpos = HBORDER; ypos = VBORDER; - ////////////////////////////////////////////////////////// - // 1) General options - tabID = myTab->addTab(" General "); - - // Video renderer - myRenderer = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedRenderers(), - "Renderer ", lwidth); - wid.push_back(myRenderer); - ypos += lineHeight + VGAP; - - // TIA Palette - items.clear(); - VarList::push_back(items, "Standard", "standard"); - VarList::push_back(items, "z26", "z26"); - if (instance().checkUserPalette()) - VarList::push_back(items, "User", "user"); - VarList::push_back(items, "Custom", "custom"); - myTIAPalette = new PopUpWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, items, "Palette ", lwidth, kPaletteChanged); - wid.push_back(myTIAPalette); - ypos += lineHeight + VGAP; - - int swidth = myTIAPalette->getWidth() - lwidth; - int plWidth = font.getStringWidth("NTSC phase "); - int pswidth = swidth - INDENT + lwidth - plWidth; - - myPhaseShiftNtsc = - new SliderWidget(myTab, font, xpos + INDENT, ypos-1, pswidth, lineHeight, - "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); - myPhaseShiftNtsc->setMinValue(262 - 45); myPhaseShiftNtsc->setMaxValue(262 + 45); - myPhaseShiftNtsc->setTickmarkIntervals(4); - wid.push_back(myPhaseShiftNtsc); - ypos += lineHeight + VGAP; - - myPhaseShiftPal = - new SliderWidget(myTab, font, xpos + INDENT, ypos-1, pswidth, lineHeight, - "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); - myPhaseShiftPal->setMinValue(313 - 45); myPhaseShiftPal->setMaxValue(313 + 45); - myPhaseShiftPal->setTickmarkIntervals(4); - wid.push_back(myPhaseShiftPal); - ypos += lineHeight + VGAP * 4; - - // TIA interpolation - myTIAInterpolate = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Interpolation "); - wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP; - - - // TIA zoom levels (will be dynamically filled later) - myTIAZoom = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, - "Zoom ", lwidth, 0, fontWidth * 4, "%"); - myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); - wid.push_back(myTIAZoom); - ypos += lineHeight + VGAP; - - // Aspect ratio (NTSC mode) - myVSizeAdjust = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); - myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); - myVSizeAdjust->setTickmarkIntervals(2); - wid.push_back(myVSizeAdjust); - ypos += lineHeight + VGAP; - - // Speed - mySpeed = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "Emul. speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); - mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); - mySpeed->setStepValue(SPEED_STEP); - mySpeed->setTickmarkIntervals(2); - wid.push_back(mySpeed); - ypos += lineHeight + VGAP; - - // Use sync to vblank - myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync"); - wid.push_back(myUseVSync); - - // Move over to the next column - xpos = myVSizeAdjust->getRight() + fontWidth * 3; - ypos = VBORDER; - - // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); - wid.push_back(myFullscreen); - ypos += lineHeight + VGAP; - - /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); - myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedScreenModes(), "Mode "); - wid.push_back(myFullScreenMode); - ypos += lineHeight + VGAP;*/ - - // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "Stretch"); - wid.push_back(myUseStretch); - ypos += lineHeight + VGAP; - - // FS overscan - myTVOverscan = new SliderWidget(myTab, font, xpos + INDENT, ypos - 1, swidth, lineHeight, - "Overscan", font.getStringWidth("Overscan "), kOverscanChanged, fontWidth * 3, "%"); - myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); - myTVOverscan->setTickmarkIntervals(2); - wid.push_back(myTVOverscan); - ypos += (lineHeight + VGAP) * 2; - - // Skip progress load bars for SuperCharger ROMs - // Doesn't really belong here, but I couldn't find a better place for it - myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fast SuperCharger load"); - wid.push_back(myFastSCBios); - ypos += lineHeight + VGAP; - - // Show UI messages onscreen - myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Show UI messages"); - wid.push_back(myUIMessages); - ypos += lineHeight + VGAP; - - // Center window (in windowed mode) - myCenter = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Center window"); - wid.push_back(myCenter); - ypos += (lineHeight + VGAP) * 2; - - // Use multi-threading - myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Multi-threading"); - wid.push_back(myUseThreads); - - // Add items for tab 0 - addToFocusList(wid, myTab, tabID); - - ////////////////////////////////////////////////////////// - // 2) TV effects options - wid.clear(); - tabID = myTab->addTab(" TV Effects "); - xpos = HBORDER; - ypos = VBORDER; - swidth = fontWidth * 8 - fontWidth / 2; - - // TV Mode - items.clear(); - VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); - VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); - VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); - VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); - VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); - VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); - lwidth = font.getStringWidth("TV Mode "); - pwidth = font.getStringWidth("Bad adjust"); - myTVMode = - new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "TV mode ", lwidth, kTVModeChanged); - wid.push_back(myTVMode); - ypos += lineHeight + VGAP; - - // Custom adjustables (using macro voodoo) - xpos += INDENT - 2; ypos += 0; - lwidth = font.getStringWidth("Saturation "); - -#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ - myTV ## obj = \ - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \ - desc, lwidth, cmd, fontWidth*4, "%"); \ - myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ - myTV ## obj->setTickmarkIntervals(2); \ - wid.push_back(myTV ## obj); \ - ypos += lineHeight + VGAP; - - CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0) - CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0) - CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0) - CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0) - CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0) - CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) - CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) - CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) - CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) - CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) - - xpos += myTVContrast->getWidth() + fontWidth * 6; - ypos = VBORDER; - - lwidth = font.getStringWidth("Intensity "); - - // TV Phosphor effect - myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); - wid.push_back(myTVPhosphor); - ypos += lineHeight + VGAP / 2; - - // TV Phosphor blend level - xpos += INDENT; - swidth = font.getMaxCharWidth() * 10; - CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged) - ypos += VGAP * 2; - - // Scanline intensity and interpolation - xpos -= INDENT; - myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanlines:"); - ypos += lineHeight + VGAP / 2; - - xpos += INDENT; - CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity ", kScanlinesChanged) - ypos += VGAP * 3; - - // Adjustable presets - xpos -= INDENT; - int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20; -#define CREATE_CLONE_BUTTON(obj, desc) \ - myClone ## obj = \ - new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\ - desc, kClone ## obj ##Cmd); \ - wid.push_back(myClone ## obj); \ - ypos += buttonHeight + VGAP; - - ypos += VGAP; - CREATE_CLONE_BUTTON(RGB, "Clone RGB") - CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") - CREATE_CLONE_BUTTON(Composite, "Clone Composite") - CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") - CREATE_CLONE_BUTTON(Custom, "Revert") - - // Add items for tab 2 - addToFocusList(wid, myTab, tabID); - - // Activate the first tab - myTab->setActiveTab(0); - - // Add Defaults, OK and Cancel buttons - wid.clear(); - addDefaultsOKCancelBGroup(wid, font); - addBGroupToFocusList(wid); - - // Disable certain functions when we know they aren't present -#ifndef WINDOWED_SUPPORT - myFullscreen->clearFlags(Widget::FLAG_ENABLED); - myCenter->clearFlags(Widget::FLAG_ENABLED); -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadConfig() -{ - // Renderer settings - myRenderer->setSelected(instance().settings().getString("video"), "default"); - - // TIA zoom levels - // These are dynamically loaded, since they depend on the size of - // the desktop and which renderer we're using - float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values - float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); - - myTIAZoom->setMinValue(minZoom * 100); - myTIAZoom->setMaxValue(maxZoom * 100); - myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% - myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); - - // TIA Palette - myTIAPalette->setSelected( - instance().settings().getString("palette"), "standard"); - - // Custom Palette - myPhaseShiftNtsc->setValue(instance().settings().getFloat("phase_ntsc") * 10); - myPhaseShiftPal->setValue(instance().settings().getFloat("phase_pal") * 10); - handlePaletteChange(); - - // TIA interpolation - myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); - - // Aspect ratio setting (NTSC and PAL) - myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); - - // Emulation speed - int speed = mapSpeed(instance().settings().getFloat("speed")); - mySpeed->setValue(speed); - mySpeed->setValueLabel(formatSpeed(speed)); - - // Fullscreen - myFullscreen->setState(instance().settings().getBool("fullscreen")); - /*string mode = instance().settings().getString("fullscreenmode"); - myFullScreenMode->setSelected(mode);*/ - // Fullscreen stretch setting - myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); - // Fullscreen overscan setting - myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); - handleFullScreenChange(); - - // Use sync to vertical blank - myUseVSync->setState(instance().settings().getBool("vsync")); - - // Show UI messages - myUIMessages->setState(instance().settings().getBool("uimessages")); - - // Center window - myCenter->setState(instance().settings().getBool("center")); - - // Fast loading of Supercharger BIOS - myFastSCBios->setState(instance().settings().getBool("fastscbios")); - - // Multi-threaded rendering - myUseThreads->setState(instance().settings().getBool("threads")); - - // TV Mode - myTVMode->setSelected( - instance().settings().getString("tv.filter"), "0"); - int preset = instance().settings().getInt("tv.filter"); - handleTVModeChange(NTSCFilter::Preset(preset)); - - // TV Custom adjustables - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - - // TV phosphor mode - myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); - - // TV phosphor blend - myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); - handlePhosphorChange(); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); - - myTab->loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::saveConfig() -{ - // Renderer setting - instance().settings().setValue("video", - myRenderer->getSelectedTag().toString()); - - // TIA zoom levels - instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); - - // TIA Palette - instance().settings().setValue("palette", - myTIAPalette->getSelectedTag().toString()); - - // Custom Palette - instance().settings().setValue("phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0); - instance().settings().setValue("phase_pal", myPhaseShiftPal->getValue() / 10.0); - - // TIA interpolation - instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); - - // Aspect ratio setting (NTSC and PAL) - int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); - int newAdjust = myVSizeAdjust->getValue(); - bool vsizeChanged = oldAdjust != newAdjust; - - instance().settings().setValue("tia.vsizeadjust", newAdjust); - - // Speed - int speedup = mySpeed->getValue(); - instance().settings().setValue("speed", unmapSpeed(speedup)); - if (instance().hasConsole()) instance().console().initializeAudio(); - - // Fullscreen - instance().settings().setValue("fullscreen", myFullscreen->getState()); - // Fullscreen stretch setting - instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); - // Fullscreen overscan - instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); - - // Use sync to vertical blank - instance().settings().setValue("vsync", myUseVSync->getState()); - - // Show UI messages - instance().settings().setValue("uimessages", myUIMessages->getState()); - - // Center window - instance().settings().setValue("center", myCenter->getState()); - - // Fast loading of Supercharger BIOS - instance().settings().setValue("fastscbios", myFastSCBios->getState()); - - // Multi-threaded rendering - instance().settings().setValue("threads", myUseThreads->getState()); - if (instance().hasConsole()) - instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); - - // TV Mode - instance().settings().setValue("tv.filter", - myTVMode->getSelectedTag().toString()); - - // TV Custom adjustables - NTSCFilter::Adjustable adj; - adj.hue = myTVHue->getValue(); - adj.saturation = myTVSatur->getValue(); - adj.contrast = myTVContrast->getValue(); - adj.brightness = myTVBright->getValue(); - adj.sharpness = myTVSharp->getValue(); - adj.gamma = myTVGamma->getValue(); - adj.resolution = myTVRes->getValue(); - adj.artifacts = myTVArtifacts->getValue(); - adj.fringing = myTVFringe->getValue(); - adj.bleed = myTVBleed->getValue(); - instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj); - - // TV phosphor mode - instance().settings().setValue("tv.phosphor", - myTVPhosphor->getState() ? "always" : "byrom"); - // TV phosphor blend - instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" - ? "0" : myTVPhosLevel->getValueLabel()); - - // TV scanline intensity - instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); - - if(instance().hasConsole()) - { - instance().console().setTIAProperties(); - - if(instance().settings().getString("palette") == "custom") - { - instance().console().generateCustomPalette(0); - instance().console().generateCustomPalette(1); - } - - if(vsizeChanged) - { - instance().console().tia().clearFrameBuffer(); - instance().console().initializeVideo(); - } - } - - // Finally, issue a complete framebuffer re-initialization... - instance().createFrameBuffer(); - - // ... and apply potential setting changes to the TIA surface - instance().frameBuffer().tiaSurface().updateSurfaceSettings(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::setDefaults() -{ - switch(myTab->getActiveTab()) - { - case 0: // General - { - myRenderer->setSelectedIndex(0); - myTIAZoom->setValue(300); - myTIAPalette->setSelected("standard", ""); - myPhaseShiftNtsc->setValue(262); - myPhaseShiftPal->setValue(313); - myTIAInterpolate->setState(false); - myVSizeAdjust->setValue(0); - mySpeed->setValue(0); - - myFullscreen->setState(false); - //myFullScreenMode->setSelectedIndex(0); - myUseStretch->setState(false); - myUseVSync->setState(true); - myUIMessages->setState(true); - myCenter->setState(false); - myFastSCBios->setState(true); - myUseThreads->setState(false); - - handlePaletteChange(); - break; - } - - case 1: // TV effects - { - myTVMode->setSelected("0", "0"); - - // TV phosphor mode - myTVPhosphor->setState(false); - - // TV phosphor blend - myTVPhosLevel->setValue(50); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(25); - - // Make sure that mutually-exclusive items are not enabled at the same time - handleTVModeChange(NTSCFilter::Preset::OFF); - handlePhosphorChange(); - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) -{ - bool enable = preset == NTSCFilter::Preset::CUSTOM; - - myTVSharp->setEnabled(enable); - myTVHue->setEnabled(enable); - myTVRes->setEnabled(enable); - myTVArtifacts->setEnabled(enable); - myTVFringe->setEnabled(enable); - myTVBleed->setEnabled(enable); - myTVBright->setEnabled(enable); - myTVContrast->setEnabled(enable); - myTVSatur->setEnabled(enable); - myTVGamma->setEnabled(enable); - myCloneComposite->setEnabled(enable); - myCloneSvideo->setEnabled(enable); - myCloneRGB->setEnabled(enable); - myCloneBad->setEnabled(enable); - myCloneCustom->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) -{ - NTSCFilter::Adjustable adj; - instance().frameBuffer().tiaSurface().ntsc().getAdjustables( - adj, NTSCFilter::Preset(preset)); - myTVSharp->setValue(adj.sharpness); - myTVHue->setValue(adj.hue); - myTVRes->setValue(adj.resolution); - myTVArtifacts->setValue(adj.artifacts); - myTVFringe->setValue(adj.fringing); - myTVBleed->setValue(adj.bleed); - myTVBright->setValue(adj.brightness); - myTVContrast->setValue(adj.contrast); - myTVSatur->setValue(adj.saturation); - myTVGamma->setValue(adj.gamma); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePaletteChange() -{ - bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; - - myPhaseShiftNtsc->setEnabled(enable); - myPhaseShiftPal->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleFullScreenChange() -{ - bool enable = myFullscreen->getState(); - myUseStretch->setEnabled(enable); - myTVOverscan->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleOverscanChange() -{ - if (myTVOverscan->getValue() == 0) - { - myTVOverscan->setValueLabel("Off"); - myTVOverscan->setValueUnit(""); - } - else - myTVOverscan->setValueUnit("%"); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePhosphorChange() -{ - myTVPhosLevel->setEnabled(myTVPhosphor->getState()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch (cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kPaletteChanged: - handlePaletteChange(); - break; - - case kNtscShiftChanged: - { - std::ostringstream ss; - - ss << std::setw(4) << std::fixed << std::setprecision(1) - << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; - myPhaseShiftNtsc->setValueLabel(ss.str()); - break; - } - case kPalShiftChanged: - { - std::ostringstream ss; - - ss << std::setw(4) << std::fixed << std::setprecision(1) - << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; - myPhaseShiftPal->setValueLabel(ss.str()); - break; - } - case kVSizeChanged: - { - int adjust = myVSizeAdjust->getValue(); - - if (!adjust) - { - myVSizeAdjust->setValueLabel("Default"); - myVSizeAdjust->setValueUnit(""); - } - else - myVSizeAdjust->setValueUnit("%"); - break; - } - - case kSpeedupChanged: - mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); - break; - - case kFullScreenChanged: - handleFullScreenChange(); - break; - - case kOverscanChanged: - handleOverscanChange(); - break; - - case kTVModeChanged: - handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); - break; - - case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); - break; - case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); - break; - case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); - break; - case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); - break; - case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - - case kScanlinesChanged: - if (myTVScanIntense->getValue() == 0) - { - myTVScanIntense->setValueLabel("Off"); - myTVScanIntense->setValueUnit(""); - } - else - myTVScanIntense->setValueUnit("%"); - break; - - case kPhosphorChanged: - handlePhosphorChange(); - break; - - case kPhosBlendChanged: - if (myTVPhosLevel->getValue() == 0) - { - myTVPhosLevel->setValueLabel("Off"); - myTVPhosLevel->setValueUnit(""); - } - else - myTVPhosLevel->setValueUnit("%"); - break; - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index eb31f7cd4..b20b8b159 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -23,14 +23,13 @@ class Dialog; -namespace GUI { - class Font; -} - #include #include "bspf.hxx" #include "Event.hxx" +#include "EventHandlerConstants.hxx" +#include "FrameBufferConstants.hxx" +#include "StellaKeys.hxx" #include "GuiObject.hxx" #include "Font.hxx" diff --git a/src/gui/module.mk b/src/gui/module.mk index f550e167d..1447b8195 100644 --- a/src/gui/module.mk +++ b/src/gui/module.mk @@ -2,7 +2,6 @@ MODULE := src/gui MODULE_OBJS := \ src/gui/AboutDialog.o \ - src/gui/AudioDialog.o \ src/gui/BrowserDialog.o \ src/gui/CheckListWidget.o \ src/gui/ColorWidget.o \ @@ -15,6 +14,7 @@ MODULE_OBJS := \ src/gui/Dialog.o \ src/gui/EditableWidget.o \ src/gui/EditTextWidget.o \ + src/gui/EmulationDialog.o \ src/gui/EventMappingWidget.o \ src/gui/FileListWidget.o \ src/gui/Font.o \ @@ -49,7 +49,7 @@ MODULE_OBJS := \ src/gui/TimeMachineDialog.o \ src/gui/TimeMachine.o \ src/gui/UIDialog.o \ - src/gui/VideoDialog.o \ + src/gui/VideoAudioDialog.o \ src/gui/Widget.o MODULE_DIRS += \ diff --git a/src/libpng/pngconf.h b/src/libpng/pngconf.h index 927a769db..b5f468ae5 100644 --- a/src/libpng/pngconf.h +++ b/src/libpng/pngconf.h @@ -230,7 +230,7 @@ * the type. */ # ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# define PNG_EXPORT_TYPE(name) name PNG_IMPEXP # endif # define PNG_DLL_EXPORT __export # else /* newer compiler */ @@ -450,7 +450,7 @@ # define PNG_FP_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) +# define PNG_FP_EXPORT(ordinal, name, name, args) # endif #endif #ifndef PNG_FIXED_EXPORT /* A fixed point API. */ @@ -458,7 +458,7 @@ # define PNG_FIXED_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# define PNG_FIXED_EXPORT(ordinal, name, name, args) # endif #endif diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common index 1893fa57b..5fafdd855 100644 --- a/src/libretro/Makefile.common +++ b/src/libretro/Makefile.common @@ -23,6 +23,7 @@ SOURCES_CXX := \ $(CORE_DIR)/common/KeyMap.cxx \ $(CORE_DIR)/common/Logger.cxx \ $(CORE_DIR)/common/MouseControl.cxx \ + $(CORE_DIR)/common/PaletteHandler.cxx \ $(CORE_DIR)/common/PhosphorHandler.cxx \ $(CORE_DIR)/common/PhysicalJoystick.cxx \ $(CORE_DIR)/common/PJoystickHandler.cxx \ diff --git a/src/libretro/SoundLIBRETRO.hxx b/src/libretro/SoundLIBRETRO.hxx index 9709e4b3d..f99c8f341 100644 --- a/src/libretro/SoundLIBRETRO.hxx +++ b/src/libretro/SoundLIBRETRO.hxx @@ -27,7 +27,6 @@ class AudioSettings; #include "bspf.hxx" #include "Sound.hxx" -#include "AudioQueue.hxx" /** This class implements the sound API for LIBRTRO. @@ -96,10 +95,9 @@ class SoundLIBRETRO : 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. diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index e3cb5073a..d670c45a9 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -21,6 +21,7 @@ #include "FrameBufferLIBRETRO.hxx" #include "AtariNTSC.hxx" +#include "PaletteHandler.hxx" #include "AudioSettings.hxx" #include "Serializer.hxx" #include "StateManager.hxx" @@ -28,7 +29,6 @@ #include "TIA.hxx" #include "TIASurface.hxx" - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StellaLIBRETRO::StellaLIBRETRO() { @@ -40,7 +40,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_aspect_ntsc = 0; video_aspect_pal = 0; - video_palette = "standard"; + video_palette = PaletteHandler::SETTING_STANDARD; video_filter = NTSCFilter::Preset::OFF; video_ready = false; @@ -374,19 +374,12 @@ void StellaLIBRETRO::setVideoFilter(NTSCFilter::Preset mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaLIBRETRO::setVideoPalette(uInt32 mode) +void StellaLIBRETRO::setVideoPalette(const string& mode) { - switch (mode) - { - case 0: video_palette = "standard"; break; - case 1: video_palette = "z26"; break; - case 2: video_palette = "user"; break; - } - if (system_ready) { myOSystem->settings().setValue("palette", video_palette); - myOSystem->console().setPalette(video_palette); + myOSystem->frameBuffer().tiaSurface().paletteHandler().setPalette(video_palette); } } diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx index f48a13708..3078e8eb1 100644 --- a/src/libretro/StellaLIBRETRO.hxx +++ b/src/libretro/StellaLIBRETRO.hxx @@ -104,7 +104,7 @@ class StellaLIBRETRO void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; }; void setVideoFilter(NTSCFilter::Preset mode); - void setVideoPalette(uInt32 mode); + void setVideoPalette(const string& mode); void setVideoPhosphor(uInt32 mode, uInt32 blend); void setAudioStereo(int mode); diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx index 6babbf07f..8caae3765 100644 --- a/src/libretro/libretro.cxx +++ b/src/libretro/libretro.cxx @@ -15,6 +15,7 @@ #include "StellaLIBRETRO.hxx" #include "Event.hxx" #include "NTSCFilter.hxx" +#include "PaletteHandler.hxx" #include "Version.hxx" @@ -30,11 +31,12 @@ static retro_audio_sample_batch_t audio_batch_cb; // libretro UI settings static int setting_ntsc, setting_pal; -static int setting_stereo, setting_palette; +static int setting_stereo; static int setting_phosphor, setting_console, setting_phosphor_blend; static int stella_paddle_joypad_sensitivity; static int setting_crop_hoverscan, crop_left; static NTSCFilter::Preset setting_filter; +static const char* setting_palette; static bool system_reset; @@ -275,17 +277,11 @@ static void update_variables(bool init = false) RETRO_GET("stella_palette") { - int value = 0; - - if(!strcmp(var.value, "standard")) value = 0; - else if(!strcmp(var.value, "z26")) value = 1; - else if(!strcmp(var.value, "user")) value = 2; - - if(setting_palette != value) + if(setting_palette != var.value) { - stella.setVideoPalette(value); + stella.setVideoPalette(var.value); - setting_palette = value; + setting_palette = var.value; } } @@ -494,7 +490,7 @@ void retro_set_environment(retro_environment_t cb) static struct retro_variable variables[] = { // Adding more variables and rearranging them is safe. { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60" }, - { "stella_palette", "Palette colors; standard|z26|user" }, + { "stella_palette", "Palette colors; standard|z26|user|custom" }, { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted" }, { "stella_ntsc_aspect", "NTSC aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, { "stella_pal_aspect", "PAL aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj index 33eccde69..d59aac510 100644 --- a/src/macos/stella.xcodeproj/project.pbxproj +++ b/src/macos/stella.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 2D9173FA09BA90380026E9FF /* FrameBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D71062895B2006265D9 /* FrameBuffer.hxx */; }; 2D9173FB09BA90380026E9FF /* Settings.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D77062895F1006265D9 /* Settings.hxx */; }; 2D91740009BA90380026E9FF /* AboutDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */; }; - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */; }; 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */; }; 2D91740309BA90380026E9FF /* Command.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAA084578BF00812C11 /* Command.hxx */; }; 2D91740409BA90380026E9FF /* Dialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAC084578BF00812C11 /* Dialog.hxx */; }; @@ -61,7 +60,6 @@ 2D91741209BA90380026E9FF /* ProgressDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAC9084578BF00812C11 /* ProgressDialog.hxx */; }; 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */; }; 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */; }; - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */; }; 2D91741809BA90380026E9FF /* Widget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD5084578BF00812C11 /* Widget.hxx */; }; 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7108457B7D00812C11 /* CartUA.hxx */; }; 2D91741A09BA90380026E9FF /* FSNode.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7308457B7D00812C11 /* FSNode.hxx */; }; @@ -142,7 +140,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2D944848062904E800DD9879 /* Settings.cxx */; }; 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */; }; 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */; }; - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */; }; 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */; }; 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAB084578BF00812C11 /* Dialog.cxx */; }; 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAD084578BF00812C11 /* DialogContainer.cxx */; }; @@ -157,7 +154,6 @@ 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAC8084578BF00812C11 /* ProgressDialog.cxx */; }; 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEACA084578BF00812C11 /* ScrollBarWidget.cxx */; }; 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */; }; - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */; }; 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD4084578BF00812C11 /* Widget.cxx */; }; 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7008457B7D00812C11 /* CartUA.cxx */; }; 2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7208457B7D00812C11 /* FSNode.cxx */; }; @@ -233,8 +229,6 @@ DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */; }; DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */; }; DC2874071F8F2278004BF21A /* TrapArray.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2874061F8F2278004BF21A /* TrapArray.hxx */; }; - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */; }; - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */; }; DC2AADB0194F389C0026C7A4 /* TIASurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */; }; DC2AADB1194F389C0026C7A4 /* TIASurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */; }; DC2AADB4194F390F0026C7A4 /* CartRamWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */; }; @@ -250,6 +244,18 @@ DC368F5918A2FB710084199C /* SoundSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC368F5318A2FB710084199C /* SoundSDL2.hxx */; }; DC36D2C814CAFAB0007DC821 /* CartFA2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */; }; DC36D2C914CAFAB0007DC821 /* CartFA2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */; }; + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */; }; + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */; }; + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */; }; + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */; }; + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */; }; + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */; }; + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */; }; + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */; }; + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */; }; + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */; }; + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */; }; + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */; }; DC3DAFAC1F2E233B00A64410 /* PointingDevice.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */; }; DC3EE8561E2C0E6D00905161 /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83C1E2C0E6D00905161 /* adler32.c */; settings = {COMPILER_FLAGS = "-w"; }; }; DC3EE8571E2C0E6D00905161 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83D1E2C0E6D00905161 /* compress.c */; settings = {COMPILER_FLAGS = "-w"; }; }; @@ -393,8 +399,6 @@ DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; }; DC73BD8A1915E5E3003FAFAD /* FBSurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD881915E5E3003FAFAD /* FBSurface.hxx */; }; DC74D6A2138D4D7E00F05C5C /* StringParser.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */; }; - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */; }; - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */; }; DC79F81217A88D9E00288B91 /* Base.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC79F81017A88D9E00288B91 /* Base.cxx */; }; DC79F81317A88D9E00288B91 /* Base.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC79F81117A88D9E00288B91 /* Base.hxx */; }; DC7A24D5173B1CF600B20FE9 /* Variant.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC7A24D4173B1CF600B20FE9 /* Variant.hxx */; }; @@ -494,10 +498,6 @@ DCAAE5F11715887B0080BB82 /* CartFAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */; }; DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */; }; DCAAE5F31715887B0080BB82 /* CartUAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */; }; - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */; }; - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */; }; - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBAD21C54298300703A9B /* CartCVPlus.cxx */; }; - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBAD31C54298300703A9B /* CartCVPlus.hxx */; }; DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */; }; DCAD60A91152F8BD00BC4184 /* CartDPCPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */; }; DCB20EC71A0C506C0048F595 /* main.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCB20EC61A0C506C0048F595 /* main.cxx */; }; @@ -828,8 +828,6 @@ 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FSNodePOSIX.cxx; sourceTree = ""; }; 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AboutDialog.cxx; sourceTree = ""; }; 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AboutDialog.hxx; sourceTree = ""; }; - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDialog.cxx; sourceTree = ""; }; - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AudioDialog.hxx; sourceTree = ""; }; 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BrowserDialog.cxx; sourceTree = ""; }; 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = BrowserDialog.hxx; sourceTree = ""; }; 2DDBEAAA084578BF00812C11 /* Command.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Command.hxx; sourceTree = ""; }; @@ -860,8 +858,6 @@ 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ScrollBarWidget.hxx; sourceTree = ""; }; 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TabWidget.cxx; sourceTree = ""; }; 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = TabWidget.hxx; sourceTree = ""; }; - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDialog.cxx; sourceTree = ""; }; - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = VideoDialog.hxx; sourceTree = ""; }; 2DDBEAD4084578BF00812C11 /* Widget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Widget.cxx; sourceTree = ""; }; 2DDBEAD5084578BF00812C11 /* Widget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Widget.hxx; sourceTree = ""; }; 2DDBEB7008457B7D00812C11 /* CartUA.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartUA.cxx; sourceTree = ""; }; @@ -972,8 +968,6 @@ DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MinUICommandDialog.hxx; sourceTree = ""; }; DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinUICommandDialog.cxx; sourceTree = ""; }; DC2874061F8F2278004BF21A /* TrapArray.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrapArray.hxx; sourceTree = ""; }; - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASH.cxx; sourceTree = ""; }; - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASH.hxx; sourceTree = ""; }; DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TIASurface.cxx; sourceTree = ""; }; DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TIASurface.hxx; sourceTree = ""; }; DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartRamWidget.cxx; sourceTree = ""; }; @@ -989,6 +983,18 @@ DC368F5318A2FB710084199C /* SoundSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundSDL2.hxx; sourceTree = ""; }; DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartFA2.cxx; sourceTree = ""; }; DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFA2.hxx; sourceTree = ""; }; + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaletteHandler.cxx; sourceTree = ""; }; + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PaletteHandler.hxx; sourceTree = ""; }; + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoAudioDialog.cxx; sourceTree = ""; }; + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationDialog.cxx; sourceTree = ""; }; + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VideoAudioDialog.hxx; sourceTree = ""; }; + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EmulationDialog.hxx; sourceTree = ""; }; + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhanced.cxx; sourceTree = ""; }; + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cart3EX.hxx; sourceTree = ""; }; + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhanced.hxx; sourceTree = ""; }; + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cart3EX.cxx; sourceTree = ""; }; + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhancedWidget.cxx; sourceTree = ""; }; + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhancedWidget.hxx; sourceTree = ""; }; DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PointingDevice.hxx; sourceTree = ""; }; DC3EE83C1E2C0E6D00905161 /* adler32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adler32.c; sourceTree = ""; }; DC3EE83D1E2C0E6D00905161 /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; }; @@ -1132,8 +1138,6 @@ DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = ""; }; DC73BD881915E5E3003FAFAD /* FBSurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurface.hxx; sourceTree = ""; }; DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringParser.hxx; sourceTree = ""; }; - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASHWidget.cxx; sourceTree = ""; }; - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASHWidget.hxx; sourceTree = ""; }; DC79F81017A88D9E00288B91 /* Base.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base.cxx; sourceTree = ""; }; DC79F81117A88D9E00288B91 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hxx; sourceTree = ""; }; DC7A24D4173B1CF600B20FE9 /* Variant.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Variant.hxx; sourceTree = ""; }; @@ -1234,10 +1238,6 @@ DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFAWidget.hxx; sourceTree = ""; }; DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartUAWidget.cxx; sourceTree = ""; }; DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartUAWidget.hxx; sourceTree = ""; }; - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlusWidget.cxx; sourceTree = ""; }; - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlusWidget.hxx; sourceTree = ""; }; - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlus.cxx; sourceTree = ""; }; - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlus.hxx; sourceTree = ""; }; DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDPCPlus.cxx; sourceTree = ""; }; DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDPCPlus.hxx; sourceTree = ""; }; DCB20EC61A0C506C0048F595 /* main.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cxx; sourceTree = ""; }; @@ -1589,12 +1589,8 @@ DC676A2C1729A0B000E4E73D /* CartCMWidget.hxx */, DC676A2D1729A0B000E4E73D /* CartCTYWidget.cxx */, DC676A2E1729A0B000E4E73D /* CartCTYWidget.hxx */, - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */, - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */, DCAAE5BA1715887B0080BB82 /* CartCVWidget.cxx */, DCAAE5BB1715887B0080BB82 /* CartCVWidget.hxx */, - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */, - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */, DC5ACB5D1FBFCEB800A213FD /* CartDebugWidget.cxx */, DCAAE5BC1715887B0080BB82 /* CartDebugWidget.hxx */, DCAACB0A188D636F00A4D282 /* CartDFSCWidget.cxx */, @@ -1615,6 +1611,8 @@ DCAAE5BE1715887B0080BB82 /* CartEFSCWidget.hxx */, DCAAE5BF1715887B0080BB82 /* CartEFWidget.cxx */, DCAAE5C01715887B0080BB82 /* CartEFWidget.hxx */, + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */, + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */, DCAAE5C11715887B0080BB82 /* CartF0Widget.cxx */, DCAAE5C21715887B0080BB82 /* CartF0Widget.hxx */, DCAAE5C31715887B0080BB82 /* CartF4SCWidget.cxx */, @@ -1744,6 +1742,8 @@ DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */, DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */, DC56FCDD14CCCC4900A31CC3 /* MouseControl.hxx */, + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */, + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */, DCA233AE23B583FE0032ABF3 /* PhosphorHandler.cxx */, DCA233AF23B583FE0032ABF3 /* PhosphorHandler.hxx */, DC6DC91A205DB879004A5FC3 /* PhysicalJoystick.cxx */, @@ -1824,6 +1824,8 @@ 2D9555DA0880E78000466554 /* Cart3E.hxx */, DCBDDE9C1D6A5F2F009DF1E9 /* Cart3EPlus.cxx */, DCBDDE9D1D6A5F2F009DF1E9 /* Cart3EPlus.hxx */, + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */, + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */, 2DE2DF160627AE07006BEC99 /* Cart3F.cxx */, 2DE2DF170627AE07006BEC99 /* Cart3F.hxx */, DCD56D360B247D920092F9F8 /* Cart4A50.cxx */, @@ -1850,10 +1852,6 @@ DC6727091556F4860023653B /* CartCTY.hxx */, 2DE2DF1C0627AE07006BEC99 /* CartCV.cxx */, 2DE2DF1D0627AE07006BEC99 /* CartCV.hxx */, - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */, - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */, - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */, - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */, DCB2ECAC1F0AECA3009738A6 /* CartDetector.cxx */, DCB2ECAD1F0AECA3009738A6 /* CartDetector.hxx */, DCAACAF2188D631500A4D282 /* CartDF.cxx */, @@ -1874,6 +1872,8 @@ DCF467BF0F939A1400B25D7A /* CartEF.hxx */, DCF467C00F939A1400B25D7A /* CartEFSC.cxx */, DCF467C10F939A1400B25D7A /* CartEFSC.hxx */, + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */, + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */, DCF7B0D910A762FC007A2870 /* CartF0.cxx */, DCF7B0DA10A762FC007A2870 /* CartF0.hxx */, 2DE2DF240627AE07006BEC99 /* CartF4.cxx */, @@ -2003,8 +2003,6 @@ children = ( 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */, 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */, - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */, - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */, 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */, 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */, 2DEF21F808BC033500B246B4 /* CheckListWidget.cxx */, @@ -2034,6 +2032,8 @@ 2D403BA1086116D1001E31A1 /* EditableWidget.hxx */, 2D403BA4086116D1001E31A1 /* EditTextWidget.cxx */, 2D403BA5086116D1001E31A1 /* EditTextWidget.hxx */, + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */, + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */, 2D05FF5E096E269100A518FE /* EventMappingWidget.cxx */, 2D05FF5F096E269100A518FE /* EventMappingWidget.hxx */, DC7A24DD173B1DBC00B20FE9 /* FileListWidget.cxx */, @@ -2107,8 +2107,8 @@ DCA82C701FEB4E780059340F /* TimeMachineDialog.hxx */, DC8078E60B4BD697005E9305 /* UIDialog.cxx */, DC8078E70B4BD697005E9305 /* UIDialog.hxx */, - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */, - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */, + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */, + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */, 2DDBEAD4084578BF00812C11 /* Widget.cxx */, 2DDBEAD5084578BF00812C11 /* Widget.hxx */, ); @@ -2391,10 +2391,9 @@ DC5AAC2D1FCB24DF00C420A6 /* RadioButtonWidget.hxx in Headers */, 2D9173E309BA90380026E9FF /* Driving.hxx in Headers */, 2D9173E409BA90380026E9FF /* Event.hxx in Headers */, + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */, 2D9173E509BA90380026E9FF /* Joystick.hxx in Headers */, 2D9173E609BA90380026E9FF /* Keyboard.hxx in Headers */, - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */, - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */, DC1B2EC81E50036100F62837 /* TrakBall.hxx in Headers */, 2D9173E709BA90380026E9FF /* M6532.hxx in Headers */, E0893AF3211B9842008B170D /* HighPass.hxx in Headers */, @@ -2417,7 +2416,7 @@ DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */, DC96162F1F817830008A2206 /* AtariMouseWidget.hxx in Headers */, DCF4907A1A0ECE5B00A67AA9 /* Vec.hxx in Headers */, - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */, + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */, DC71EA9E1FDA06D2008827CB /* CartE78K.hxx in Headers */, 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */, 2D91740309BA90380026E9FF /* Command.hxx in Headers */, @@ -2446,7 +2445,6 @@ 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */, 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */, DCB2ECB01F0AECA3009738A6 /* CartDetector.hxx in Headers */, - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */, 2D91741809BA90380026E9FF /* Widget.hxx in Headers */, 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */, DCE8B1871E7E03B300189864 /* FrameLayout.hxx in Headers */, @@ -2476,6 +2474,7 @@ DC3EE86C1E2C0E6D00905161 /* zconf.h in Headers */, 2D91743609BA90380026E9FF /* DebuggerSystem.hxx in Headers */, 2D91743A09BA90380026E9FF /* Expression.hxx in Headers */, + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */, 2D91744F09BA90380026E9FF /* InputTextDialog.hxx in Headers */, DC1B2EC61E50036100F62837 /* AtariMouse.hxx in Headers */, DC9616331F817830008A2206 /* PointingDeviceWidget.hxx in Headers */, @@ -2502,7 +2501,7 @@ DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */, DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */, 2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */, - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */, + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */, 2D91745A09BA90380026E9FF /* RamWidget.hxx in Headers */, 2D91745B09BA90380026E9FF /* RomListWidget.hxx in Headers */, 2D91745C09BA90380026E9FF /* RomWidget.hxx in Headers */, @@ -2513,6 +2512,7 @@ 2D91746109BA90380026E9FF /* TogglePixelWidget.hxx in Headers */, 2D91746209BA90380026E9FF /* ToggleWidget.hxx in Headers */, 2D91746409BA90380026E9FF /* TiaZoomWidget.hxx in Headers */, + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */, DC1BC6672066B4390076F74A /* PKeyboardHandler.hxx in Headers */, 2D91746609BA90380026E9FF /* AudioWidget.hxx in Headers */, DC70065E241EC97900A459AB /* Stella14x28tFont.hxx in Headers */, @@ -2593,7 +2593,6 @@ DCD6FC7111C281ED005DA767 /* png.h in Headers */, DCD6FC7211C281ED005DA767 /* pngconf.h in Headers */, DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */, - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */, DCD6FC7711C281ED005DA767 /* pngpriv.h in Headers */, CFE3F60C1E84A9A200A8204E /* CartBUSWidget.hxx in Headers */, DCD6FC9411C28C6F005DA767 /* PNGLibrary.hxx in Headers */, @@ -2637,6 +2636,7 @@ DCE395EF16CB0B5F008DB1E5 /* FSNodeFactory.hxx in Headers */, DCE395F116CB0B5F008DB1E5 /* FSNodeZIP.hxx in Headers */, DCE395F316CB0B5F008DB1E5 /* ZipHandler.hxx in Headers */, + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */, DCAAE5D41715887B0080BB82 /* Cart2KWidget.hxx in Headers */, DCF7F129223D796000701A47 /* ProfilingRunner.hxx in Headers */, DCAAE5D61715887B0080BB82 /* Cart3FWidget.hxx in Headers */, @@ -2816,7 +2816,9 @@ E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */, E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */, 2D91747409BA90380026E9FF /* SDLMain.m in Sources */, + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */, 2D91747509BA90380026E9FF /* Booster.cxx in Sources */, + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */, DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */, 2D91747609BA90380026E9FF /* Cart.cxx in Sources */, 2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */, @@ -2844,6 +2846,7 @@ DCF3A6FA1DFC75E3008A8AF3 /* Player.cxx in Sources */, 2D91748609BA90380026E9FF /* CartFE.cxx in Sources */, 2D91748909BA90380026E9FF /* Console.cxx in Sources */, + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */, DC6DC91E205DB879004A5FC3 /* PhysicalJoystick.cxx in Sources */, E08FCD5323A037EB0051F59B /* QisBlitter.cxx in Sources */, DCCE0355225104BF008C246F /* StellaSettingsDialog.cxx in Sources */, @@ -2867,7 +2870,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */, 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */, 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */, - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */, 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */, 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */, 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */, @@ -2877,6 +2879,7 @@ 2D9174B309BA90380026E9FF /* LauncherDialog.cxx in Sources */, 2D9174B509BA90380026E9FF /* ListWidget.cxx in Sources */, 2D9174B609BA90380026E9FF /* Menu.cxx in Sources */, + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */, CFE3F60D1E84A9A200A8204E /* CartCDFWidget.cxx in Sources */, 2D9174B709BA90380026E9FF /* OptionsDialog.cxx in Sources */, 2D9174B809BA90380026E9FF /* PopUpWidget.cxx in Sources */, @@ -2886,7 +2889,6 @@ 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */, 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */, 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */, - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */, DC6A18FC19B3E67A00DEB242 /* CartMDM.cxx in Sources */, 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */, 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */, @@ -2914,7 +2916,6 @@ 2D9174F109BA90380026E9FF /* InputTextDialog.cxx in Sources */, DC6DC920205DB879004A5FC3 /* PJoystickHandler.cxx in Sources */, DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */, - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */, 2D9174F209BA90380026E9FF /* CheckListWidget.cxx in Sources */, 2D9174F309BA90380026E9FF /* StringListWidget.cxx in Sources */, 2D9174F409BA90380026E9FF /* CommandDialog.cxx in Sources */, @@ -2931,7 +2932,6 @@ DC5963132139FA14002736F2 /* Bankswitch.cxx in Sources */, DCDFF08120B781B0001227C0 /* DispatchResult.cxx in Sources */, 2D9174FC09BA90380026E9FF /* RamWidget.cxx in Sources */, - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */, DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */, E007231F210FBF5E002CF343 /* FpsMeter.cxx in Sources */, 2D9174FD09BA90380026E9FF /* RomListWidget.cxx in Sources */, @@ -2960,7 +2960,6 @@ DC47455A09C34BFA00EDDA3A /* CheatManager.cxx in Sources */, DC47455C09C34BFA00EDDA3A /* CheetahCheat.cxx in Sources */, DC62E6471960E87B007AEF05 /* AtariVoxWidget.cxx in Sources */, - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */, DC47455E09C34BFA00EDDA3A /* RamCheat.cxx in Sources */, E0FABEEC20E9948200EB8E28 /* AudioSettings.cxx in Sources */, DCD56D380B247D920092F9F8 /* Cart4A50.cxx in Sources */, @@ -3003,6 +3002,7 @@ DC6B2BA411037FF200F199A7 /* CartDebug.cxx in Sources */, DCB20EC71A0C506C0048F595 /* main.cxx in Sources */, DC6B2BA611037FF200F199A7 /* DiStella.cxx in Sources */, + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */, CFE3F6151E84A9CE00A8204E /* CartCDF.cxx in Sources */, E08D2F3E23089B9B000BD709 /* JoyMap.cxx in Sources */, DCA82C711FEB4E780059340F /* TimeMachine.cxx in Sources */, @@ -3103,6 +3103,7 @@ DC676A531729A0B000E4E73D /* CartFA2Widget.cxx in Sources */, DC676A551729A0B000E4E73D /* CartFEWidget.cxx in Sources */, DC676A591729A0B000E4E73D /* CartSBWidget.cxx in Sources */, + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */, DC676A5B1729A0B000E4E73D /* CartX07Widget.cxx in Sources */, DC7A24DF173B1DBC00B20FE9 /* FileListWidget.cxx in Sources */, DC13B53F176FF2F500B8B4BB /* RomListSettings.cxx in Sources */, @@ -3116,7 +3117,6 @@ DCAACAFC188D631500A4D282 /* CartDF.cxx in Sources */, DCAACAFE188D631500A4D282 /* CartDFSC.cxx in Sources */, DCAACB0E188D636F00A4D282 /* Cart4KSCWidget.cxx in Sources */, - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */, DCAACB10188D636F00A4D282 /* CartBFSCWidget.cxx in Sources */, DCAACB12188D636F00A4D282 /* CartBFWidget.cxx in Sources */, DCAACB14188D636F00A4D282 /* CartDFSCWidget.cxx in Sources */, diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 1095f2c09..6fef5d589 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -503,6 +503,7 @@ + @@ -757,6 +758,7 @@ + @@ -906,7 +908,6 @@ true - @@ -938,7 +939,7 @@ - + CompileAsC @@ -1503,6 +1504,7 @@ + @@ -1789,6 +1791,7 @@ + @@ -1965,7 +1968,6 @@ - @@ -2001,7 +2003,7 @@ - + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index fb763da4c..0e4f58929 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -342,9 +342,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -438,9 +435,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -1002,6 +996,15 @@ Source Files\emucore + + Source Files + + + Source Files\gui + + + Source Files\gui + @@ -1313,9 +1316,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -1421,9 +1421,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -2057,6 +2054,15 @@ Header Files\emucore + + Header Files + + + Header Files\gui + + + Header Files\gui +