Skip to content

Commit d9f875b

Browse files
committed
Port over classes from LEC, update to new TOC implementation
1 parent 278cf1f commit d9f875b

File tree

7 files changed

+784
-152
lines changed

7 files changed

+784
-152
lines changed

AutoTOC/AutoTOC.csproj

+30
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
<FileAlignment>512</FileAlignment>
1414
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
1515
<TargetFrameworkProfile />
16+
<PublishUrl>publish\</PublishUrl>
17+
<Install>true</Install>
18+
<InstallFrom>Disk</InstallFrom>
19+
<UpdateEnabled>false</UpdateEnabled>
20+
<UpdateMode>Foreground</UpdateMode>
21+
<UpdateInterval>7</UpdateInterval>
22+
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
23+
<UpdatePeriodically>false</UpdatePeriodically>
24+
<UpdateRequired>false</UpdateRequired>
25+
<MapFileExtensions>true</MapFileExtensions>
26+
<ApplicationRevision>0</ApplicationRevision>
27+
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
28+
<IsWebBootstrapper>false</IsWebBootstrapper>
29+
<UseApplicationTrust>false</UseApplicationTrust>
30+
<BootstrapperEnabled>true</BootstrapperEnabled>
1631
</PropertyGroup>
1732
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1833
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -50,10 +65,25 @@
5065
<ItemGroup>
5166
<Compile Include="Program.cs" />
5267
<Compile Include="Properties\AssemblyInfo.cs" />
68+
<Compile Include="StreamIO.cs" />
69+
<Compile Include="TOCBinFile.cs" />
70+
<Compile Include="TOCCreator.cs" />
5371
</ItemGroup>
5472
<ItemGroup>
5573
<None Include="App.config" />
5674
</ItemGroup>
75+
<ItemGroup>
76+
<BootstrapperPackage Include=".NETFramework,Version=v4.8">
77+
<Visible>False</Visible>
78+
<ProductName>Microsoft .NET Framework 4.8 %28x86 and x64%29</ProductName>
79+
<Install>true</Install>
80+
</BootstrapperPackage>
81+
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
82+
<Visible>False</Visible>
83+
<ProductName>.NET Framework 3.5 SP1</ProductName>
84+
<Install>false</Install>
85+
</BootstrapperPackage>
86+
</ItemGroup>
5787
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
5888
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
5989
Other similar extension points exist, see Microsoft.Common.targets.

AutoTOC/Program.cs

+39-147
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.IO;
45
using System.Linq;
56
using System.Threading.Tasks;
@@ -12,36 +13,24 @@ namespace AutoTOC
1213
{
1314
class Program
1415
{
15-
enum MEGame
16-
{
17-
ME3,
18-
LE1,
19-
LE2,
20-
LE3
21-
}
22-
2316
static void Main(string[] args)
2417
{
2518
string gameDir;
19+
MEGame game = MEGame.ME3;
2620

2721
if (args.Length == 1)
2822
{
29-
// Path is passed in, hopefully is game root directory or .exe
23+
// Path is passed in, hopefully is game .exe
3024
gameDir = args[0];
31-
if (gameDir.EndsWith("\""))
25+
if (gameDir.EndsWith(".exe"))
3226
{
33-
gameDir = gameDir.Remove(gameDir.Length - 1);
34-
}
35-
else if (gameDir.EndsWith(".exe"))
36-
{
37-
gameDir = GetGamepathFromExe(gameDir);
27+
(gameDir, game) = GetGamepathFromExe(gameDir);
3828
}
3929
}
4030
else if (args.Length == 2 && args[0] == "-r")
4131
{
4232
try {
43-
MEGame game = (MEGame)Enum.Parse(typeof(MEGame), args[1], true);
44-
33+
game = (MEGame)Enum.Parse(typeof(MEGame), args[1], true);
4534
gameDir = GetGamepathFromRegistry(game);
4635
if(game != MEGame.ME3)
4736
{
@@ -72,18 +61,18 @@ static void Main(string[] args)
7261
}
7362
else
7463
{
75-
Console.WriteLine("Requires one argument: the install dir or .exe of the game you're trying to TOC.");
76-
Console.WriteLine("(eg. \"D:\\Origin Games\\Mass Effect Legendary Edition\\ME3\")");
64+
Console.WriteLine("Requires one argument: .exe of the game you're trying to TOC.");
65+
Console.WriteLine("(eg. \"D:\\Origin Games\\Mass Effect Legendary Edition\\ME3\\Binaries\\Win64\\MassEffect3.exe)");
7766
Console.WriteLine("Detect game from registry with -r {game}. Options: ME3, LE1, LE2, LE3");
7867
return;
7968
}
8069

8170
Console.WriteLine($"Generating TOCs for {gameDir}");
82-
GenerateTocFromGamedir(gameDir);
71+
GenerateTocFromGamedir(gameDir, game);
8372
Console.WriteLine("Done!");
8473
}
8574

86-
static void GenerateTocFromGamedir(string gameDir)
75+
static void GenerateTocFromGamedir(string gameDir, MEGame game)
8776
{
8877
string baseDir = Path.Combine(gameDir, @"BIOGame\");
8978
string dlcDir = Path.Combine(baseDir, @"DLC\");
@@ -97,151 +86,54 @@ static void GenerateTocFromGamedir(string gameDir)
9786
{
9887
Console.WriteLine("DLC folder not detected, TOCing basegame only...");
9988
}
100-
Task.WhenAll(folders.Select(loc => TOCAsync(loc))).Wait();
89+
Task.WhenAll(folders.Select(loc => TOCAsync(loc, game))).Wait();
10190
}
10291

103-
static Task TOCAsync(string tocLoc)
92+
static Task TOCAsync(string tocLoc, MEGame game)
10493
{
105-
return Task.Run(() => PrepareToCreateTOC(tocLoc));
94+
return Task.Run(() => CreateTOC(tocLoc, game));
10695
}
10796

108-
static void PrepareToCreateTOC(string consoletocFile)
97+
static void CreateTOC(string tocLoc, MEGame game)
10998
{
110-
if (!consoletocFile.EndsWith("\\")) consoletocFile += "\\";
111-
List<string> files = GetFiles(consoletocFile);
112-
113-
if (files.Count > 0)
114-
{
115-
string t = files[0];
116-
int n = t.LastIndexOf("DLC_");
117-
if (n > 0)
118-
{
119-
for (int i = 0; i < files.Count; i++)
120-
files[i] = files[i].Substring(n);
121-
string t2 = files[0];
122-
n = t2.IndexOf("\\");
123-
for (int i = 0; i < files.Count; i++)
124-
files[i] = files[i].Substring(n + 1);
125-
}
126-
else
127-
{
128-
n = t.LastIndexOf("BIOGame");
129-
if (n > 0)
130-
{
131-
for (int i = 0; i < files.Count; i++)
132-
files[i] = files[i].Substring(n);
133-
}
134-
}
135-
string pathbase;
136-
string t3 = files[0];
137-
int n2 = t3.LastIndexOf("BIOGame");
138-
if (n2 >= 0)
139-
{
140-
pathbase = Path.GetDirectoryName(Path.GetDirectoryName(consoletocFile)) + "\\";
141-
}
142-
else
143-
{
144-
pathbase = consoletocFile;
145-
}
146-
CreateTOC(pathbase, consoletocFile + "PCConsoleTOC.bin", files.ToArray());
147-
}
148-
}
149-
150-
static void CreateTOC(string basepath, string tocFile, string[] files)
151-
{
152-
FileStream fs = new FileStream(tocFile, FileMode.Create, FileAccess.Write);
153-
long selfSizePosition = -1;
154-
fs.Write(BitConverter.GetBytes((int)0x3AB70C13), 0, 4);
155-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);
156-
fs.Write(BitConverter.GetBytes((int)0x1), 0, 4);
157-
fs.Write(BitConverter.GetBytes((int)0x8), 0, 4);
158-
fs.Write(BitConverter.GetBytes((int)files.Length), 0, 4);
159-
for (int i = 0; i < files.Length; i++)
160-
{
161-
string file = files[i];
162-
if (i == files.Length - 1)//Entry Size
163-
fs.Write(new byte[2], 0, 2);
164-
else
165-
fs.Write(BitConverter.GetBytes((ushort)(0x1D + file.Length)), 0, 2);
166-
fs.Write(BitConverter.GetBytes((ushort)0), 0, 2);//Flags
167-
if (Path.GetFileName(file).ToLower() != "pcconsoletoc.bin")
168-
{
169-
fs.Write(BitConverter.GetBytes((int) (new FileInfo(basepath + file).Length)), 0, 4);//Filesize
170-
}
171-
else
172-
{
173-
selfSizePosition = fs.Position;
174-
fs.Write(BitConverter.GetBytes((int)0), 0, 4);//Filesize
175-
}
176-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);//SHA1
177-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);
178-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);
179-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);
180-
fs.Write(BitConverter.GetBytes((int)0x0), 0, 4);
181-
foreach (char c in file)
182-
fs.WriteByte((byte)c);
183-
fs.WriteByte(0);
184-
}
185-
if (selfSizePosition >= 0)
186-
{
187-
// Write the size of our own TOC. This ensures TOC appears up to date when we try to update it later
188-
// (important for DLC TOCs)
189-
fs.Seek(selfSizePosition, SeekOrigin.Begin);
190-
fs.Write(BitConverter.GetBytes((int)fs.Length), 0, 4);
191-
}
192-
fs.Close();
193-
}
194-
195-
static List<string> GetFiles(string basefolder)
196-
{
197-
List<string> res = new List<string>();
198-
string test = Path.GetFileName(Path.GetDirectoryName(basefolder));
199-
string[] files = GetTocableFiles(basefolder);
200-
res.AddRange(files);
201-
DirectoryInfo folder = new DirectoryInfo(basefolder);
202-
DirectoryInfo[] folders = folder.GetDirectories();
203-
if (folders.Length != 0)
204-
if (test != "BIOGame")
205-
foreach (DirectoryInfo f in folders)
206-
res.AddRange(GetFiles(basefolder + f.Name + "\\"));
207-
else
208-
foreach (DirectoryInfo f in folders)
209-
if (f.Name == "CookedPCConsole" || f.Name == "Movies" || f.Name == "Splash")
210-
res.AddRange(GetFiles(Path.Combine(basefolder, f.Name)));
211-
else if (f.Name == "Content")
212-
res.AddRange(GetFiles(Path.Combine(basefolder, f.Name, "Packages\\ISACT")));
213-
214-
return res;
215-
}
216-
217-
static string[] Pattern = { "*.pcc", "*.afc", "*.bik", "*.bin", "*.tlk", "*.txt", "*.cnd", "*.upk", "*.tfc", "*.isb" };
218-
219-
static string[] GetTocableFiles(string path)
220-
{
221-
List<string> res = new List<string>();
222-
foreach (string s in Pattern)
223-
res.AddRange(Directory.GetFiles(path, s));
224-
return res.ToArray();
99+
var TOC = TOCCreator.CreateTOCForDirectory(tocLoc, game);
100+
TOC.WriteToFile(Path.Combine(tocLoc, "PCConsoleTOC.bin"));
225101
}
226102

227103
static string[] ValidExecutables = { "MassEffect1.exe", "MassEffect2.exe", "MassEffect3.exe" };
228104

229-
static string GetGamepathFromExe(string path)
105+
static (string, MEGame) GetGamepathFromExe(string path)
230106
{
231-
if(path != null && ValidExecutables.Any((exe) => path.EndsWith(exe)))
107+
if(File.Exists(path) && ValidExecutables.Any((exe) => path.EndsWith(exe)))
232108
{
233-
return path.Substring(0, path.LastIndexOf("Binaries", StringComparison.OrdinalIgnoreCase));
109+
var dir = path.Substring(0, path.LastIndexOf("Binaries", StringComparison.OrdinalIgnoreCase));
110+
if (path.EndsWith(ValidExecutables[0])) return (dir, MEGame.LE1);
111+
if (path.EndsWith(ValidExecutables[1])) return (dir, MEGame.LE2);
112+
if (path.EndsWith(ValidExecutables[2]))
113+
{
114+
var versionInfo = FileVersionInfo.GetVersionInfo(path);
115+
if (versionInfo.FileVersion.StartsWith("1")) return (dir, MEGame.ME3);
116+
else return (dir, MEGame.LE3);
117+
}
118+
// Should never get here
119+
throw new ArgumentException("Executable file is not a supported Mass Effect game.");
234120
}
235-
else throw new ArgumentException("Executable file is not a supported Mass Effect game.");
121+
throw new ArgumentException("Executable file is not a supported Mass Effect game.");
236122
}
237123

238124
static string GetGamepathFromRegistry(MEGame game)
239125
{
240126
if(game != MEGame.ME3)
241127
{
242-
// Get LE path from registry
243-
string hkey64 = @"HKEY_LOCAL_MACHINE\SOFTWARE\BioWare\Mass Effect Legendary Edition";
244-
return (string)Registry.GetValue(hkey64, "Install Dir", null);
128+
string hkey64 = @"HKEY_LOCAL_MACHINE\SOFTWARE\BioWare\Mass Effectâ„¢ Legendary Edition"; // Yes all that weird garbage in this name is required... but not for everyone
129+
string test = (string)Registry.GetValue(hkey64, "Install Dir", null);
130+
if (test != null)
131+
{
132+
return test;
133+
}
134+
hkey64 = @"HKEY_LOCAL_MACHINE\SOFTWARE\BioWare\Mass Effect Legendary Edition"; //For those without weird garbage
135+
test = (string)Registry.GetValue(hkey64, "Install Dir", null);
136+
return test;
245137
}
246138
else
247139
{

AutoTOC/Properties/AssemblyInfo.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("2.0.*")]
36-
[assembly: AssemblyFileVersion("2.0.1.0")]
35+
[assembly: AssemblyVersion("2.1.*")]
36+
[assembly: AssemblyFileVersion("2.1.0.0")]

0 commit comments

Comments
 (0)