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 //