rmdec/RMDEC/MVProject.cs

186 lines
4.7 KiB
C#

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RMDEC
{
public class MVProject
{
public MVProject() { }
//Private internal variables
private byte[] encryptionKey = new byte[0x10];
private bool encryptedImages = false;
private bool encryptedAudio = false;
private string gameTitle;
private string filePath;
//Public readable variables
public Boolean IsEncrypted
{
get
{
if (EncryptedAudio == true || EncryptedImages == true)
{
return true;
}
else
{
return false;
}
}
}
public Byte[] EncryptionKey
{
get
{
return encryptionKey;
}
}
public String GameTitle
{
get
{
return gameTitle;
}
}
public Boolean EncryptedImages
{
get
{
return encryptedImages;
}
}
public Boolean EncryptedAudio
{
get
{
return encryptedAudio;
}
}
public String FilePath
{
get
{
return filePath;
}
}
//Private functions
private static byte[] hexStr2Bytes(String HexStr)
{
if (HexStr.Length % 2 != 0)
{
throw new InvalidDataException(HexStr + " Is not divisible by 2!");
}
List<byte> byteList = new List<byte>();
for (int i = 0; i < HexStr.Length; i += 2)
{
string curHex = HexStr.Substring(i, 2);
byte hexByte = Byte.Parse(curHex, NumberStyles.HexNumber);
byteList.Add(hexByte);
}
byte[] resultingByteArray = byteList.ToArray();
return resultingByteArray;
}
private static byte[] xor(byte[] input, byte[] key)
{
long inpLen = input.LongLength;
byte[] output = new byte[inpLen];
for(long i = 0; i < input.LongLength; i++)
{
output[i] = (byte)(input[i] ^ key[i % key.LongLength]);
}
return output;
}
//Public functions
public static MVProject ParseSystemJson(string path)
{
if (File.Exists(path))
{
string jsonStr = File.ReadAllText(path, Encoding.UTF8);
dynamic systemJson = JObject.Parse(jsonStr);
//Check if valid system.json
MVProject mvp = new MVProject();
if (systemJson.gameTitle != null)
{
mvp.gameTitle = systemJson.gameTitle;
}
else
{
throw new InvalidDataException("Not a valid system.json!");
}
if (systemJson.hasEncryptedAudio != null)
{
mvp.encryptedAudio = systemJson.hasEncryptedAudio;
}
if (systemJson.hasEncryptedImages != null)
{
mvp.encryptedImages = systemJson.hasEncryptedImages;
}
if (systemJson.encryptionKey != null)
{
string encKey = systemJson.encryptionKey;
mvp.encryptionKey = hexStr2Bytes(encKey);
}
mvp.filePath = Path.GetDirectoryName(Path.GetDirectoryName(path));
return mvp;
}
else
{
throw new FileNotFoundException(path + " was not found!");
}
}
public void DecryptFile(Stream inStream, Stream outStream)
{
inStream.Seek(0x00, SeekOrigin.Begin);
byte[] magic = new byte[0x05];
inStream.Read(magic, 0x00,0x05);
string magicStr = Encoding.UTF8.GetString(magic);
if(magicStr != "RPGMV")
{
throw new InvalidDataException("Not an encrypted file!");
}
inStream.Seek(0x10, SeekOrigin.Begin);
byte[] encryptedHeader = new byte[0x10];
inStream.Read(encryptedHeader, 0x00, 0x10);
byte[] plaintextHeader = xor(encryptedHeader, encryptionKey);
outStream.Write(plaintextHeader, 0x00, plaintextHeader.Length);
inStream.CopyTo(outStream);
}
}
}