diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/GameResourcesCrcHelper.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/GameResourcesCrcHelper.cs new file mode 100644 index 0000000..485e817 --- /dev/null +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/GameResourcesCrcHelper.cs @@ -0,0 +1,96 @@ +using Sm5sh.ResourceProviders.Constants; +using System.Collections.Generic; + +namespace Sm5sh.Mods.Music.Helpers +{ + public class GameResourcesCrcHelper + { + public static List VersionCrcSets = new List() + { + new GameCrcSet() + { + Version = 10.0, + CrcResources = new Dictionary() + { + { BgmPropertyFileConstants.BGM_PROPERTY_PATH, 0x5DA473DC }, + { PrcExtConstants.PRC_UI_BGM_DB_PATH, 0x0B40201B }, + { PrcExtConstants.PRC_UI_GAMETITLE_DB_PATH, 0x64A6B3F2 }, + { PrcExtConstants.PRC_UI_STAGE_DB_PATH, 0xBEC70A05 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_de"), 0x5ACB4CD9 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_en"), 0xBB7D6832 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_es"), 0xBC2DFC42 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_fr"), 0xCA1466A3 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_it"), 0x6929D1A6 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_nl"), 0xB7BE4024 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_ru"), 0x17FE6AA8 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "jp_ja"), 0x4E871500 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "kr_ko"), 0xAAA93540 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_en"), 0x62BBB2A9 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_es"), 0x86AA1535 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_fr"), 0xACFFA15E }, + { string.Format(MsbtExtConstants.MSBT_BGM, "zh_cn"), 0x109189D2 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "zh_tw"), 0x47BD1B25 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_de"), 0x7671A994 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_en"), 0x8819E6D4 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_es"), 0x42F6A770 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_fr"), 0xA3373FD7 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_it"), 0xDA270DB7 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_nl"), 0x1D7F72C3 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_ru"), 0x2A8F96FC }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "jp_ja"), 0xA3AD4A34 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "kr_ko"), 0x64252510 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_en"), 0x773E88AC }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_es"), 0x73F11E85 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_fr"), 0x07C29D63 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "zh_cn"), 0x17BCC77D }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "zh_tw"), 0x6E8482F9 } + } + }, + new GameCrcSet() + { + Version = 10.1, + CrcResources = new Dictionary() + { + { BgmPropertyFileConstants.BGM_PROPERTY_PATH, 0x5DA473DC }, + { PrcExtConstants.PRC_UI_BGM_DB_PATH, 0x83C7244A }, + { PrcExtConstants.PRC_UI_GAMETITLE_DB_PATH, 0x64A6B3F2 }, + { PrcExtConstants.PRC_UI_STAGE_DB_PATH, 0xBEC70A05 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_de"), 0x5ACB4CD9 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_en"), 0xBB7D6832 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_es"), 0xBC2DFC42 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_fr"), 0xCA1466A3 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_it"), 0x6929D1A6 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_nl"), 0xB7BE4024 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "eu_ru"), 0x17FE6AA8 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "jp_ja"), 0x4E871500 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "kr_ko"), 0xAAA93540 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_en"), 0x62BBB2A9 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_es"), 0x86AA1535 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "us_fr"), 0xACFFA15E }, + { string.Format(MsbtExtConstants.MSBT_BGM, "zh_cn"), 0x109189D2 }, + { string.Format(MsbtExtConstants.MSBT_BGM, "zh_tw"), 0x47BD1B25 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_de"), 0x88394D04 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_en"), 0x481B25B8 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_es"), 0x6431BB7F }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_fr"), 0x090AD9CB }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_it"), 0xFE5BC0B2 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_nl"), 0x350A6DD3 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "eu_ru"), 0x51E6AC28 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "jp_ja"), 0x7185EFAE }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "kr_ko"), 0x85E1CC5C }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_en"), 0xFC6E27E0 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_es"), 0x02EECC25 }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "us_fr"), 0xFDF911CC }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "zh_cn"), 0xC086A18E }, + { string.Format(MsbtExtConstants.MSBT_TITLE, "zh_tw"), 0xA817D5A3 } + } + }, + }; + } + + public class GameCrcSet + { + public double Version { get; set; } + public Dictionary CrcResources { get; set; } + } +} diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/MusicConstants.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/MusicConstants.cs index 1be4431..67c2e38 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/MusicConstants.cs +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Helpers/MusicConstants.cs @@ -2,6 +2,9 @@ { public class MusicConstants { + public const double VersionSm5shMusic = 0.9; + public const double VersionSm5shMusicOverride = 0.9; + public class MusicModFiles { public const string MUSIC_MOD_METADATA_JSON_FILE = "metadata_mod.json"; diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Interfaces/IAudioStateService.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Interfaces/IAudioStateService.cs index 513c3e9..efbef64 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Interfaces/IAudioStateService.cs +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Interfaces/IAudioStateService.cs @@ -21,6 +21,8 @@ public interface IAudioStateService IEnumerable GetLocales(); IEnumerable GetPlaylists(); + double GameVersion { get; } + bool CanAddBgmDbRootEntry(string uiBgmId); bool CanAddBgmStreamSetEntry(string streamSetId); bool CanAddBgmAssignedInfoEntry(string infoId); diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Services/AudioStateService.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Services/AudioStateService.cs index 79980d0..f51a54d 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Services/AudioStateService.cs +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Services/AudioStateService.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Force.Crc32; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Sm5sh.Data; @@ -37,6 +38,8 @@ public class AudioStateService : IAudioStateService private readonly Dictionary _playlistsEntries; private readonly Dictionary _stageEntries; + public double GameVersion { get; private set; } + public AudioStateService(IOptions config, IMapper mapper, IStateManager state, ILogger logger) { _config = config; @@ -577,6 +580,8 @@ public bool SaveBgmEntriesToStateManager() #region Private public void InitBgmEntriesFromStateManager() { + GuessGameVersion(); + //Make sure resources are unloaded _state.UnloadResources(); _bgmDbRootEntries.Clear(); @@ -693,6 +698,39 @@ public void InitBgmEntriesFromStateManager() } } + public void GuessGameVersion() + { + var gameCrcSets = GameResourcesCrcHelper.VersionCrcSets; + GameVersion = 0.0; + foreach(var versionCrcSet in gameCrcSets) + { + bool allMatch = true; + foreach(var resource in versionCrcSet.CrcResources) + { + var file = Path.Combine(_config.Value.GameResourcesPath, resource.Key); + if (File.Exists(file)) + { + var hash = Crc32Algorithm.Compute(File.ReadAllBytes(file)); + if (hash != resource.Value) + { + _logger.LogDebug("CRC Check: File {File} did not match expected CRC32 hash for Version {Version}. Expected: 0x{ExpectedHash:x}, Was: 0x{ActualHash:x}", file, versionCrcSet.Version, resource.Value, hash); + allMatch = false; + break; + } + } + else + { + _logger.LogDebug("CRC Check: File {File} could not be found", file); + } + } + if (allMatch) + { + GameVersion = versionCrcSet.Version; + break; + } + } + } + #region Utils private string GetNewNameId() { diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5sh.Mods.Music.csproj b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5sh.Mods.Music.csproj index fec377f..7ec79e9 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5sh.Mods.Music.csproj +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5sh.Mods.Music.csproj @@ -7,6 +7,7 @@ + diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusic.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusic.cs index cf9c518..481d785 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusic.cs +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusic.cs @@ -15,7 +15,6 @@ public class Sm5shMusic : BaseSm5shMod private readonly IAudioStateService _audioStateService; private readonly IMusicModManagerService _musicModManagerService; private readonly INus3AudioService _nus3AudioService; - private const double Version = 0.9; public override string ModName => "Sm5shMusic"; @@ -34,7 +33,7 @@ public Sm5shMusic(IOptions config, IMusicModManagerService mu public override bool Init() { _logger.LogInformation("Sm5shMusic Path: {MusicModPath}", _config.Value.Sm5shMusic.ModPath); - _logger.LogInformation("Sm5shMusic Version: {Version}", Version); + _logger.LogInformation("Sm5shMusic Version: {Version}", MusicConstants.VersionSm5shMusic); _logger.LogInformation("Audio Conversion Format: {AudioConversionFormat}", _config.Value.Sm5shMusic.AudioConversionFormat); _logger.LogInformation("Resources Path: {ResourcesPath}", _config.Value.Sm5shMusic.EnableAudioCaching ? "Enabled - If songs are mismatched try to clear the cache!" : "Disabled"); _logger.LogInformation("Cache Path: {CachePath}", _config.Value.Sm5shMusic.CachePath); diff --git a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusicOverride.cs b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusicOverride.cs index 8841b10..1a2ea26 100644 --- a/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusicOverride.cs +++ b/Sm5sh/Mods/Sm5sh.Mods.Music/Sm5shMusicOverride.cs @@ -23,7 +23,6 @@ public class Sm5shMusicOverride : BaseSm5shMod, ISm5shMusicOverride private readonly IAudioStateService _audioStateService; private const Formatting _defaultFormatting = Formatting.Indented; private MusicOverrideConfig _musicOverrideConfig; - private const double Version = 0.9; public override string ModName => "Sm5shMusicOverride"; @@ -40,7 +39,7 @@ public Sm5shMusicOverride(IOptions config, IStateMana public override bool Init() { _logger.LogInformation("Sm5shMusic Override Path: {MusicModPath}", _config.Value.Sm5shMusicOverride.ModPath); - _logger.LogInformation("Sm5shMusic Override Version: {Version}", Version); + _logger.LogInformation("Sm5shMusic Override Version: {Version}", MusicConstants.VersionSm5shMusicOverride); //Load Music Override _logger.LogInformation("Loading Sm5shMusic Override Config"); diff --git a/Sm5shMusic.GUI/Helpers/WebBrowserHelper.cs b/Sm5shMusic.GUI/Helpers/WebBrowserHelper.cs new file mode 100644 index 0000000..6315ba7 --- /dev/null +++ b/Sm5shMusic.GUI/Helpers/WebBrowserHelper.cs @@ -0,0 +1,36 @@ +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Sm5shMusic.GUI.Helpers +{ + public static class WebBrowserHelper + { + public static void OpenBrowser(string url) + { + try + { + Process.Start(url); + } + catch + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + url = url.Replace("&", "^&"); + Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } + else + { + throw; + } + } + } + } +} diff --git a/Sm5shMusic.GUI/Interfaces/IGUIStateManager.cs b/Sm5shMusic.GUI/Interfaces/IGUIStateManager.cs index 66d3cb2..cd7ac35 100644 --- a/Sm5shMusic.GUI/Interfaces/IGUIStateManager.cs +++ b/Sm5shMusic.GUI/Interfaces/IGUIStateManager.cs @@ -28,5 +28,9 @@ public interface IGUIStateManager Task UpdateGlobalSettings(ApplicationSettings appSettings); Task WipeAudioCache(); Task ReorderSongs(); + + string GameVersion { get; } + + bool IsGameVersionFound { get; } } } diff --git a/Sm5shMusic.GUI/Models/ApplicationSettings.cs b/Sm5shMusic.GUI/Models/ApplicationSettings.cs index 2801ba1..d2b8391 100644 --- a/Sm5shMusic.GUI/Models/ApplicationSettings.cs +++ b/Sm5shMusic.GUI/Models/ApplicationSettings.cs @@ -18,6 +18,7 @@ public class Sm5shMusicGuiOptionsSection public string DefaultMSBTLocale { get; set; } public bool CopyToEmptyLocales { get; set; } public ushort PlaylistIncidenceDefault { get; set; } + public bool SkipWarningGameVersion { get; set; } } } } diff --git a/Sm5shMusic.GUI/Models/AutoMapper/MappingViewModels.cs b/Sm5shMusic.GUI/Models/AutoMapper/MappingViewModels.cs index 2a149f5..d9313dd 100644 --- a/Sm5shMusic.GUI/Models/AutoMapper/MappingViewModels.cs +++ b/Sm5shMusic.GUI/Models/AutoMapper/MappingViewModels.cs @@ -32,7 +32,8 @@ public MappingViewModels() DefaultGUILocale = p.DefaultGUILocale, DefaultMSBTLocale = p.DefaultMSBTLocale, CopyToEmptyLocales = p.CopyToEmptyLocales, - PlaylistIncidenceDefault = p.PlaylistIncidenceDefault + PlaylistIncidenceDefault = p.PlaylistIncidenceDefault, + SkipWarningGameVersion = p.SkipWarningGameVersion })) .ForMember(i => i.Sm5shMusicOverride, me => me.MapFrom(p => new Sm5shMusicOverrideOptions.Sm5shMusicOverrideOptionsSection() { @@ -59,6 +60,7 @@ public MappingViewModels() .ForMember(i => i.DefaultMSBTLocale, me => me.MapFrom(p => p.Sm5shMusicGUI.DefaultMSBTLocale)) .ForMember(i => i.CopyToEmptyLocales, me => me.MapFrom(p => p.Sm5shMusicGUI.CopyToEmptyLocales)) .ForMember(i => i.PlaylistIncidenceDefault, me => me.MapFrom(p => p.Sm5shMusicGUI.PlaylistIncidenceDefault)) + .ForMember(i => i.SkipWarningGameVersion, me => me.MapFrom(p => p.Sm5shMusicGUI.SkipWarningGameVersion)) .ForMember(i => i.ModOverridePath, me => me.MapFrom(p => p.Sm5shMusicOverride.ModPath)) .ForMember(i => i.TempPath, me => me.MapFrom(p => p.TempPath)) .ForMember(i => i.ToolsPath, me => me.MapFrom(p => p.ToolsPath)); diff --git a/Sm5shMusic.GUI/Program.cs b/Sm5shMusic.GUI/Program.cs index e023bf3..9459f6f 100644 --- a/Sm5shMusic.GUI/Program.cs +++ b/Sm5shMusic.GUI/Program.cs @@ -131,6 +131,7 @@ private static Dictionary GetDefaultConfiguration() { "Sm5shMusicGUI:CopyToEmptyLocales", "true" }, { "Sm5shMusicGUI:DefaultMSBTLocale", "us_en" }, { "Sm5shMusicGUI:PlaylistIncidenceDefault", "0" }, + { "Sm5shMusicGUI:SkipWarningGameVersion", "false" }, { "Sm5shMusicOverride:ModPath", $"Mods{Path.DirectorySeparatorChar}MusicOverride" }, }; } diff --git a/Sm5shMusic.GUI/Services/GUIStateManager.cs b/Sm5shMusic.GUI/Services/GUIStateManager.cs index 7607a5a..f9b3e3b 100644 --- a/Sm5shMusic.GUI/Services/GUIStateManager.cs +++ b/Sm5shMusic.GUI/Services/GUIStateManager.cs @@ -673,6 +673,22 @@ await Dispatcher.UIThread.InvokeAsync(async () => } #endregion + public string GameVersion + { + get + { + return _audioState.GameVersion == 0 ? "?? (custom)" : _audioState.GameVersion.ToString(); + } + } + + public bool IsGameVersionFound + { + get + { + return _audioState.GameVersion != 0; + } + } + public async Task UpdateGlobalSettings(ApplicationSettings appSettings) { bool result; diff --git a/Sm5shMusic.GUI/ViewModels/MainWindowViewModel.cs b/Sm5shMusic.GUI/ViewModels/MainWindowViewModel.cs index 8cadf79..e026dea 100644 --- a/Sm5shMusic.GUI/ViewModels/MainWindowViewModel.cs +++ b/Sm5shMusic.GUI/ViewModels/MainWindowViewModel.cs @@ -20,6 +20,7 @@ using Microsoft.Extensions.Options; using Sm5sh.Mods.Music; using Avalonia.Threading; +using Sm5sh.Mods.Music.Helpers; namespace Sm5shMusic.GUI.ViewModels { @@ -51,6 +52,9 @@ public class MainWindowViewModel : ViewModelBase private readonly PlaylistStageAssignementModalWindowViewModel _vmStageAssignement; private readonly ToneIdCreationModalWindowModel _vmToneIdCreation; + [Reactive] + public string Title { get; set; } + [Reactive] public bool IsAdvanced { get; set; } [Reactive] @@ -69,7 +73,8 @@ public class MainWindowViewModel : ViewModelBase public ReactiveCommand ActionRefreshData { get; } public ReactiveCommand ActionToggleAdvanced { get; } public ReactiveCommand ActionToggleConsole { get; } - public ReactiveCommand ActionOpenAbout { get; } + public ReactiveCommand ActionOpenThanks { get; } + public ReactiveCommand ActionOpenWiki { get; } public ReactiveCommand ActionOpenGlobalSettings { get; } public MainWindowViewModel(IServiceProvider serviceProvider, IViewModelManager viewModelManager, IGUIStateManager guiStateManager, IMapper mapper, IVGMMusicPlayer musicPlayer, @@ -87,7 +92,8 @@ public MainWindowViewModel(IServiceProvider serviceProvider, IViewModelManager v _appSettings = appSettings; IsLoading = true; - _logger.LogInformation($"GUI Version: {Constants.GUIVersion}"); + _logger.LogInformation($"GUI v{Constants.GUIVersion} | Game v{_guiStateManager.GameVersion}"); + Title = $"Sm5shMusic - GUI v{Constants.GUIVersion}"; //Set values IsAdvanced = appSettings.Value.Sm5shMusicGUI.Advanced; @@ -179,7 +185,8 @@ public MainWindowViewModel(IServiceProvider serviceProvider, IViewModelManager v ActionRefreshData = ReactiveCommand.CreateFromTask(OnInitData); ActionToggleAdvanced = ReactiveCommand.Create(OnAdvancedToggle); ActionToggleConsole = ReactiveCommand.Create(OnConsoleToggle); - ActionOpenAbout = ReactiveCommand.CreateFromTask(OnAboutOpen); + ActionOpenThanks = ReactiveCommand.CreateFromTask(OnThanksOpen); + ActionOpenWiki = ReactiveCommand.Create(OnWikiOpen); ActionOpenGlobalSettings = ReactiveCommand.CreateFromTask(OnGlobalSettingsOpen); } @@ -244,6 +251,16 @@ await Dispatcher.UIThread.InvokeAsync(async () => }, DispatcherPriority.Background); VMContextMenu.ChangeLocale(newDefaultLanguage); } + + if(!_guiStateManager.IsGameVersionFound && !_appSettings.Value.Sm5shMusicGUI.SkipWarningGameVersion) + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + await _messageDialog.ShowInformation("Game version not found", $"The version of your game could not be identified. It might be that you are using a version that is unsupported or that your game files are customized."); + }, DispatcherPriority.Background); + } + Title = $"{Title} | Game v{_guiStateManager.GameVersion}"; + IsLoading = false; }, (o) => { @@ -252,10 +269,13 @@ await Dispatcher.UIThread.InvokeAsync(async () => }); } - public async Task OnAboutOpen() + public async Task OnThanksOpen() { await _messageDialog.ShowInformation("About", - $"Sm5sh Music - v{Constants.GUIVersion} by deinonychus71\r\n" + + $"Sm5shMusic - GUI v{Constants.GUIVersion} by deinonychus71\r\n" + + $"Mod Sm5shMusic - v{MusicConstants.VersionSm5shMusic} by deinonychus71\r\n" + + $"Mod Sm5shMusicOverride - v{MusicConstants.VersionSm5shMusicOverride} by deinonychus71\r\n" + + $"Game - v{_guiStateManager.GameVersion}\r\n" + "https://github.com/Deinonychus71/Sm5shMusic \r\n\r\n" + "Research: soneek\r\n" + "Testing: Demonslayerx8, Segtendo\r\n" + @@ -270,6 +290,11 @@ await _messageDialog.ShowInformation("About", "CrossArc: https://github.com/Ploaj/ArcCross \r\nPloaj, ScanMountGoat, BenHall-7, shadowninja108, jam1garner, M-1-RLG\r\n\r\n"); } + public void OnWikiOpen() + { + WebBrowserHelper.OpenBrowser("https://github.com/Deinonychus71/Sm5shMusic/wiki"); + } + public async Task OnGlobalSettingsOpen() { var vmGlobalSettings = new GlobalConfigurationViewModel(_mapper, _appSettings.Value); diff --git a/Sm5shMusic.GUI/ViewModels/Modals/BgmPropertiesModalWindowViewModel.cs b/Sm5shMusic.GUI/ViewModels/Modals/BgmPropertiesModalWindowViewModel.cs index 157359c..235b4a8 100644 --- a/Sm5shMusic.GUI/ViewModels/Modals/BgmPropertiesModalWindowViewModel.cs +++ b/Sm5shMusic.GUI/ViewModels/Modals/BgmPropertiesModalWindowViewModel.cs @@ -32,6 +32,8 @@ public class BgmPropertiesModalWindowViewModel : ModalBaseViewModel _streamSetIds; private readonly Subject _whenNewRequestToAddGameEntry; private bool _isUpdatingSpecialRule = false; + private const float _minimumVolume = -20.0; + private const float _maximumVolume = 20.0; public IObservable WhenNewRequestToAddGameEntry { get { return _whenNewRequestToAddGameEntry; } } public GamePropertiesModalWindowViewModel VMGamePropertiesModal { get; set; } @@ -181,6 +183,11 @@ private void SetGameTitleId(GameTitleEntryViewModel gameTitle) protected override Task SaveChanges() { _logger.LogDebug("Save Changes"); + if (BgmPropertyViewModel.AudioVolume < _minimumVolume) + BgmPropertyViewModel.AudioVolume = _minimumVolume; + if (BgmPropertyViewModel.AudioVolume > _maximumVolume) + BgmPropertyViewModel.AudioVolume = _maximumVolume; + DbRootViewModel.TestDispOrder = (short)(IsInSoundTest ? DbRootViewModel.TestDispOrder > -1 ? DbRootViewModel.TestDispOrder : short.MaxValue : -1); if (SelectedRecordType != null) DbRootViewModel.RecordType = SelectedRecordType.Id; diff --git a/Sm5shMusic.GUI/ViewModels/ReactiveObjects/BgmEntry/BgmPropertyEntryViewModel.cs b/Sm5shMusic.GUI/ViewModels/ReactiveObjects/BgmEntry/BgmPropertyEntryViewModel.cs index 062b408..217ea29 100644 --- a/Sm5shMusic.GUI/ViewModels/ReactiveObjects/BgmEntry/BgmPropertyEntryViewModel.cs +++ b/Sm5shMusic.GUI/ViewModels/ReactiveObjects/BgmEntry/BgmPropertyEntryViewModel.cs @@ -21,7 +21,7 @@ public class BgmPropertyEntryViewModel : BgmBaseViewModel public uint Frequency { get { return TotalTimeMs == 0 ? 0 : (uint)((double)TotalSamples / (double)TotalTimeMs * 1000.0); } } public string Filename { get; } [Reactive] - public string AudioVolume { get; set; } + public float AudioVolume { get; set; } //Music player public bool DoesFileExist { get; set; } diff --git a/Sm5shMusic.GUI/ViewModels/ReactiveObjects/GlobalConfigurationViewModel.cs b/Sm5shMusic.GUI/ViewModels/ReactiveObjects/GlobalConfigurationViewModel.cs index 2494bdc..ba60027 100644 --- a/Sm5shMusic.GUI/ViewModels/ReactiveObjects/GlobalConfigurationViewModel.cs +++ b/Sm5shMusic.GUI/ViewModels/ReactiveObjects/GlobalConfigurationViewModel.cs @@ -42,6 +42,8 @@ public class GlobalConfigurationViewModel : ReactiveObjectBaseViewModel public string ResourcesPath { get; set; } [Reactive] public string LogPath { get; set; } + [Reactive] + public bool SkipWarningGameVersion { get; set; } public ApplicationSettings GetReference() { diff --git a/Sm5shMusic.GUI/Views/MainWindow.axaml b/Sm5shMusic.GUI/Views/MainWindow.axaml index 97655c3..725f90e 100644 --- a/Sm5shMusic.GUI/Views/MainWindow.axaml +++ b/Sm5shMusic.GUI/Views/MainWindow.axaml @@ -10,7 +10,7 @@ xmlns:fields="clr-namespace:Sm5shMusic.GUI.Views.Fields" xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity" xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions" - Title="Sm5sh Music"> + Title="{Binding Title}"> @@ -19,16 +19,13 @@ - - + + - @@ -42,8 +39,11 @@ + + + - + diff --git a/Sm5shMusic.GUI/Views/Modals/BgmAdvancedPropertiesModalWindow.axaml b/Sm5shMusic.GUI/Views/Modals/BgmAdvancedPropertiesModalWindow.axaml index 6224da6..ce6ed44 100644 --- a/Sm5shMusic.GUI/Views/Modals/BgmAdvancedPropertiesModalWindow.axaml +++ b/Sm5shMusic.GUI/Views/Modals/BgmAdvancedPropertiesModalWindow.axaml @@ -99,9 +99,11 @@ - + - diff --git a/Sm5shMusic.GUI/Views/Modals/BgmPropertiesModalWindow.axaml b/Sm5shMusic.GUI/Views/Modals/BgmPropertiesModalWindow.axaml index 0c8d2d3..45c4484 100644 --- a/Sm5shMusic.GUI/Views/Modals/BgmPropertiesModalWindow.axaml +++ b/Sm5shMusic.GUI/Views/Modals/BgmPropertiesModalWindow.axaml @@ -99,9 +99,11 @@ - + - diff --git a/Sm5shMusic.GUI/Views/Modals/GlobalSettingsModalWindow.axaml b/Sm5shMusic.GUI/Views/Modals/GlobalSettingsModalWindow.axaml index 4b577c3..37a0a59 100644 --- a/Sm5shMusic.GUI/Views/Modals/GlobalSettingsModalWindow.axaml +++ b/Sm5shMusic.GUI/Views/Modals/GlobalSettingsModalWindow.axaml @@ -66,8 +66,9 @@ - + +