示例#1
0
        public void CreateAndSaveEmptyGame()
        {
            UndertaleData data = UndertaleData.CreateNew();

            using (MemoryStream ms = new MemoryStream())
            {
                UndertaleIO.Write(ms, data);
            }
        }
示例#2
0
        public void SaveDataAndCompare()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                UndertaleIO.Write(ms, data);

                ms.Position = 0;
                string writtenMD5 = GenerateMD5(ms);
                Assert.AreEqual(expectedMD5, writtenMD5, "Written file doesn't match read file");
            }
        }
示例#3
0
 /// <summary>
 /// Read supplied filename and return the data file.
 /// </summary>
 /// <param name="datafile">The datafile to read</param>
 /// <param name="warningHandler">Handler for Warnings</param>
 /// <param name="messageHandler">Handler for Messages</param>
 /// <returns></returns>
 /// <exception cref="FileNotFoundException">If the data file cannot be found</exception>
 private static UndertaleData ReadDataFile(FileInfo datafile, WarningHandlerDelegate?warningHandler = null, MessageHandlerDelegate?messageHandler = null)
 {
     try
     {
         using FileStream fs = datafile.OpenRead();
         return(UndertaleIO.Read(fs, warningHandler, messageHandler));
     }
     catch (FileNotFoundException e)
     {
         throw new FileNotFoundException($"Data file '{e.FileName}' does not exist");
     }
 }
示例#4
0
        static void Main(string[] args)
        {
            UndertaleData data = UndertaleIO.Read(new FileStream(@"deltarune\data.win", FileMode.Open, FileAccess.Read));

            foreach (var code in data.Code)
            {
                Debug.WriteLine(code.Name.Content);
                code.Replace(Assembler.Assemble(code.Disassemble(data.Variables, data.CodeLocals.For(code)), data.Functions, data.Variables, data.Strings));
            }

            UndertaleIO.Write(new FileStream(@"deltarune\newdata.win", FileMode.Create), data);
        }
 private void saveOutputButton_Click(object sender, EventArgs e)
 {
     label1.Text = boxWorkingMsg;
     try {
         UndertaleIO.Write(fsin, Data);
     }
     catch (Exception es) {
         label1.Text = es.ToString();
         MessageBox.Show(es.Message, "Writing error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
     label1.Text = boxCompleteMsg;
 }
示例#6
0
        //Finding salt
        public static string[] Decompile(string inFile)
        {
            FileStream    file = new FileStream(inFile, FileMode.Open, FileAccess.Read);
            UndertaleData data = UndertaleIO.Read(file);
            var           scrSetGlobalOptions = data.Scripts.ByName("scrSetGlobalOptions");
            var           locals      = scrSetGlobalOptions.Code.Instructions;
            string        instruction = "";

            for (int i = 0; i < locals.Count; i++)
            {
                if (locals[i].ToString().Contains("md5StrAdd"))
                {
                    instruction = locals[i - 1].ToString();
                    instruction = instruction[(instruction.IndexOf('"') + 1)..];
示例#7
0
        /// <summary>
        /// Saves the currently loaded <see cref="Data"/> to an output path.
        /// </summary>
        /// <param name="outputPath">The path where to save the data.</param>
        private void SaveDataFile(string outputPath)
        {
            if (Verbose)
            {
                Console.WriteLine($"Saving new data file to '{outputPath}'");
            }

            using FileStream fs = new FileInfo(outputPath).OpenWrite();
            UndertaleIO.Write(fs, Data, MessageHandler);
            if (Verbose)
            {
                Console.WriteLine($"Saved data file to '{outputPath}'");
            }
        }
        private async void MenuItem_OffsetMap_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.DefaultExt = "win";
            dlg.Filter     = "Game Maker Studio data files (.win, .unx, .ios)|*.win;*.unx;*.ios|All files|*";

            if (dlg.ShowDialog() == true)
            {
                SaveFileDialog dlgout = new SaveFileDialog();

                dlgout.DefaultExt = "txt";
                dlgout.Filter     = "Text files (.txt)|*.txt|All files|*";
                dlgout.FileName   = dlg.FileName + ".offsetmap.txt";

                if (dlgout.ShowDialog() == true)
                {
                    LoaderDialog dialog = new LoaderDialog("Generating", "Loading, please wait...");
                    dialog.Owner = this;
                    Task t = Task.Run(() =>
                    {
                        try
                        {
                            using (var stream = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read))
                            {
                                var offsets = UndertaleIO.GenerateOffsetMap(stream);
                                using (var writer = File.CreateText(dlgout.FileName))
                                {
                                    foreach (var off in offsets.OrderBy((x) => x.Key))
                                    {
                                        writer.WriteLine(off.Key.ToString("X8") + " " + off.Value.ToString().Replace("\n", "\\\n"));
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("An error occured while trying to load:\n" + ex.Message, "Load error", MessageBoxButton.OK, MessageBoxImage.Error);
                        }

                        Dispatcher.Invoke(() =>
                        {
                            dialog.Hide();
                        });
                    });
                    dialog.ShowDialog();
                    await t;
                }
            }
        }
示例#9
0
 /// <summary>
 /// Read supplied filename and return the data file
 /// </summary>
 /// <param name="datafile"></param>
 /// <param name="OnWarning"></param>
 /// <param name="OnMessage"></param>
 /// <returns></returns>
 /// <exception cref="DataFileNotFoundException">If the data file cannot be found</exception>
 public static UndertaleData ReadDataFile(FileInfo datafile, WarningHandlerDelegate?OnWarning = null, MessageHandlerDelegate?OnMessage = null)
 {
     try
     {
         using (var fs = datafile.OpenRead())
         {
             return(UndertaleIO.Read(fs, OnWarning, OnMessage));
         }
     }
     catch (FileNotFoundException e)
     {
         throw new DataFileNotFoundException($"data file {e.FileName} does not exist");
     }
 }
示例#10
0
        public void CliSave(string to)
        {
            if (Verbose)
            {
                Console.WriteLine($"Saving new data file to {this.Output.FullName}");
            }

            using (var fs = new FileInfo(to).OpenWrite())
            {
                UndertaleIO.Write(fs, Data, OnMessage);
                if (Verbose)
                {
                    Console.WriteLine($"Saved data file to {this.Output.FullName}");
                }
            }
        }
示例#11
0
        /// <summary>
        /// Reads the data from data.win using UndertaleModLib
        /// </summary>
        /// <param name="dataWinPath">Path to data.win</param>
        static void ReadData(string dataWinPath)
        {
            Console.WriteLine("Reading data.win");
            FileStream fs = new FileStream(dataWinPath, FileMode.Open, FileAccess.Read);

            try
            {
                data = UndertaleIO.Read(fs);
            } catch (IOException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
                Environment.Exit(1);
            }
            fs.Close();
        }
示例#12
0
        static void Main(string[] args)
        {
            UndertaleData data = UndertaleIO.Read(new FileStream(@"C:\Program Files (x86)\Steam\steamapps\common\undertale\data.win", FileMode.Open));

            //UndertaleIO.Write(new FileStream("newdata.win", FileMode.Create), data);

            UndertaleDebugData debug = DebugDataGenerator.GenerateDebugData(data, DebugDataMode.Decompiled);

            using (FileStream stream = new FileStream("data.yydebug", FileMode.Create))
            {
                using (UndertaleWriter writer = new UndertaleWriter(stream))
                {
                    debug.FORM.Serialize(writer);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Writes the data to a new data.win using UndertaleModLib
        /// </summary>
        /// <param name="outputPath">Output path for new data.win</param>
        static void WriteData(string outputPath)
        {
            Console.WriteLine("Writing randomised data.win");
            FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write);

            try
            {
                UndertaleIO.Write(fs, data);
            }
            catch (IOException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
                Environment.Exit(1);
            }
            fs.Close();
        }
示例#14
0
        /// <summary>
        /// Method that gets executed on the "new" command
        /// </summary>
        /// <param name="options">The arguments that have been provided with the "new" command</param>
        /// <returns><see cref="EXIT_SUCCESS"/> and <see cref="EXIT_FAILURE"/> for being successful and failing respectively</returns>
        private static int New(NewOptions options)
        {
            //TODO: this should probably create a new Program instance, with just the properties that it needs

            UndertaleData data = UndertaleData.CreateNew();

            // If stdout flag is set, write new data to stdout and quit
            if (options.Stdout)
            {
                if (options.Verbose)
                {
                    Console.WriteLine("Attempting to write new Data file to STDOUT...");
                }
                using MemoryStream ms = new MemoryStream();
                UndertaleIO.Write(ms, data);
                Console.OpenStandardOutput().Write(ms.ToArray(), 0, (int)ms.Length);
                Console.Out.Flush();
                if (options.Verbose)
                {
                    Console.WriteLine("Successfully wrote new Data file to STDOUT.");
                }

                return(EXIT_SUCCESS);
            }

            // If not STDOUT, write to file instead. Check first if we have permission to overwrite
            if (options.Output.Exists && !options.Overwrite)
            {
                Console.Error.WriteLine($"'{options.Output}' already exists. Pass --overwrite to overwrite");
                return(EXIT_FAILURE);
            }

            // We're not writing to STDOUT, and overwrite flag was given, so we write to specified file.
            if (options.Verbose)
            {
                Console.WriteLine($"Attempting to write new Data file to '{options.Output}'...");
            }
            using FileStream fs = options.Output.OpenWrite();
            UndertaleIO.Write(fs, data);
            if (options.Verbose)
            {
                Console.WriteLine($"Successfully wrote new Data file to '{options.Output}'.");
            }
            return(EXIT_SUCCESS);
        }
 private void loadInputButton_Click(object sender, EventArgs e)
 {
     label1.Text = boxWorkingMsg;
     try
     {
         fsin = new FileStream(inputFileTB.Text, FileMode.Open);
         Data = UndertaleIO.Read(fsin);
         while (null == Data)
         {
             Application.DoEvents();
         }
     }
     catch (Exception es)
     {
         label1.Text = es.ToString();
         MessageBox.Show(es.Message, "Loading error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
     label1.Text = boxCompleteMsg;
 }
示例#16
0
        public void LoadData()
        {
            if (!File.Exists(path))
            {
                Assert.Inconclusive("Unable to test, file not found: " + path);
            }

            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                string fileMD5 = GenerateMD5(fs);
                if (fileMD5 != expectedMD5)
                {
                    Assert.Inconclusive("Unable to test, incorrect file: got " + fileMD5 + " expected " + expectedMD5);
                }
                fs.Position = 0;

                data = UndertaleIO.Read(fs);
            }
        }
示例#17
0
        public static int New(NewOptions options)
        {
            var data = UndertaleData.CreateNew();

            if (options.Stdout)
            {
                WriteStdout();
            }
            else
            {
                if (WriteFile() == EXIT_FAILURE)
                {
                    return(EXIT_FAILURE);
                }
            }
            return(EXIT_SUCCESS);


            int WriteFile()
            {
                if (options.Output.Exists && !options.Overwrite)
                {
                    Console.Error.WriteLine($"{options.Output} already exists. Pass --overwrite to overwrite");
                    return(EXIT_FAILURE);
                }
                using (var fs = options.Output.OpenWrite())
                {
                    UndertaleIO.Write(fs, data);
                    return(EXIT_SUCCESS);
                }
            }

            void WriteStdout()
            {
                using (var ms = new MemoryStream())
                {
                    UndertaleIO.Write(ms, data);
                    System.Console.OpenStandardOutput().Write(ms.ToArray(), 0, (int)ms.Length);
                    System.Console.Out.Flush();
                }
            }
        }
示例#18
0
        private async Task LoadFile(string filename)
        {
            LoaderDialog dialog = new LoaderDialog("Loading", "Loading, please wait...");

            dialog.Owner = this;
            Task t = Task.Run(() =>
            {
                UndertaleData data = null;
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Open))
                    {
                        data = UndertaleIO.Read(stream);
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to load:\n" + e.Message, "Load error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    if (data != null)
                    {
                        if (data.GeneralInfo.Major >= 2)
                        {
                            MessageBox.Show("Game Maker: Studio 2 game loaded! I just hacked this together quickly for the Nintendo Switch release of Undertale, so some things may be broken. Saving should work, but not all editors have the new data. Expect a release with fixes soon!", "GMS2 game loaded", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }
                        this.Data     = data;
                        this.FilePath = filename;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Data"));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsGMS2"));
                        ChangeSelection(Highlighted = new DescriptionView("Welcome to UndertaleModTool!", "Double click on the items on the left to view them!"));
                        SelectionHistory.Clear();
                    }
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }
        private async Task LoadFile(string filename)
        {
            LoadDlg dialogue = new LoadDlg {
                Owner = this
            };

            Task t = Task.Run(() =>
            {
                Data = null;
                UndertaleData data = null;
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Open))
                    {
                        data = UndertaleIO.Read(stream, warning =>
                        {
                            MessageBox.Show(warning, "Loading warning", MessageBoxButton.OK, MessageBoxImage.Warning);
                        });
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to load:\n" + e.Message, "Load error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    //if (data != null)
                    //{
                    this.Data     = data;
                    this.FilePath = filename;
                    //}
                    dialogue.Close();
                });
            });

            dialogue.ShowDialog();
            await t;
        }
        private async Task SaveFile(string filename)
        {
            if (Data == null || Data.UnsupportedBytecodeVersion)
            {
                return;
            }
            SetStatics();
            LoadDlg dialogue = null;
            Task    t        = null;
            bool    thingy   = await DoCorrupt.DoThing(Data, Values.DoSprite, Values.DoBackground, Values.DoSound, Values.DoText, Values.DoFont, Values.SpriteType, FilePath, rng, IsDelta());

            if (thingy)
            {
                MessageBox.Show("Corrupted succesfully! Probably!", "Egg?!?!?!?!??!", MessageBoxButton.OK, MessageBoxImage.None);
                dialogue = new LoadDlg {
                    Owner = this
                };

                t = Task.Run(() =>
                {
                    //OldData = Data;
                    //MessageBox.Show("Data old set", "", MessageBoxButton.OK, MessageBoxImage.None);
                    using (var stream = new FileStream(filename, FileMode.Create))
                    {
                        UndertaleIO.Write(stream, Data);
                    }

                    Dispatcher.Invoke(() =>
                    {
                        dialogue.Close();
                        //Data = OldData;
                        //MessageBox.Show("New data set", "", MessageBoxButton.OK, MessageBoxImage.None);
                    });
                });
                dialogue.ShowDialog();
                await t;
            }
        }
        private async Task SaveFile(string filename)
        {
            if (Data == null || Data.UnsupportedBytecodeVersion)
            {
                return;
            }

            LoaderDialog dialog = new LoaderDialog("Saving", "Saving, please wait...");
            IProgress <Tuple <int, string> > progress = new Progress <Tuple <int, string> >(i => { dialog.ReportProgress(i.Item2, i.Item1); });
            IProgress <double?> setMax = new Progress <double?>(i => { dialog.Maximum = i; });

            dialog.Owner = this;
            FilePath     = filename;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FilePath"));
            if (System.IO.Path.GetDirectoryName(FilePath) != System.IO.Path.GetDirectoryName(filename))
            {
                CloseChildFiles();
            }

            DebugDataDialog.DebugDataMode debugMode = DebugDataDialog.DebugDataMode.NoDebug;
            if (!Data.GeneralInfo.DisableDebugger) // TODO: I think the game itself can also use the .yydebug file on crash reports
            {
                DebugDataDialog debugDialog = new DebugDataDialog();
                debugDialog.Owner = this;
                debugDialog.ShowDialog();
                debugMode = debugDialog.Result;
            }
            Task t = Task.Run(() =>
            {
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
                    {
                        UndertaleIO.Write(stream, Data);
                    }

                    if (debugMode != DebugDataDialog.DebugDataMode.NoDebug)
                    {
                        Debug.WriteLine("Generating debugger data...");

                        UndertaleDebugData debugData = UndertaleDebugData.CreateNew();

                        setMax.Report(Data.Code.Count);
                        int count        = 0;
                        object countLock = new object();
                        string[] outputs = new string[Data.Code.Count];
                        UndertaleDebugInfo[] outputsOffsets = new UndertaleDebugInfo[Data.Code.Count];
                        Parallel.For(0, Data.Code.Count, (i) =>
                        {
                            var code = Data.Code[i];

                            if (debugMode == DebugDataDialog.DebugDataMode.Decompiled)
                            {
                                //Debug.WriteLine("Decompiling " + code.Name.Content);
                                string output;
                                try
                                {
                                    output = Decompiler.Decompile(code, Data);
                                }
                                catch (Exception e)
                                {
                                    Debug.WriteLine(e.Message);
                                    output = "/*\nEXCEPTION!\n" + e.ToString() + "\n*/";
                                }
                                outputs[i] = output;

                                UndertaleDebugInfo debugInfo = new UndertaleDebugInfo();
                                debugInfo.Add(new UndertaleDebugInfo.DebugInfoPair()
                                {
                                    SourceCodeOffset = 0, BytecodeOffset = 0
                                });                                                                                                 // TODO: generate this too! :D
                                outputsOffsets[i] = debugInfo;
                            }
                            else
                            {
                                StringBuilder sb             = new StringBuilder();
                                UndertaleDebugInfo debugInfo = new UndertaleDebugInfo();

                                foreach (var instr in code.Instructions)
                                {
                                    if (debugMode == DebugDataDialog.DebugDataMode.FullAssembler || instr.Kind == UndertaleInstruction.Opcode.Pop || instr.Kind == UndertaleInstruction.Opcode.Popz || instr.Kind == UndertaleInstruction.Opcode.B || instr.Kind == UndertaleInstruction.Opcode.Bt || instr.Kind == UndertaleInstruction.Opcode.Bf || instr.Kind == UndertaleInstruction.Opcode.Ret || instr.Kind == UndertaleInstruction.Opcode.Exit)
                                    {
                                        debugInfo.Add(new UndertaleDebugInfo.DebugInfoPair()
                                        {
                                            SourceCodeOffset = (uint)sb.Length, BytecodeOffset = instr.Address * 4
                                        });
                                    }
                                    sb.Append(instr.ToString(code, Data.Variables));
                                    sb.Append("\n");
                                }
                                outputs[i]        = sb.ToString();
                                outputsOffsets[i] = debugInfo;
                            }

                            lock (countLock)
                            {
                                progress.Report(new Tuple <int, string>(++count, code.Name.Content));
                            }
                        });
                        setMax.Report(null);

                        for (int i = 0; i < Data.Code.Count; i++)
                        {
                            debugData.SourceCode.Add(new UndertaleScriptSource()
                            {
                                SourceCode = debugData.Strings.MakeString(outputs[i])
                            });
                            debugData.DebugInfo.Add(outputsOffsets[i]);
                            debugData.LocalVars.Add(Data.CodeLocals[i]);
                            if (debugData.Strings.IndexOf(Data.CodeLocals[i].Name) < 0)
                            {
                                debugData.Strings.Add(Data.CodeLocals[i].Name);
                            }
                            foreach (var local in Data.CodeLocals[i].Locals)
                            {
                                if (debugData.Strings.IndexOf(local.Name) < 0)
                                {
                                    debugData.Strings.Add(local.Name);
                                }
                            }
                        }

                        using (UndertaleWriter writer = new UndertaleWriter(new FileStream(System.IO.Path.ChangeExtension(FilePath, ".yydebug"), FileMode.Create, FileAccess.Write)))
                        {
                            debugData.FORM.Serialize(writer);
                            writer.ThrowIfUnwrittenObjects();
                        }
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to save:\n" + e.Message, "Save error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }
        private async Task LoadFile(string filename)
        {
            LoaderDialog dialog = new LoaderDialog("Loading", "Loading, please wait...");

            dialog.Owner = this;
            Task t = Task.Run(() =>
            {
                bool hadWarnings   = false;
                UndertaleData data = null;
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
                    {
                        data = UndertaleIO.Read(stream, warning =>
                        {
                            MessageBox.Show(warning, "Loading warning", MessageBoxButton.OK, MessageBoxImage.Warning);
                            hadWarnings = true;
                        });
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to load:\n" + e.Message, "Load error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    if (data != null)
                    {
                        if (data.UnsupportedBytecodeVersion)
                        {
                            MessageBox.Show("Only bytecode versions 15, 16, and (partially) 17 are supported for now, you are trying to load " + data.GeneralInfo.BytecodeVersion + ". A lot of code is disabled and will likely break something. Saving/exporting is disabled.", "Unsupported bytecode version", MessageBoxButton.OK, MessageBoxImage.Warning);
                            CanSave = false;
                        }
                        else if (hadWarnings)
                        {
                            MessageBox.Show("Warnings occurred during loading. Saving has been disabled.", "Saving disabled", MessageBoxButton.OK, MessageBoxImage.Warning);
                            CanSave = false;
                        }
                        else
                        {
                            CanSave = true;
                        }
                        if (data.Code == null)
                        {
                            MessageBox.Show("This game uses YYC (YoYo Compiler), which means the code is embedded into the game .exe. This configuration is currently not fully supported, continue at your own risk", "YYC", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }
                        if (data.GeneralInfo?.BytecodeVersion == 17)
                        {
                            MessageBox.Show("Bytecode version 17 has been loaded. There may be some problems remaining, as thorough research into the changes are yet to be done.", "Bytecode version 17", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }
                        if (System.IO.Path.GetDirectoryName(FilePath) != System.IO.Path.GetDirectoryName(filename))
                        {
                            CloseChildFiles();
                        }
                        this.Data     = data;
                        this.FilePath = filename;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Data"));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FilePath"));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsGMS2"));
                        ChangeSelection(Highlighted = new DescriptionView("Welcome to UndertaleModTool!", "Double click on the items on the left to view them!"));
                        SelectionHistory.Clear();
                    }
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }
示例#23
0
        private void Play_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSound sound = DataContext as UndertaleSound;

            if ((sound.Flags & UndertaleSound.AudioEntryFlags.IsEmbedded) != UndertaleSound.AudioEntryFlags.IsEmbedded &&
                (sound.Flags & UndertaleSound.AudioEntryFlags.IsCompressed) != UndertaleSound.AudioEntryFlags.IsCompressed)
            {
                try
                {
                    string filename;
                    if (!sound.File.Content.Contains("."))
                    {
                        filename = sound.File.Content + ".ogg";
                    }
                    else
                    {
                        filename = sound.File.Content;
                    }
                    string audioPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName((Application.Current.MainWindow as MainWindow).FilePath), filename);
                    if (File.Exists(audioPath))
                    {
                        switch (System.IO.Path.GetExtension(filename).ToLower())
                        {
                        case ".wav":
                            wavReader = new WaveFileReader(audioPath);
                            InitAudio();
                            waveOut.Init(wavReader);
                            waveOut.Play();
                            break;

                        case ".ogg":
                            oggReader = new VorbisWaveReader(audioPath);
                            InitAudio();
                            waveOut.Init(oggReader);
                            waveOut.Play();
                            break;

                        case ".mp3":
                            mp3Reader = new Mp3FileReader(audioPath);
                            InitAudio();
                            waveOut.Init(mp3Reader);
                            waveOut.Play();
                            break;

                        default:
                            throw new Exception("Unknown file type.");
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to find audio file.");
                    }
                } catch (Exception ex)
                {
                    waveOut = null;
                    MessageBox.Show("Failed to play audio!\r\n" + ex.Message, "Audio failure", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
                return;
            }

            UndertaleEmbeddedAudio target;

            if (sound.GroupID != 0 && sound.AudioID != -1)
            {
                try
                {
                    string path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName((Application.Current.MainWindow as MainWindow).FilePath), "audiogroup" + sound.GroupID + ".dat");
                    if (File.Exists(path))
                    {
                        if (loadedPath != path)
                        {
                            loadedPath = path;
                            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
                            {
                                audioGroupData = UndertaleIO.Read(stream, warning =>
                                {
                                    throw new Exception(warning);
                                });
                            }
                        }

                        target = audioGroupData.EmbeddedAudio[sound.AudioID];
                    }
                    else
                    {
                        throw new Exception("Failed to find audio group file.");
                    }
                } catch (Exception ex)
                {
                    waveOut = null;
                    MessageBox.Show("Failed to play audio!\r\n" + ex.Message, "Audio failure", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
            }
            else
            {
                target = sound.AudioFile;
            }

            if (target != null)
            {
                if (target.Data.Length > 4)
                {
                    try
                    {
                        if (target.Data[0] == 'R' && target.Data[1] == 'I' && target.Data[2] == 'F' && target.Data[3] == 'F')
                        {
                            wavReader = new WaveFileReader(new MemoryStream(target.Data));
                            InitAudio();
                            waveOut.Init(wavReader);
                            waveOut.Play();
                        }
                        else if (target.Data[0] == 'O' && target.Data[1] == 'g' && target.Data[2] == 'g' && target.Data[3] == 'S')
                        {
                            oggReader = new VorbisWaveReader(new MemoryStream(target.Data));
                            InitAudio();
                            waveOut.Init(oggReader);
                            waveOut.Play();
                        }
                        else
                        {
                            MessageBox.Show("Failed to play audio!\r\nNot a WAV or OGG.", "Audio failure", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }
                    }
                    catch (Exception ex)
                    {
                        waveOut = null;
                        MessageBox.Show("Failed to play audio!\r\n" + ex.Message, "Audio failure", MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
            }
            else
            {
                MessageBox.Show("Failed to play audio!\r\nNo options for playback worked.", "Audio failure", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }
示例#24
0
        static void Main(string[] args)
        {
            bool israel = false;

            if (args.Length < 1 || args.Contains("help"))
            {
                Console.WriteLine(@"Sanae's Disappearing Rabbit Patcher v1.1
A game patcher for Oh Jeez, Oh No, My Rabbits Are Gone!
Command Line Usage: RMP.exe <path to data.win> [patches]
The path to the data.win file should be where you downloaded your game.
If you downloaded it on Steam, look up how to get to a game's local files.
Patches available are:
- all - default option, applies all patches, all must be the first patch in the command
  all other supplied patches will be ignored
  if you want to specific patches, please type them instead of using all
- speedrun - the main patch for speedrunning, some patches have a dependency on this one
- intro - skips the intro in speedrunning mode (depends on speedrun)
- clock - adds a clock to the top left of the window (depends on speedrun)
- frame - press P to change maximum frame speed between 1000 and 60
- debug - adds several debug options to the game (disabled by default) (see github readme for more info)
- color - a cute little bunny color changer, randomized on room (re)entry
- nosave - prevents savepoints from being created (disabled by default)
- decomp - dumps all game code to a folder inside current directory (disabled by default)
- everything - runs *every* patch/action, unlike all, which just runs all non-severe actions/patches
- every - everything except for the decomp action
- ever - every but no decomp and no debug
");
                if (args.Length == 1 && args[0] != "help")
                {
                    Console.WriteLine("Press any key to exit");
                    Console.ReadKey();
                    return;
                }
                var ofd = new OpenFileDialog();
                ofd.Title  = "Locate your data.win file";
                ofd.Filter = "data.win|data.win";
                DialogResult dr = ofd.ShowDialog();
                if (dr == DialogResult.Cancel)
                {
                    return;
                }
                baseloc = ofd.FileName;
                israel  = true;
            }
            else
            {
                baseloc = args[0];
            }
            List <string> actions;

            {
                if (israel || args.Length == 1 || (args[1] == "all"))
                {
                    actions = new List <string>()
                    {
                        "speedrun",
                        "frame",
                        "color",
                        "clock",
                        "intro"
                    }
                }
                ;
                else if (args[1] == "everything")
                {
                    actions = new List <string>()
                    {
                        "speedrun",
                        "frame",
                        "color",
                        "clock",
                        "intro",
                        "debug",
                        "nosave",
                        "decomp"
                    };
                }
                else if (args[1] == "every")
                {
                    actions = new List <string>()
                    {
                        "speedrun",
                        "frame",
                        "color",
                        "clock",
                        "intro",
                        "debug",
                        "nosave"
                    };
                }
                else
                {
                    actions = new List <string>()
                    {
                        ""
                    };
                    actions.AddRange(args.Skip(1));
                }
            }
            if (!Path.HasExtension(baseloc) || !Directory.Exists(Path.GetDirectoryName(baseloc)))
            {
                Console.Error.WriteLine("Invalid data.win path!\n" + baseloc);
                return;
            }
            baseloc = Path.GetDirectoryName(baseloc) + "\\";
            if (!File.Exists(baseloc + "data.win.orig"))
            {
                if (File.Exists(baseloc + "data.win"))
                {
                    File.Move(baseloc + "data.win", baseloc + "data.win.orig");
                }
                else
                {
                    Console.Error.WriteLine("There's no data.win in this folder, and there's no data.win.orig!");
                    return;
                }
            }
            File.Delete(baseloc + "data.win");
            File.Copy(baseloc + "data.win.orig", baseloc + "data.win");
            FileStream    fileStream = File.Open(baseloc + "data.win", FileMode.Open);
            UndertaleData data       = UndertaleIO.Read(fileStream);

            fileStream.Close();
            File.Delete(baseloc + "data.win");
            if (data.GeneralInfo.DisplayName.Content != "My Rabbits Are Gone")
            {
                Console.Error.WriteLine("This data.win is not from Oh Jeez, Oh No, My Rabbits Are Gone\nPlease provide that one instead.");
                File.Copy(baseloc + "data.win.orig", baseloc + "data.win");
                return;
            }

            List <string> usedActions = new List <string>();
            var           gi          = new UndertaleGlobalInit();
            var           code        = new UndertaleCode();

            code.ReplaceGML("global.patched = true", data);
            code.Name = data.Strings.MakeString("gml_global_set_patched");
            gi.Code   = code;
            bool speedran = false;

            for (int i = 0; i < actions.Count; i++)
            {
                if (actions[i] != "")
                {
                    if (usedActions.Contains(actions[i]))
                    {
                        continue;
                    }
                    usedActions.Add(actions[i]);//prevent repatching actions that are already patched
                    Console.WriteLine(actions[i]);
                }
                switch (actions[i])
                {
                case "speedrun":
                    speedran = true;
                    SpeedrunPatches(data);
                    break;

                case "debug":
                    DebugPatches(data);
                    break;

                case "clock":
                    if (!speedran)
                    {
                        YUNORAN();
                    }
                    ClockPatches(data);
                    break;

                case "intro":
                    if (!speedran)
                    {
                        YUNORAN();
                    }
                    IntroPatch(data);
                    break;

                case "nosave":
                    if (!speedran)
                    {
                        YUNORAN();
                    }
                    SavePointPatch(data);
                    break;

                case "decomp":
                    Directory.CreateDirectory("./decomp/");
                    for (int ia = 0; ia < data.Code.Count; ia++)
                    {
                        UndertaleCode uc = data.Code[ia];
                        Console.WriteLine("Writing " + uc.Name.Content);
                        try
                        {
                            File.WriteAllText(baseloc + "/decomp/" + uc.Name.Content, Decompiler.Decompile(uc, new DecompileContext(data, false)));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("failed! " + e.Message);
                        }
                        Console.WriteLine("Wrote " + uc.Name.Content);
                    }
                    break;

                case "frame":
                    FramecapRemover(data);
                    break;

                case "color":
                    ColorRandomizer(data);
                    break;

                case "multiplayer":
                    Console.WriteLine("maybe one day, not today 😭");
                    break;

                case "":
                    break;

                default:
                    Console.Error.WriteLine($"Invalid action {actions[i]}\n Run RMP.exe with no arguments to see proper usage of the program.");
                    File.Copy(baseloc + "data.win.orig", baseloc + "data.win");
                    return;
                }
            }

            UndertaleIO.Write(File.Open(baseloc + "data.win", FileMode.OpenOrCreate), data);
            Console.WriteLine("Wrote data.win! A new option has been added to the main menu.");
        }
        private static void Main()
        {
            Console.WriteLine("Main() called!");
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Downwell Custom Controls Mod Installer Thing...");
            Console.WriteLine("Open the game folder, what do you see?");
            Console.WriteLine("1 - A single Downwell.exe file, that's it.");
            Console.WriteLine("2 - A lot of files, and data.win is one of them.");
            Console.Write("Input: ");
            var key = Console.ReadKey(false);

            Console.WriteLine();
            bool   singleexe = false;
            string datawinpath;

            if (key.Key == ConsoleKey.D2)
            {
                Console.WriteLine("Please drag data.win onto this window and press enter:");
                datawinpath = Console.ReadLine();
            }
            else if (key.Key == ConsoleKey.D1)
            {
                Console.WriteLine("Please start the game, and press any key.");
                Console.ReadKey(true);
                Console.WriteLine("Copying IXP000.TMP...");
                if (!CopyIXPFolder())
                {
                    Console.WriteLine("Cannot detect or copy the game's folder, ask nik on Steam Discussion forums.");
                    Console.ReadKey(true);
                    return;
                }

                // We copied the folder without any issues.
                datawinpath = Environment.GetEnvironmentVariable("TEMP") + Path.DirectorySeparatorChar + "ForPatchTemp" + Path.DirectorySeparatorChar + "data.win";

                singleexe = true;
            }
            else
            {
                Console.WriteLine("Unknown Input, relaunch this program and try again.");
                Console.ReadKey(true);
                return;
            }

            if (!File.Exists(datawinpath))
            {
                Console.WriteLine("What? Somehow data.win is missing, ask nik on Steam Discussion forums.");
                Console.ReadKey(true);
                return;
            }

            Console.WriteLine("Please make sure you've closed the game. If you did, press any key.");
            Console.ReadKey(true);

            // Ok, we can finally patch!!!
            Console.WriteLine("Loading data.win in UndertaleModLib...");
            bool quit = false;

            try
            {
                using (var stream = new FileStream(datawinpath, FileMode.Open, FileAccess.Read))
                {
                    Data = UndertaleIO.Read(stream, warning =>
                    {
                        Console.WriteLine("[MODLIB|WARN]: " + warning);
                        quit = true;
                    });
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("[MODLIB|ERR ]: " + e.Message);
                quit = true;
            }

            if (quit)
            {
                Console.WriteLine("Warnings or errors occured when loading data.win!");
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey(true);
                Environment.Exit(-1); // forcefully quit.
            }

            Console.WriteLine("Executing PatchThing();");
            PatchThing();
            Console.WriteLine();
            Console.WriteLine("Writing new data.win...");
            File.Delete(datawinpath);
            using (var stream = new FileStream(datawinpath, FileMode.Create, FileAccess.Write))
            {
                UndertaleIO.Write(stream, Data);
            }
            Console.WriteLine("Writing default controls.ini...");
            File.WriteAllText(Path.GetDirectoryName(datawinpath) + Path.DirectorySeparatorChar + "controls.ini", DefaultIni);
            if (singleexe)
            {
                FindDownwellExe(new DirectoryInfo(Path.GetDirectoryName(datawinpath)));
                Process.Start("explorer.exe", Path.GetDirectoryName(datawinpath));
                Console.WriteLine("Copy all files from this folder to your game folder.");
                Console.WriteLine("(if it asks to replace, agree, then press any key)");
                Console.ReadKey(true);
            }
            Console.WriteLine("Ok, we're done here, launch the game and press any key to exit.");
            Console.ReadKey(true);
            Console.WriteLine("Cleaning up...");
            if (singleexe)
            {
                Directory.Delete(Path.GetDirectoryName(datawinpath), true);
            }
        }
示例#26
0
        private async Task SaveFile(string filename)
        {
            if (Data == null || Data.UnsupportedBytecodeVersion)
            {
                return;
            }

            if (IsGMS2 == Visibility.Visible)
            {
                MessageBox.Show("This is not yet fully stable and may break. You have been warned.", "GMS2 game", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            LoaderDialog dialog = new LoaderDialog("Saving", "Saving, please wait...");

            dialog.Owner = this;
            FilePath     = filename;
            if (System.IO.Path.GetDirectoryName(FilePath) != System.IO.Path.GetDirectoryName(filename))
            {
                CloseChildFiles();
            }

            DebugDataMode debugMode = DebugDataMode.NoDebug;

            if (!Data.GeneralInfo.DisableDebugger) // TODO: I think the game itself can also use the .yydebug file on crash reports
            {
                DebugDataDialog debugDialog = new DebugDataDialog();
                debugDialog.Owner = this;
                debugDialog.ShowDialog();
                debugMode = debugDialog.Result;
                // TODO: Add an option to generate debug data for just selected scripts (to make running faster / make the full assembly not take forever to load)
            }
            Task t = Task.Run(() =>
            {
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Create))
                    {
                        UndertaleIO.Write(stream, Data);
                    }

                    if (debugMode != DebugDataMode.NoDebug)
                    {
                        Debug.WriteLine("Generating debugger data...");
                        UndertaleDebugData debugData = DebugDataGenerator.GenerateDebugData(Data, debugMode);
                        using (FileStream stream = new FileStream(System.IO.Path.ChangeExtension(FilePath, ".yydebug"), FileMode.Create))
                        {
                            using (UndertaleWriter writer = new UndertaleWriter(stream))
                            {
                                debugData.FORM.Serialize(writer);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to save:\n" + e.Message, "Save error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }
示例#27
0
        private async Task LoadFile(string filename)
        {
            LoaderDialog dialog = new LoaderDialog("Loading", "Loading, please wait...");

            dialog.Owner = this;
            Task t = Task.Run(() =>
            {
                bool hadWarnings   = false;
                UndertaleData data = null;
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Open))
                    {
                        data = UndertaleIO.Read(stream, warning =>
                        {
                            MessageBox.Show(warning, "Loading warning", MessageBoxButton.OK, MessageBoxImage.Warning);
                            hadWarnings = true;
                        });
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to load:\n" + e.Message, "Load error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    if (data != null)
                    {
                        if (data.UnsupportedBytecodeVersion)
                        {
                            MessageBox.Show("Only bytecode versions 15 and 16 are supported for now, you are trying to load " + data.GeneralInfo.BytecodeVersion + ". A lot of code is disabled and will likely break something. Saving/exporting is disabled.", "Unsupported bytecode version", MessageBoxButton.OK, MessageBoxImage.Warning);
                            CanSave = false;
                        }
                        else if (hadWarnings)
                        {
                            MessageBox.Show("Warnings occurred during loading. Saving has been disabled.", "Saving disabled", MessageBoxButton.OK, MessageBoxImage.Warning);
                            CanSave = false;
                        }
                        else
                        {
                            CanSave = true;
                        }
                        if (data.GeneralInfo?.Major >= 2)
                        {
                            MessageBox.Show("Game Maker: Studio 2 game loaded! I just hacked this together quickly for the Nintendo Switch release of Undertale. Most things work, but some editors don't display all the data.", "GMS2 game loaded", MessageBoxButton.OK, MessageBoxImage.Warning);
                        }
                        if (System.IO.Path.GetDirectoryName(FilePath) != System.IO.Path.GetDirectoryName(filename))
                        {
                            CloseChildFiles();
                        }
                        this.Data     = data;
                        this.FilePath = filename;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Data"));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsGMS2"));
                        ChangeSelection(Highlighted = new DescriptionView("Welcome to UndertaleModTool!", "Double click on the items on the left to view them!"));
                        SelectionHistory.Clear();
                    }
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }