diff --git a/.clang-format b/.clang-format
index 0f47c95e..2dcae007 100644
--- a/.clang-format
+++ b/.clang-format
@@ -38,7 +38,7 @@ BraceWrapping:
AfterExternBlock: true
BeforeCatch: false
BeforeElse: true
- # BeforeLambdaBody: true
+ BeforeLambdaBody: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
@@ -56,8 +56,8 @@ ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
-ConstructorInitializerIndentWidth: 2
-ContinuationIndentWidth: 2
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
@@ -84,7 +84,7 @@ IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: None
-IndentWidth: 2
+IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
@@ -132,7 +132,7 @@ Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
-TabWidth: 2
+TabWidth: 4
UseCRLF: false
UseTab: Always
...
diff --git a/README.md b/README.md
index c411800b..d31cad9d 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,12 @@ Please report issues in our [issue tracker](https://github.com/Chordian/sidfacto
![Commits since last
release](https://img.shields.io/github/commits-since/chordian/sidfactory2/release-20221007)
-- Changed: New default driver 11.05
+- Added: [#102](https://github.com/Chordian/sidfactory2/issues/102) Visualizers
+ for pulse width (per channel), filter cutoff and an indication per channel if
+ it is being filtered.
+- Added: Config option `Visualizer.PulseWidth.Style` to set the default style
+ for the pulse width visualizer.
+- Changed: New default driver is 11.05.00
- Added: [#156](https://github.com/Chordian/sidfactory2/issues/156)
Configuration option `Disk.Hide.Extensions` to hide files with certain
extensions in the file browser. Default values are `.sid`, `.wav` and `.mp3`
diff --git a/SIDFactoryII/SIDFactoryII.vcxproj b/SIDFactoryII/SIDFactoryII.vcxproj
index cd94eb77..36e1ddc3 100644
--- a/SIDFactoryII/SIDFactoryII.vcxproj
+++ b/SIDFactoryII/SIDFactoryII.vcxproj
@@ -195,6 +195,7 @@
+
@@ -232,6 +233,7 @@
+
@@ -283,6 +285,7 @@
+
@@ -373,6 +376,7 @@
+
@@ -410,6 +414,7 @@
+
@@ -471,6 +476,7 @@
+
diff --git a/SIDFactoryII/color_schemes/ash.ini b/SIDFactoryII/color_schemes/ash.ini
index ce928fd4..129cde54 100644
--- a/SIDFactoryII/color_schemes/ash.ini
+++ b/SIDFactoryII/color_schemes/ash.ini
@@ -103,6 +103,15 @@ Color.Orderlist.End.Stop = :LightGray
Color.Orderlist.Value = :Gray
Color.Orderlist.Value.Loop.Marker = :LightGreen
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :LowerGray
+Color.Visualizer.Bar.Background = :DarkGreen
+Color.Visualizer.Bar.BackgroundMuted = :LowGray
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x4e4e4e
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :Green
+Color.Visualizer.Bar.FillColorFilter = 0xd0d0d0
+
Color.Dialog.Background = :DarkerGray
Color.Dialog.Header = :DarkGray
Color.Dialog.Header.Text = :White
diff --git a/SIDFactoryII/color_schemes/classic.ini b/SIDFactoryII/color_schemes/classic.ini
index 3411ec5e..5235c67b 100644
--- a/SIDFactoryII/color_schemes/classic.ini
+++ b/SIDFactoryII/color_schemes/classic.ini
@@ -100,6 +100,15 @@ Color.Orderlist.End.Stop = :LightGray
Color.Orderlist.Value = :Gray
Color.Orderlist.Value.Loop.Marker = :LightGreen
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :Black
+Color.Visualizer.Bar.Background = :DarkerGray
+Color.Visualizer.Bar.BackgroundMuted = :LowGray
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x636363
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :Green
+Color.Visualizer.Bar.FillColorFilter = 0xa8a8a8
+
Color.Dialog.Background = :DarkerGray
Color.Dialog.Header = :Green
Color.Dialog.Header.Text = :Black
diff --git a/SIDFactoryII/color_schemes/default.ini b/SIDFactoryII/color_schemes/default.ini
index fa41133e..4a987820 100644
--- a/SIDFactoryII/color_schemes/default.ini
+++ b/SIDFactoryII/color_schemes/default.ini
@@ -1,30 +1,31 @@
// Default color scheme.
-Black = 0x000000
-White = 0xffffff
-Red = 0xff0000
-Green = 0x00c000
-Blue = 0x0000ff
-Yellow = 0xbfbf00
-LightRed = 0xff8080
-LightGreen = 0x40ff40
-LightBlue = 0x8080ff
-LightYellow = 0xffff60
-DarkRed = 0x800000
-DarkGreen = 0x006000
-DarkBlue = 0x000080
-DarkYellow = 0x707000
-LighterGreen = 0x80ff80
+Black = 0x000000
+White = 0xffffff
+Red = 0xff0000
+Green = 0x00c000
+Blue = 0x0000ff
+Yellow = 0xbfbf00
+LightRed = 0xff8080
+LightGreen = 0x40ff40
+LightBlue = 0x8080ff
+LightYellow = 0xffff60
+DarkRed = 0x800000
+DarkGreen = 0x006000
+DarkBlue = 0x000080
+DarkYellow = 0x707000
+LighterGreen = 0x80ff80
LighterGrey = 0xc0c0c0
-LightGrey = 0x888888
-Grey = 0x707070
-DarkGrey = 0x404040
-DarkerGrey = 0x202020
-DarkerRed = 0x600000
-DarkerGreen = 0x004800
-DarkerBlue = 0x000060
+LightGrey = 0x888888
+Grey = 0x707070
+DarkGrey = 0x404040
+DarkerGrey = 0x202020
+DarkerRed = 0x600000
+DarkerGreen = 0x004800
+DarkerBlue = 0x000060
DarkerYellow = 0x4c4c00
DarkestBlue = 0x000038
+DarkestGrey = 0x101010
Color.Table.Default = :LightGrey
@@ -32,13 +33,13 @@ Color.Table.Highlight = :White
Color.Table.Text.Background = :DarkGrey
Color.Table.Text = :White
Color.Table.Text.Editing = :LightYellow
-Color.Button.Text = :White
+Color.Button.Text = :White
Color.Button.Default = :Black
Color.Button.Default.MouseOver = :DarkGrey
Color.Button.Highlight = :Red
Color.Button.Highlight.MouseOver = :LightRed
Color.FileSelector.Background = :DarkBlue
-Color.FileSelector.List.Text = :White
+Color.FileSelector.List.Text = :White
Color.FileSelector.Text.Input = :White
Color.FileSelector.Cursor.Default = :DarkGrey
Color.FileSelector.Cursor.Focus.Default = :LightRed
@@ -47,14 +48,14 @@ Color.FileSelector.Cursor.Focus.Import.Song = :DarkYellow
Color.FileSelector.Cursor.Focus.Save.Song = :Red
Color.FileSelector.Cursor.Focus.Save.Packed = :Blue
Color.MarkerList.Background = :DarkBlue
-Color.MarkerList.Text = :White
+Color.MarkerList.Text = :White
Color.MarkerList.Cursor.Default = :DarkGrey
Color.MarkerList.Cursor.Focus.Default = :LightBlue
Color.SongList.Background = :DarkGrey
Color.SongList.BackgroundText = :DarkerGrey
Color.SongList.Text = :White
Color.SongList.Text.Editing = :LightYellow
-Color.SongList.EventPos = :White
+Color.SongList.EventPos = :White
Color.SongList.Values = :White
Color.SongList.Cursor = :DarkBlue
Color.SongList.Cursor.Focus = :Blue
@@ -108,15 +109,24 @@ Color.Orderlist.End.Stop = :White
Color.Orderlist.Value = :LightGrey
Color.Orderlist.Value.Loop.Marker = :LightGreen
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :DarkestGrey
+Color.Visualizer.Bar.Background = :DarkGrey
+Color.Visualizer.Bar.BackgroundMuted = :DarkerGrey
+Color.Visualizer.Bar.BackgroundFilteredChannel = :Grey // 0x643d00
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :White // 0xff8c82
+Color.Visualizer.Bar.FillColorFilter = :LightGrey // 0xcc7c00
+
Color.Dialog.Background = :DarkRed
Color.Dialog.Header = :Red
-Color.Dialog.Header.Text = :White
+Color.Dialog.Header.Text = :White
Color.Dialog.Text = :White
Color.Dialog.ListSelector.Cursor = :DarkGrey
Color.Dialog.ListSelector.Cursor.Focus = :DarkBlue
Color.Dialog.Optimizer.Used = :White
Color.Dialog.Optimizer.Unused = :LighterGrey
-Color.StatusBar.Text = :White
+Color.StatusBar.Text = :White
Color.StatusBar.Background.Stopped = :Blue
Color.StatusBar.Background.Stopped.MouseOver = :LightBlue
Color.StatusBar.Background.Playing = :DarkGreen
@@ -148,5 +158,5 @@ Color.FlightRecorder.Visualizer.CPUUsageHigh = :LightRed
Color.FlightRecorder.Visualizer.HorizontalLine1 = :White
Color.FlightRecorder.Visualizer.HorizontalLine2 = :Grey
-Color.DriverTableColor.Set = :LightGreen
+Color.DriverTableColor.Set = :LightGreen
Color.DriverTableColor.Jump = :LightYellow
\ No newline at end of file
diff --git a/SIDFactoryII/color_schemes/earth.ini b/SIDFactoryII/color_schemes/earth.ini
index 711388d9..72458af0 100644
--- a/SIDFactoryII/color_schemes/earth.ini
+++ b/SIDFactoryII/color_schemes/earth.ini
@@ -113,6 +113,15 @@ Color.Orderlist.End.Stop = :BgBright
Color.Orderlist.Value = :BgLightWeak
Color.Orderlist.Value.Loop.Marker = :DgLight
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :BgDarker
+Color.Visualizer.Bar.Background = :Ash
+Color.Visualizer.Bar.BackgroundMuted = :BgDark
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x474c42
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :Mist
+Color.Visualizer.Bar.FillColorFilter = 0x89967c
+
Color.Dialog.Background = :DgDark
Color.Dialog.Header = :DgDefault
Color.Dialog.Header.Text = :White
diff --git a/SIDFactoryII/color_schemes/isildur.ini b/SIDFactoryII/color_schemes/isildur.ini
index 2587906c..c8b3981f 100644
--- a/SIDFactoryII/color_schemes/isildur.ini
+++ b/SIDFactoryII/color_schemes/isildur.ini
@@ -1,29 +1,29 @@
// Isildur's color scheme.
-Black = 0x000000
-White = 0xbdbdbd
-Red = 0x844b40
-Green = 0x2f504a
-Blue = 0x364469
-Yellow = 0xbd9441
-LightRed = 0xff8080
-LightGreen = 0x69c68b
-LightBlue = 0x6b72a5
-LightYellow = 0xe7be8e
-DarkRed = 0x800000
-DarkGreen = 0x006000
-DarkBlue = 0x1e222f
-DarkYellow = 0x707000
-LighterGrey = 0xc0c0c0
-LightGrey = 0x888888
+Black = 0x000000
+White = 0xbdbdbd
+Red = 0x844b40
+Green = 0x2f504a
+Blue = 0x364469
+Yellow = 0xbd9441
+LightRed = 0xff8080
+LightGreen = 0x69c68b
+LightBlue = 0x6b72a5
+LightYellow = 0xe7be8e
+DarkRed = 0x800000
+DarkGreen = 0x006000
+DarkBlue = 0x1e222f
+DarkYellow = 0x707000
+LighterGrey = 0xc0c0c0
+LightGrey = 0x888888
Grey = 0x707070
-MidGrey = 0x505050
-DarkGrey = 0x25282d
-DarkerGrey = 0x202020
-DarkerRed = 0x5d2323
-DarkerGreen = 0x004800
-DarkerBlue = 0x000060
-DarkerYellow = 0x4c4c00
+MidGrey = 0x505050
+DarkGrey = 0x25282d
+DarkerGrey = 0x202020
+DarkerRed = 0x5d2323
+DarkerGreen = 0x004800
+DarkerBlue = 0x000060
+DarkerYellow = 0x4c4c00
Color.Table.Default = :LightGrey
@@ -103,6 +103,15 @@ Color.Orderlist.End.Stop = :White
Color.Orderlist.Value = :LightGrey
Color.Orderlist.Value.Loop.Marker = :LightGreen
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :Black
+Color.Visualizer.Bar.Background = :DarkBlue
+Color.Visualizer.Bar.BackgroundMuted = :DarkerGrey
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x403000
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :LightBlue
+Color.Visualizer.Bar.FillColorFilter = :Yellow
+
Color.Dialog.Background = :DarkRed
Color.Dialog.Header = :Red
Color.Dialog.Text = :White
@@ -141,5 +150,5 @@ Color.FlightRecorder.Visualizer.CPUUsageHigh = :LightRed
Color.FlightRecorder.Visualizer.HorizontalLine1 = 0xffffff
Color.FlightRecorder.Visualizer.HorizontalLine2 = 0x707070
-Color.DriverTableColor.Set = :LightGreen
+Color.DriverTableColor.Set = :LightGreen
Color.DriverTableColor.Jump = :LightYellow
\ No newline at end of file
diff --git a/SIDFactoryII/color_schemes/navy.ini b/SIDFactoryII/color_schemes/navy.ini
index 6a24511f..058ec1b7 100644
--- a/SIDFactoryII/color_schemes/navy.ini
+++ b/SIDFactoryII/color_schemes/navy.ini
@@ -105,6 +105,15 @@ Color.Orderlist.End.Stop = :BgBright
Color.Orderlist.Value = :BgLightWeak
Color.Orderlist.Value.Loop.Marker = :DgLight
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :Black
+Color.Visualizer.Bar.Background = :BgDefault
+Color.Visualizer.Bar.BackgroundMuted = :BgDark
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x383f1d
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :BgLightWeak
+Color.Visualizer.Bar.FillColorFilter = :TxDark
+
Color.Dialog.Background = :DgDark
Color.Dialog.Header = :DgDefault
Color.Dialog.Header.Text = :White
diff --git a/SIDFactoryII/color_schemes/ocean.ini b/SIDFactoryII/color_schemes/ocean.ini
index d1c9ea9d..f41f4e3f 100644
--- a/SIDFactoryII/color_schemes/ocean.ini
+++ b/SIDFactoryII/color_schemes/ocean.ini
@@ -1,4 +1,4 @@
-// Color scheme "Ocean" by JCH - based on a 5-color palette from Coolors.
+// Color scheme "Ocean" by JCH - based on a 5-color palette from Coolors.
CoolorsWhite = 0xffffff
@@ -105,6 +105,15 @@ Color.Orderlist.End.Stop = :CoolorsNovaOcean
Color.Orderlist.Value = :CoolorsLightWeakOcean
Color.Orderlist.Value.Loop.Marker = :CoolorsLightGreen
Color.Orderlist.Value.Input = :CoolorsWhite
+
+Color.Visualizer.Area = :CoolorsDarkerOcean
+Color.Visualizer.Bar.Background = :CoolorsOcean
+Color.Visualizer.Bar.BackgroundMuted = :CoolorsDarkOcean
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x423c2e
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :CoolorsLightWeakOcean
+Color.Visualizer.Bar.FillColorFilter = :CoolorsYellow
+
Color.Dialog.Background = :CoolorsDarkGreen
Color.Dialog.Header = :CoolorsGreen
Color.Dialog.Header.Text = :CoolorsWhite
@@ -145,5 +154,5 @@ Color.FlightRecorder.Visualizer.CPUUsageHigh = 0xff8080
Color.FlightRecorder.Visualizer.HorizontalLine1 = 0xffffff
Color.FlightRecorder.Visualizer.HorizontalLine2 = 0x707070
-Color.DriverTableColor.Set = :CoolorsLightGreen
+Color.DriverTableColor.Set = :CoolorsLightGreen
Color.DriverTableColor.Jump = :CoolorsLightYellow
\ No newline at end of file
diff --git a/SIDFactoryII/color_schemes/toilet.ini b/SIDFactoryII/color_schemes/toilet.ini
deleted file mode 100644
index 4742376d..00000000
--- a/SIDFactoryII/color_schemes/toilet.ini
+++ /dev/null
@@ -1,138 +0,0 @@
-// Toilet color scheme.
-
-Brown-2 = 0x201102
-Brown-1 = 0x402304
-Brown = 0x542f07
-Brown+1 = 0xc26b0e
-Brown+2 = 0xe37d10
-Brown+3 = 0xe89f51
-Brown+4 = 0xe3b584
-Brown+5 = 0xedd0b2
-Brown+6 = 0xedddcc
-White = 0xffffff
-Grey = 0xa0a0a0
-Grey+1 = 0xc0c0c0
-
-Color.Table.Default = 0xaaaaaa
-Color.Table.Highlight = :White
-Color.Table.Text.Background = 0x404040
-Color.Table.Text = :Brown+2
-Color.Table.Text.Editing = :White
-Color.Button.Text = :White // NEWNEWNEW
-Color.Button.Default = 0x000000
-Color.Button.Default.MouseOver = 0x404040
-Color.Button.Highlight = 0xff0000
-Color.Button.Highlight.MouseOver = 0xff8080
-Color.FileSelector.Background = :Brown
-Color.FileSelector.List.Text = :White // NEW
-Color.FileSelector.Text.Input = :White
-Color.FileSelector.Cursor.Default = 0x404040
-Color.FileSelector.Cursor.Focus.Default = 0xff8080
-Color.FileSelector.Cursor.Focus.Load.Song = 0x006000
-Color.FileSelector.Cursor.Focus.Import.Song = 0x707000
-Color.FileSelector.Cursor.Focus.Save.Song = 0xff0000
-Color.FileSelector.Cursor.Focus.Save.Packed = 0x0000ff
-Color.MarkerList.Background = :Brown
-Color.MarkerList.Text = :White // NEWNEW
-Color.MarkerList.Cursor.Default = 0x404040
-Color.MarkerList.Cursor.Focus.Default = :Brown+1
-Color.SongList.Background = :Brown-1
-Color.SongList.BackgroundText = :Brown-2
-Color.SongList.Text = :Brown+6
-Color.SongList.Text.Editing = :White
-Color.SongList.EventPos = :White // NEW
-Color.SongList.Values = :White
-Color.SongList.Cursor = :Brown
-Color.SongList.Cursor.Focus = :Brown+1
-Color.SongList.AreaMarking = :Brown
-Color.SongList.AreaMarking.Focus = :Brown+1
-Color.SongList.Playback.Marker = 0xff0000
-Color.SongList.Loop.Marker = :Brown+4
-Color.Track.Background = :Brown
-Color.Track.Background.FocusLine = :Brown-1
-Color.Track.BackgroundMuted = 0x404040
-Color.Track.BackgroundMuted.FocusLine = 0x202020
-Color.Track.MarkingArea = :Brown-1
-Color.Track.MarkingAreaMuted = 0x202020
-Color.Track.Name = :Brown+1
-Color.Track.Name.Selected = :Brown+3
-Color.Track.Name.Focus = :Brown+2
-Color.Track.Name.Selected.Focus = :White
-Color.Tracks.EventNumbers.Background = 0x202020
-Color.Tracks.EventNumbers.Default = 0x888888
-Color.Tracks.EventNumbers.FocusLine = 0xbfbf00
-Color.Tracks.EventNumbers.Highlight = :White
-Color.Tracks.EventNumbers.Highlight.FocusLine = 0xffff60
-Color.Tracks.EventNumbers.Playback.Marker = 0xff0000
-Color.Sequence.Error = 0xff8080
-Color.Sequence.Instrument.Empty = 0x888888
-Color.Sequence.Instrument.Empty.FocusLine = 0xc0c0c0
-Color.Sequence.Instrument.Tie = 0x888888
-Color.Sequence.Instrument.Tie.FocusLine = 0xc0c0c0
-Color.Sequence.Instrument.Value = :Brown+4
-Color.Sequence.Instrument.Value.FocusLine = :White
-Color.Sequence.Instrument.Value.Selected.Highlight = :Brown+5
-Color.Sequence.Instrument.Value.Selected.Highlight.FocusLine = :Brown+6
-Color.Sequence.Command.Empty = 0x888888
-Color.Sequence.Command.Empty.FocusLine = 0xc0c0c0
-Color.Sequence.Command.Value = :Brown+3
-Color.Sequence.Command.Value.FocusLine = :White
-Color.Sequence.Command.Value.Selected.Highlight = :Brown+5
-Color.Sequence.Command.Value.Selected.Highlight.FocusLine = :Brown+6
-Color.Sequence.Note.Empty = 0x888888
-Color.Sequence.Note.Empty.FocusLine = 0xc0c0c0
-Color.Sequence.Note.Gate.On = :Brown+2
-Color.Sequence.Note.Gate.On.FocusLine = :Brown+3
-Color.Sequence.Note.Value = :Brown+3
-Color.Sequence.Note.Value.FocusLine = :Brown+4
-Color.Sequence.Note.Value.Tied = :Grey
-Color.Sequence.Note.Value.Tied.FocusLine = :Grey+1
-Color.Sequence.Note.Value.Selected.Highlight = :Brown+5
-Color.Sequence.Note.Value.Selected.Highlight.FocusLine = :Brown+6
-Color.Orderlist.End.Loop = :White
-Color.Orderlist.End.Stop = :White
-Color.Orderlist.Value = 0x888888
-Color.Orderlist.Value.Loop.Marker = :Brown+3
-Color.Orderlist.Value.Input = :White
-Color.Dialog.Background = 0x800000
-Color.Dialog.Header = 0xff0000
-Color.Dialog.Header.Text = :White // NEW
-Color.Dialog.Text = :White
-Color.Dialog.ListSelector.Cursor = 0x404040
-Color.Dialog.ListSelector.Cursor.Focus = :Brown
-Color.Dialog.Optimizer.Used = :White
-Color.Dialog.Optimizer.Unused = 0xc0c0c0
-Color.StatusBar.Text = :White // NEWNEW
-Color.StatusBar.Background.Stopped = :Brown+1
-Color.StatusBar.Background.Stopped.MouseOver = :Brown+2
-Color.StatusBar.Background.Playing = 0x006000
-Color.StatusBar.Background.Playing.MouseOver = 0x00c000
-Color.StatusBar.Background.PlayingInput = 0x707000
-Color.StatusBar.Background.PlayingInput.MouseOver = 0xbfbf00
-Color.ScreenEdit.InfoRect.Background = 0x202020
-Color.ScreenEdit.InfoRect.Text = 0x808080
-Color.ScreenEdit.InfoRect.Text.Time.PlaybackState = :White
-Color.ScreenEdit.Table.Headline = :Brown+1
-Color.ScreenEdit.Table.Headline.HotkeyLetter = :Brown+3
-
-Color.Converters.Background = 0x202020
-Color.Console.Background = 0x000000
-Color.Console.Text = :Brown+3
-
-Color.FlightRecorder.Background = 0x202020
-Color.FlightRecorder.Description = 0xffffff
-Color.FlightRecorder.GateOn = 0xffffff
-Color.FlightRecorder.GateOff = 0xc0c0c0
-Color.FlightRecorder.FilterAndVolume = 0x8080ff
-Color.FlightRecorder.CPUUsageLow = 0x40ff40
-Color.FlightRecorder.CPUUsageMedium = 0xffff60
-Color.FlightRecorder.CPUUsageHigh = 0xff8080
-Color.FlightRecorder.Visualizer.Background = 0x404040
-Color.FlightRecorder.Visualizer.CPUUsageLow = 0x40ff40
-Color.FlightRecorder.Visualizer.CPUUsageMedium = 0xffff60
-Color.FlightRecorder.Visualizer.CPUUsageHigh = 0xff8080
-Color.FlightRecorder.Visualizer.HorizontalLine1 = 0xffffff
-Color.FlightRecorder.Visualizer.HorizontalLine2 = 0x707070
-
-Color.DriverTableColor.Set = :Brown+3
-Color.DriverTableColor.Jump = :Brown+2
\ No newline at end of file
diff --git a/SIDFactoryII/color_schemes/uglygreen.ini b/SIDFactoryII/color_schemes/uglygreen.ini
index b94987a5..6a09c7a7 100644
--- a/SIDFactoryII/color_schemes/uglygreen.ini
+++ b/SIDFactoryII/color_schemes/uglygreen.ini
@@ -102,6 +102,15 @@ Color.Orderlist.End.Stop = :White
Color.Orderlist.Value = 0x888888
Color.Orderlist.Value.Loop.Marker = :Green+5
Color.Orderlist.Value.Input = :White
+
+Color.Visualizer.Area = :Black
+Color.Visualizer.Bar.Background = :Green-1
+Color.Visualizer.Bar.BackgroundMuted = 0x202020
+Color.Visualizer.Bar.BackgroundFilteredChannel = 0x505050
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :Green+4
+Color.Visualizer.Bar.FillColorFilter = :Grey
+
Color.Dialog.Background = :Grey-1
Color.Dialog.Header = :Grey
Color.Dialog.Header.Text = :White // NEW
@@ -142,5 +151,5 @@ Color.FlightRecorder.Visualizer.CPUUsageHigh = 0xff8080
Color.FlightRecorder.Visualizer.HorizontalLine1 = 0xffffff
Color.FlightRecorder.Visualizer.HorizontalLine2 = 0x707070
-Color.DriverTableColor.Set = :Blue+4
+Color.DriverTableColor.Set = :Blue+4
Color.DriverTableColor.Jump = :Blue+2
\ No newline at end of file
diff --git a/SIDFactoryII/color_schemes/wisdom.ini b/SIDFactoryII/color_schemes/wisdom.ini
index 64bd5137..74f64518 100644
--- a/SIDFactoryII/color_schemes/wisdom.ini
+++ b/SIDFactoryII/color_schemes/wisdom.ini
@@ -24,13 +24,13 @@ Color.Table.Text.Background = :Black
Color.Table.Text = :MediumGrey
Color.Table.Text.Editing = :MediumGrey
-Color.Button.Text = :White
+Color.Button.Text = :White
Color.Button.Default = :Black
Color.Button.Default.MouseOver = :MediumGrey
Color.Button.Highlight = :Black
Color.Button.Highlight.MouseOver = :MediumGrey
Color.FileSelector.Background = :Blue
-Color.FileSelector.List.Text = :White
+Color.FileSelector.List.Text = :White
Color.FileSelector.Text.Input = :White
Color.FileSelector.Cursor.Default = :LightBlue
Color.FileSelector.Cursor.Focus.Default = :LightBlue
@@ -104,15 +104,29 @@ Color.Orderlist.Value = :White
Color.Orderlist.Value.Loop.Marker = :Purple
Color.Orderlist.Value.Input = :Purple
+Color.StateBar.Area = :Black
+Color.StateBar.Bar.Background = :Blue
+Color.StateBar.Bar.BackgroundFilteredChannel = :LightBlue
+Color.StateBar.Bar.FillColorPulse = :White
+Color.StateBar.Bar.FillColorFilter = :LightBlue
+
+Color.Visualizer.Area = :Black
+Color.Visualizer.Bar.Background = :Blue
+Color.Visualizer.Bar.BackgroundMuted = :Black
+Color.Visualizer.Bar.BackgroundFilteredChannel = :DarkGrey
+Color.Visualizer.Bar.Separator = :Black
+Color.Visualizer.Bar.FillColorPulse = :LightBlue
+Color.Visualizer.Bar.FillColorFilter = :LightGrey
+
Color.Dialog.Background = :Purple
Color.Dialog.Header = :LightRed
-Color.Dialog.Header.Text = :White
+Color.Dialog.Header.Text = :White
Color.Dialog.Text = :White
Color.Dialog.ListSelector.Cursor = :DarkGrey
Color.Dialog.ListSelector.Cursor.Focus = :DarkBlue
Color.Dialog.Optimizer.Used = :White
Color.Dialog.Optimizer.Unused = :LightGrey
-Color.StatusBar.Text = :White
+Color.StatusBar.Text = :White
Color.StatusBar.Background.Stopped = :Blue
Color.StatusBar.Background.Stopped.MouseOver = :LightBlue
Color.StatusBar.Background.Playing = :Green
diff --git a/SIDFactoryII/config.ini b/SIDFactoryII/config.ini
index d02d8b17..023a4a86 100644
--- a/SIDFactoryII/config.ini
+++ b/SIDFactoryII/config.ini
@@ -6,7 +6,7 @@
// The config.ini file contains the factory default settings. You can change these if you want, but it may be overwritten
// when you download and paste the next release. This is where the user.ini file comes in handy. If you want to make sure
// that your personal settings remain sticky, copy the changed entries to the user.ini file (you may have to create the
-// file first). All entries in user.ini will always override the corresponding entries in the config.ini file.
+// file first). All entries in user.ini will always override the corresponding entries in the config.ini file.
//
// A genuine settings dialog box is planned for a future release of SID Factory II.
//
@@ -48,18 +48,18 @@ Editor.Driver.Default = "sf2driver11_05.prg" // This determines
Editor.Skip.Intro = 0 // If you set this to 1, the black intro screen with logo and credits will never be shown.
-Editor.Follow.Play = 0 // If you set this to 1, follow play is on by default.
+Editor.Follow.Play = 0 // If you set this to 1, follow play is on by default.
-Editor.Sequence.Highlights = 0 // If you set this to 1, sequence highlights are on by default.
+Editor.Sequence.Highlights = 0 // If you set this to 1, sequence highlights are on by default.
Editor.Confirm.QuickSave = 1 // If you set this to 1, a confirmation dialog pops up when quick saving
// If set to 0, the quick save is performed without asking for confirmation
-
+
//
// PLAYBACK OPTIONS
//
-Playback.StopEmulationIfDriverStops = 1 // If the driver stops (at the end of a jingle, for instance), setting this value to non-zero
+Playback.StopEmulationIfDriverStops = 1 // If the driver stops (at the end of a jingle, for instance), setting this value to non-zero
// will stop the emulation and follow play also.
// Virtual piano keyboard layout
@@ -82,6 +82,12 @@ Window.Scaling = 1.0 // Scale window contents. Pixels
Window.Scaling.Smooth = 1 // If you set this to 1, scaling will smooth pixels.
// Set to 0 will use "nearest neighbour" scaling.
+//
+// Visualizers
+//
+Visualizer.PulseWidth.Style = 0 // The way pulse width is visualized
+ // 0 = absolute value, 1 = alternative style
+
//
// OVERLAY
//
diff --git a/SIDFactoryII/source/foundation/graphics/color.cpp b/SIDFactoryII/source/foundation/graphics/color.cpp
index e2853175..942e5fef 100644
--- a/SIDFactoryII/source/foundation/graphics/color.cpp
+++ b/SIDFactoryII/source/foundation/graphics/color.cpp
@@ -33,6 +33,7 @@ namespace Foundation
m_Colors[0x14] = 0xff004800; // Darker Green
m_Colors[0x15] = 0xff000060; // Darker Blue
m_Colors[0x16] = 0xff4c4c00; // Darker Yellow
+ m_Colors[0x17] = 0xff101010; // Darkest Grey
}
diff --git a/SIDFactoryII/source/foundation/graphics/color.h b/SIDFactoryII/source/foundation/graphics/color.h
index 30ee15de..50a25f17 100644
--- a/SIDFactoryII/source/foundation/graphics/color.h
+++ b/SIDFactoryII/source/foundation/graphics/color.h
@@ -29,6 +29,7 @@ namespace Foundation
DarkerGreen, // 20
DarkerBlue, // 21
DarkerYellow, // 22
+ DarkestGrey, // 23
UserColor00 = 0x40,
};
diff --git a/SIDFactoryII/source/runtime/editor/components/component_base.cpp b/SIDFactoryII/source/runtime/editor/components/component_base.cpp
index 110a4bd3..5655d823 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_base.cpp
+++ b/SIDFactoryII/source/runtime/editor/components/component_base.cpp
@@ -90,6 +90,11 @@ namespace Editor
//----------------------------------------------------------------------------------------------------------------------------------------
+ bool ComponentBase::CanReceiveFocus() const
+ {
+ return true;
+ }
+
bool ComponentBase::MayTabOutOfFocus(bool inForward) const
{
return true;
diff --git a/SIDFactoryII/source/runtime/editor/components/component_base.h b/SIDFactoryII/source/runtime/editor/components/component_base.h
index 4f598eb3..9eaf863f 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_base.h
+++ b/SIDFactoryII/source/runtime/editor/components/component_base.h
@@ -52,6 +52,7 @@ namespace Editor
virtual bool HasDataChange() const;
+ virtual bool CanReceiveFocus() const;
virtual bool MayTabOutOfFocus(bool inForward) const;
virtual bool IsNoteInputSilenced() const;
virtual bool IsFastForwardAllowed() const;
diff --git a/SIDFactoryII/source/runtime/editor/components/component_list_selector.cpp b/SIDFactoryII/source/runtime/editor/components/component_list_selector.cpp
index 08708697..4719c820 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_list_selector.cpp
+++ b/SIDFactoryII/source/runtime/editor/components/component_list_selector.cpp
@@ -213,6 +213,7 @@ namespace Editor
void ComponentListSelector::SetSelectionIndex(int inSelectionIndex)
{
m_CursorPos = inSelectionIndex;
+ AdjustTopVisibleToSelected();
m_RequireRefresh = true;
}
@@ -285,9 +286,7 @@ namespace Editor
if (m_CursorPos < m_DataSource->GetSize() - 1)
{
++m_CursorPos;
-
- if (m_CursorPos >= m_TopVisibleIndex + m_ContentHeight)
- m_TopVisibleIndex = m_CursorPos - m_ContentHeight + 1;
+ AdjustTopVisibleToSelected();
}
}
@@ -297,9 +296,7 @@ namespace Editor
if (m_CursorPos > 0)
{
--m_CursorPos;
-
- if (m_TopVisibleIndex > m_CursorPos)
- m_TopVisibleIndex = m_CursorPos;
+ AdjustTopVisibleToSelected();
}
}
@@ -314,9 +311,7 @@ namespace Editor
if (m_CursorPos != new_cursor_pos)
{
m_CursorPos = new_cursor_pos;
-
- if (m_CursorPos >= m_TopVisibleIndex + m_ContentHeight)
- m_TopVisibleIndex = m_CursorPos - m_ContentHeight + 1;
+ AdjustTopVisibleToSelected();
}
}
@@ -331,9 +326,7 @@ namespace Editor
if (m_CursorPos != new_cursor_pos)
{
m_CursorPos = new_cursor_pos;
-
- if (m_TopVisibleIndex > m_CursorPos)
- m_TopVisibleIndex = m_CursorPos;
+ AdjustTopVisibleToSelected();
}
}
@@ -343,9 +336,7 @@ namespace Editor
if (m_CursorPos != 0)
{
m_CursorPos = 0;
-
- if (m_TopVisibleIndex > m_CursorPos)
- m_TopVisibleIndex = m_CursorPos;
+ AdjustTopVisibleToSelected();
}
}
@@ -357,13 +348,20 @@ namespace Editor
if (m_CursorPos != new_cursor_pos)
{
m_CursorPos = new_cursor_pos;
-
- if (m_CursorPos >= m_TopVisibleIndex + m_ContentHeight)
- m_TopVisibleIndex = m_CursorPos - m_ContentHeight + 1;
+ AdjustTopVisibleToSelected();
}
}
+ void ComponentListSelector::AdjustTopVisibleToSelected()
+ {
+ if (m_CursorPos >= m_TopVisibleIndex + m_ContentHeight)
+ m_TopVisibleIndex = m_CursorPos - m_ContentHeight + 1;
+ if (m_TopVisibleIndex > m_CursorPos)
+ m_TopVisibleIndex = m_CursorPos;
+ }
+
+
std::string ComponentListSelector::CondenseString(const std::string& inString, const char* inPostFix, int inMaxLength) const
{
diff --git a/SIDFactoryII/source/runtime/editor/components/component_list_selector.h b/SIDFactoryII/source/runtime/editor/components/component_list_selector.h
index 6e66b750..9145227c 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_list_selector.h
+++ b/SIDFactoryII/source/runtime/editor/components/component_list_selector.h
@@ -51,6 +51,8 @@ namespace Editor
void DoPageHome();
void DoPageEnd();
+ void AdjustTopVisibleToSelected();
+
std::string CondenseString(const std::string& inString, const char* inPostFix, int inMaxLength) const;
Foundation::Color m_TextColor;
diff --git a/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.cpp b/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.cpp
index 37d7f13a..ec424f9c 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.cpp
+++ b/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.cpp
@@ -45,6 +45,7 @@ namespace Editor
int inGroupID,
Undo* inUndo,
TextField* inTextField,
+ const EditState& inEditState,
const Utility::KeyHookStore& inKeyHookStore,
std::shared_ptr inDataSourceTableText,
std::vector>& inOrderLists,
@@ -55,6 +56,7 @@ namespace Editor
std::function inSetTrackEventPosFunction
)
: ComponentBase(inID, inGroupID, inUndo, inTextField, inX, inY, ComponentOrderListOverview::GetWidthFromChannelCount(static_cast(inOrderLists.size())), inHeight)
+ , m_EditState(inEditState)
, m_TableText(inDataSourceTableText)
, m_OrderLists(inOrderLists)
, m_SequenceList(inSequenceList)
@@ -313,6 +315,12 @@ namespace Editor
}
}
+ if(consume)
+ {
+ if(UpdateHoveredSequence())
+ m_RequireRefresh = true;
+ }
+
if (m_TextEditingDataSourceTableText->RequireRefresh())
{
m_RequireRefresh = true;
@@ -340,6 +348,7 @@ namespace Editor
m_RequireRefresh = true;
consume = true;
+ UpdateHoveredSequence();
}
else if (inMouse.IsButtonPressed(Mouse::Left))
{
@@ -390,6 +399,8 @@ namespace Editor
}
consume = true;
+ UpdateHoveredSequence();
+
}
}
@@ -477,10 +488,11 @@ namespace Editor
}
int local_y = 0;
- int overview_list_size = static_cast(m_Overview.size());
-
- Color event_pos_values = ToColor(UserColor::SongListEventPos);
-
+
+ const int overview_list_size = static_cast(m_Overview.size());
+ const Color event_pos_values = ToColor(UserColor::SongListEventPos);
+ const int cursor_screen_y = cursor_position + m_Position.m_Y;
+
for (int i = m_TopPosition; i < overview_list_size && local_y < m_Dimensions.m_Height; ++i)
{
OverviewEntry& entry = m_Overview[i];
@@ -504,8 +516,17 @@ namespace Editor
int sequence_index = sequence_entry.m_Index;
if (sequence_index >= 0)
{
- const Color color = sequence_index < 0x100 ? ToColor(UserColor::SongListValues) : ToColor(UserColor::SongListLoopMarker);
- m_TextField->PrintHexValue(x, y, color, is_uppercase, static_cast(sequence_index & 0x0ff));
+ const unsigned char sequence_value = static_cast(sequence_index & 0x0ff);
+
+ if(m_EditState.IsSequenceHighlightingEnabled() && m_HasControl && y != cursor_screen_y && m_HoveredSequenceValue.HasValue() && m_HoveredSequenceValue.GetValue() == sequence_value)
+ {
+ m_TextField->PrintHexValue(x, y, Color::Yellow, is_uppercase, sequence_value);
+ }
+ else
+ {
+ const Color color = sequence_index < 0x100 ? ToColor(UserColor::SongListValues) : ToColor(UserColor::SongListLoopMarker);
+ m_TextField->PrintHexValue(x, y, color, is_uppercase, sequence_value);
+ }
}
x += 3;
@@ -1172,6 +1193,27 @@ namespace Editor
m_CursorY = m_MaxCursorY;
}
+ bool ComponentOrderListOverview::UpdateHoveredSequence()
+ {
+ HoveredSequenceValue NewValue;
+
+ if(m_CursorY < static_cast(m_Overview.size()))
+ {
+ const auto& Row = m_Overview[m_CursorY];
+ if(m_CursorX < static_cast(Row.m_SequenceEntries.size()))
+ NewValue.SetValue(Row.m_SequenceEntries[m_CursorX].m_Index);
+ }
+
+ if(m_HoveredSequenceValue != NewValue)
+ {
+ m_HoveredSequenceValue = NewValue;
+ return true;
+ }
+
+ return false;
+ }
+
+
void ComponentOrderListOverview::ConfigureKeyHooks(const Utility::KeyHookStore& inKeyHookStore)
{
using namespace Utility;
diff --git a/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.h b/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.h
index b0572b41..7de9448a 100644
--- a/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.h
+++ b/SIDFactoryII/source/runtime/editor/components/component_orderlistoverview.h
@@ -1,6 +1,7 @@
#pragma once
#include "component_base.h"
+#include "runtime/editor/edit_state.h"
#include "utils/event.h"
#include
@@ -36,6 +37,46 @@ namespace Editor
ComponentsManager& m_ComponentsManager;
};
+ struct HoveredSequenceValue
+ {
+ bool operator == (const HoveredSequenceValue& InRhs) const
+ {
+ return m_Value == InRhs.m_Value;
+ }
+
+ bool operator != (const HoveredSequenceValue& InRhs) const
+ {
+ return m_Value != InRhs.m_Value;
+ }
+
+ void Reset()
+ {
+ m_Value = 0x80;
+ }
+
+ bool HasValue() const
+ {
+ return (m_Value & 0x80) == 0;
+ }
+
+ void SetValue(int inValue)
+ {
+ if(inValue >= 0 && inValue < 0x7f)
+ m_Value = inValue;
+ else
+ m_Value = 0x80;
+ }
+
+ unsigned char GetValue() const
+ {
+ FOUNDATION_ASSERT(HasValue());
+ return m_Value;
+ }
+
+ private:
+ unsigned char m_Value = 0x80;
+ };
+
public:
using OrderListChangedEvent = Utility::TEvent;
@@ -43,7 +84,8 @@ namespace Editor
int inID,
int inGroupID,
Undo* inUndo,
- Foundation::TextField* inTextField,
+ Foundation::TextField* inTextField,
+ const EditState& inEditState,
const Utility::KeyHookStore& inKeyHookStore,
std::shared_ptr inDataSourceTableText,
std::vector>& inOrderLists,
@@ -110,6 +152,9 @@ namespace Editor
void RebuildOverview();
+ // Update hovered sequence
+ bool UpdateHoveredSequence();
+
// Key hooks
void ConfigureKeyHooks(const Utility::KeyHookStore& inKeyHookStore);
@@ -145,6 +190,9 @@ namespace Editor
OrderListChangedEvent m_OrderListChangedEvent;
+ const EditState& m_EditState;
+ HoveredSequenceValue m_HoveredSequenceValue;
+
int m_CursorY;
int m_CursorX;
int m_MaxCursorY;
diff --git a/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.cpp b/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.cpp
new file mode 100644
index 00000000..e1244add
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.cpp
@@ -0,0 +1,85 @@
+#include "runtime/editor/components/component_pulse_filter_visualizer.h"
+
+#include "foundation/graphics/drawfield.h"
+#include "foundation/graphics/textfield.h"
+#include "foundation/graphics/viewport.h"
+#include "runtime/editor/components_manager.h"
+#include "runtime/editor/datasources/datasource_sidregistersbuffer.h"
+#include "runtime/editor/datasources/datasource_track_components.h"
+#include "runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.h"
+#include "runtime/execution/executionhandler.h"
+
+namespace Editor
+{
+ ComponentPulseFilterVisualizer::ComponentPulseFilterVisualizer(
+ int inID,
+ int inGroupID,
+ Undo* inUndo,
+ Emulation::ExecutionHandler* inExecutionHandler,
+ Foundation::TextField* inTextField,
+ Foundation::Viewport* inViewport,
+ ComponentsManager* inComponentsManager,
+ std::shared_ptr inTracks,
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight)
+ : ComponentBase(inID, inGroupID, inUndo, inTextField, inX, inY, inWidth, inHeight)
+ , m_Viewport(inViewport)
+ , m_ComponentsManager(inComponentsManager)
+ {
+ unsigned int viewport_width = inWidth * Foundation::TextField::font_width;
+ unsigned int viewport_height = inHeight * Foundation::TextField::font_height;
+
+ m_DrawField = m_Viewport->CreateDrawField(viewport_width, viewport_height, inX * Foundation::TextField::font_width, inY * Foundation::TextField::font_height);
+ m_DrawField->SetEnable(true);
+
+ std::shared_ptr data_source_sid_registers_buffer = std::make_shared(inExecutionHandler);
+
+ m_VisualizerComponent = std::make_shared(1, m_DrawField, 0, 0, viewport_width, viewport_height, data_source_sid_registers_buffer, inTracks);
+ m_VisualizerComponent->SetEnabled(true);
+ m_ComponentsManager->AddVisualizerComponent(m_VisualizerComponent);
+ }
+
+ ComponentPulseFilterVisualizer::~ComponentPulseFilterVisualizer()
+ {
+ m_Viewport->Destroy(m_DrawField);
+ }
+
+
+ bool ComponentPulseFilterVisualizer::ConsumeInput(const Foundation::Keyboard& inKeyboard, CursorControl& inCursorControl, ComponentsManager& inComponentsManager)
+ {
+ return false;
+ }
+
+ bool ComponentPulseFilterVisualizer::ConsumeInput(const Foundation::Mouse& inMouse, bool inModifierKeyMask, CursorControl& inCursorControl, ComponentsManager& inComponentsManager)
+ {
+ return false;
+ }
+
+ bool ComponentPulseFilterVisualizer::ConsumeNonExclusiveInput(const Foundation::Mouse& inMouse)
+ {
+ return false;
+ }
+
+ void ComponentPulseFilterVisualizer::Refresh(const DisplayState& inDisplayState)
+ {
+ }
+
+ void ComponentPulseFilterVisualizer::HandleDataChange()
+ {
+ }
+
+ void ComponentPulseFilterVisualizer::PullDataFromSource(const bool inFromUndo)
+ {
+ }
+
+ void ComponentPulseFilterVisualizer::ExecuteInsertDeleteRule(const DriverInfo::TableInsertDeleteRule& inRule, int inSourceTableID, int inIndexPre, int inIndexPost)
+ {
+ }
+
+ void ComponentPulseFilterVisualizer::ExecuteAction(int inActionInput)
+ {
+ }
+
+}
diff --git a/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.h b/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.h
new file mode 100644
index 00000000..59ba25b2
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/components/component_pulse_filter_visualizer.h
@@ -0,0 +1,69 @@
+#pragma once
+#include "component_base.h"
+#include "runtime/editor/datasources/datasource_track_components.h"
+
+namespace Emulation
+{
+ class ExecutionHandler;
+}
+
+namespace Editor
+{
+ class DataSourceFlightRecorder;
+ class VisualizerComponentPulseFilterState;
+}
+
+namespace Foundation
+{
+ class DrawField;
+}
+
+namespace Foundation
+{
+ class Viewport;
+}
+
+namespace Editor
+{
+ class ComponentPulseFilterVisualizer : public ComponentBase
+ {
+ public:
+ ComponentPulseFilterVisualizer(
+ int inID,
+ int inGroupID,
+ Undo* inUndo,
+ Emulation::ExecutionHandler* inExecutionHandler,
+ Foundation::TextField* inTextField,
+ Foundation::Viewport* inViewport,
+ ComponentsManager* inComponentsManager,
+ std::shared_ptr inTracks,
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight);
+ virtual ~ComponentPulseFilterVisualizer();
+
+ bool CanReceiveFocus() const override { return false; }
+
+ bool ConsumeInput(const Foundation::Keyboard& inKeyboard, CursorControl& inCursorControl, ComponentsManager& inComponentsManager) override;
+ bool ConsumeInput(const Foundation::Mouse& inMouse, bool inModifierKeyMask, CursorControl& inCursorControl, ComponentsManager& inComponentsManager) override;
+ bool ConsumeNonExclusiveInput(const Foundation::Mouse& inMouse) override;
+
+ void Refresh(const DisplayState& inDisplayState) override;
+ void HandleDataChange() override;
+ void PullDataFromSource(const bool inFromUndo) override;
+
+ void ExecuteInsertDeleteRule(const DriverInfo::TableInsertDeleteRule& inRule, int inSourceTableID, int inIndexPre, int inIndexPost) override;
+ void ExecuteAction(int inActionInput) override;
+
+ private:
+ Foundation::Viewport* m_Viewport;
+ Foundation::DrawField* m_DrawField;
+
+ ComponentsManager* m_ComponentsManager;
+
+ Emulation::ExecutionHandler* m_ExecutionHandler;
+
+ std::shared_ptr m_VisualizerComponent;
+ };
+}
diff --git a/SIDFactoryII/source/runtime/editor/components_manager.cpp b/SIDFactoryII/source/runtime/editor/components_manager.cpp
index 2d45be88..f1bdb712 100644
--- a/SIDFactoryII/source/runtime/editor/components_manager.cpp
+++ b/SIDFactoryII/source/runtime/editor/components_manager.cpp
@@ -369,7 +369,7 @@ namespace Editor
{
ComponentBase* component = GetComponentAt(inMouse.GetPosition());
- if (component != nullptr)
+ if (component != nullptr && component->CanReceiveFocus())
{
if (component != m_FocusComponent)
SetComponentInFocus(component);
@@ -402,6 +402,12 @@ namespace Editor
}
}
}
+
+ // Let visualizer components consume non exclusive mouse input (if the mouse is over them)
+ auto* VisualComponent = GetVisualizerComponentAt(inMouse.GetPosition());
+
+ if(VisualComponent != nullptr)
+ VisualComponent->ConsumeNonExclusiveInput(inMouse);
}
return false;
@@ -464,7 +470,7 @@ namespace Editor
void ComponentsManager::SetComponentInFocus(ComponentBase* inFocusComponent)
{
- if (m_FocusComponent != inFocusComponent)
+ if (m_FocusComponent != inFocusComponent && (inFocusComponent == nullptr || inFocusComponent->CanReceiveFocus()))
{
if (m_FocusComponent != nullptr)
m_FocusComponent->ClearHasControl(*m_CursorControl);
@@ -532,7 +538,7 @@ namespace Editor
while (next_candidate != nullptr && next_candidate != m_FocusComponent)
{
- if (IsTabGroupEnabled(next_candidate->GetComponentGroupID()))
+ if (IsTabGroupEnabled(next_candidate->GetComponentGroupID()) && next_candidate->CanReceiveFocus())
{
SetComponentInFocusByTabbing(next_candidate, true);
return;
@@ -549,7 +555,7 @@ namespace Editor
while (next_candidate != nullptr && next_candidate != m_FocusComponent)
{
- if (IsTabGroupEnabled(next_candidate->GetComponentGroupID()))
+ if (IsTabGroupEnabled(next_candidate->GetComponentGroupID()) && next_candidate->CanReceiveFocus())
{
SetComponentInFocusByTabbing(next_candidate, false);
return;
@@ -635,4 +641,17 @@ namespace Editor
return nullptr;
}
+
+
+ VisualizerComponentBase* ComponentsManager::GetVisualizerComponentAt(const Foundation::Point& inPosition) const
+ {
+ for (auto visualizerComponent : m_VisualizerComponents)
+ {
+ if (visualizerComponent->ContainsPosition(inPosition))
+ return &*visualizerComponent;
+ }
+
+ return nullptr;
+ }
+
}
\ No newline at end of file
diff --git a/SIDFactoryII/source/runtime/editor/components_manager.h b/SIDFactoryII/source/runtime/editor/components_manager.h
index 78530dac..1bff13d7 100644
--- a/SIDFactoryII/source/runtime/editor/components_manager.h
+++ b/SIDFactoryII/source/runtime/editor/components_manager.h
@@ -84,6 +84,7 @@ namespace Editor
ComponentBase* GetComponentAfter(ComponentBase* inComponent) const;
ComponentBase* GetComponentBefore(ComponentBase* inComponent) const;
ComponentBase* GetComponentAt(const Foundation::Point& inPosition) const;
+ VisualizerComponentBase* GetVisualizerComponentAt(const Foundation::Point& inPosition) const;
bool m_Suspended;
diff --git a/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.cpp b/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.cpp
index 6d31bf80..dc733020 100644
--- a/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.cpp
+++ b/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.cpp
@@ -38,6 +38,14 @@ namespace Editor
return m_FlightRecorder->GetFrame(inIndex);
}
+ const Emulation::FlightRecorder::Frame& DataSourceFlightRecorder::GetMostRecentFrame() const
+ {
+ FOUNDATION_ASSERT(m_FlightRecorder != nullptr);
+ FOUNDATION_ASSERT(m_FlightRecorder->GetCapacity() > 0);
+
+ return m_FlightRecorder->GetNewestFrame();
+ }
+
const bool DataSourceFlightRecorder::IsRecording() const
{
diff --git a/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.h b/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.h
index 346dc2c2..7d6268ea 100644
--- a/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.h
+++ b/SIDFactoryII/source/runtime/editor/datasources/datasource_flightrecorder.h
@@ -15,6 +15,7 @@ namespace Editor
void Unlock();
const Emulation::FlightRecorder::Frame& operator [](unsigned int inIndex) const;
+ const Emulation::FlightRecorder::Frame& GetMostRecentFrame() const;
const int GetSize() const override;
const bool IsRecording() const;
const unsigned int GetNewestRecordingIndex() const;
diff --git a/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.cpp b/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.cpp
new file mode 100644
index 00000000..91397064
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.cpp
@@ -0,0 +1,40 @@
+#include "datasource_sidregistersbuffer.h"
+#include "foundation/base/assert.h"
+
+namespace Editor
+{
+ DataSourceSIDRegistersBufferAfLastDriverUpdate::DataSourceSIDRegistersBufferAfLastDriverUpdate(Emulation::ExecutionHandler* inExecutionHandler)
+ : m_ExecutionHandler(inExecutionHandler)
+ {
+
+ }
+
+
+ DataSourceSIDRegistersBufferAfLastDriverUpdate::~DataSourceSIDRegistersBufferAfLastDriverUpdate()
+ {
+
+ }
+
+
+ const unsigned char DataSourceSIDRegistersBufferAfLastDriverUpdate::operator [](unsigned int inIndex) const
+ {
+ FOUNDATION_ASSERT(inIndex < sizeof(m_SIDRegistersBuffer.m_Buffer));
+
+ return m_SIDRegistersBuffer.m_Buffer[inIndex];
+ }
+
+ const int DataSourceSIDRegistersBufferAfLastDriverUpdate::GetSize() const
+ {
+ return static_cast(sizeof(m_SIDRegistersBuffer.m_Buffer));
+ }
+
+ void DataSourceSIDRegistersBufferAfLastDriverUpdate::PullDataFromSource()
+ {
+ FOUNDATION_ASSERT(m_ExecutionHandler != nullptr);
+
+ m_ExecutionHandler->Lock();
+ m_SIDRegistersBuffer = m_ExecutionHandler->GetSIDRegistersBufferAfterLastDriverUpdate();
+ m_ExecutionHandler->Unlock();
+ }
+}
+
diff --git a/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.h b/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.h
new file mode 100644
index 00000000..6b4e37f8
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/datasources/datasource_sidregistersbuffer.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "idatasource.h"
+#include "runtime/execution/executionhandler.h"
+#include "runtime/execution/flightrecorder.h"
+
+namespace Editor
+{
+ class DataSourceSIDRegistersBufferAfLastDriverUpdate : public IDataSource
+ {
+ public:
+ DataSourceSIDRegistersBufferAfLastDriverUpdate(Emulation::ExecutionHandler* inExecutionHandler);
+ virtual ~DataSourceSIDRegistersBufferAfLastDriverUpdate();
+
+ const unsigned char operator [](unsigned int inIndex) const;
+ const int GetSize() const override;
+
+ bool PushDataToSource() override { return true; }
+ void PullDataFromSource();
+
+ protected:
+ Emulation::ExecutionHandler* m_ExecutionHandler;
+ Emulation::ExecutionHandler::SIDRegistersBuffer m_SIDRegistersBuffer;
+ };
+}
diff --git a/SIDFactoryII/source/runtime/editor/driver/driver_utils.cpp b/SIDFactoryII/source/runtime/editor/driver/driver_utils.cpp
index 0fca6812..97293092 100644
--- a/SIDFactoryII/source/runtime/editor/driver/driver_utils.cpp
+++ b/SIDFactoryII/source/runtime/editor/driver/driver_utils.cpp
@@ -65,11 +65,9 @@ namespace Editor
{
if (inDriverInfo.HasParsedHeaderBlock(DriverInfo::HeaderBlockID::ID_MusicData))
{
- // Get song count
- const unsigned char song_count = inDriverInfo.GetAuxilaryDataCollection().GetSongs().GetSongCount();
-
-
- std::vector usage_count(inDriverInfo.GetMusicData().m_SequenceCount, 0);
+ // Output collection
+ const int SequenceCount = static_cast(inDriverInfo.GetMusicData().m_SequenceCount);
+ std::vector usage_count(SequenceCount, 0);
// Get Music data descriptor
const DriverInfo::MusicData& music_data = inDriverInfo.GetMusicData();
@@ -77,15 +75,18 @@ namespace Editor
// Find highest used sequence index
unsigned short order_list_1 = music_data.m_OrderListTrack1Address;
+ // Get song count
+ const unsigned char song_count = inDriverInfo.GetAuxilaryDataCollection().GetSongs().GetSongCount();
+
for (unsigned char i = 0; i < music_data.m_TrackCount * song_count; ++i)
{
unsigned short order_list_address = order_list_1 + static_cast(i) * music_data.m_OrderListSize;
for (unsigned short j = 0; j < music_data.m_OrderListSize; ++j)
{
unsigned char value = inMemoryReader[order_list_address + j];
- if (value < 0x80)
+ if (value < SequenceCount)
{
- if (value == 0x7f)
+ if (value == 0x7e)
break;
usage_count[value]++;
diff --git a/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp b/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp
index 11cd650c..539308b0 100644
--- a/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp
+++ b/SIDFactoryII/source/runtime/editor/screens/screen_edit.cpp
@@ -59,6 +59,8 @@
#include "SDL.h"
#include
#include "foundation/base/assert.h"
+#include "runtime/editor/components/component_pulse_filter_visualizer.h"
+
#include
@@ -71,6 +73,7 @@ namespace Editor
const unsigned char ScreenEdit::OrderListOverviewID = 0x40;
const unsigned char ScreenEdit::PlayMarkerListID = 41;
const unsigned char ScreenEdit::TracksTableID = 0x42;
+ const unsigned char ScreenEdit::PulseFilterVisualizerID = 0x43;
ScreenEdit::ScreenEdit(
Foundation::Viewport* inViewport,
@@ -697,7 +700,7 @@ namespace Editor
AuxilaryDataEditingPreferences::NotationMode notation_mode = editing_preferences.GetNotationMode();
editing_preferences.SetNotationMode(notation_mode == AuxilaryDataEditingPreferences::NotationMode::Sharp
- ? AuxilaryDataEditingPreferences::NotationMode::Flat
+ ? AuxilaryDataEditingPreferences::NotationMode::Flat
: AuxilaryDataEditingPreferences::NotationMode::Sharp);
m_TracksComponent->ForceRefresh();
@@ -709,7 +712,7 @@ namespace Editor
if (inUp)
{
- const unsigned int max_octave = EditorUtils::Has2ndInputOctave() ? 6 : 7;
+ const unsigned int max_octave = EditorUtils::Has2ndNoteInputOctave() ? 6 : 7;
if (octave < max_octave)
m_EditState.SetOctave(octave + 1);
@@ -727,8 +730,8 @@ namespace Editor
if (!inToggleRegion)
{
- const AuxilaryDataHardwarePreferences::SIDModel sid_model = hardware_preferences.GetSIDModel() == AuxilaryDataHardwarePreferences::SIDModel::MOS6581
- ? AuxilaryDataHardwarePreferences::SIDModel::MOS8580
+ const AuxilaryDataHardwarePreferences::SIDModel sid_model = hardware_preferences.GetSIDModel() == AuxilaryDataHardwarePreferences::SIDModel::MOS6581
+ ? AuxilaryDataHardwarePreferences::SIDModel::MOS8580
: AuxilaryDataHardwarePreferences::SIDModel::MOS6581;
hardware_preferences.SetSIDModel(sid_model);
@@ -742,8 +745,8 @@ namespace Editor
}
else
{
- const AuxilaryDataHardwarePreferences::Region hardware_region = hardware_preferences.GetRegion() == AuxilaryDataHardwarePreferences::Region::PAL
- ? AuxilaryDataHardwarePreferences::Region::NTSC
+ const AuxilaryDataHardwarePreferences::Region hardware_region = hardware_preferences.GetRegion() == AuxilaryDataHardwarePreferences::Region::PAL
+ ? AuxilaryDataHardwarePreferences::Region::NTSC
: AuxilaryDataHardwarePreferences::Region::PAL;
hardware_preferences.SetRegion(hardware_region);
@@ -761,6 +764,7 @@ namespace Editor
{
m_EditState.SetSequenceHighlighting(!m_EditState.IsSequenceHighlightingEnabled());
m_TracksComponent->ForceRefresh();
+ m_OrderListOverviewComponent->ForceRefresh();
}
@@ -838,7 +842,7 @@ namespace Editor
m_CPUMemory->Unlock();
- m_ComponentsManager->StartDialog(std::make_shared("Statistics", text, 60, false, []() {}));
+ m_ComponentsManager->StartDialog(std::make_shared("Statistics", text, 60, false, []() {}));
}
break;
case DialogUtilities::Selection::Optimize:
@@ -889,10 +893,10 @@ namespace Editor
{
const unsigned short default_destination_address = 0x1000;
m_ComponentsManager->StartDialog(std::make_shared(
- default_destination_address,
- zp_range.m_LowestZeroPage,
- zp_range,
- dialog_ok,
+ default_destination_address,
+ zp_range.m_LowestZeroPage,
+ zp_range,
+ dialog_ok,
dialog_cancel
));
}
@@ -925,7 +929,7 @@ namespace Editor
m_CPUMemory->Lock();
DataSourceUtils::ExpandSequences(m_SequenceDataSources);
-
+
m_CPUMemory->Unlock();
m_ComponentsManager->ForceRefresh();
@@ -1114,7 +1118,7 @@ namespace Editor
return first_free_sequence_index;
};
-
+
auto get_first_empty_sequence_index = [&]() -> unsigned char
{
m_CPUMemory->Lock();
@@ -1157,7 +1161,7 @@ namespace Editor
const int top = 2;
const int bottom = text_field_dimensions.m_Height - 1;
- const int order_list_overview_bottom = bottom - (1 + AuxilaryDataPlayMarkers::MaxPlayMarkers);
+ const int order_list_overview_bottom = bottom - (2 + AuxilaryDataPlayMarkers::MaxPlayMarkers);
const int player_markers_list_top = order_list_overview_bottom + 1;
// Create orderlist overview component
@@ -1169,19 +1173,20 @@ namespace Editor
);
m_OrderListOverviewComponent = std::make_shared(
- OrderListOverviewID, 0,
+ OrderListOverviewID, 0,
undo,
- m_MainTextField,
+ m_MainTextField,
+ m_EditState,
m_KeyHookStore,
song_view_text_buffer,
- m_OrderListDataSources,
- m_SequenceDataSources,
- 1,
- top,
- order_list_overview_bottom - top,
+ m_OrderListDataSources,
+ m_SequenceDataSources,
+ 1,
+ top,
+ order_list_overview_bottom - top,
[&](int inEventPosition, bool inStartPlayingFromPosition)
{
- m_TracksComponent->SetEventPosition(inEventPosition, false);
+ m_TracksComponent->SetEventPosition(inEventPosition, false);
if(inStartPlayingFromPosition)
DoPlay(inEventPosition);
}
@@ -1193,18 +1198,19 @@ namespace Editor
// Play markers component
const int play_markers_width = orderlist_overview_rect.m_Dimensions.m_Width;
+ const int play_markers_height = 4;
auto play_markers_data_source = std::make_shared(m_DriverInfo->GetAuxilaryDataCollection().GetPlayMarkers(), m_DriverInfo->GetAuxilaryDataCollection().GetSongs(), m_DisplayState);
m_PlayMarkerListComponent = std::make_shared(
PlayMarkerListID, 0,
- undo,
- play_markers_data_source,
- m_MainTextField,
- 1,
- player_markers_list_top,
- play_markers_width,
- bottom - player_markers_list_top,
- 1,
+ undo,
+ play_markers_data_source,
+ m_MainTextField,
+ 1,
+ player_markers_list_top,
+ play_markers_width,
+ play_markers_height,
+ 1,
0
);
m_PlayMarkerListComponent->SetColors(ToColor(UserColor::MarkerListBackground), ToColor(UserColor::MarkerListCursorFocus), ToColor(UserColor::MarkerListCursorNoFocus));
@@ -1218,17 +1224,34 @@ namespace Editor
});
m_ComponentsManager->AddComponent(m_PlayMarkerListComponent);
+ // Create pulse/filter visualizer component
+ const int pulse_filter_visualzer_top = player_markers_list_top + play_markers_height + 1;
+ auto pulse_filter_visualizer = std::make_shared(
+ PulseFilterVisualizerID, 0,
+ undo,
+ m_ExecutionHandler,
+ m_MainTextField,
+ m_Viewport,
+ m_ComponentsManager.get(),
+ m_TracksDataSource,
+ 1,
+ pulse_filter_visualzer_top,
+ play_markers_width,
+ 4);
+
+ m_ComponentsManager->AddComponent(pulse_filter_visualizer);
+
// Create the tracks component for editing orderlist and sequence data
m_TracksComponent = std::make_shared(
- TracksTableID, 0,
- undo,
- m_TracksDataSource,
+ TracksTableID, 0,
+ undo,
+ m_TracksDataSource,
m_NotSelectedSongOrderListDataSources,
- m_MainTextField,
- m_DriverInfo->GetAuxilaryDataCollection(),
+ m_MainTextField,
+ m_DriverInfo->GetAuxilaryDataCollection(),
m_EditState,
- tracks_table_x,
- top,
+ tracks_table_x,
+ top,
bottom - top);
m_ComponentsManager->AddComponent(m_TracksComponent);
@@ -1241,7 +1264,7 @@ namespace Editor
// Create tables as configured by the driver
const std::vector& table_definitions = m_DriverInfo->GetTableDefinitions();
-
+
int highest_table = 0;
int widest_table = 0;
@@ -1381,9 +1404,9 @@ namespace Editor
table->GetSelectedRowChangedEvent().Add(
nullptr,
- Utility::TDelegate([&](int inSelectedRow)
- {
- m_EditState.SetSelectedInstrument(static_cast(inSelectedRow));
+ Utility::TDelegate([&](int inSelectedRow)
+ {
+ m_EditState.SetSelectedInstrument(static_cast(inSelectedRow));
m_TracksComponent->ForceRefresh();
})
);
@@ -1395,9 +1418,9 @@ namespace Editor
table->GetSelectedRowChangedEvent().Add(
nullptr,
- Utility::TDelegate([&](int inSelectedRow)
- {
- m_EditState.SetSelectedCommand(static_cast(inSelectedRow));
+ Utility::TDelegate([&](int inSelectedRow)
+ {
+ m_EditState.SetSelectedCommand(static_cast(inSelectedRow));
m_TracksComponent->ForceRefresh();
})
);
@@ -1720,7 +1743,7 @@ namespace Editor
std::string note_keys_octave1 = GetSingleConfigurationValue(config, "Key.Input.Notes.Octave1", std::string(""));
std::string note_keys_octave2 = GetSingleConfigurationValue(config, "Key.Input.Notes.Octave2", std::string(""));
- EditorUtils::SetNoteValueKeys(note_keys_octave1, note_keys_octave2);
+ EditorUtils::SetNoteInputValueKeys(note_keys_octave1, note_keys_octave2);
}
}
@@ -1752,7 +1775,7 @@ namespace Editor
return true;
} });
-
+
m_KeyHooks.push_back({ "Key.ScreenEdit.PlayFromMarker", m_KeyHookStore, [&]()
{
if (IsPlaying())
@@ -1821,31 +1844,31 @@ namespace Editor
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.OctaveDown", m_KeyHookStore, [&]()
- {
- DoOctaveChange(false);
+ {
+ DoOctaveChange(false);
return true;
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.OctaveUp", m_KeyHookStore, [&]()
- {
- DoOctaveChange(true);
+ {
+ DoOctaveChange(true);
return true;
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.ToggleSIDModel", m_KeyHookStore, [&]()
- {
- DoToggleSIDModelAndRegion(false);
+ {
+ DoToggleSIDModelAndRegion(false);
return true;
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.ToggleRegion", m_KeyHookStore, [&]()
- {
- DoToggleSIDModelAndRegion(true);
+ {
+ DoToggleSIDModelAndRegion(true);
return true;
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.LoadSong", m_KeyHookStore, [&]()
- {
+ {
DoStop();
DoLoadSong();
@@ -1853,7 +1876,7 @@ namespace Editor
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.LoadInstrument", m_KeyHookStore, [&]()
- {
+ {
DoStop();
DoLoadInstrument();
@@ -1861,7 +1884,7 @@ namespace Editor
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.ImportSong", m_KeyHookStore, [&]()
- {
+ {
DoStop();
DoLoadImportSong();
@@ -1869,7 +1892,7 @@ namespace Editor
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.SaveSong", m_KeyHookStore, [&]()
- {
+ {
DoStop();
DoSaveSong();
@@ -1877,7 +1900,7 @@ namespace Editor
} });
m_KeyHooks.push_back({ "Key.ScreenEdit.SaveInstrument", m_KeyHookStore, [&]()
- {
+ {
DoStop();
DoSaveInstrument();
@@ -1967,7 +1990,7 @@ namespace Editor
{
if (m_Undo->HasRedoStep())
{
- m_Undo->DoRedo(*m_CursorControl);
+ m_Undo->DoRedo(*m_CursorControl);
m_ComponentsManager->PullDataFromAllSources(true);
}
@@ -2113,7 +2136,7 @@ namespace Editor
if (it == m_KeyTableIDPairs.end())
return static_cast(i);
}
-
+
return -1;
}(table_definition.m_Name);
diff --git a/SIDFactoryII/source/runtime/editor/screens/screen_edit.h b/SIDFactoryII/source/runtime/editor/screens/screen_edit.h
index 972081cd..316b7986 100644
--- a/SIDFactoryII/source/runtime/editor/screens/screen_edit.h
+++ b/SIDFactoryII/source/runtime/editor/screens/screen_edit.h
@@ -63,9 +63,10 @@ namespace Editor
};
public:
- static const unsigned char OrderListOverviewID;
+ static const unsigned char OrderListOverviewID;
static const unsigned char PlayMarkerListID;
- static const unsigned char TracksTableID;
+ static const unsigned char TracksTableID;
+ static const unsigned char PulseFilterVisualizerID;
ScreenEdit(
Foundation::Viewport* inViewport,
diff --git a/SIDFactoryII/source/runtime/editor/utilities/editor_utils.cpp b/SIDFactoryII/source/runtime/editor/utilities/editor_utils.cpp
index e256ad0a..7d809510 100644
--- a/SIDFactoryII/source/runtime/editor/utilities/editor_utils.cpp
+++ b/SIDFactoryII/source/runtime/editor/utilities/editor_utils.cpp
@@ -18,13 +18,13 @@ namespace Editor
static std::string g_noteKeyListOctave1 = "zsxdcvgbhnjm,l.";
static std::string g_noteKeyListOctave2 = "q2w3er5t6y7ui9o0p";
- void SetNoteValueKeys(const std::string& inNoteKeyListOctave1, const std::string& inNoteKeyListOctave2)
+ void SetNoteInputValueKeys(const std::string& inNoteKeyListOctave1, const std::string& inNoteKeyListOctave2)
{
g_noteKeyListOctave1 = inNoteKeyListOctave1;
g_noteKeyListOctave2 = inNoteKeyListOctave2;
}
- bool Has2ndInputOctave()
+ bool Has2ndNoteInputOctave()
{
return !g_noteKeyListOctave2.empty();
}
diff --git a/SIDFactoryII/source/runtime/editor/utilities/editor_utils.h b/SIDFactoryII/source/runtime/editor/utilities/editor_utils.h
index 17bb8c1b..c85b297d 100644
--- a/SIDFactoryII/source/runtime/editor/utilities/editor_utils.h
+++ b/SIDFactoryII/source/runtime/editor/utilities/editor_utils.h
@@ -17,20 +17,27 @@ namespace Editor
{
static constexpr int MAX_SONG_COUNT = 0x10;
- void SetNoteValueKeys(const std::string& inNoteKeyListOctave1, const std::string& inNoteKeyListOctave2);
- bool Has2ndInputOctave();
+ // Function for note inputs
+ void SetNoteInputValueKeys(const std::string& inNoteKeyListOctave1, const std::string& inNoteKeyListOctave2);
+ bool Has2ndNoteInputOctave();
+
int GetNoteValue(SDL_Keycode inKeyCode, int inOctave);
int GetNoteValue(char inKeyCharacter, int inOctave);
+
+ // Hex conversion functions
unsigned char ConvertSingleCharHexValueToValue(char inKeyCharacter);
char ConvertValueToSingleCharHexValue(unsigned char inValue, bool inUppercase);
std::string ConvertToHexValue(unsigned char inValue, bool inUppercase);
std::string ConvertToHexValue(unsigned short inValue, bool inUppercase);
+ // Table ID query functions
unsigned char GetTableIDFromNameInTableDefinition(const DriverInfo& inDriverinfo, const std::string& inTableName);
+ // Utility methods for upgrading to multi song packages
void UpdateSongNameOfSingleSongPackages(DriverInfo& inDriverInfo);
void AddMissingPlayerMarkerLayers(DriverInfo& inDriverInfo);
+ // Multi song utility functions
void SelectSong(unsigned int inIndex, DriverInfo& inDriverInfo, Emulation::CPUMemory& inCPUMemory);
void AddSong(const std::string& inName, DriverInfo& inDriverInfo, Emulation::CPUMemory& inCPUMemory, ComponentsManager* inComponentsManager, unsigned char inSongOverviewTableID);
void RemoveSong(unsigned int inIndex, DriverInfo& inDriverInfo, Emulation::CPUMemory& inCPUMemory, ComponentsManager* inComponentsManager, unsigned char inSongOverviewTableID);
diff --git a/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_base.cpp b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_base.cpp
index 6c60d9c9..c546cc44 100644
--- a/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_base.cpp
+++ b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_base.cpp
@@ -62,7 +62,8 @@ namespace Editor
bool VisualizerComponentBase::ContainsPosition(const Foundation::Point& inPixelPosition) const
{
- return m_Rect.Contains(inPixelPosition);
+ Foundation::Rect Rect = { m_DrawField->GetPosition(), m_Rect.m_Dimensions };
+ return Rect.Contains(inPixelPosition);
}
diff --git a/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.cpp b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.cpp
new file mode 100644
index 00000000..1ad95945
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.cpp
@@ -0,0 +1,195 @@
+#include "visualizer_component_pulse_filter_state.h"
+
+#include "foundation/graphics/drawfield.h"
+#include "foundation/input/mouse.h"
+#include "runtime/editor/components/component_file_selector.h"
+#include "runtime/editor/datasources/datasource_sidregistersbuffer.h"
+#include "runtime/execution/executionhandler.h"
+#include "runtime/execution/flightrecorder.h"
+#include "utils/configfile.h"
+#include "utils/global.h"
+#include "utils/usercolors.h"
+
+using namespace Foundation;
+using namespace Utility;
+using namespace Utility::Config;
+
+namespace Editor
+{
+ VisualizerComponentPulseFilterState::VisualizerComponentPulseFilterState(
+ int inID,
+ Foundation::DrawField* inDrawField,
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ std::shared_ptr inDataSource,
+ std::shared_ptr inTracks)
+ : VisualizerComponentBase(inID, inDrawField, inX, inY, inWidth, inHeight)
+ , m_DataSource(inDataSource)
+ , m_Tracks(inTracks)
+ {
+ ConfigFile& config_file = Global::instance().GetConfig();
+ m_PulseWidthStyle = GetSingleConfigurationValue(config_file, "Visualizer.PulseWidth.Style", 0);
+ }
+
+
+ VisualizerComponentPulseFilterState::~VisualizerComponentPulseFilterState()
+ {
+ }
+
+
+ bool VisualizerComponentPulseFilterState::ConsumeNonExclusiveInput(const Foundation::Mouse& inMouse)
+ {
+ if (inMouse.IsButtonPressed(Mouse::Button::Left))
+ {
+ m_PulseWidthStyle = (m_PulseWidthStyle + 1) & 1;
+ return true;
+ }
+
+ return false;
+ }
+
+
+ void VisualizerComponentPulseFilterState::Refresh(const DisplayState& inDisplayState)
+ {
+ if (m_Enabled)
+ {
+ const Color color_background = ToColor(UserColor::VisualizerArea);
+ const Color color_bar = ToColor(UserColor::VisualizerBarBackground);
+ const Color color_bar_filtered_channel = ToColor(UserColor::VisualizerBarBackgroundFilteredChannel);
+ const Color color_bar_fill = ToColor(UserColor::VisualizerBarFillColorPulse);
+ const Color color_bar_fill_filter = ToColor(UserColor::VisualizerBarFillColorFilter);
+ const Color color_muted = ToColor(UserColor::VisualizerBarBackgroundMuted);
+ const Color color_separator = ToColor(UserColor::VisualizerBarSeparator);
+
+ m_DataSource->PullDataFromSource();
+
+ m_DrawField->DrawBox(color_background, 0, 0, m_Dimensions.m_Width, m_Dimensions.m_Height);
+
+ const int bar_width = m_Dimensions.m_Width - 4;
+ const int bar_height = 12;
+ const int bar_spacing = 16;
+
+ int bar_x = 2;
+ int bar_y = 2;
+
+ const auto& data_source = *m_DataSource;
+
+ const auto get_pulse_value = [&data_source](unsigned int inChannel) -> unsigned short
+ {
+ if (inChannel > 2)
+ return 0;
+
+ const unsigned int offset = inChannel * 7;
+
+ const unsigned short pulse_high = data_source[offset + 3] & 0x0f;
+ const unsigned short pulse_low = data_source[offset + 2];
+
+ const unsigned short value = (pulse_high << 8) | pulse_low;
+
+ return value;
+ };
+
+ const auto is_channel_filtered = [&data_source](unsigned int inChannel) -> bool
+ {
+ if (inChannel > 2)
+ return false;
+
+ return (data_source[0x17] & (1 << inChannel)) != 0;
+ };
+
+ for (unsigned int i = 0; i < 3; ++i)
+ {
+ if ((*m_Tracks)[i]->IsMuted())
+ {
+ m_DrawField->DrawBox(color_muted, bar_x, bar_y, bar_width, bar_height);
+ }
+ else
+ {
+ DrawPulseWidthBar(
+ bar_x,
+ bar_y,
+ bar_width,
+ bar_height,
+ get_pulse_value(i),
+ is_channel_filtered(i) ? color_bar_filtered_channel : color_bar, color_bar_fill,
+ color_separator);
+ }
+ bar_y += bar_spacing;
+ }
+
+ const auto get_filter_value = [&data_source]() -> unsigned short
+ {
+ const unsigned short filter_high = data_source[0x16];
+ const unsigned short filter_low = data_source[0x15] & 7;
+
+ const unsigned short value = (filter_high << 3) | filter_low;
+
+ return value;
+ };
+
+ DrawBar(bar_x, bar_y, bar_width, bar_height, get_filter_value(), 0x07ff, color_bar, color_bar_fill_filter);
+ }
+ }
+
+
+ void VisualizerComponentPulseFilterState::DrawBar(
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ int inValue,
+ int inMaxValue,
+ const Foundation::Color& inBarColor,
+ const Foundation::Color& inBarColorFill)
+ {
+ m_DrawField->DrawBox(inBarColor, inX, inY, inWidth, inHeight);
+
+ if (inValue > 0)
+ {
+ float width_fraction = static_cast(inValue) / static_cast(inMaxValue);
+ int width = static_cast(static_cast(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
+
+ m_DrawField->DrawBox(inBarColorFill, inX, inY + 1, width, inHeight - 2);
+ }
+ }
+
+
+ // Draw a bar for pulse width
+ void VisualizerComponentPulseFilterState::DrawPulseWidthBar(
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ int inValue,
+ const Foundation::Color& inBarColor,
+ const Foundation::Color& inBarColorFill,
+ const Foundation::Color& inSeparatorColor)
+ {
+ m_DrawField->DrawBox(inBarColor, inX, inY, inWidth, inHeight);
+
+ int maxValue = 0xfff;
+ int middleValue = (maxValue / 2);
+
+ if (inValue > 0)
+ {
+ if (m_PulseWidthStyle == 1)
+ {
+ int abs_value = inValue > middleValue ? maxValue - inValue : inValue;
+ float width_fraction = static_cast(abs_value) / static_cast(maxValue);
+ int width = static_cast(static_cast(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
+ int x = inValue > middleValue ? inX + (inWidth - width) : inX;
+ m_DrawField->DrawBox(inBarColorFill, x, inY + 1, width, inHeight - 2);
+ }
+ else
+ {
+ float width_fraction = static_cast(inValue) / static_cast(maxValue);
+ int width = static_cast(static_cast(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
+ m_DrawField->DrawBox(inBarColorFill, inX, inY + 1, width, inHeight - 2);
+ }
+ }
+
+ m_DrawField->DrawVerticalLine(inSeparatorColor, inX + inWidth / 2, inY, inY + inHeight);
+ }
+}
diff --git a/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.h b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.h
new file mode 100644
index 00000000..e11d5b61
--- /dev/null
+++ b/SIDFactoryII/source/runtime/editor/visualizer_components/visualizer_component_pulse_filter_state.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "visualizer_component_base.h"
+#include
+#include "runtime/editor/datasources/datasource_track_components.h"
+
+namespace Foundation
+{
+ enum class Color : unsigned short;
+}
+
+namespace Editor
+{
+ class DataSourceSIDRegistersBufferAfLastDriverUpdate;
+
+ class VisualizerComponentPulseFilterState : public VisualizerComponentBase
+ {
+ public:
+ VisualizerComponentPulseFilterState(
+ int inID,
+ Foundation::DrawField* inDrawField,
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ std::shared_ptr inDataSource,
+ std::shared_ptr inTracks
+ );
+ virtual ~VisualizerComponentPulseFilterState();
+
+ bool ConsumeNonExclusiveInput(const Foundation::Mouse& inMouse) override;
+ void Refresh(const DisplayState& inDisplayState) override;
+
+ private:
+ void DrawBar(
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ int inValue,
+ int inMaxValue,
+ const Foundation::Color& inBarColor,
+ const Foundation::Color& inBarColorFill);
+
+ void DrawPulseWidthBar(
+ int inX,
+ int inY,
+ int inWidth,
+ int inHeight,
+ int inValue,
+ const Foundation::Color& inBarColor,
+ const Foundation::Color& inBarColorFill,
+ const Foundation::Color& inSeparatorColor);
+
+ std::shared_ptr m_DataSource;
+ std::shared_ptr m_Tracks;
+
+ int m_PulseWidthStyle;
+ };
+}
diff --git a/SIDFactoryII/source/runtime/emulation/sid/sidproxy.cpp b/SIDFactoryII/source/runtime/emulation/sid/sidproxy.cpp
index bcb885da..655104fc 100644
--- a/SIDFactoryII/source/runtime/emulation/sid/sidproxy.cpp
+++ b/SIDFactoryII/source/runtime/emulation/sid/sidproxy.cpp
@@ -225,27 +225,6 @@ namespace Emulation
// Clock
int nSamplesWritten = m_pSID->clock(nInternalDeltaCycles, pBuffer/*nBufferSize*/);
- // Overwrite with sine wave to test output consistency
-// for (int i = 0; i < nSamplesWritten; ++i)
-// {
-// float r = (static_cast(m_SampleCounter) * 2.0f * 3.1416f) / 25.0f;
-// short v = static_cast(std::sinf(r) * 65535.0f / 4.0f);
- //
-//
- //
-//
- //
-//
- //
-//
- //
-// pBuffer[i] = v;
- //
-//
- //
- // m_SampleCounter++;
- // }
-
if (IsRecordingToFile())
{
m_FileOutput.push_back(0);
diff --git a/SIDFactoryII/source/runtime/execution/executionhandler.cpp b/SIDFactoryII/source/runtime/execution/executionhandler.cpp
index 2657f9df..a28c2957 100644
--- a/SIDFactoryII/source/runtime/execution/executionhandler.cpp
+++ b/SIDFactoryII/source/runtime/execution/executionhandler.cpp
@@ -56,10 +56,14 @@ namespace Emulation
m_OutputGain = GetSingleConfigurationValue(Global::instance().GetConfig(), "Sound.Output.Gain", -1.0f);
Logging::instance().Info("Sound.Output.Gain = %f", m_OutputGain);
+
// Set default action vector
m_InitVector = 0x1000;
m_StopVector = 0x1003;
m_UpdateVector = 0x1006;
+
+ // Clear SID registers after last driver update
+ memset(m_SIDRegisterLastDriverUpdate.m_Buffer, 0, sizeof(m_SIDRegisterLastDriverUpdate.m_Buffer));
}
ExecutionHandler::~ExecutionHandler()
@@ -487,6 +491,9 @@ namespace Emulation
m_SIDRegisterFlightRecorder->Unlock();
}
+ // Copy sid registers after driver update
+ m_Memory->GetData(0xd400, m_SIDRegisterLastDriverUpdate.m_Buffer, sizeof(m_SIDRegisterLastDriverUpdate.m_Buffer));
+
// Unlock memory access
m_Memory->Unlock();
diff --git a/SIDFactoryII/source/runtime/execution/executionhandler.h b/SIDFactoryII/source/runtime/execution/executionhandler.h
index 1eeb5b81..bcf26e78 100644
--- a/SIDFactoryII/source/runtime/execution/executionhandler.h
+++ b/SIDFactoryII/source/runtime/execution/executionhandler.h
@@ -28,6 +28,11 @@ namespace Emulation
class ExecutionHandler : public Foundation::IAudioStreamFeeder
{
public:
+ struct SIDRegistersBuffer
+ {
+ unsigned char m_Buffer[0x200];
+ };
+
ExecutionHandler(
CPUmos6510* pCPU,
CPUMemory* pMemory,
@@ -82,8 +87,12 @@ namespace Emulation
// Frame
unsigned int GetFrameCounter() const { return m_CPUFrameCounter; }
+ // Flight recorder
FlightRecorder* GetFlightRecorder() const { return m_SIDRegisterFlightRecorder; }
+ // SID registers buffer
+ SIDRegistersBuffer GetSIDRegistersBufferAfterLastDriverUpdate() const { return m_SIDRegisterLastDriverUpdate; }
+
// Write output to file
void StartWriteOutputToFile(const std::string& inFilename);
void StopWriteOutputToFile();
@@ -154,6 +163,9 @@ namespace Emulation
// Flight recorder
FlightRecorder* m_SIDRegisterFlightRecorder;
+ // SID Registers last update
+ SIDRegistersBuffer m_SIDRegisterLastDriverUpdate;
+
// Audio output
unsigned int m_SampleBufferSize;
short* m_SampleBuffer;
diff --git a/SIDFactoryII/source/runtime/execution/flightrecorder.cpp b/SIDFactoryII/source/runtime/execution/flightrecorder.cpp
index e663aae6..4cfa9d16 100644
--- a/SIDFactoryII/source/runtime/execution/flightrecorder.cpp
+++ b/SIDFactoryII/source/runtime/execution/flightrecorder.cpp
@@ -93,7 +93,11 @@ namespace Emulation
{
FOUNDATION_ASSERT(m_TopIndex == 0);
- RecordFrame(inFrame, inMemory, inCyclesSpend, m_Frames[m_RecordedFrameCount]);
+ Frame& frame = m_Frames[m_RecordedFrameCount];
+ RecordFrame(inFrame, inMemory, inCyclesSpend, frame);
+
+ m_LastRecordedFrame = frame;
+
m_RecordedFrameCount++;
}
else
@@ -101,7 +105,11 @@ namespace Emulation
FOUNDATION_ASSERT(m_RecordedFrameCount == m_FrameCapacity);
FOUNDATION_ASSERT(m_TopIndex < m_FrameCapacity);
- RecordFrame(inFrame, inMemory, inCyclesSpend, m_Frames[m_TopIndex]);
+ Frame& frame = m_Frames[m_TopIndex];
+ RecordFrame(inFrame, inMemory, inCyclesSpend, frame);
+
+ m_LastRecordedFrame = frame;
+
m_TopIndex++;
if (m_TopIndex >= m_FrameCapacity)
@@ -132,6 +140,11 @@ namespace Emulation
return m_Frames[inIndex];
}
+ const FlightRecorder::Frame& FlightRecorder::GetNewestFrame() const
+ {
+ return m_LastRecordedFrame;
+ }
+
//------------------------------------------------------------------------------------------------
void FlightRecorder::RecordFrame(unsigned int inFrame, CPUMemory* inMemory, unsigned int inCyclesSpend, Frame& inFrameData)
diff --git a/SIDFactoryII/source/runtime/execution/flightrecorder.h b/SIDFactoryII/source/runtime/execution/flightrecorder.h
index 44da1373..a26c687a 100644
--- a/SIDFactoryII/source/runtime/execution/flightrecorder.h
+++ b/SIDFactoryII/source/runtime/execution/flightrecorder.h
@@ -17,9 +17,9 @@ namespace Emulation
public:
struct Frame
{
- unsigned int m_nFrameNumber;
- unsigned int m_nCyclesSpend;
- unsigned char m_TempoCounter;
+ unsigned int m_nFrameNumber = 0;
+ unsigned int m_nCyclesSpend = 0;
+ unsigned char m_TempoCounter = 0;
unsigned char m_DriverSync[3];
unsigned char m_SIDData[0x19];
@@ -53,6 +53,7 @@ namespace Emulation
unsigned int RecordedFrameCount() const;
const Frame& GetFrame(unsigned int inIndex) const;
+ const Frame& GetNewestFrame() const;
const unsigned int GetCapacity() const { return m_FrameCapacity; }
@@ -73,6 +74,7 @@ namespace Emulation
bool m_Locked;
+ Frame m_LastRecordedFrame;
Frame* m_Frames;
};
}
diff --git a/SIDFactoryII/source/utils/config/configcolors.cpp b/SIDFactoryII/source/utils/config/configcolors.cpp
index c030404a..543b293e 100644
--- a/SIDFactoryII/source/utils/config/configcolors.cpp
+++ b/SIDFactoryII/source/utils/config/configcolors.cpp
@@ -102,6 +102,15 @@ namespace Utility
Details::SetUserColor(inConfigFile, "Color.Orderlist.Value", UserColor::OrderlistValue, ioViewport, Color::LightGrey);
Details::SetUserColor(inConfigFile, "Color.Orderlist.Value.Loop.Marker", UserColor::OrderlistValueLoopMarker, ioViewport, Color::LightGreen);
Details::SetUserColor(inConfigFile, "Color.Orderlist.Value.Input", UserColor::OrderlistValueInput, ioViewport, Color::White);
+
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Area", UserColor::VisualizerArea, ioViewport, Color::DarkestGrey);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.Background", UserColor::VisualizerBarBackground, ioViewport, Color::DarkGrey);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.BackgroundMuted", UserColor::VisualizerBarBackgroundMuted, ioViewport, Color::DarkerGrey);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.BackgroundFilteredChannel", UserColor::VisualizerBarBackgroundFilteredChannel, ioViewport, Color::Grey);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.Separator", UserColor::VisualizerBarSeparator, ioViewport, Color::DarkestGrey);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.FillColorPulse", UserColor::VisualizerBarFillColorPulse, ioViewport, Color::White);
+ Details::SetUserColor(inConfigFile, "Color.Visualizer.Bar.FillColorFilter", UserColor::VisualizerBarFillColorFilter, ioViewport, Color::LightGrey);
+
Details::SetUserColor(inConfigFile, "Color.Dialog.Background", UserColor::DialogBackground, ioViewport, Color::DarkRed);
Details::SetUserColor(inConfigFile, "Color.Dialog.Header", UserColor::DialogHeader, ioViewport, Color::Red);
Details::SetUserColor(inConfigFile, "Color.Dialog.Header.Text", UserColor::DialogHeaderText, ioViewport, Color::White);
diff --git a/SIDFactoryII/source/utils/usercolors.h b/SIDFactoryII/source/utils/usercolors.h
index 95bcab7e..e9e94254 100644
--- a/SIDFactoryII/source/utils/usercolors.h
+++ b/SIDFactoryII/source/utils/usercolors.h
@@ -93,6 +93,13 @@ namespace Utility
OrderlistValue,
OrderlistValueLoopMarker,
OrderlistValueInput,
+ VisualizerArea,
+ VisualizerBarBackground,
+ VisualizerBarBackgroundMuted,
+ VisualizerBarBackgroundFilteredChannel,
+ VisualizerBarSeparator,
+ VisualizerBarFillColorPulse,
+ VisualizerBarFillColorFilter,
DialogBackground,
DialogHeader,
DialogHeaderText,
diff --git a/dist/documentation/user.default.ini b/dist/documentation/user.default.ini
index f810fc78..ed59d413 100644
--- a/dist/documentation/user.default.ini
+++ b/dist/documentation/user.default.ini
@@ -61,6 +61,13 @@ Window.Scaling = 1.0 // Scale window contents. Pixels
// (or accept the glitch).
Window.Scaling.Smooth = 1 // If you set this to 1, scaling will smooth pixels.
// Set to 0 will use "nearest neighbour" scaling.
+
+//
+// Visualizers
+//
+Visualizer.PulseWidth.Style = 0 // The way pulse width is visualized
+ // 0 = absolute value, 1 = alternative style
+
//
// OVERLAY
//