diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6abcc4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,222 @@
+## Ignore Visual Studio build files, cache files, and rubbish files.
+## This .gitignore file only use in this project(bus_rode).
+
+# Windows
+Thumbs.db
+ehthumbs.db
+Desktop.ini
+
+*.dat
+*.tdb
+
+## ------------------------Visual Studio normal settings---------------------------------------
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Visual Studio 2015 cache/options directory
+.vs/
+
+# Build result
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
diff --git a/BallanceRecordChanger.sln b/BallanceRecordChanger.sln
new file mode 100644
index 0000000..05ebf4b
--- /dev/null
+++ b/BallanceRecordChanger.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2047
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BallanceRecordChanger", "BallanceRecordChanger\BallanceRecordChanger.csproj", "{EB572C45-D97B-492A-B050-4BE0AA5B2CD7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EB572C45-D97B-492A-B050-4BE0AA5B2CD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EB572C45-D97B-492A-B050-4BE0AA5B2CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EB572C45-D97B-492A-B050-4BE0AA5B2CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EB572C45-D97B-492A-B050-4BE0AA5B2CD7}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CB598B34-00DC-4454-893C-C902FA4B12E4}
+ EndGlobalSection
+EndGlobal
diff --git a/BallanceRecordChanger/BallanceRecordChanger.csproj b/BallanceRecordChanger/BallanceRecordChanger.csproj
new file mode 100644
index 0000000..87bad9f
--- /dev/null
+++ b/BallanceRecordChanger/BallanceRecordChanger.csproj
@@ -0,0 +1,54 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {EB572C45-D97B-492A-B050-4BE0AA5B2CD7}
+ Exe
+ BallanceRecordChanger
+ BallanceRecordChanger
+ v4.0
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.11.0.2\lib\net40\Newtonsoft.Json.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BallanceRecordChanger/DBReader.cs b/BallanceRecordChanger/DBReader.cs
new file mode 100644
index 0000000..68474f6
--- /dev/null
+++ b/BallanceRecordChanger/DBReader.cs
@@ -0,0 +1,433 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Net;
+using System.ComponentModel;
+using System.Threading;
+using System.Collections;
+
+namespace BallanceRecordChanger {
+ ///
+ /// 数据库读取器
+ ///
+ static class DBReader {
+
+ static byte[] byteCut(byte[] b, byte cut) {
+ List list = new List();
+ list.AddRange(b);
+ for (int i = list.Count - 1; i >= 0; i--) {
+ if (list[i] == cut)
+ list.RemoveAt(i);
+ }
+ byte[] lastbyte = new byte[list.Count];
+ for (int i = 0; i < list.Count; i++) {
+ lastbyte[i] = list[i];
+ }
+ return lastbyte;
+ }
+ static void scanstr(byte[] str, ref int Pstr, ref byte[] mem) {
+ for (int c = 0; ;) {
+ mem[c] = str[Pstr];
+ if (mem[c] == 0)
+ break;
+ c++;
+ Pstr++;
+ }
+ Pstr++;
+ mem = byteCut(mem, 0);
+ }
+
+ static void scanint(byte[] str, ref int Pstr, ref byte[] mem) {
+ Array.Copy(str, Pstr, mem, 0, 4);
+ Pstr += 4;
+ }
+ static void scanint(byte[] str, ref int Pstr, ref int num) {
+ Byte[] mem;
+ mem = BitConverter.GetBytes(num);
+ Array.Copy(str, Pstr, mem, 0, 4);
+ Pstr += 4;
+ num = BitConverter.ToInt32(mem, 0);
+ }
+ static byte[] PreReadDB(string path) {
+ FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read);
+ fstream.Seek(0, SeekOrigin.End);
+ long FileLen = fstream.Length;
+ fstream.Seek(0, SeekOrigin.Begin);
+ Byte[] FileData = new Byte[FileLen];
+ fstream.Read(FileData, 0, (int)FileLen);
+ fstream.Close();
+ fstream.Dispose();
+ for (int i = 0; i < FileLen; i++) {
+ Byte j = FileData[i];
+ j = (byte)(j << 3 | j >> 5);
+ FileData[i] = (byte)(-(j ^ 0xAF));
+ }
+ return FileData;
+ }
+
+ ///
+ /// 读取数据库
+ ///
+ /// 数据库路径
+ /// 数据库
+ public static Database ReadDB(string path) {
+ Database temp = new Database();
+ Byte[] FileData = PreReadDB(path);
+ Byte[] str = new Byte[100];
+ int pData = 0;
+ for (int i = 0; i < 12; i++) {
+ temp.HighScores[i].LevelIndex = i + 1;
+ pData += 60;
+ for (int j = 0; j < 10; j++) {
+ scanstr(FileData, ref pData, ref str);
+ temp.HighScores[i].Play[j].Player = Encoding.Default.GetString(str).Trim();
+ str = new Byte[100];
+ }
+
+ Byte[] score = new Byte[4];
+ for (int j = 0; j < 10; j++) {
+ scanint(FileData, ref pData, ref score);
+ temp.HighScores[i].Play[j].Points = BitConverter.ToInt32(score, 0);
+ }
+ }
+ pData += 54;
+ Byte[] forbid = new Byte[4];
+ for (int j = 0; j < 13; j++) {
+ scanint(FileData, ref pData, ref forbid);
+ temp.Settings.LevelOpened[j] = BitConverter.ToBoolean(forbid, 0);
+ }
+ pData += 211;
+
+ Byte[] volume = new Byte[4];
+ scanint(FileData, ref pData, ref volume);
+ temp.Settings.MusicVolume = (float)BitConverter.ToSingle(volume, 0);
+
+ Byte[] SynToScr = new Byte[4];
+ scanint(FileData, ref pData, ref SynToScr);
+ temp.Settings.SynchToScreen = BitConverter.ToBoolean(SynToScr, 0);
+
+
+ int up = 0;
+ int down = 0;
+ int left = 0;
+ int right = 0;
+ scanint(FileData, ref pData, ref up);
+ scanint(FileData, ref pData, ref down);
+ scanint(FileData, ref pData, ref left);
+ scanint(FileData, ref pData, ref right);
+
+ string[] keys = new string[]{"1","2","3","4","5","6","7","8","9","0","-","=","BackSpace","Tab","Q","W","E","R","T","Y","U","I","O","P",
+ "[","]","Ctrl","A","S","D","F","G","H","J","K","L",";","'","`","Shift","\\","Z","X","C","V","B","N","M",",",".","/",
+ "Right Shift","Alt","Space","Num 7","Num 8","Num 9","Num -","Num 4","Num 5","Num 6","Num +","Num 1","Num 2","Num 3","Num 0","Num Del","<","Up","Down","Left","Right"};
+ temp.Settings.BallKeys = new BallKeys { Up = keys[up], Down = keys[down], Left = keys[left], Right = keys[right] };
+
+ int RotCam = 0, LiftCam = 0;
+ scanint(FileData, ref pData, ref RotCam);
+ scanint(FileData, ref pData, ref LiftCam);
+ temp.Settings.CameraKeys = new CameraKeys { Rotate = keys[RotCam], Lift = keys[LiftCam] };
+
+ int InvCamRot = 0;
+ scanint(FileData, ref pData, ref InvCamRot);
+ temp.Settings.InventCameraRotation = Convert.ToBoolean(InvCamRot);
+
+
+ Byte[] RecPlayer = new Byte[100];
+ scanstr(FileData, ref pData, ref RecPlayer);
+ temp.Settings.RecentPlayer = Encoding.Default.GetString(RecPlayer).Trim();
+
+ int Cloud = 0;
+ scanint(FileData, ref pData, ref Cloud);
+ temp.Settings.Cloud = Convert.ToBoolean(Cloud);
+
+ for (int i = 0; i < 8; i++) {
+ temp.HighScores[i + 12] = new Level();
+ temp.HighScores[i + 12].LevelIndex = i + 13;
+ pData += 60;
+ for (int j = 0; j < 10; j++) {
+ scanstr(FileData, ref pData, ref str);
+ temp.HighScores[i + 12].Play[j].Player = Encoding.Default.GetString(str).Trim();
+ str = new Byte[100];
+ }
+
+ Byte[] score = new Byte[4];
+ for (int j = 0; j < 10; j++) {
+ scanint(FileData, ref pData, ref score);
+ temp.HighScores[i + 12].Play[j].Points = BitConverter.ToInt32(score, 0);
+
+ }
+ }
+ return temp;
+ }
+
+
+
+ //15,16 need be replaced
+ static readonly byte[] RECORD_HEAD = new byte[] { 0x44, 0x42, 0x5F, 0x48, 0x69, 0x67, 0x68, 0x73, 0x63, 0x6F, 0x72, 0x65, 0x5F, 0x4C, 0x76,
+ 0x00, 0x00, 0x00,
+ //data length
+ 0xC4, 0x00, 0x00, 0x00,
+
+ 0x02, 0x00, 0x00, 0x00,
+ 0x0A, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00
+ };
+ static byte[] GetLevelHead(int level, int length) {
+ byte[] newByte = new byte[RECORD_HEAD.Length];
+ RECORD_HEAD.CopyTo(newByte, 0);
+ newByte[15] = (byte)(((int)(level / 10)) + 48);
+ newByte[16] = (byte)((level % 10) + 48);
+
+ var num = BitConverter.GetBytes(length);
+ newByte[18] = num[0];
+ newByte[19] = num[1];
+ newByte[20] = num[2];
+ newByte[21] = num[3];
+
+ return newByte;
+ }
+
+ //FREISCHALTUNG head
+ static readonly byte[] FREISCHALTUNG_HEAD = new byte[] {
+ 0x44, 0x42, 0x5F, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x66, 0x72, 0x65, 0x69,
+ 0x73, 0x63, 0x68, 0x61, 0x6C, 0x74, 0x75, 0x6E, 0x67, 0x00, 0x50, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x46, 0x72, 0x65, 0x69, 0x67, 0x65, 0x73, 0x63, 0x68, 0x61,
+ 0x6C, 0x74, 0x65, 0x74, 0x3F, 0x00
+ };
+
+ //option head
+ static readonly byte[] OPTION_HEAD = new byte[] {
+ 0x44, 0x42, 0x5F, 0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x00, 0xF6,
+ 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x53, 0x79, 0x6E, 0x63, 0x68, 0x20, 0x74, 0x6F, 0x20, 0x53,
+ 0x63, 0x72, 0x65, 0x65, 0x6E, 0x3F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4B,
+ 0x65, 0x79, 0x20, 0x46, 0x6F, 0x72, 0x77, 0x61, 0x72, 0x64, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, 0x20, 0x42, 0x61, 0x63, 0x6B, 0x77,
+ 0x61, 0x72, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, 0x20,
+ 0x4C, 0x65, 0x66, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79,
+ 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4B,
+ 0x65, 0x79, 0x20, 0x52, 0x6F, 0x74, 0x61, 0x74, 0x65, 0x20, 0x43, 0x61,
+ 0x6D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, 0x20, 0x4C, 0x69,
+ 0x66, 0x74, 0x20, 0x43, 0x61, 0x6D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x49,
+ 0x6E, 0x76, 0x65, 0x72, 0x74, 0x20, 0x43, 0x61, 0x6D, 0x20, 0x52, 0x6F,
+ 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3F, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x4C, 0x61, 0x73, 0x74, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x43, 0x6C, 0x6F, 0x75, 0x64, 0x4C, 0x61, 0x79, 0x65,
+ 0x72, 0x3F, 0x00, 0x01, 0x00, 0x00, 0x00
+ };
+
+ static void FixBoolFormat(List list) {
+ list.Add(0x00);
+ list.Add(0x00);
+ list.Add(0x00);
+ }
+
+ static void PreWriteDB(Byte[] FileData, string path) {
+ using (FileStream fstream = new FileStream(path, FileMode.Create, FileAccess.Write)) {
+ var FileLen = FileData.LongLength;
+ for (int i = 0; i < FileLen; i++) {
+ Byte cache = (byte)((-FileData[i]) ^ 0xAF);
+ fstream.WriteByte((byte)(cache << 5 | cache >> 3));
+ //fstream.WriteByte(FileData[i]);
+ }
+ fstream.Close();
+ }
+ }
+ ///
+ /// 保存数据库
+ ///
+ /// 数据库
+ /// 保存路径
+ public static void SaveDB(Database db, string path) {
+ List FileData = new List();
+
+ var levelDataCache = new List();
+ for (int i = 0; i < 12; i++) {
+ for (int j = 0; j < 10; j++) {
+ levelDataCache.AddRange(Encoding.Default.GetBytes(db.HighScores[i].Play[j].Player));
+ levelDataCache.Add(0x00);
+ }
+
+ for (int j = 0; j < 10; j++) {
+ levelDataCache.AddRange(BitConverter.GetBytes(db.HighScores[i].Play[j].Points));
+ }
+
+ FileData.AddRange(GetLevelHead(i + 1, levelDataCache.Count + 38));
+ FileData.AddRange(levelDataCache.ToArray());
+ levelDataCache.Clear();
+ }
+
+ FileData.AddRange(FREISCHALTUNG_HEAD);
+ for (int j = 0; j < 13; j++) {
+ FileData.Add((byte)(db.Settings.LevelOpened[j] ? 0x01 : 0x00));
+ FixBoolFormat(FileData);
+ }
+
+ FileData.AddRange(OPTION_HEAD);
+ FileData.AddRange(BitConverter.GetBytes(db.Settings.MusicVolume));
+ FileData.AddRange(BitConverter.GetBytes(db.Settings.SynchToScreen));
+ FixBoolFormat(FileData);
+
+ List keys = new List() {"1","2","3","4","5","6","7","8","9","0","-","=","BackSpace","Tab","Q","W","E","R","T","Y","U","I","O","P",
+ "[","]","Ctrl","A","S","D","F","G","H","J","K","L",";","'","`","Shift","\\","Z","X","C","V","B","N","M",",",".","/",
+ "Right Shift","Alt","Space","Num 7","Num 8","Num 9","Num -","Num 4","Num 5","Num 6","Num +","Num 1","Num 2","Num 3","Num 0","Num Del","<","Up","Down","Left","Right"};
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.BallKeys.Up)));
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.BallKeys.Down)));
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.BallKeys.Left)));
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.BallKeys.Right)));
+
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.CameraKeys.Rotate)));
+ FileData.AddRange(BitConverter.GetBytes(keys.IndexOf(db.Settings.CameraKeys.Lift)));
+
+ FileData.AddRange(BitConverter.GetBytes(db.Settings.InventCameraRotation));
+ FixBoolFormat(FileData);
+
+ FileData.AddRange(Encoding.Default.GetBytes(db.Settings.RecentPlayer));
+ FileData.Add(0x00);
+
+ FileData.AddRange(BitConverter.GetBytes(db.Settings.Cloud));
+ FixBoolFormat(FileData);
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 10; j++) {
+ levelDataCache.AddRange(Encoding.Default.GetBytes(db.HighScores[i+12].Play[j].Player));
+ levelDataCache.Add(0x00);
+ }
+
+ for (int j = 0; j < 10; j++) {
+ levelDataCache.AddRange(BitConverter.GetBytes(db.HighScores[i+12].Play[j].Points));
+ }
+
+ FileData.AddRange(GetLevelHead(i + 13, levelDataCache.Count + 38));
+ FileData.AddRange(levelDataCache.ToArray());
+ levelDataCache.Clear();
+
+ }
+
+ PreWriteDB(FileData.ToArray(), path);
+
+ }
+
+
+ }
+ ///
+ /// 数据库
+ ///
+ class Database {
+ ///
+ /// 构造函数
+ ///
+ public Database() {
+ for (int i = 0; i < 20; i++) {
+ HighScores[i] = new Level();
+ }
+ }
+ ///
+ /// 关卡成绩
+ ///
+ public Level[] HighScores = new Level[20];
+ ///
+ /// 游戏设置
+ ///
+ public BallanceSettings Settings = new BallanceSettings();
+ }
+ ///
+ /// 关卡成绩
+ ///
+ class Level {
+ ///
+ /// 构造函数
+ ///
+ public Level() {
+ for (int i = 0; i < 10; i++)
+ Play[i] = new Score();
+ }
+ ///
+ /// 关卡编号
+ ///
+ public int LevelIndex;
+ ///
+ /// 成绩信息
+ ///
+ public Score[] Play = new Score[10];
+ }
+ ///
+ /// 游戏设置
+ ///
+ class BallanceSettings {
+ ///
+ /// 关卡是否打开
+ ///
+ public bool[] LevelOpened = new bool[13];
+ ///
+ /// 音量
+ ///
+ public float MusicVolume { get; set; }
+ ///
+ /// 垂直同步
+ ///
+ public bool SynchToScreen { get; set; }
+ ///
+ /// 游戏控制按键
+ ///
+ public BallKeys BallKeys = new BallKeys();
+ ///
+ /// 镜头控制按键
+ ///
+ public CameraKeys CameraKeys = new CameraKeys();
+ ///
+ /// 旋转反转
+ ///
+ public bool InventCameraRotation { get; set; }
+ ///
+ /// 最近玩家
+ ///
+ public string RecentPlayer { get; set; }
+ ///
+ /// 云层
+ ///
+ public bool Cloud { get; set; }
+ }
+ ///
+ /// 游戏控制按键
+ ///
+ class BallKeys {
+ ///
+ /// 上
+ ///
+ public string Up { get; set; }
+ ///
+ /// 下
+ ///
+ public string Down { get; set; }
+ ///
+ /// 左
+ ///
+ public string Left { get; set; }
+ ///
+ /// 右
+ ///
+ public string Right { get; set; }
+ }
+ ///
+ /// 镜头控制按键
+ ///
+ class CameraKeys {
+ ///
+ /// 旋转
+ ///
+ public string Rotate { get; set; }
+ ///
+ /// 抬升
+ ///
+ public string Lift { get; set; }
+ }
+
+ class Score {
+ public string Player { get; set; }
+ public int Points { get; set; }
+ }
+}
diff --git a/BallanceRecordChanger/Program.cs b/BallanceRecordChanger/Program.cs
new file mode 100644
index 0000000..1577fca
--- /dev/null
+++ b/BallanceRecordChanger/Program.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace BallanceRecordChanger {
+ class Program {
+ static void Main(string[] args) {
+
+ Console.WriteLine("Ballance Record Changer");
+ Console.WriteLine("Please put your Database.tdb in this app's folder. Then press any key to read it.");
+ Console.ReadKey();
+
+ var data = DBReader.ReadDB(Environment.CurrentDirectory + "\\Database.tdb");
+ using (StreamWriter fs = new StreamWriter(Environment.CurrentDirectory + "\\DecodeData.json", false, Encoding.UTF8)) {
+ fs.Write(Newtonsoft.Json.JsonConvert.SerializeObject(data));
+ fs.Close();
+ }
+
+ Console.WriteLine("Database file has been decoded into Database.json. Please modify it. Then press any key. This app will encode your modified file into new Database.tdb.");
+ Console.ReadKey();
+
+ string oriData;
+ using (StreamReader fs = new StreamReader(Environment.CurrentDirectory + "\\DecodeData.json", Encoding.UTF8)) {
+ oriData = fs.ReadToEnd();
+ fs.Close();
+ }
+
+ var dataR = Newtonsoft.Json.JsonConvert.DeserializeObject(oriData);
+
+ DBReader.SaveDB(dataR, Environment.CurrentDirectory + "\\Database.new.tdb");
+
+ Console.WriteLine("New Database.tdb file has been written into Database.new.tdb. Press any key to quit app.");
+ Console.ReadKey();
+
+ }
+ }
+}
diff --git a/BallanceRecordChanger/Properties/AssemblyInfo.cs b/BallanceRecordChanger/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..afb871a
--- /dev/null
+++ b/BallanceRecordChanger/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("BallanceRecordChanger")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BallanceRecordChanger")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("eb572c45-d97b-492a-b050-4be0aa5b2cd7")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/BallanceRecordChanger/packages.config b/BallanceRecordChanger/packages.config
new file mode 100644
index 0000000..07048c7
--- /dev/null
+++ b/BallanceRecordChanger/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..73fc34a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 BearKidsTeam
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..acfdf0d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# Ballance Record Changer
+
+This console app provide the way to changing Ballance internal highscore list's data.
+
+Follow the tips which is displayed by this app on screen. Then, you can build your Ballance highscore list.
+
+This app is dangerous for Ballance speedrun. **DON'T DISTRIBUTE IT.**
+
+Thx @jxpxxzj's code.