-
Notifications
You must be signed in to change notification settings - Fork 41
/
RGSSADv3.cs
99 lines (82 loc) · 2.95 KB
/
RGSSADv3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RPGMakerDecrypter.Decrypter.Exceptions;
namespace RPGMakerDecrypter.Decrypter
{
/// <summary>
/// Represents RGSSAD format used in RPG Maker VX Ace.
/// </summary>
public class RGSSADv3 : RGSSAD
{
public RGSSADv3(string filePath) : base(filePath)
{
int version = GetVersion();
if (version != Constants.RGASSDv3)
{
throw new InvalidArchiveException("Archive is in invalid format.");
}
ReadRGSSAD();
}
/// <summary>
/// Reads the contents of RGSSAD archive and populates ArchivedFiles property.
/// </summary>
private void ReadRGSSAD()
{
BinaryReader.BaseStream.Seek(8, SeekOrigin.Begin);
uint key = (uint)BinaryReader.ReadInt32();
key *= 9;
key += 3;
ArchivedFiles = new List<ArchivedFile>();
while (true)
{
ArchivedFile archivedFile = new ArchivedFile();
archivedFile.Offset = DecryptInteger(BinaryReader.ReadInt32(), key);
archivedFile.Size = DecryptInteger(BinaryReader.ReadInt32(), key);
archivedFile.Key = (uint)DecryptInteger(BinaryReader.ReadInt32(), key);
int length = DecryptInteger(BinaryReader.ReadInt32(), key);
if (archivedFile.Offset == 0)
{
break;
}
archivedFile.Name = DecryptFilename(BinaryReader.ReadBytes(length), key);
ArchivedFiles.Add(archivedFile);
}
}
/// <summary>
/// Decrypts integer from given value.
/// </summary>
/// <param name="value">Encrypted value</param>
/// <param name="key">Key</param>
/// <returns>Decrypted integer</returns>
private int DecryptInteger(int value, uint key)
{
long result = value ^ key;
return (int)result;
}
/// <summary>
/// Decrypts file name from given bytes using given key.
/// </summary>
/// <param name="encryptedName">Encrypted filename</param>
/// <param name="key">Key</param>
/// <returns>Decrypted filename</returns>
private string DecryptFilename(byte[] encryptedName, uint key)
{
byte[] decryptedName = new byte[encryptedName.Length];
byte[] keyBytes = BitConverter.GetBytes(key);
int j = 0;
for (int i = 0; i <= encryptedName.Length - 1; i++)
{
if (j == 4)
j = 0;
decryptedName[i] = (byte)(encryptedName[i] ^ keyBytes[j]);
j += 1;
}
string result = Encoding.UTF8.GetString(decryptedName);
return result;
}
}
}