|  | @@ -0,0 +1,255 @@
 | 
	
		
			
				|  |  | +using System;
 | 
	
		
			
				|  |  | +using System.Collections.Generic;
 | 
	
		
			
				|  |  | +using System.IO;
 | 
	
		
			
				|  |  | +using System.Linq;
 | 
	
		
			
				|  |  | +using Newtonsoft.Json;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace CacheReader
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    public class CachedItem
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public string texName;
 | 
	
		
			
				|  |  | +        public string m_strMenuName;
 | 
	
		
			
				|  |  | +        public string m_strInfo;
 | 
	
		
			
				|  |  | +        public string m_mpn;
 | 
	
		
			
				|  |  | +        public string m_strCateName;
 | 
	
		
			
				|  |  | +        public string m_eColorSetMPN;
 | 
	
		
			
				|  |  | +        public string m_strMenuNameInColorSet;
 | 
	
		
			
				|  |  | +        public string m_pcMultiColorID;
 | 
	
		
			
				|  |  | +        public bool m_boDelOnly;
 | 
	
		
			
				|  |  | +        public float m_fPriority;
 | 
	
		
			
				|  |  | +        public bool m_bMan;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    public class CacheData
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public int version;
 | 
	
		
			
				|  |  | +        public string menuHash;
 | 
	
		
			
				|  |  | +        public string modMenuHash;
 | 
	
		
			
				|  |  | +        public Dictionary<string, CachedItem> cachedItems;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    internal class Program
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        private static List<string> mpnList = new List<string>
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "null_mpn",
 | 
	
		
			
				|  |  | +            "MuneL",
 | 
	
		
			
				|  |  | +            "MuneS",
 | 
	
		
			
				|  |  | +            "MuneTare",
 | 
	
		
			
				|  |  | +            "RegFat",
 | 
	
		
			
				|  |  | +            "ArmL",
 | 
	
		
			
				|  |  | +            "Hara",
 | 
	
		
			
				|  |  | +            "RegMeet",
 | 
	
		
			
				|  |  | +            "KubiScl",
 | 
	
		
			
				|  |  | +            "UdeScl",
 | 
	
		
			
				|  |  | +            "EyeScl",
 | 
	
		
			
				|  |  | +            "EyeSclX",
 | 
	
		
			
				|  |  | +            "EyeSclY",
 | 
	
		
			
				|  |  | +            "EyePosX",
 | 
	
		
			
				|  |  | +            "EyePosY",
 | 
	
		
			
				|  |  | +            "EyeClose",
 | 
	
		
			
				|  |  | +            "EyeBallPosX",
 | 
	
		
			
				|  |  | +            "EyeBallPosY",
 | 
	
		
			
				|  |  | +            "EyeBallSclX",
 | 
	
		
			
				|  |  | +            "EyeBallSclY",
 | 
	
		
			
				|  |  | +            "EarNone",
 | 
	
		
			
				|  |  | +            "EarElf",
 | 
	
		
			
				|  |  | +            "EarRot",
 | 
	
		
			
				|  |  | +            "EarScl",
 | 
	
		
			
				|  |  | +            "NosePos",
 | 
	
		
			
				|  |  | +            "NoseScl",
 | 
	
		
			
				|  |  | +            "FaceShape",
 | 
	
		
			
				|  |  | +            "FaceShapeSlim",
 | 
	
		
			
				|  |  | +            "MayuShapeIn",
 | 
	
		
			
				|  |  | +            "MayuShapeOut",
 | 
	
		
			
				|  |  | +            "MayuX",
 | 
	
		
			
				|  |  | +            "MayuY",
 | 
	
		
			
				|  |  | +            "MayuRot",
 | 
	
		
			
				|  |  | +            "HeadX",
 | 
	
		
			
				|  |  | +            "HeadY",
 | 
	
		
			
				|  |  | +            "DouPer",
 | 
	
		
			
				|  |  | +            "sintyou",
 | 
	
		
			
				|  |  | +            "koshi",
 | 
	
		
			
				|  |  | +            "kata",
 | 
	
		
			
				|  |  | +            "west",
 | 
	
		
			
				|  |  | +            "MuneUpDown",
 | 
	
		
			
				|  |  | +            "MuneYori",
 | 
	
		
			
				|  |  | +            "MuneYawaraka",
 | 
	
		
			
				|  |  | +            "body",
 | 
	
		
			
				|  |  | +            "moza",
 | 
	
		
			
				|  |  | +            "head",
 | 
	
		
			
				|  |  | +            "hairf",
 | 
	
		
			
				|  |  | +            "hairr",
 | 
	
		
			
				|  |  | +            "hairt",
 | 
	
		
			
				|  |  | +            "hairs",
 | 
	
		
			
				|  |  | +            "hairaho",
 | 
	
		
			
				|  |  | +            "haircolor",
 | 
	
		
			
				|  |  | +            "skin",
 | 
	
		
			
				|  |  | +            "acctatoo",
 | 
	
		
			
				|  |  | +            "accnail",
 | 
	
		
			
				|  |  | +            "underhair",
 | 
	
		
			
				|  |  | +            "hokuro",
 | 
	
		
			
				|  |  | +            "mayu",
 | 
	
		
			
				|  |  | +            "lip",
 | 
	
		
			
				|  |  | +            "eye",
 | 
	
		
			
				|  |  | +            "eye_hi",
 | 
	
		
			
				|  |  | +            "eye_hi_r",
 | 
	
		
			
				|  |  | +            "chikubi",
 | 
	
		
			
				|  |  | +            "chikubicolor",
 | 
	
		
			
				|  |  | +            "eyewhite",
 | 
	
		
			
				|  |  | +            "nose",
 | 
	
		
			
				|  |  | +            "facegloss",
 | 
	
		
			
				|  |  | +            "wear",
 | 
	
		
			
				|  |  | +            "skirt",
 | 
	
		
			
				|  |  | +            "mizugi",
 | 
	
		
			
				|  |  | +            "bra",
 | 
	
		
			
				|  |  | +            "panz",
 | 
	
		
			
				|  |  | +            "stkg",
 | 
	
		
			
				|  |  | +            "shoes",
 | 
	
		
			
				|  |  | +            "headset",
 | 
	
		
			
				|  |  | +            "glove",
 | 
	
		
			
				|  |  | +            "acchead",
 | 
	
		
			
				|  |  | +            "accha",
 | 
	
		
			
				|  |  | +            "acchana",
 | 
	
		
			
				|  |  | +            "acckamisub",
 | 
	
		
			
				|  |  | +            "acckami",
 | 
	
		
			
				|  |  | +            "accmimi",
 | 
	
		
			
				|  |  | +            "accnip",
 | 
	
		
			
				|  |  | +            "acckubi",
 | 
	
		
			
				|  |  | +            "acckubiwa",
 | 
	
		
			
				|  |  | +            "accheso",
 | 
	
		
			
				|  |  | +            "accude",
 | 
	
		
			
				|  |  | +            "accashi",
 | 
	
		
			
				|  |  | +            "accsenaka",
 | 
	
		
			
				|  |  | +            "accshippo",
 | 
	
		
			
				|  |  | +            "accanl",
 | 
	
		
			
				|  |  | +            "accvag",
 | 
	
		
			
				|  |  | +            "megane",
 | 
	
		
			
				|  |  | +            "accxxx",
 | 
	
		
			
				|  |  | +            "handitem",
 | 
	
		
			
				|  |  | +            "acchat",
 | 
	
		
			
				|  |  | +            "onepiece",
 | 
	
		
			
				|  |  | +            "set_maidwear",
 | 
	
		
			
				|  |  | +            "set_mywear",
 | 
	
		
			
				|  |  | +            "set_underwear",
 | 
	
		
			
				|  |  | +            "set_body",
 | 
	
		
			
				|  |  | +            "folder_eye",
 | 
	
		
			
				|  |  | +            "folder_mayu",
 | 
	
		
			
				|  |  | +            "folder_underhair",
 | 
	
		
			
				|  |  | +            "folder_skin",
 | 
	
		
			
				|  |  | +            "folder_eyewhite",
 | 
	
		
			
				|  |  | +            "kousoku_upper",
 | 
	
		
			
				|  |  | +            "kousoku_lower",
 | 
	
		
			
				|  |  | +            "seieki_naka",
 | 
	
		
			
				|  |  | +            "seieki_hara",
 | 
	
		
			
				|  |  | +            "seieki_face",
 | 
	
		
			
				|  |  | +            "seieki_mune",
 | 
	
		
			
				|  |  | +            "seieki_hip",
 | 
	
		
			
				|  |  | +            "seieki_ude",
 | 
	
		
			
				|  |  | +            "seieki_ashi"
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private static Dictionary<int, string> mpns =
 | 
	
		
			
				|  |  | +            mpnList.ToDictionary(v => mpnList.IndexOf(v), v => v);
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        private static Dictionary<int, string> parts = new Dictionary<int, string>
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            [-1] = "NONE",
 | 
	
		
			
				|  |  | +            [0]="EYE_L",
 | 
	
		
			
				|  |  | +            [1] = "EYE_R",
 | 
	
		
			
				|  |  | +            [2]="HAIR",
 | 
	
		
			
				|  |  | +            [3]="EYE_BROW",
 | 
	
		
			
				|  |  | +            [4]="UNDER_HAIR",
 | 
	
		
			
				|  |  | +            [5]="SKIN",
 | 
	
		
			
				|  |  | +            [6]="NIPPLE",
 | 
	
		
			
				|  |  | +            [7]="HAIR_OUTLINE",
 | 
	
		
			
				|  |  | +            [8]="SKIN_OUTLINE",
 | 
	
		
			
				|  |  | +            [9]="EYE_WHITE",
 | 
	
		
			
				|  |  | +            [10]="MAX"
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        public static void Main(string[] args)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (args.Length < 1)
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var path = args[0];
 | 
	
		
			
				|  |  | +            if (!File.Exists(path))
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  | +            var data = new CacheData();
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  | +            using var br = new BinaryReader(File.OpenRead(path));
 | 
	
		
			
				|  |  | +            try
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                data.version = br.ReadInt32();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var menuFilesHashSize = br.ReadInt32();
 | 
	
		
			
				|  |  | +                var menuFilesHash = br.ReadBytes(menuFilesHashSize);
 | 
	
		
			
				|  |  | +                data.menuHash = Convert.ToBase64String(menuFilesHash);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var modMenuFilesHashSize = br.ReadInt32();
 | 
	
		
			
				|  |  | +                var modMenuFilesHash = br.ReadBytes(modMenuFilesHashSize);
 | 
	
		
			
				|  |  | +                data.modMenuHash = Convert.ToBase64String(modMenuFilesHash);
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +                data.cachedItems = new Dictionary<string, CachedItem>();
 | 
	
		
			
				|  |  | +                while (true)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var key = br.ReadNullableString();
 | 
	
		
			
				|  |  | +                    Console.WriteLine(key);
 | 
	
		
			
				|  |  | +                    var item = new CachedItem
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        texName = br.ReadNullableString(),
 | 
	
		
			
				|  |  | +                        m_strMenuName = br.ReadNullableString(),
 | 
	
		
			
				|  |  | +                        m_strInfo = br.ReadNullableString(),
 | 
	
		
			
				|  |  | +                        m_mpn =
 | 
	
		
			
				|  |  | +                            mpns.TryGetValue(br.ReadInt32(), out var val)
 | 
	
		
			
				|  |  | +                                ? val
 | 
	
		
			
				|  |  | +                                : "INVALID",
 | 
	
		
			
				|  |  | +                        m_strCateName = br.ReadNullableString(),
 | 
	
		
			
				|  |  | +                        m_eColorSetMPN =
 | 
	
		
			
				|  |  | +                            mpns.TryGetValue(br.ReadInt32(), out val)
 | 
	
		
			
				|  |  | +                                ? val
 | 
	
		
			
				|  |  | +                                : "INVALID",
 | 
	
		
			
				|  |  | +                        m_strMenuNameInColorSet = br.ReadNullableString(),
 | 
	
		
			
				|  |  | +                        m_pcMultiColorID =
 | 
	
		
			
				|  |  | +                            parts.TryGetValue(br.ReadInt32(), out val)
 | 
	
		
			
				|  |  | +                                ? val
 | 
	
		
			
				|  |  | +                                : "INVALID",
 | 
	
		
			
				|  |  | +                        m_boDelOnly = br.ReadBoolean(),
 | 
	
		
			
				|  |  | +                        m_fPriority = br.ReadSingle(),
 | 
	
		
			
				|  |  | +                        m_bMan = br.ReadBoolean()
 | 
	
		
			
				|  |  | +                    };
 | 
	
		
			
				|  |  | +                    data.cachedItems[key] = item;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            catch (FormatException e)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Console.WriteLine($"Failed to deserialize cache because {e.Message}");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            catch (EndOfStreamException)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // End of file, no need to read more
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  | +            File.WriteAllText("data.json", JsonConvert.SerializeObject(data, Formatting.Indented));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    internal static class BinaryExtensions
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        public static string ReadNullableString(this BinaryReader br)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return br.ReadBoolean() ? br.ReadString() : null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public static void WriteNullableString(this BinaryWriter bw, string value)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            bw.Write(value != null);
 | 
	
		
			
				|  |  | +            if (value != null)
 | 
	
		
			
				|  |  | +                bw.Write(value);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |