Clean BC converter, implement port to windows function

mac
Miepee 3 years ago
parent 9847521e70
commit 3c95489227

@ -20,6 +20,7 @@ internal static class Program
var interactiveOption = new Option<bool>(new[] { "-i", "--interactive" }, "Use an interactive mode. This will ignore all other options.");
var fileOption = new Option<FileInfo>(new[] { "-f", "--file" }, "The file path to the raw mod that should be ported. *REQUIRED IN NON-INTERACTIVE*");
var windowsOption = new Option<FileInfo>(new[] { "-w", "--windows" }, "The output file path for the Windows mod. None given equals to no Windows port.");
var linuxOption = new Option<FileInfo>(new[] { "-l", "--linux" }, "The output file path for the Linux mod. None given equals to no Linux port.");
var androidOption = new Option<FileInfo>(new[] { "-a", "--android" }, "The output file path for the Android mod. None given equals to no Android port.");
var macOption = new Option<FileInfo>(new[] { "-m", "--mac" }, "The output file path for the Mac mod. None given equals to no Mac port.");
@ -32,13 +33,14 @@ internal static class Program
// TODO: double check whether its not possible to have the same splash screen for both desktop and mobile
var customSaveOption = new Option<bool>(new[] { "-s", "--customsave" }, "Whether the Android Port should use a custom save location. Has no effect on other OS.");
var internetOption = new Option<bool>(new[] { "-w", "--internet" }, "Add internet usage permissions to the Android mod. Has no effect on other OS.");
var internetOption = new Option<bool>(new[] { "-n", "--internet" }, "Add internet usage permissions to the Android mod. Has no effect on other OS.");
var verboseOption = new Option<bool>(new[] { "-v", "--verbose" }, "Whether to show verbose output.");
RootCommand rootCommand = new RootCommand("A utility to port Windows AM2R Mods to other operating systems.")
{
interactiveOption,
fileOption,
windowsOption,
linuxOption,
androidOption,
macOption,
@ -52,6 +54,7 @@ internal static class Program
{
bool interactive = context.ParseResult.GetValueForOption(interactiveOption);
FileInfo inputModPath = context.ParseResult.GetValueForOption(fileOption);
FileInfo windowsPath = context.ParseResult.GetValueForOption(windowsOption);
FileInfo linuxPath = context.ParseResult.GetValueForOption(linuxOption);
FileInfo androidPath = context.ParseResult.GetValueForOption(androidOption);
FileInfo macPath = context.ParseResult.GetValueForOption(macOption);
@ -61,13 +64,13 @@ internal static class Program
bool beVerbose = context.ParseResult.GetValueForOption(verboseOption);
FileInfo iconPath = context.ParseResult.GetValueForOption(iconOption);
return RootMethod(interactive, inputModPath, linuxPath, androidPath, macPath, splashPath, iconPath, useCustomSave, usesInternet, beVerbose);
return RootMethod(interactive, inputModPath, windowsPath, linuxPath, androidPath, macPath, splashPath, iconPath, useCustomSave, usesInternet, beVerbose);
});
return rootCommand.InvokeAsync(args).Result;
}
#pragma warning disable CS1998
private static async Task<int> RootMethod(bool interactive, FileInfo inputModPath, FileInfo linuxPath, FileInfo androidPath, FileInfo macPath,
private static async Task<int> RootMethod(bool interactive, FileInfo inputModPath, FileInfo windowsPath, FileInfo linuxPath, FileInfo androidPath, FileInfo macPath,
FileInfo iconPath, FileInfo splashPath, bool useCustomSave, bool usesInternet, bool beVerbose)
#pragma warning restore CS1998
{
@ -92,6 +95,10 @@ internal static class Program
OutputHandlerDelegate(output);
}
if (windowsPath is not null)
{
RawMods.PortToWindows(inputModPath.FullName, windowsPath.FullName, LocalOutput);
}
if (linuxPath is not null)
{
RawMods.PortToLinux(inputModPath.FullName, linuxPath.FullName, iconPath?.FullName, splashPath?.FullName, LocalOutput);

@ -47,7 +47,7 @@ public partial class MainForm : Form
mainLayout.AddRow(labelOSHeader);
mainLayout.EndCentered();
mainLayout.BeginCentered();
mainLayout.AddRow(checkboxLinux, checkboxAndroid, checkboxMac);
mainLayout.AddRow(checkboxWindows, checkboxLinux, checkboxAndroid, checkboxMac);
mainLayout.AddSpace();
mainLayout.EndCentered();
mainLayout.BeginCentered();
@ -146,6 +146,7 @@ public partial class MainForm : Form
void OutputHandlerDelegate(string output) => Application.Instance.Invoke(() => labelProgress.Text = $"Info: {output}");
string modZipPath = filePicker.FilePath;
string currentDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
string windowsPath = $"{currentDir}/{Path.GetFileNameWithoutExtension(modZipPath)}_WINDOWS.zip";
string linuxPath = $"{currentDir}/{Path.GetFileNameWithoutExtension(modZipPath)}_LINUX.zip";
string androidPath = $"{currentDir}/{Path.GetFileNameWithoutExtension(modZipPath)}_ANDROID.apk";
string macPath = $"{currentDir}/{Path.GetFileNameWithoutExtension(modZipPath)}_MACOS.zip";
@ -155,6 +156,13 @@ public partial class MainForm : Form
try
{
if (checkboxWindows.Checked.Value)
{
if (File.Exists(windowsPath))
File.Delete(windowsPath);
await Task.Run(() => RawMods.PortToWindows(modZipPath, windowsPath, OutputHandlerDelegate));
}
if (checkboxLinux.Checked.Value)
{
if (File.Exists(linuxPath))
@ -205,7 +213,7 @@ public partial class MainForm : Form
{
// there needs to be a selected mod + any checkbox
if (!String.IsNullOrWhiteSpace(filePicker.FilePath) &&
(checkboxAndroid.Checked.Value || checkboxLinux.Checked.Value || checkboxMac.Checked.Value))
(checkboxWindows.Checked.Value || checkboxLinux.Checked.Value || checkboxAndroid.Checked.Value || checkboxMac.Checked.Value))
buttonPort.Enabled = true;
else
buttonPort.Enabled = false;
@ -242,6 +250,10 @@ public partial class MainForm : Form
Text = "Choose the OS to port to",
Font = new Font(SystemFont.Bold)
};
private readonly CheckBox checkboxWindows = new CheckBox
{
Text = "Windows"
};
private readonly CheckBox checkboxLinux = new CheckBox
{
Text = "Linux"

@ -0,0 +1,11 @@
using UndertaleModLib.Compiler;
namespace AM2RPortHelperLib;
public static class ExtensionMethods
{
public static void SendOutput(this ModsBase.OutputHandlerDelegate outputDelegate, string output)
{
outputDelegate?.Invoke(output);
}
}

@ -15,16 +15,16 @@ public abstract class LauncherMods : ModsBase
/// <param name="outputDelegate">The function that should handle in-progress output messages.</param>
/// <exception cref="NotSupportedException">WIP</exception>
/// TODO: other exceptions
public static void PortLauncherMod(string inputLauncherZipPath, Core.ModOS modTarget, bool includeAndroid, string outputLauncherZipPath, string am2r11ZipPath = null, OutputHandlerDelegate outputDelegate = null)
public static void PortLauncherMod(string inputLauncherZipPath, Core.ModOS modTarget, bool includeAndroid, string outputLauncherZipPath, string am2r11ZipPath = null,
OutputHandlerDelegate outputDelegate = null)
{
OutputHandler = outputDelegate;
string extractDirectory = TempDir + "/" + Path.GetFileNameWithoutExtension(inputLauncherZipPath);
string filesToCopyDir = extractDirectory + "/files_to_copy";
// Check if temp folder exists, delete if yes, extract zip to there
if (Directory.Exists(extractDirectory))
Directory.Delete(extractDirectory, true);
SendOutput("Extracting Launcher mod...");
outputDelegate.SendOutput("Extracting Launcher mod...");
ZipFile.ExtractToDirectory(inputLauncherZipPath, extractDirectory);
var profile = Serializer.Deserialize<ProfileXML>(File.ReadAllText(extractDirectory + "/profile.xml"));
@ -36,7 +36,7 @@ public abstract class LauncherMods : ModsBase
if (modTarget.ToString() == profile.OperatingSystem)
{
SendOutput("Target OS and Launcher OS are the same; exiting.");
outputDelegate.SendOutput("Target OS and Launcher OS are the same; exiting.");
return;
}
@ -143,7 +143,7 @@ public abstract class LauncherMods : ModsBase
}
//zip the result
SendOutput($"Creating Launcher zip for {modTarget}...");
outputDelegate.SendOutput($"Creating Launcher zip for {modTarget}...");
ZipFile.CreateFromDirectory(extractDirectory, outputLauncherZipPath);
// Clean up

@ -4,13 +4,6 @@ public abstract class ModsBase
{
public delegate void OutputHandlerDelegate(string output);
protected static OutputHandlerDelegate OutputHandler;
protected static void SendOutput(string output)
{
OutputHandler?.Invoke(output);
}
// Create before accessing anything
static ModsBase()
{

@ -85,10 +85,64 @@ public abstract class RawMods : ModsBase
}
}
// TODO: Port to Windows
public static void PortToWindows(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputHandlerDelegate = null)
/// <summary>
/// Ports a raw AM2R mod zip for Linux.
/// </summary>
/// <param name="inputRawZipPath">The path to the raw mod zip.</param>
/// <param name="outputRawZipPath">The path where the ported Windows mod zip should be saved to.</param>
/// <param name="outputDelegate">A delegate to post output info to.</param>
/// <exception cref="NotSupportedException">The raw mod zip was made for an OS that can't be determined.</exception>
public static void PortToWindows(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputDelegate = null)
{
ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
outputDelegate.SendOutput("Zip Recognized as " + currentOS);
if (currentOS == ModOS.Windows)
{
outputDelegate.SendOutput("Zip is already a raw Windows zip. Copying to output directory...");
File.Copy(inputRawZipPath, outputRawZipPath, true);
return;
}
string extractDirectory = TempDir + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
// Check if temp folder exists, delete if yes, extract zip to there
if (Directory.Exists(extractDirectory))
Directory.Delete(extractDirectory, true);
outputDelegate.SendOutput("Extracting for Raw Windows...");
Directory.CreateDirectory(extractDirectory);
ZipFile.ExtractToDirectory(inputRawZipPath, extractDirectory);
// Delete unnecessary files, rename data.win, move in the new runner
outputDelegate.SendOutput("Delete unnecessary files for Windows...");
switch (currentOS)
{
case ModOS.Linux:
File.Delete(extractDirectory + "/runner");
HelperMethods.DirectoryCopy(extractDirectory + "/assets", extractDirectory);
Directory.Delete(extractDirectory + "/assets", true);
File.Move(extractDirectory + "/game.unx", extractDirectory + "/data.win");
break;
case ModOS.Mac:
var appDir = new DirectoryInfo(extractDirectory).GetDirectories().First(n => n.Name.EndsWith(".app"));
HelperMethods.DirectoryCopy(extractDirectory + "/" + appDir.Name + "/Contents/Resources", extractDirectory);
File.Delete(extractDirectory + "/gamecontrollerdb.txt");
File.Delete(extractDirectory + "/yoyorunner.config");
Directory.Delete(extractDirectory + "/English.lproj", true);
Directory.Delete(extractDirectory + "/" + appDir.Name, true);
File.Move(extractDirectory + "/game.ios", extractDirectory + "/data.win");
break;
default: throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported.");
}
File.Copy(UtilDir + "/executable.exe", extractDirectory + "/AM2R.exe");
//zip the result
outputDelegate.SendOutput("Creating raw Windows zip...");
ZipFile.CreateFromDirectory(extractDirectory, outputRawZipPath);
// Clean up
Directory.Delete(TempDir, true);
}
/// <summary>
@ -106,28 +160,27 @@ public abstract class RawMods : ModsBase
OutputHandlerDelegate outputDelegate = null)
{
ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
SendOutput("Zip Recognized as " + currentOS);
outputDelegate.SendOutput("Zip Recognized as " + currentOS);
if (currentOS == ModOS.Linux)
{
SendOutput("Zip is already a raw Linux zip. Copying to output directory...");
outputDelegate.SendOutput("Zip is already a raw Linux zip. Copying to output directory...");
File.Copy(inputRawZipPath, outputRawZipPath, true);
return;
}
OutputHandler = outputDelegate;
string extractDirectory = TempDir + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string assetsDir = extractDirectory + "/assets";
// Check if temp folder exists, delete if yes, extract zip to there
if (Directory.Exists(extractDirectory))
Directory.Delete(extractDirectory, true);
SendOutput("Extracting for Raw Linux...");
outputDelegate.SendOutput("Extracting for Raw Linux...");
Directory.CreateDirectory(assetsDir);
ZipFile.ExtractToDirectory(inputRawZipPath, assetsDir);
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Linux and lowercase them...");
outputDelegate.SendOutput("Delete unnecessary files for Linux...");
switch (currentOS)
{
case ModOS.Windows:
@ -153,10 +206,11 @@ public abstract class RawMods : ModsBase
File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.splash), pathToSplashScreen), assetsDir + "/splash.png");
//recursively lowercase everything in the assets folder
outputDelegate.SendOutput("Lowercase everything in the assets folder...");
HelperMethods.LowercaseFolder(assetsDir);
//zip the result
SendOutput("Creating raw Linux zip...");
outputDelegate.SendOutput("Creating raw Linux zip...");
ZipFile.CreateFromDirectory(extractDirectory, outputRawZipPath);
// Clean up
@ -181,9 +235,8 @@ public abstract class RawMods : ModsBase
bool useCustomSaveDirectory = false, bool usesInternet = false, OutputHandlerDelegate outputDelegate = null)
{
ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
SendOutput("Zip Recognized as " + currentOS);
outputDelegate.SendOutput("Zip Recognized as " + currentOS);
OutputHandler = outputDelegate;
string extractDirectory = TempDir + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string apkDir = extractDirectory + "/apk";
string apkAssetsDir = apkDir + "/assets";
@ -199,7 +252,7 @@ public abstract class RawMods : ModsBase
Directory.CreateDirectory(extractDirectory);
// Run APKTOOL and decompress the file
SendOutput("Decompiling apk...");
outputDelegate.SendOutput("Decompiling apk...");
ProcessStartInfo pStartInfo = new ProcessStartInfo
{
FileName = bin,
@ -210,11 +263,11 @@ public abstract class RawMods : ModsBase
p.Start();
p.WaitForExit();
SendOutput("Extracting for Raw Android...");
outputDelegate.SendOutput("Extracting for Raw Android...");
ZipFile.ExtractToDirectory(inputRawZipPath, apkAssetsDir);
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Android and lowercase them...");
outputDelegate.SendOutput("Delete unnecessary files for Android...");
switch (currentOS)
{
case ModOS.Windows:
@ -245,15 +298,16 @@ public abstract class RawMods : ModsBase
File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.splashAndroid), pathToSplashScreen), apkAssetsDir + "/splash.png", true);
//recursively lowercase everything in the assets folder
outputDelegate.SendOutput("Lowercase everything in the assets folder...");
HelperMethods.LowercaseFolder(apkAssetsDir);
// Edit apktool.yml to not compress music
SendOutput("Edit settings file to not compress OGGs...");
outputDelegate.SendOutput("Edit settings file to not compress OGGs...");
string yamlFile = File.ReadAllText(apkDir + "/apktool.yml");
yamlFile = yamlFile.Replace("doNotCompress:", "doNotCompress:\n- ogg");
File.WriteAllText(apkDir + "/apktool.yml", yamlFile);
SendOutput("Save new icons");
outputDelegate.SendOutput("Save new icons");
// Edit the icons in the apk. Wrapper always has these, so we need to overwrite these too.
string resPath = apkDir + "/res";
// Icon should only be read from if its there, otherwise default frog icon should be in the assembly
@ -274,12 +328,12 @@ public abstract class RawMods : ModsBase
// If a custom name was given, replace it everywhere.
if (useCustomSaveDirectory)
{
SendOutput("Get display name...");
outputDelegate.SendOutput("Get display name...");
string modName;
FileInfo datafile = new FileInfo(apkAssetsDir + "/game.droid");
using (FileStream fs = datafile.OpenRead())
{
UndertaleData gmData = UndertaleIO.Read(fs, SendOutput, SendOutput);
UndertaleData gmData = UndertaleIO.Read(fs, outputDelegate.SendOutput, outputDelegate.SendOutput);
modName = gmData.GeneralInfo.DisplayName.Content;
}
modName = modName.Replace(" ", "").Replace(":", "");
@ -289,7 +343,7 @@ public abstract class RawMods : ModsBase
if (!nameReg.Match(modName).Success)
throw new InvalidDataException("The display name " + modName + " is invalid! The name has to start with letters (a-z), and can only contain letters, digits, space, colon and underscore!");
SendOutput("Replace Android save directory...");
outputDelegate.SendOutput("Replace Android save directory...");
// first in the manifest
manifestFile = manifestFile.Replace("com.companyname.AM2RWrapper", $"com.companyname.{modName}");
@ -324,7 +378,7 @@ public abstract class RawMods : ModsBase
// Add internet permission, keying off the Bluetooth permission.
if (usesInternet)
{
SendOutput("Replace Internet permission...");
outputDelegate.SendOutput("Replace Internet permission...");
const string bluetoothPermission = "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>";
const string internetPermission = "<uses-permission android:name=\"android.permission.INTERNET\"/>";
manifestFile = manifestFile.Replace(bluetoothPermission, internetPermission + "\n " + bluetoothPermission);
@ -333,7 +387,7 @@ public abstract class RawMods : ModsBase
}
// Run APKTOOL and build the apk
SendOutput("Rebuild apk...");
outputDelegate.SendOutput("Rebuild apk...");
pStartInfo = new ProcessStartInfo
{
FileName = bin,
@ -345,7 +399,7 @@ public abstract class RawMods : ModsBase
p.WaitForExit();
// Sign the apk
SendOutput("Sign apk...");
outputDelegate.SendOutput("Sign apk...");
pStartInfo = new ProcessStartInfo
{
FileName = bin,
@ -378,16 +432,15 @@ public abstract class RawMods : ModsBase
OutputHandlerDelegate outputDelegate = null)
{
ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
SendOutput("Zip Recognized as " + currentOS);
outputDelegate.SendOutput("Zip Recognized as " + currentOS);
if (currentOS == ModOS.Mac)
{
SendOutput("Zip is already a raw Mac zip. Copying to output dir...");
outputDelegate.SendOutput("Zip is already a raw Mac zip. Copying to output dir...");
File.Copy(inputRawZipPath, outputRawZipPath, true);
return;
}
OutputHandler = outputDelegate;
string baseTempDirectory = TempDir + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string extractDirectory = baseTempDirectory + "/extract";
string appDirectory = baseTempDirectory + "/AM2R.app";
@ -397,16 +450,16 @@ public abstract class RawMods : ModsBase
// Check if temp folder exists, delete if yes, copy bare runner to there
if (Directory.Exists(baseTempDirectory))
Directory.Delete(baseTempDirectory, true);
SendOutput("Copying Mac Runner...");
outputDelegate.SendOutput("Copying Mac Runner...");
Directory.CreateDirectory(contentsDir);
HelperMethods.DirectoryCopy(UtilDir + "/Contents", contentsDir);
// Extract mod to temp location
SendOutput("Extracting Mac...");
outputDelegate.SendOutput("Extracting Mac...");
ZipFile.ExtractToDirectory(inputRawZipPath, extractDirectory);
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Mac and lowercase them...");
outputDelegate.SendOutput("Delete unnecessary files for Mac...");
switch (currentOS)
{
case ModOS.Windows:
@ -432,10 +485,11 @@ public abstract class RawMods : ModsBase
Directory.Delete(extractDirectory + "/lang/fonts", true);
// Lowercase every file first
outputDelegate.SendOutput("Lowercase everything in the assets folder...");
HelperMethods.LowercaseFolder(extractDirectory);
// Convert data.win to BC16 and get rid of not needed functions anymore
SendOutput("Editing data.win to change ByteCode version and functions...");
outputDelegate.SendOutput("Editing data.win to change ByteCode version and functions...");
string modName;
FileInfo datafile = new FileInfo(extractDirectory + "/game.ios");
@ -445,15 +499,15 @@ public abstract class RawMods : ModsBase
UndertaleData gmData;
using (FileStream fs = datafile.OpenRead())
{
gmData = UndertaleIO.Read(fs, SendOutput, SendOutput);
gmData = UndertaleIO.Read(fs, outputDelegate.SendOutput, outputDelegate.SendOutput);
modName = gmData.GeneralInfo.DisplayName.Content;
ChangeToByteCode16(gmData);
ChangeToByteCode16(gmData, outputDelegate.SendOutput);
}
using (FileStream fs = new FileInfo(extractDirectory + "/game.ios").OpenWrite())
{
UndertaleIO.Write(fs, gmData, SendOutput);
UndertaleIO.Write(fs, gmData, outputDelegate.SendOutput);
}
}
@ -462,13 +516,13 @@ public abstract class RawMods : ModsBase
Process.Start("chmod", "+x \"" + contentsDir + "/MacOS/Mac_Runner");
// Copy assets to the place where they belong to
SendOutput("Copy files over...");
outputDelegate.SendOutput("Copy files over...");
HelperMethods.DirectoryCopy(extractDirectory, assetsDir);
// Edit config and plist to change display name
// Escape invalid xml characters
modName = SecurityElement.Escape(modName);
SendOutput("Editing Runner references to AM2R...");
outputDelegate.SendOutput("Editing Runner references to AM2R...");
string textFile = File.ReadAllText(assetsDir + "/yoyorunner.config");
textFile = textFile.Replace("YoYo Runner", modName);
File.WriteAllText(assetsDir + "/yoyorunner.config", textFile);
@ -484,44 +538,55 @@ public abstract class RawMods : ModsBase
Directory.Delete(extractDirectory, true);
//zip the result
SendOutput("Creating Mac zip...");
outputDelegate.SendOutput("Creating Mac zip...");
ZipFile.CreateFromDirectory(baseTempDirectory, outputRawZipPath);
// Clean up
Directory.Delete(TempDir, true);
}
// TODO: clean this
private static void ChangeToByteCode16(UndertaleData Data)
/// <summary>
/// Converts a GameMaker data file to bytecode version 16
/// </summary>
/// <param name="Data">The GameMaker data file.</param>
/// <param name="output">Delegate on where to send output messages to.</param>
/// <exception cref="NotSupportedException"><paramref name="Data"/> has a not supported Bytecode version.</exception>
private static void ChangeToByteCode16(UndertaleData Data, OutputHandlerDelegate output)
{
if (Data is null) return;
string currentBytecodeVersion = Data?.GeneralInfo.BytecodeVersion.ToString();
string game_name = Data.GeneralInfo.Name.Content;
void ScriptError(string s) => Console.WriteLine(s, ConsoleColor.Red);
void ScriptMessage(string s) => Console.WriteLine(s);
void ScriptMessage(string s) => output(s);
if (!Data.FORM.Chunks.ContainsKey("AGRP"))
{
ScriptError("Bytecode 13 is not supported.");
return;
throw new NotSupportedException("Bytecode 13 is not supported.");
}
if (Data?.GeneralInfo.BytecodeVersion == 14)
byte? bcVersion = Data?.GeneralInfo.BytecodeVersion;
if (bcVersion == 14)
{
ScriptError("Bytecode 14 is not supported.");
return;
throw new NotSupportedException("Bytecode 14 is not supported.");
}
if (bcVersion == 17)
{
throw new NotSupportedException("Bytecode 17 is not supported.");
}
if (!((Data.GMS2_3 == false) && (Data.GMS2_3_1 == false) && (Data.GMS2_3_2 == false)))
{
ScriptError(game_name + "is GMS 2.3+ and is ineligible");
return;
throw new NotSupportedException(game_name + "is GMS 2.3+ and is ineligible");
}
if (bcVersion != 14 && bcVersion != 15 && bcVersion != 16)
{
throw new NotSupportedException("Unknown Bytecode version!");
}
if ((Data?.GeneralInfo.BytecodeVersion == 14) || (Data?.GeneralInfo.BytecodeVersion == 15))
if ((bcVersion == 14) || (bcVersion == 15))
{
if (Data?.GeneralInfo.BytecodeVersion <= 14)
// For BC 14
if (bcVersion <= 14)
{
foreach (UndertaleCode code in Data.Code)
{
@ -539,7 +604,8 @@ public abstract class RawMods : ModsBase
Data.CodeLocals.Add(locals);
}
}
if (!(Data.FORM.Chunks.ContainsKey("AGRP")))
// For BC 13
if (!Data.FORM.Chunks.ContainsKey("AGRP"))
{
Data.FORM.Chunks["AGRP"] = new UndertaleChunkAGRP();
var previous = -1;
@ -598,43 +664,16 @@ public abstract class RawMods : ModsBase
newChunks[name] = Data.FORM.Chunks[name];
Data.FORM.Chunks = newChunks;
Data.GeneralInfo.BytecodeVersion = 16;
ScriptMessage("Upgraded from " + currentBytecodeVersion + " to 16 successfully. Save the game to apply the changes.");
ScriptMessage("Trying to remove functions \"immersion_play_effect\", \"immersion_stop\" and \"font_replace\"!");
RemoveFunctions();
}
else if (Data?.GeneralInfo.BytecodeVersion == 17)
{
ScriptMessage("Cancelled.");
return;
ScriptMessage("Upgraded from " + bcVersion + " to 16 successfully.");
}
else if (Data?.GeneralInfo.BytecodeVersion == 16)
else if (bcVersion == 16)
{
ScriptMessage("This is already bytecode 16.");
ScriptMessage("Trying to remove functions \"immersion_play_effect\", \"immersion_stop\" and \"font_replace\"!");
RemoveFunctions();
return;
}
else
{
string error = @"This game is not bytecode 13,
14, 15, 16, or 17, and is not made in GameMaker 2.3
or greater. Please report this game to Grossley#2869
on Discord and provide the name of the game, where
you obtained it from, and additionally send the
data.win file of the game." + @"
Current status of game '" + game_name + @"':
GMS 2.3 == " + Data.GMS2_3 + @"
GMS 2.3.1 == " + Data.GMS2_3_1 + @"
GMS 2.3.2 == " + Data.GMS2_3_2 + @"
Bytecode == " + (Data?.GeneralInfo.BytecodeVersion);
ScriptError(error);
return;
}
ScriptMessage("Trying to remove functions \"immersion_play_effect\", \"immersion_stop\" and \"font_replace\"!");
RemoveFunctions();
void RemoveFunctions()
{
List<UndertaleFunction> funcsToRemove = new List<UndertaleFunction>();

Loading…
Cancel
Save