Compare commits

...

9 Commits

41 changed files with 1027 additions and 917 deletions

View File

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F1C1B6BF-626C-4F10-8672-2F9596706CA6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CachedDataManager</RootNamespace>
<AssemblyName>Assembly-CSharp.CachedDataManager.mm</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Manager\MaiStudio\Serialize\patch_FilePath.cs" />
<Compile Include="Manager\patch_DataManager.cs" />
<Compile Include="SerializationCache.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,205 +0,0 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Serialization;
namespace Manager;
public class patch_DataManager : DataManager
{
private const string _cacheDirectory = "dataCache";
[Serializable]
[XmlType(TypeName="KeyValuePair")]
public class SerializableKeyValuePair<TK, TV>
{
public TK Key;
public TV Value;
}
private static Dictionary<string, T> LoadCacheFile<T>(string fileName)
{
if (!File.Exists(fileName))
{
return new Dictionary<string, T>();
}
using var fs = File.OpenRead(fileName);
var serializer = new XmlSerializer(typeof(List<SerializableKeyValuePair<string, T>>));
var entries = (List<SerializableKeyValuePair<string, T>>)serializer.Deserialize(fs);
return entries.ToDictionary(e => e.Key, e => e.Value);
}
private static void SaveCacheFile<T>(string destination, Dictionary<string, T> collection)
{
if (collection == null)
{
return;
}
using var fs = File.Open(destination, FileMode.Create);
var serializer = new XmlSerializer(typeof(List<SerializableKeyValuePair<string, T>>));
serializer.Serialize(
fs,
collection
.Select(kvp => new SerializableKeyValuePair<string, T> { Key = kvp.Key, Value = kvp.Value })
.ToList());
}
private static void SaveCache()
{
if (!Directory.Exists(_cacheDirectory))
{
Directory.CreateDirectory(_cacheDirectory);
}
SaveCacheFile(Path.Combine(_cacheDirectory, "RomConfigs.xml"), Cache.RomConfigs);
SaveCacheFile(Path.Combine(_cacheDirectory, "DataConfigs.xml"), Cache.DataConfigs);
SaveCacheFile(Path.Combine(_cacheDirectory, "Charas.xml"), Cache.Charas);
SaveCacheFile(Path.Combine(_cacheDirectory, "CharaAwakes.xml"), Cache.CharaAwakes);
SaveCacheFile(Path.Combine(_cacheDirectory, "CharaGenres.xml"), Cache.CharaGenres);
SaveCacheFile(Path.Combine(_cacheDirectory, "Events.xml"), Cache.Events);
SaveCacheFile(Path.Combine(_cacheDirectory, "Musics.xml"), Cache.Musics);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicGenres.xml"), Cache.MusicGenres);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicGroups.xml"), Cache.MusicGroups);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicVersions.xml"), Cache.MusicVersions);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicNameSorts.xml"), Cache.MusicNameSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicClearRanks.xml"), Cache.MusicClearRanks);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicDifficultys.xml"), Cache.MusicDifficultys);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicLevels.xml"), Cache.MusicLevels);
SaveCacheFile(Path.Combine(_cacheDirectory, "TournamentMusics.xml"), Cache.TournamentMusics);
SaveCacheFile(Path.Combine(_cacheDirectory, "Courses.xml"), Cache.Courses);
SaveCacheFile(Path.Combine(_cacheDirectory, "CourseModes.xml"), Cache.CourseModes);
SaveCacheFile(Path.Combine(_cacheDirectory, "LoginBonuses.xml"), Cache.LoginBonuses);
SaveCacheFile(Path.Combine(_cacheDirectory, "Maps.xml"), Cache.Maps);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapColors.xml"), Cache.MapColors);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapTreasures.xml"), Cache.MapTreasures);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapBonusMusics.xml"), Cache.MapBonusMusics);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapOtomodachis.xml"), Cache.MapOtomodachis);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapSilhouettes.xml"), Cache.MapSilhouettes);
SaveCacheFile(Path.Combine(_cacheDirectory, "MapTitles.xml"), Cache.MapTitles);
SaveCacheFile(Path.Combine(_cacheDirectory, "ItemMusics.xml"), Cache.ItemMusics);
SaveCacheFile(Path.Combine(_cacheDirectory, "Icons.xml"), Cache.Icons);
SaveCacheFile(Path.Combine(_cacheDirectory, "Plates.xml"), Cache.Plates);
SaveCacheFile(Path.Combine(_cacheDirectory, "Titles.xml"), Cache.Titles);
SaveCacheFile(Path.Combine(_cacheDirectory, "Partners.xml"), Cache.Partners);
SaveCacheFile(Path.Combine(_cacheDirectory, "Frames.xml"), Cache.Frames);
SaveCacheFile(Path.Combine(_cacheDirectory, "Tickets.xml"), Cache.Tickets);
SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionTypes.xml"), Cache.CollectionTypes);
SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionGenres.xml"), Cache.CollectionGenres);
SaveCacheFile(Path.Combine(_cacheDirectory, "PhotoFrames.xml"), Cache.PhotoFrames);
SaveCacheFile(Path.Combine(_cacheDirectory, "Informations.xml"), Cache.Informations);
SaveCacheFile(Path.Combine(_cacheDirectory, "Udemaes.xml"), Cache.Udemaes);
SaveCacheFile(Path.Combine(_cacheDirectory, "Classes.xml"), Cache.Classes);
SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeBosses.xml"), Cache.UdemaeBosses);
SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeSeasonEvents.xml"), Cache.UdemaeSeasonEvents);
SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeSeasonRewards.xml"), Cache.UdemaeSeasonRewards);
SaveCacheFile(Path.Combine(_cacheDirectory, "Cards.xml"), Cache.Cards);
SaveCacheFile(Path.Combine(_cacheDirectory, "CardCharas.xml"), Cache.CardCharas);
SaveCacheFile(Path.Combine(_cacheDirectory, "CardTypes.xml"), Cache.CardTypes);
SaveCacheFile(Path.Combine(_cacheDirectory, "WeekdayBonuses.xml"), Cache.WeekdayBonuses);
SaveCacheFile(Path.Combine(_cacheDirectory, "Challenges.xml"), Cache.Challenges);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicRankings.xml"), Cache.MusicRankings);
SaveCacheFile(Path.Combine(_cacheDirectory, "MusicSorts.xml"), Cache.MusicSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "LoginBonusSorts.xml"), Cache.LoginBonusSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "IconSorts.xml"), Cache.IconSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "PlateSorts.xml"), Cache.PlateSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "TitleSorts.xml"), Cache.TitleSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "PartnerSorts.xml"), Cache.PartnerSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "FrameSorts.xml"), Cache.FrameSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "TicketSorts.xml"), Cache.TicketSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionGenreSorts.xml"), Cache.CollectionGenreSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "CharaSorts.xml"), Cache.CharaSorts);
SaveCacheFile(Path.Combine(_cacheDirectory, "CharaGenreSorts.xml"), Cache.CharaGenreSorts);
}
private static extern bool orig_Deserialize<T>(string filePath, out T dsr) where T : new();
private static bool Deserialize<T>(string filePath, out T dsr) where T : new()
{
var fileName = Path.GetFileName(filePath);
var collectionName = fileName switch
{
"UdemaeBoss.xml" => "UdemaeBosses",
"Class.xml" => "Classes",
"LoginBonus.xml" => "LoginBonuses",
"ScoreRanking.xml" => "TournamentMusics",
"Holiday.xml" => "WeekdayBonuses",
_ => fileName.Replace(".xml", "s"),
};
var collectionField =
typeof(CachedDataManager.SerializationCache).GetField(collectionName, BindingFlags.Public | BindingFlags.Instance);
if (collectionField == null)
{
System.Console.WriteLine("[CachedDataManager] [WARN] Could not find suitable collection for {0} (tried name {1})", fileName, collectionName);
return orig_Deserialize(filePath, out dsr);
}
try
{
var collection = (Dictionary<string, T>)collectionField.GetValue(Cache);
if (collection == null)
{
collection = LoadCacheFile<T>(Path.Combine(_cacheDirectory, $"{collectionName}.xml"));
collectionField.SetValue(Cache, collection);
}
if (collection.TryGetValue(filePath, out dsr))
{
return true;
}
if (!orig_Deserialize(filePath, out dsr))
{
return false;
}
collection.Add(filePath, dsr);
_cacheBusted = true;
return true;
}
catch (Exception e)
{
System.Console.WriteLine("[CachedDataManager] [ERROR] Could not load from cache: {0}", e);
return orig_Deserialize(filePath, out dsr);
}
}
private extern bool orig_IsLoaded();
public new bool IsLoaded()
{
var loaded = orig_IsLoaded();
if (!loaded || !_cacheBusted)
{
return loaded;
}
try
{
SaveCache();
}
catch (Exception e)
{
System.Console.WriteLine("[CachedDataManager] [ERROR] Could not save to cache: {0}", e);
}
_cacheBusted = false;
return true;
}
private static readonly CachedDataManager.SerializationCache Cache = new();
private static bool _cacheBusted;
}

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CachedDataManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CachedDataManager")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("F1C1B6BF-626C-4F10-8672-2F9596706CA6")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,67 +0,0 @@
// ReSharper disable UnassignedField.Global
using System.Collections.Generic;
using Manager.MaiStudio.Serialize;
namespace CachedDataManager;
public class SerializationCache
{
public Dictionary<string, RomConfig> RomConfigs;
public Dictionary<string, DataConfig> DataConfigs;
public Dictionary<string, CharaData> Charas;
public Dictionary<string, CharaAwakeData> CharaAwakes;
public Dictionary<string, CharaGenreData> CharaGenres;
public Dictionary<string, EventData> Events;
public Dictionary<string, MusicData> Musics;
public Dictionary<string, MusicGenreData> MusicGenres;
public Dictionary<string, MusicGroupData> MusicGroups;
public Dictionary<string, MusicVersionData> MusicVersions;
public Dictionary<string, MusicNameSortData> MusicNameSorts;
public Dictionary<string, MusicClearRankData> MusicClearRanks;
public Dictionary<string, MusicDifficultyData> MusicDifficultys;
public Dictionary<string, MusicLevelData> MusicLevels;
public Dictionary<string, ScoreRankingData> TournamentMusics;
public Dictionary<string, CourseData> Courses;
public Dictionary<string, CourseModeData> CourseModes;
public Dictionary<string, LoginBonusData> LoginBonuses;
public Dictionary<string, MapData> Maps;
public Dictionary<string, MapColorData> MapColors;
public Dictionary<string, MapTreasureData> MapTreasures;
public Dictionary<string, MapBonusMusicData> MapBonusMusics;
public Dictionary<string, MapOtomodachiData> MapOtomodachis;
public Dictionary<string, MapSilhouetteData> MapSilhouettes;
public Dictionary<string, MapTitleData> MapTitles;
public Dictionary<string, ItemMusicData> ItemMusics;
public Dictionary<string, IconData> Icons;
public Dictionary<string, PlateData> Plates;
public Dictionary<string, TitleData> Titles;
public Dictionary<string, PartnerData> Partners;
public Dictionary<string, FrameData> Frames;
public Dictionary<string, TicketData> Tickets;
public Dictionary<string, CollectionTypeData> CollectionTypes;
public Dictionary<string, CollectionGenreData> CollectionGenres;
public Dictionary<string, PhotoFrameData> PhotoFrames;
public Dictionary<string, InformationData> Informations;
public Dictionary<string, UdemaeData> Udemaes;
public Dictionary<string, ClassData> Classes;
public Dictionary<string, UdemaeBossData> UdemaeBosses;
public Dictionary<string, UdemaeSeasonEventData> UdemaeSeasonEvents;
public Dictionary<string, UdemaeSeasonRewardData> UdemaeSeasonRewards;
public Dictionary<string, CardData> Cards;
public Dictionary<string, CardCharaData> CardCharas;
public Dictionary<string, CardTypeData> CardTypes;
public Dictionary<string, HolidayData> WeekdayBonuses;
public Dictionary<string, ChallengeData> Challenges;
public Dictionary<string, SerializeSortData> MusicRankings;
public Dictionary<string, SerializeSortData> MusicSorts;
public Dictionary<string, SerializeSortData> LoginBonusSorts;
public Dictionary<string, SerializeSortData> IconSorts;
public Dictionary<string, SerializeSortData> PlateSorts;
public Dictionary<string, SerializeSortData> TitleSorts;
public Dictionary<string, SerializeSortData> PartnerSorts;
public Dictionary<string, SerializeSortData> FrameSorts;
public Dictionary<string, SerializeSortData> TicketSorts;
public Dictionary<string, SerializeSortData> CollectionGenreSorts;
public Dictionary<string, SerializeSortData> CharaSorts;
public Dictionary<string, SerializeSortData> CharaGenreSorts;
}

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.DisableEncryption.mm</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
namespace Net.Packet;
public class patch_Packet : Packet
{
[MonoModIgnore]
public override PacketState Proc()
{
throw new NotImplementedException();
}
[MonoModReplace]
public new static string Obfuscator(string srcStr)
{
return srcStr;
}
}

View File

@ -0,0 +1,21 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
namespace Net;
[MonoModPatch("global::Net.CipherAES")]
public class patch_CipherAES
{
[MonoModReplace]
public static byte[] Encrypt(byte[] data)
{
return data;
}
[MonoModReplace]
public static byte[] Decrypt(byte[] data)
{
return data;
}
}

View File

@ -0,0 +1,17 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using MonoMod;
namespace Net;
public class patch_NetHttpClient : NetHttpClient
{
[MonoModReplace]
public new static bool CheckServerHash(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
}
}

View File

@ -0,0 +1,17 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
namespace System.Net;
public class patch_WebHeaderCollection : WebHeaderCollection
{
public extern void orig_Add(string header, string value);
public new void Add(string header, string value)
{
if (header.ToLowerInvariant() == "mai-encoding")
{
return;
}
orig_Add(header, value);
}
}

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.DisableReboot.mm</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,21 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
namespace Manager.Operation;
public class patch_MaintenanceTimer : MaintenanceTimer
{
[MonoModReplace]
public new bool IsAutoRebootNeeded()
{
return false;
}
[MonoModReplace]
public new int GetAutoRebootSec()
{
return 86400;
}
}

View File

@ -0,0 +1,39 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
namespace Manager.Operation;
public class patch_SegaBootTimer : SegaBootTimer
{
[MonoModReplace]
public new bool IsSegaBootTime()
{
return false;
}
[MonoModReplace]
public new int GetGotoSegaBootSec()
{
return 86400;
}
[MonoModReplace]
public new bool IsSegaBootNeeded()
{
return false;
}
[MonoModReplace]
public new int GetRemainingMinutes()
{
return 1440;
}
[MonoModReplace]
public new bool IsCoinAcceptable()
{
return true;
}
}

View File

@ -1,43 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{48B5F480-D749-48E9-9D26-E0E5260D95DE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FixLocaleIssues</RootNamespace>
<AssemblyName>Assembly-CSharp.FixLocaleIssues.mm</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.FixLocaleIssues.mm</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
@ -55,19 +26,5 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MAI2System\patch_IniSection.cs" />
<Compile Include="Manager\patch_MA2Record.cs" />
<Compile Include="Manager\patch_SlideManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -18,4 +18,4 @@ class patch_IniSection : IniSection
{
return float.TryParse(_variableValue, NumberStyles.Float, CultureInfo.InvariantCulture, out value);
}
}
}

View File

@ -6,7 +6,7 @@ using MonoMod;
namespace Manager;
class patch_MA2Record : MA2Record
public class patch_MA2Record : MA2Record
{
[MonoModIgnore]
private static extern Ma2fileParamID.Def getParamIDFromRec(Ma2fileRecordID.Def rec, int index);

View File

@ -1,9 +1,7 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using MonoMod;
@ -16,7 +14,9 @@ public class patch_SlideManager : SlideManager
[MonoModIgnore]
private struct SlidePath
{
#pragma warning disable CS0649
public List<ControlPoint> Points;
#pragma warning restore CS0649
}
[MonoModIgnore]

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("FixLocaleIssues")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FixLocaleIssues")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("48B5F480-D749-48E9-9D26-E0E5260D95DE")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.ImproveLoadTimes.mm</AssemblyName>
<NoWarn>CS0626</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,12 @@
// ReSharper disable CheckNamespace
using MonoMod;
namespace Manager.MaiStudio.Serialize;
[MonoModReplace]
[Serializable]
public class SerializeBase
{
public virtual void AddPath(string parentPath) { }
}

View File

@ -17,4 +17,4 @@ public class patch_FilePath : FilePath
path = parentPath + path;
}
}
}

View File

@ -0,0 +1,99 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System.Runtime.Serialization.Formatters.Binary;
namespace Manager;
public class patch_DataManager : DataManager
{
private const string _cacheFilename = "data_cache.bin";
private static Dictionary<string, object>? _cache;
private static bool _cacheBusted;
private static extern bool orig_Deserialize<T>(string filePath, out T dsr) where T : new();
private static bool Deserialize<T>(string filePath, out T dsr) where T : new()
{
try
{
_cache ??= LoadCache(_cacheFilename);
}
catch (Exception e)
{
System.Console.WriteLine("[ImproveLoadTimes] Could not load data cache: {0}", e);
_cache ??= new Dictionary<string, object>();
}
try
{
if (_cache.TryGetValue(filePath, out var dsrObject))
{
dsr = (T)dsrObject;
return true;
}
if (!orig_Deserialize(filePath, out dsr))
{
return false;
}
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (filePath == null || dsr == null)
{
return true;
}
_cache.Add(filePath, dsr);
_cacheBusted = true;
return true;
}
catch (Exception e)
{
System.Console.WriteLine("[ImproveLoadTimes] [ERROR] Could not load from cache: {0}", e);
return orig_Deserialize(filePath, out dsr);
}
}
private extern bool orig_IsLoaded();
public new bool IsLoaded()
{
var loaded = orig_IsLoaded();
if (!loaded || !_cacheBusted || _cache == null)
{
return loaded;
}
try
{
SaveCache(_cacheFilename, _cache);
}
catch (Exception e)
{
System.Console.WriteLine("[ImproveLoadTimes] [ERROR] Could not save to cache: {0}", e);
}
_cacheBusted = false;
return true;
}
private static Dictionary<string, object> LoadCache(string fileName)
{
if (!File.Exists(fileName))
{
return new Dictionary<string, object>();
}
System.Console.WriteLine("[ImproveLoadTimes] Loading data cache...");
using var fs = File.OpenRead(fileName);
return (Dictionary<string, object>)new BinaryFormatter().Deserialize(fs);
}
private static void SaveCache(string fileName, Dictionary<string, object> cache)
{
using var fs = File.Open(fileName, FileMode.Create, FileAccess.Write);
new BinaryFormatter().Serialize(fs, cache);
}
}

View File

@ -0,0 +1,21 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
using Process;
namespace Manager;
public class patch_PowerOnProcess : PowerOnProcess
{
#pragma warning disable CS0414 // Field is assigned but its value is never used
[MonoModIgnore]
private float _waitTime;
#pragma warning restore CS0414 // Field is assigned but its value is never used
[MonoModConstructor]
public patch_PowerOnProcess(ProcessDataContainer dataContainer) : base(dataContainer)
{
_waitTime = 0f;
}
}

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.Ports" Version="9.0.0-preview.4.24266.19" />
</ItemGroup>
</Project>

View File

@ -1,154 +0,0 @@
// See https://aka.ms/new-console-template for more information
using System.Collections.Immutable;
using System.Reflection;
using System.Text;
var assemblyPath = args[0];
var targetPath = args[1];
var assembly = Assembly.LoadFrom(assemblyPath);
var types = assembly.GetTypes().Where(t => t.FullName.StartsWith("DB.") && t.FullName.EndsWith("IDEnum")).ToImmutableList();
foreach (var type in types)
{
var tableRecordType = assembly.GetType(type.FullName.Replace("IDEnum", "TableRecord"))!;
var patchClassName = $"patch_{type.Name}";
var readCommands = new StringBuilder();
var writeCommands = new StringBuilder();
var tableRecordFields = new StringBuilder();
foreach (var field in tableRecordType.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
tableRecordFields.Append("public ");
if (field.FieldType.IsEnum)
{
tableRecordFields.Append("System.Int32 ");
}
else
{
tableRecordFields.Append(field.FieldType.FullName);
tableRecordFields.Append(" ");
}
tableRecordFields.Append(field.Name);
tableRecordFields.AppendLine(";");
readCommands.Append(field.Name)
.Append(" = (")
.Append(field.FieldType.FullName)
.Append(")src[i].")
.Append(field.Name)
.Append(", ");
writeCommands.Append(field.Name)
.Append(" = (")
.Append(field.FieldType.IsEnum ? "int" : field.FieldType.FullName)
.Append(")src[i].")
.Append(field.Name)
.Append(", ");
}
using var sw = File.CreateText(Path.Combine(targetPath, patchClassName + ".cs"));
sw.WriteLine($$"""
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text;
using MonoMod;
using LooseDBTables;
using UnityEngine;
namespace DB;
[MonoModIgnore]
[GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")]
public class {{type.Name}}
{
public static extern bool LoadFromFile(string filename);
public static extern void DumpToFile(string filename);
protected static {{tableRecordType.Name}}[] records;
}
[GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")]
[Serializable]
public class Serializable{{tableRecordType.Name}} {
{{tableRecordFields}}
}
[GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")]
public class {{patchClassName}} : {{type.Name}} {
public new static bool LoadFromFile(string filename) {
if (!File.Exists(filename)) {
return false;
}
var table = JsonUtility.FromJson<Table<Serializable{{tableRecordType.Name}}>>(File.ReadAllText(filename));
try
{
if (table.records.Length != records.Length) {
Debug.LogError($"Count read error: {filename}");
return false;
}
var src = table.records;
var dst = records;
for (var i = 0; i < table.records.Length; i++) {
dst[i] = new {{tableRecordType.Name}} { {{readCommands}} };
}
}
catch
{
Debug.LogError($"File read error: {filename}");
return false;
}
return true;
}
public new static void DumpToFile(string filename) {
var table = new Table<Serializable{{tableRecordType.Name}}>() {
records = new Serializable{{tableRecordType.Name}}[records.Length]
};
var src = records;
var dst = table.records;
for (var i = 0; i < records.Length; i++) {
dst[i] = new Serializable{{tableRecordType.Name}} { {{writeCommands}} };
}
File.WriteAllText(filename, JsonUtility.ToJson(table, true), Encoding.UTF8);
}
}
""");
}
using var dbLoaderSw = File.CreateText(Path.Combine(targetPath, "DBLoader.cs"));
dbLoaderSw.WriteLine($$"""
// ReSharper disable CheckNamespace
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text;
namespace DB;
[GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")]
public class DBLoader
{
public static void LoadAll(string dirPath)
{
{{string.Join("\n", types.Select(t => $"{t.Name}.LoadFromFile(Path.Combine(dirPath, \"{t.Name.Replace("IDEnum", "TableRecord")}.json\"));"))}}
}
public static void DumpAll(string dirPath)
{
{{string.Join("\n", types.Select(t => $"{t.Name}.DumpToFile(Path.Combine(dirPath, \"{t.Name.Replace("IDEnum", "TableRecord")}.json\"));"))}}
}
}
""");

View File

@ -1,43 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F15988CC-BDF0-4F86-811B-BAE18EEA6519}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LooseDBTables</RootNamespace>
<AssemblyName>Assembly-CSharp.LooseDBTables.mm</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.LooseDBTables.mm</AssemblyName>
<NoWarn>CS0626,CS0436,CS8618</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
@ -59,19 +31,5 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DB\*.cs" />
<Compile Include="Process\patch_PowerOnProcess.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="Table.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LooseDBTables")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LooseDBTables")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("F15988CC-BDF0-4F86-811B-BAE18EEA6519")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -17,7 +17,6 @@ public class SxtReader(NotesReferences refs) : SxtReaderBase(refs)
throw new Exception($"Slide head at row {rowIdx} does not declare a valid slide ID");
}
System.Console.WriteLine("[MoreChartFormats] Saving slide head with ID {0}", row.SlideId);
SlideHeads[row.SlideId] = row;
return;
}
@ -74,7 +73,6 @@ public class SxtReader(NotesReferences refs) : SxtReaderBase(refs)
note.end.copy(rowTime);
}
System.Console.WriteLine("[MoreChartFormats] [SXT] Adding note {0} at {1}", note.type.getEnumName(), note.time.getBar());
Refs.Notes._noteData.Add(note);
NoteIndex++;
}

View File

@ -1,43 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A375F626-7238-4227-95C9-2BB1E5E099F6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MoreChartFormats</RootNamespace>
<AssemblyName>Assembly-CSharp.MoreChartFormats.mm</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.MoreChartFormats.mm</AssemblyName>
<NoWarn>CS8618,CS8625</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
@ -55,37 +27,5 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MaiSxt\SrtReader.cs" />
<Compile Include="MaiSxt\Structures\SxtRow.cs" />
<Compile Include="MaiSxt\SxtReader.cs" />
<Compile Include="MaiSxt\SxtReaderBase.cs" />
<Compile Include="NotesReferences.cs" />
<Compile Include="ParserUtilities.cs" />
<Compile Include="patch_NotesReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="Simai\BpmChangeDataExtensions.cs" />
<Compile Include="Simai\SimaiReader.cs" />
<Compile Include="Simai\LexicalAnalysis\Token.cs" />
<Compile Include="Simai\LexicalAnalysis\Tokenizer.cs" />
<Compile Include="Simai\LexicalAnalysis\TokenType.cs" />
<Compile Include="Simai\Errors\*.cs" />
<Compile Include="Simai\Structures\SlideSegment.cs" />
<Compile Include="Simai\Structures\SlideTiming.cs" />
<Compile Include="Simai\SyntacticAnalysis\Deserializer.cs" />
<Compile Include="Simai\SyntacticAnalysis\States\NoteReader.cs" />
<Compile Include="Simai\SyntacticAnalysis\States\SlideReader.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Simai\LexicalAnalysis\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MoreChartFormats")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MoreChartFormats")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("A375F626-7238-4227-95C9-2BB1E5E099F6")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,17 +1,13 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System;
using System.IO;
using System.Xml.Serialization;
using MAI2.Util;
using Manager.MaiStudio.Serialize;
using MonoMod;
using MoreChartFormats;
using MoreChartFormats.MaiSxt;
using MoreChartFormats.Simai;
using MoreChartFormats.Simai.Errors;
using MoreChartFormats.Simai.Structures;
namespace Manager;
@ -135,7 +131,15 @@ class patch_NotesReader : NotesReader
{
note.time.calcMsec(this);
note.end.calcMsec(this);
note.startButtonPos = ConvertMirrorPosition(note.startButtonPos);
if (note.type.isTouch() && note.touchArea is TouchSensorType.D or TouchSensorType.E)
{
note.startButtonPos = ConvertMirrorTouchEPosition(note.startButtonPos);
}
else
{
note.startButtonPos = ConvertMirrorPosition(note.startButtonPos);
}
if (note.type.isSlide() || note.type == NotesTypeID.Def.ConnectSlide)
{
@ -144,31 +148,29 @@ class patch_NotesReader : NotesReader
note.slideData.targetNote = ConvertMirrorPosition(note.slideData.targetNote);
note.slideData.type = ConvertMirrorSlide(note.slideData.type);
}
if (note.type.isTouch() && note.touchArea is TouchSensorType.D or TouchSensorType.E)
{
note.startButtonPos = ConvertMirrorTouchEPosition(note.startButtonPos);
}
}
#if DEBUG
System.Console.WriteLine("[MoreChartFormats] [Simai] Calculating chart data");
#endif
calcAll();
#if DEBUG
System.Console.WriteLine("[MoreChartFormats] [Simai] Loaded {0} notes", _total.GetAllNoteNum());
System.Console.WriteLine("[MoreChartFormats] [Simai] > {0} taps", _total.GetTapNum());
System.Console.WriteLine("[MoreChartFormats] [Simai] > {0} holds", _total.GetHoldNum());
System.Console.WriteLine("[MoreChartFormats] [Simai] > {0} slides", _total.GetSlideNum());
System.Console.WriteLine("[MoreChartFormats] [Simai] > {0} touches", _total.GetTouchNum());
System.Console.WriteLine("[MoreChartFormats] [Simai] > {0} break", _total.GetBreakNum());
#endif
}
catch (SimaiException e)
{
System.Console.WriteLine($"[MoreChartFormats] There was an error loading the chart at line {e.line}, col {e.character}: {e} ");
System.Console.WriteLine($"[MoreChartFormats] [Simai] There was an error loading the chart at line {e.line}, col {e.character}: {e} ");
return false;
}
catch (Exception e)
{
System.Console.WriteLine($"[MoreChartFormats] There was an error loading the chart: {e}");
System.Console.WriteLine($"[MoreChartFormats] [Simai] There was an error loading the chart: {e}");
return false;
}

167
README.md
View File

@ -1,59 +1,108 @@
## sinmai-mods
Miscellaneous mods for maimai DX
### CachedDataManager
Speeds up game reboots by caching loaded data. Cache is stored in the `dataCache` folder
and should be deleted if any issues arise.
### FixLocaleIssues
Attempts to fix charts not loading on some system locales.
Adds `CultureInfo.InvariantCulture` to all instances of `float.Parse` and `float.TryParse`
so charts will still load on locales where the comma is the decimal separator.
### LooseDBTables
Enables loading tables from loose `.json` files in `Sinmai_Data/StreamingAssets/DB`.
Useful for string edits (a.k.a. english patch).
Tables are automatically generated if `Sinmai_Data/StreamingAssets/DB` doesn't exist.
### MoreChartFormats
Loads charts written in various known formats:
- [simai](https://w.atwiki.jp/simai) (powered by a custom fork of [SimaiSharp](https://github.com/reflektone-games/SimaiSharp))
- srt/szt/sct/sdt (maimai classic chart format)
To use, edit Music.xml to point the chart file path to your chart file:
```xml
<Notes>
<file>
<path>{filename}.sdt</path>
</file>
<!-- snip -->
</Notes>
```
The chart loader used depends on the file extension:
- simai chart files must end with `.simai`
- srt chart files must end with `.srt`
- szt/sct/sdt files can use `.szt`/`.sct`/`.sdt` interchangeably, since they only
differ by two ending columns. [details](https://listed.to/@donmai/18173/the-four-chart-formats-of-maimai-classic)
#### Simai caveats
- **`maidata.txt` is not supported. If you have one, paste the content of each
`inote_x` into their own `.simai` file.**
- Both `?` and `!` will create a slide without a star note, but both of them will
make the slide fade in (`!` makes the slide suddenly appear in standard simai).
- `$` cannot be used to create a tapless slide (maiPad PLUS syntax).
- `$$` is ignored, as star notes only spin when there's an associated slide.
- `[BPM#a:b]` is not supported for specifying hold time.
- `` ` `` (fake EACH) makes taps 1/384 measures apart.
#### SXT caveats
- Encrypted chart files (`.srb`/`.szb`/`.scb`/`.sdb`) are not supported. Decrypt
them before loading into the game.
- Since this chart format does not contain timing data, the song's BPM is retrieved
by loading the `Music.xml` associated with the chart, **and it is assumed that the
chart and `Music.xml` is in the same folder**. The SXT loader will not work if the
chart file is somehow in a different folder from `Music.xml`.
## sinmai-mods
Mods for maimai DX. Patch with MonoMod except specified
otherwise.
## Mod list
### DisableEncryption
Disables title server encryption.
### DisableReboot
Disables automatic reboots.
### FixLocaleIssues
Attempt to fix charts not loading on regions where the system's
decimal separator is not the dot (`.`).
### ImproveLoadTimes
Speed up game reboots by caching game data. Cache data is stored
in `data_cache.bin` and can be safely deleted if issues arise.
### LooseDBTables
Load game tables from `.json` files in `Sinmai_Data/StreamingAssets/DB`.
Useful for string edits (e.g. translation).
Tables are automatically generated if the `DB` folder does not
exist.
### MoreChartFormats
Load charts written in various formats:
- [simai](https://w.atwiki.jp/simai)
- srt/szt/sct/sdt (maimai classic chart format)
To use, edit Music.xml to point the chart file path to your chart
file:
```xml
<Notes>
<file>
<path>{filename}.sdt</path>
</file>
<!-- snip -->
</Notes>
```
The chart loader depends on the file extension:
- simai chart files must end with .simai
- srt chart files must end with .srt
- szt/sct/sdt files can use .szt/.sct/.sdt interchangeably.
<details>
<summary>Simai caveats</summary>
- **`maidata.txt` is not supported. If you have one, paste the
content of each`inote_x` into their own `.simai` file.**
- Both `?` and `!` will create a slide without a star note, but
both of them will make the slide fade in (`!` makes the slide
suddenly appear in standard simai).
- `$` cannot be used to create a tapless slide (maiPad PLUS
syntax).
- `$$` is ignored, as star notes only spin when there's an
associated slide.
- `[BPM#a:b]` is not supported for specifying hold time.
- `` ` `` (fake EACH) makes taps 1/384 measures apart.
</details>
<details>
<summary>SXT caveats</summary>
- Encrypted chart files (`.srb`/`.szb`/`.scb`/`.sdb`) are not
supported. Decrypt them before loading into the game.
- Since this chart format does not contain timing data, the
song's BPM is retrieved by loading the `Music.xml` associated
with the chart, **and it is assumed that the chart and
`Music.xml` is in the same folder**. The SXT loader will not
work if the chart file is somehow in a different folder
from `Music.xml`.
</details>
### Singleplayer
Show only the left monitor at the center of the screen.
### TouchPanel
Set touch panel sensitivity for individual regions, or introduce
delay on the touch panel. It is configured by adding an optional
section to `mai2.ini`:
```ini
[TouchPanel]
; Introduce delay to touch inputs to make it line up with
; button inputs
DelayMs=0
; Customize the activation threshold for specific touch
; sensors (optional). The touch sensor values can be found by
; going into input test in the game test menu.
SensitivityA1=90
SensitivityA2=90
...
```
### UnlockFrameRate
**BepInEx mod.**
Change the target FPS. Also comes with an FPS counter. The
configuration file for changing the FPS is at
`BepInEx/config/io.github.beerpsi.sinmai.framerate.cfg` and is
already documented.

View File

@ -0,0 +1,30 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MonoMod;
using UnityEngine;
namespace Main;
public class patch_GameMainObject : GameMainObject
{
[MonoModIgnore]
private Transform rightMonitor;
private extern void orig_Start();
private void Start()
{
orig_Start();
var mainCamera = Camera.main;
if (mainCamera == null)
{
return;
}
var position = mainCamera.gameObject.transform.position;
mainCamera.gameObject.transform.position = new Vector3(-540f, position.y, position.z);
rightMonitor.transform.localScale = Vector3.zero;
}
}

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.Singleplayer.mm</AssemblyName>
<NoWarn>CS0626,CS0649,CS8618</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,65 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System.Globalization;
using MAI2System;
using Manager;
namespace IO;
class patch_NewTouchPanel : NewTouchPanel
{
private int _touchPanelDelayMsec;
private Dictionary<InputManager.TouchPanelArea, byte> _sensitivityOverrides = new();
public extern void orig_Initialize(uint index);
public new void Initialize(uint index)
{
orig_Initialize(index);
using var ini = new IniFile("mai2.ini");
_touchPanelDelayMsec = ini.getIntValue("TouchPanel", "DelayMs", 0);
foreach (InputManager.TouchPanelArea sensor in Enum.GetValues(typeof(InputManager.TouchPanelArea)))
{
var sensitivityStr = ini.getValue("TouchPanel", $"Sensitivity{sensor}", null);
if (sensitivityStr == null)
{
continue;
}
if (byte.TryParse(sensitivityStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out var sensitivity))
{
System.Console.WriteLine($"[TouchPanel] [WARN] Invalid value for TouchPanel.Sensitivity{sensor}: {sensitivityStr}");
continue;
}
_sensitivityOverrides[sensor] = sensitivity;
}
}
private extern void orig_Recv();
private void Recv()
{
if (_touchPanelDelayMsec > 0)
{
Thread.Sleep(_touchPanelDelayMsec);
}
orig_Recv();
}
private extern void orig_SetTouchPanelSensitivity(List<byte> sensitivity);
private void SetTouchPanelSensitivity(List<byte> sensitivity)
{
foreach (var s in _sensitivityOverrides)
{
System.Console.WriteLine($"[TouchPanel] Overriding sensitivity for panel {s.Key}: {s.Value}");
sensitivity[(int)s.Key] = s.Value;
}
orig_SetTouchPanelSensitivity(sensitivity);
}
}

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Assembly-CSharp.TouchPanel.mm</AssemblyName>
<NoWarn>CS0626</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,112 @@
#pragma warning disable IDE0051
// ReSharper disable UnusedMember.Local
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
namespace UnlockFrameRate;
[BepInPlugin("io.github.beerpsi.sinmai.framerate", "FrameRate", "0.1.0")]
[BepInProcess("Sinmai.exe")]
public class FrameRatePlugin : BaseUnityPlugin
{
public new static ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("FrameRate");
public static FrameRatePlugin Instance { get; private set; }
public int TargetFrameRate => _configFrameRate.Value;
public bool PatchJudgementTiming => _configChangeJudgementTiming.Value;
private ConfigEntry<int> _configFrameRate;
private ConfigEntry<int> _configVSyncCount;
private ConfigEntry<bool> _configDisplayFps;
private ConfigEntry<bool> _configChangeJudgementTiming;
private Harmony _harmony;
private void Awake()
{
Instance = this;
_configFrameRate = Config.Bind(
"Config",
"FrameRate",
60,
"The frame rate to run the game at");
_configVSyncCount = Config.Bind(
"Config",
"VSyncCount",
0,
"Supported values are 0 to 4. 0 disables VSync and the rest enables it.\nWhen this is enabled, FrameRate is ignored and the target frame rate\nis calculated by taking the current refresh rate divided by VSyncCount\n(e.g. 120Hz at VSyncCount 2 => 60fps).");
_configDisplayFps = Config.Bind(
"Config",
"DisplayFPS",
false,
"Show an FPS counter");
_configChangeJudgementTiming = Config.Bind(
"Config",
"ChangeJudgementTiming",
true,
"Adjusts JUDGEMENT TIMING options to match the new frame rate.\nIf this is enabled, 0.1 in-game offset is equivalent to 10000 / FrameRate.");
if (_configVSyncCount.Value is > 0 and <= 4)
{
QualitySettings.vSyncCount = _configVSyncCount.Value;
Logger.LogInfo(
"VSync is enabled (VSyncCount={0}), target frame rate is {1}fps",
_configVSyncCount.Value,
TargetFrameRate);
}
else
{
Application.targetFrameRate = TargetFrameRate;
QualitySettings.vSyncCount = 0;
Logger.LogInfo(
"VSync is disabled, target frame rate is {0}fps",
TargetFrameRate);
}
Time.fixedDeltaTime = 1f / TargetFrameRate * Time.timeScale;
Logger.LogDebug(
"Setting Time.fixedDeltaTime to {0}s",
Time.fixedDeltaTime);
Logger.LogDebug("Patching hardcoded frame time usages");
_harmony = new Harmony("io.github.beerpsi.sinmai.framerate");
_harmony.PatchAll();
}
private const int FpsSamples = 100;
private int _currentFps = 0;
private int _currentSampleCount = FpsSamples;
private float _totalTime = 0;
private void OnGUI()
{
if (!_configDisplayFps.Value)
{
return;
}
_totalTime += Time.deltaTime;
_currentSampleCount--;
if (_currentSampleCount == 0)
{
_currentFps = (int)(FpsSamples / _totalTime);
_totalTime = 0f;
_currentSampleCount = FpsSamples;
}
GUI.Label(new Rect(10f, 10f, 150f, 100f), "FPS: " + _currentFps);
}
private void OnDestroy()
{
_harmony?.UnpatchSelf();
}
}

View File

@ -0,0 +1,17 @@
using BepInEx.Logging;
namespace UnlockFrameRate;
internal static class ManualLogSourceExtensions
{
public static void LogInfo(this ManualLogSource logger, string format, params object[] args)
{
logger.LogInfo(string.Format(format, args));
}
public static void LogDebug(this ManualLogSource logger, string format, params object[] args)
{
logger.LogDebug(string.Format(format, args));
}
}

View File

@ -0,0 +1,97 @@
// ReSharper disable InconsistentNaming
using HarmonyLib;
using Manager;
using Manager.UserDatas;
using Monitor;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace UnlockFrameRate;
[HarmonyPatch]
internal class PatchFrameTime
{
private const float OriginalFrameRate = 60f;
private const float OriginalFrameTime = 1000f / OriginalFrameRate;
private const float OriginalFramePerMilliseconds = OriginalFrameRate / 1000;
private static IEnumerable<MethodBase> TargetMethods()
{
// This shouldn't be patched, because they make the judgements
// harder or easier depending on your frame rate.
// var noteJudge = AccessTools.TypeByName("NoteJudge");
// var juggeTiming = AccessTools.Inner(noteJudge, "JuggeTiming"); // lol
// yield return AccessTools.Constructor(juggeTiming);
// This changes the effect of judgement timing based on the set FPS,
// so +2.0 at 120Hz will only add 17ms instead of 33ms.
if (FrameRatePlugin.Instance.PatchJudgementTiming)
{
yield return AccessTools.Method(typeof(NoteJudge), nameof(NoteJudge.GetJudgeTiming));
yield return AccessTools.Method(typeof(NoteJudge), nameof(NoteJudge.GetSlideJudgeTiming));
yield return AccessTools.Method(typeof(UserOption), nameof(UserOption.GetAdjustMSec));
}
yield return AccessTools.Method(typeof(NoteBase), "IsNoteCheckTimeStart");
yield return AccessTools.Method(typeof(TouchNoteB), "GetNoteYPosition");
yield return AccessTools.Method(typeof(SlideRoot), "IsNoteCheckTimeStart");
yield return AccessTools.Method(typeof(SlideJudge), nameof(SlideJudge.Initialize));
yield return AccessTools.Method(typeof(JudgeGrade), nameof(JudgeGrade.Initialize));
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getPlayFirstMsec));
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getPlayFinalMsec));
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getCurrentDrawFrame));
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.calcFrame));
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.GetBPM_Frame));
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.getMeter_Frame));
yield return AccessTools.Method(typeof(NoteData), nameof(NoteData.getLengthFrame));
yield return AccessTools.Method(typeof(GameManager), nameof(GameManager.UpdateGameTimer));
yield return AccessTools.PropertyGetter(typeof(NotesTime), nameof(NotesTime.frame));
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
{
var targetFrameTime = 1000f / FrameRatePlugin.Instance.TargetFrameRate;
var targetFramePerMs = (float)FrameRatePlugin.Instance.TargetFrameRate / 1000;
var i = 0;
foreach (var instruction in instructions)
{
if (instruction.opcode != OpCodes.Ldc_R4 || instruction.operand is not float operand)
{
yield return instruction;
i++;
continue;
}
var overridden = false;
if (Math.Abs(operand - OriginalFrameTime) < float.Epsilon)
{
instruction.operand = targetFrameTime;
overridden = true;
}
else if (Math.Abs(operand - OriginalFramePerMilliseconds) < float.Epsilon)
{
instruction.operand = targetFramePerMs;
overridden = true;
}
if (overridden)
{
FrameRatePlugin.Logger.LogDebug(
"Overrode constant at opcode index {0} in {1}: {2} => {3}",
i,
__originalMethod.Name,
operand,
instruction.operand);
}
yield return instruction;
i++;
}
}
}

View File

@ -0,0 +1,43 @@
using HarmonyLib;
using Monitor;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace UnlockFrameRate;
[HarmonyPatch(typeof(NoteBase), "GetMaiBugAdjustMSec")]
internal class PatchGetMaiBugAdjustMSec
{
private const float OriginalFrameRate = 60f;
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
{
var i = 0;
foreach (var instruction in instructions)
{
if (instruction.opcode != OpCodes.Ldc_R4 || instruction.operand is not float operand)
{
yield return instruction;
i++;
continue;
}
if (Math.Abs(operand - OriginalFrameRate) < float.Epsilon)
{
instruction.operand = (float)FrameRatePlugin.Instance.TargetFrameRate;
FrameRatePlugin.Logger.LogDebug(
"Overrode constant at opcode index {0} in {1}: {2} => {3}",
i,
__originalMethod.Name,
operand,
instruction.operand);
}
yield return instruction;
i++;
}
}
}

View File

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<LangVersion>latest</LangVersion>
<AssemblyName>UnlockFrameRate</AssemblyName>
<Version>1.0.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all"/>
<PackageReference Include="BepInEx.Core" Version="5.*"/>
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*"/>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>..\External\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all"/>
</ItemGroup>
</Project>

View File

@ -1,40 +1,70 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CachedDataManager", "CachedDataManager\CachedDataManager.csproj", "{F1C1B6BF-626C-4F10-8672-2F9596706CA6}"
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FixLocaleIssues", "FixLocaleIssues\FixLocaleIssues.csproj", "{C1D1272C-5BC5-4EFD-A9DA-BB8BE8B16280}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FixLocaleIssues", "FixLocaleIssues\FixLocaleIssues.csproj", "{48B5F480-D749-48E9-9D26-E0E5260D95DE}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImproveLoadTimes", "ImproveLoadTimes\ImproveLoadTimes.csproj", "{B18FA6C6-79C3-4851-A88E-161D273CBC0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LooseDBTables", "LooseDBTables\LooseDBTables.csproj", "{F15988CC-BDF0-4F86-811B-BAE18EEA6519}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchPanel", "TouchPanel\TouchPanel.csproj", "{B8E4A429-DE84-4565-AD51-87ECCBD629C5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LooseDBTables.GeneratePatches", "LooseDBTables.GeneratePatches\LooseDBTables.GeneratePatches.csproj", "{7DF53594-C7B2-44D1-ADF7-CCE4BC9E7625}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Singleplayer", "Singleplayer\Singleplayer.csproj", "{0A9D8A7E-984F-4406-B497-E45CFF1073E6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreChartFormats", "MoreChartFormats\MoreChartFormats.csproj", "{A375F626-7238-4227-95C9-2BB1E5E099F6}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisableEncryption", "DisableEncryption\DisableEncryption.csproj", "{FCBAB1FC-A47F-4939-B17B-F07F1A9DF4F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisableReboot", "DisableReboot\DisableReboot.csproj", "{B645EB54-CC74-437F-9255-2D9BFED87DF2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreChartFormats", "MoreChartFormats\MoreChartFormats.csproj", "{1966AAE3-19E7-4BA0-862A-A3C54DB51B3F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LooseDBTables", "LooseDBTables\LooseDBTables.csproj", "{10E43267-ADB6-44AC-BABA-80D4CF4C7BC8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnlockFrameRate", "UnlockFrameRate\UnlockFrameRate.csproj", "{54622F97-9187-482C-A9DC-06E1855EF2D7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F1C1B6BF-626C-4F10-8672-2F9596706CA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1C1B6BF-626C-4F10-8672-2F9596706CA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1C1B6BF-626C-4F10-8672-2F9596706CA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1C1B6BF-626C-4F10-8672-2F9596706CA6}.Release|Any CPU.Build.0 = Release|Any CPU
{48B5F480-D749-48E9-9D26-E0E5260D95DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48B5F480-D749-48E9-9D26-E0E5260D95DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48B5F480-D749-48E9-9D26-E0E5260D95DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48B5F480-D749-48E9-9D26-E0E5260D95DE}.Release|Any CPU.Build.0 = Release|Any CPU
{F15988CC-BDF0-4F86-811B-BAE18EEA6519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F15988CC-BDF0-4F86-811B-BAE18EEA6519}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F15988CC-BDF0-4F86-811B-BAE18EEA6519}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F15988CC-BDF0-4F86-811B-BAE18EEA6519}.Release|Any CPU.Build.0 = Release|Any CPU
{7DF53594-C7B2-44D1-ADF7-CCE4BC9E7625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DF53594-C7B2-44D1-ADF7-CCE4BC9E7625}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DF53594-C7B2-44D1-ADF7-CCE4BC9E7625}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DF53594-C7B2-44D1-ADF7-CCE4BC9E7625}.Release|Any CPU.Build.0 = Release|Any CPU
{A375F626-7238-4227-95C9-2BB1E5E099F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A375F626-7238-4227-95C9-2BB1E5E099F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A375F626-7238-4227-95C9-2BB1E5E099F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A375F626-7238-4227-95C9-2BB1E5E099F6}.Release|Any CPU.Build.0 = Release|Any CPU
{C1D1272C-5BC5-4EFD-A9DA-BB8BE8B16280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1D1272C-5BC5-4EFD-A9DA-BB8BE8B16280}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1D1272C-5BC5-4EFD-A9DA-BB8BE8B16280}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1D1272C-5BC5-4EFD-A9DA-BB8BE8B16280}.Release|Any CPU.Build.0 = Release|Any CPU
{B18FA6C6-79C3-4851-A88E-161D273CBC0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B18FA6C6-79C3-4851-A88E-161D273CBC0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B18FA6C6-79C3-4851-A88E-161D273CBC0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B18FA6C6-79C3-4851-A88E-161D273CBC0F}.Release|Any CPU.Build.0 = Release|Any CPU
{B8E4A429-DE84-4565-AD51-87ECCBD629C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8E4A429-DE84-4565-AD51-87ECCBD629C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8E4A429-DE84-4565-AD51-87ECCBD629C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8E4A429-DE84-4565-AD51-87ECCBD629C5}.Release|Any CPU.Build.0 = Release|Any CPU
{0A9D8A7E-984F-4406-B497-E45CFF1073E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A9D8A7E-984F-4406-B497-E45CFF1073E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A9D8A7E-984F-4406-B497-E45CFF1073E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A9D8A7E-984F-4406-B497-E45CFF1073E6}.Release|Any CPU.Build.0 = Release|Any CPU
{FCBAB1FC-A47F-4939-B17B-F07F1A9DF4F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCBAB1FC-A47F-4939-B17B-F07F1A9DF4F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCBAB1FC-A47F-4939-B17B-F07F1A9DF4F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCBAB1FC-A47F-4939-B17B-F07F1A9DF4F7}.Release|Any CPU.Build.0 = Release|Any CPU
{B645EB54-CC74-437F-9255-2D9BFED87DF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B645EB54-CC74-437F-9255-2D9BFED87DF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B645EB54-CC74-437F-9255-2D9BFED87DF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B645EB54-CC74-437F-9255-2D9BFED87DF2}.Release|Any CPU.Build.0 = Release|Any CPU
{1966AAE3-19E7-4BA0-862A-A3C54DB51B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1966AAE3-19E7-4BA0-862A-A3C54DB51B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1966AAE3-19E7-4BA0-862A-A3C54DB51B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1966AAE3-19E7-4BA0-862A-A3C54DB51B3F}.Release|Any CPU.Build.0 = Release|Any CPU
{10E43267-ADB6-44AC-BABA-80D4CF4C7BC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10E43267-ADB6-44AC-BABA-80D4CF4C7BC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10E43267-ADB6-44AC-BABA-80D4CF4C7BC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10E43267-ADB6-44AC-BABA-80D4CF4C7BC8}.Release|Any CPU.Build.0 = Release|Any CPU
{54622F97-9187-482C-A9DC-06E1855EF2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54622F97-9187-482C-A9DC-06E1855EF2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54622F97-9187-482C-A9DC-06E1855EF2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54622F97-9187-482C-A9DC-06E1855EF2D7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal