public void OnApplicationRequestExportAsProject() { string path = GetUserPath(WSettingsManager.GetSettings().LastStagePath.FilePath); if (path == null) { return; } try { MainWorld.Map.ExportToDirectory(path); } catch (Exception e) { string error = ""; error += e.GetType().FullName + "\n"; error += e.Message + "\n"; error += e.StackTrace; MessageBox.Show(error, "Error building project"); return; } WSettingsManager.GetSettings().LastStagePath.FilePath = path; }
public static J3D LoadResource(string filePath) { var existRef = m_j3dList.Find(x => string.Compare(x.FilePath, filePath, StringComparison.InvariantCultureIgnoreCase) == 0); if (existRef == null) { J3D j3d = new J3D(Path.GetFileNameWithoutExtension(filePath)); using (EndianBinaryReader reader = new EndianBinaryReader(File.ReadAllBytes(filePath), Endian.Big)) j3d.LoadFromStream(reader, WSettingsManager.GetSettings().DumpTextures, WSettingsManager.GetSettings().DumpShaders); j3d.SetHardwareLight(0, m_mainLight); j3d.SetHardwareLight(1, m_secondaryLight); // Apply patches for Wind Waker by default, since they don't seem to break anything else. j3d.SetTextureOverride("ZBtoonEX", "resources/textures/ZBtoonEX.png"); j3d.SetTextureOverride("ZAtoon", "resources/textures/ZAtoon.png"); j3d.SetColorWriteOverride("eyeLdamA", false); j3d.SetColorWriteOverride("eyeLdamB", false); j3d.SetColorWriteOverride("mayuLdamA", false); j3d.SetColorWriteOverride("mayuLdamB", false); j3d.SetColorWriteOverride("eyeRdamA", false); j3d.SetColorWriteOverride("eyeRdamB", false); j3d.SetColorWriteOverride("mayuRdamA", false); j3d.SetColorWriteOverride("mayuRdamB", false); existRef = new TSharedRef <J3D>(); existRef.FilePath = filePath; existRef.Asset = j3d; m_j3dList.Add(existRef); } existRef.ReferenceCount++; return(existRef.Asset); }
public void OnApplicationRequestExportProject() { if (MainWorld.Map.MapName.Length > 7) { string error = ""; error += "The name of the stage you are currently saving is too long.\n"; error += "Stage names must be 7 characters or shorter.\n"; error += "The game will crash if you load this map without shortening its name."; MessageBox.Show(error, "Warning"); } string path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "stage", MainWorld.Map.MapName); try { MainWorld.Map.ExportToDirectory(path); } catch (Exception e) { string error = ""; error += e.GetType().FullName + "\n"; error += e.Message + "\n"; error += e.StackTrace; MessageBox.Show(error, "Error building project"); return; } WSettingsManager.GetSettings().LastStagePath.FilePath = path; }
/// <summary> /// Make a backup of system files. /// </summary> private void BackupSystemFiles() { // Make backup of system files List <string> filesToBackUp = new List <string> { "sys/main.dol", "sys/boot.bin" }; m_BackedUpFilePaths = new List <string>(); foreach (string filePath in filesToBackUp) { string fullPath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, filePath); m_BackedUpFilePaths.Add(fullPath); } foreach (string filePath in m_BackedUpFilePaths) { string backupPath = filePath + ".bak"; // If something went wrong and the file got deleted but the backup remains, restore from the backup. if (!File.Exists(filePath) && File.Exists(backupPath)) { File.Move(backupPath, filePath); } // Make the backup. if (File.Exists(backupPath)) { File.Delete(backupPath); } File.Copy(filePath, backupPath); } }
private void UpdateModel() { // Loads the necessary information about which figurine model to load dynamically from the REL and the DOL. m_actorMeshes = WResourceManager.LoadActorResource("Figurine Stand"); int modelFileID; int modelArcIndex; int figurineIndex = (int)WhichFigurine; string figurine_rel_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "rels/d_a_obj_figure.rel"); MemoryStream figurine_rel_data = null; using (EndianBinaryReader reader = new EndianBinaryReader(File.ReadAllBytes(figurine_rel_path), Endian.Big)) { figurine_rel_data = Yaz0.Decode(reader); } using (EndianBinaryReader reader = new EndianBinaryReader(figurine_rel_data, Endian.Big)) { int l_figure_dat_entry_offset = l_figure_dat_tbl_offset + figurineIndex * 0xC; modelFileID = reader.ReadInt32At(l_figure_dat_entry_offset + 0x00); modelArcIndex = reader.ReadInt32At(l_figure_dat_entry_offset + 0x08); } if (modelArcIndex == -1) { string main_dol_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "sys", "main.dol"); using (FileStream strm = new FileStream(main_dol_path, FileMode.Open, FileAccess.Read)) { EndianBinaryReader reader = new EndianBinaryReader(strm, Endian.Big); long l_CharaData_entry_address = l_CharaData_address + figurineIndex * 0x12; long l_CharaData_entry_offset = DOL.AddressToOffset(l_CharaData_entry_address, reader); modelArcIndex = reader.ReadByteAt(l_CharaData_entry_offset + 0x10); } } var arc_name = l_arcname_tbl[modelArcIndex]; string arc_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", arc_name + ".arc"); if (File.Exists(arc_path)) { VirtualFilesystemDirectory model_arc = ArchiveUtilities.LoadArchive(arc_path); if (model_arc.FindByID((ushort)modelFileID) != null) { var figurine_model = WResourceManager.LoadModelFromVFS(model_arc, fileID: (ushort)modelFileID); figurine_model.SetOffsetTranslation(new Vector3(0, 100, 0)); m_actorMeshes.Add(figurine_model); } } }
private void StartPlaytest(WMap map, MapLayer active_layer) { Console.WriteLine($"Stage name: { map.MapName }, Room Name: { map.FocusedSceneLabel }"); string map_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "stage", map.MapName); map.ExportToDirectory(map_path); string dol_dir = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "sys"); m_DolPath = Path.Combine(dol_dir, "main.dol"); m_BackupDolPath = Path.Combine(dol_dir, "main_backup.dol"); m_DolphinStartInfo = new ProcessStartInfo(@"dolphin\Dolphin.exe"); m_DolphinStartInfo.Arguments = $"-b -e \"{ m_DolPath }\""; byte room_no = 0; byte spawn_id = 0; GetRoomAndSpawnID(map.FocusedScene, out room_no, out spawn_id); Patch p = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\test_room_diff.json")); p.Files[0].Patchlets.Add(new Patchlet(2149765112, new List <byte>(Encoding.ASCII.GetBytes(map.MapName)))); p.Files[0].Patchlets.Add(new Patchlet(2147824099, new List <byte>(new byte[] { spawn_id }))); p.Files[0].Patchlets.Add(new Patchlet(2147824103, new List <byte>(new byte[] { room_no }))); p.Files[0].Patchlets.Add(new Patchlet(2147824107, new List <byte>(new byte[] { (byte)(active_layer - 1) }))); if (!File.Exists(m_DolPath)) { Console.WriteLine("ISO root has no executable!"); return; } if (File.Exists(m_BackupDolPath)) { File.Delete(m_BackupDolPath); } File.Copy(m_DolPath, m_BackupDolPath); p.Apply(WSettingsManager.GetSettings().RootDirectoryPath); m_DolphinInstance = Process.Start(m_DolphinStartInfo); m_DolphinInstance.EnableRaisingEvents = true; m_DolphinInstance.Exited += OnDolphinExited; }
public void OnApplicationRequestExportProject() { string path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "stage", MainWorld.Map.MapName); try { MainWorld.Map.ExportToDirectory(path); } catch (Exception e) { string error = ""; error += e.GetType().FullName + "\n"; error += e.Message + "\n"; error += e.StackTrace; MessageBox.Show(error, "Error building project"); return; } WSettingsManager.GetSettings().LastStagePath.FilePath = path; }
public void OnApplicationRequestOpenRooms() { var ofd = new CommonOpenFileDialog() { Title = "Choose Rooms to Open", AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, EnsureValidNames = true, Multiselect = true, ShowPlacesList = true }; ofd.Filters.Add(new CommonFileDialogFilter("RARC Archives", ".arc")); ofd.Filters.Add(new CommonFileDialogFilter("All Files", ".*")); if (WSettingsManager.GetSettings().LastStagePath.FilePath != "") { ofd.InitialDirectory = WSettingsManager.GetSettings().LastStagePath.FilePath; } if (ofd.ShowDialog() == CommonFileDialogResult.Ok) { List <string> files = new List <string>(ofd.FileNames); string dirPath = Path.GetDirectoryName(files[0]); string stageArcPath = Path.Combine(dirPath, "Stage.arc"); if (!files.Contains(stageArcPath) && File.Exists(stageArcPath)) { // Always load the stage arc even if it wasn't selected by the user. files.Add(stageArcPath); } string tempMapPath = Path.Combine(GetStageDumpPath(), Path.GetFileName(dirPath)); // This is where we'll dump the arc contents to DeleteDumpContentsFromTempDir(); if (!Directory.Exists(GetStageDumpPath())) { Directory.CreateDirectory(GetStageDumpPath()); } if (!Directory.Exists(tempMapPath)) { Directory.CreateDirectory(tempMapPath); } foreach (var arc in files) { VirtualFilesystemDirectory archiveRoot = ArchiveUtilities.LoadArchive(arc); if (archiveRoot == null) { continue; } string tempArcPath = $"{tempMapPath}\\{archiveRoot.Name}"; if (!Directory.Exists(tempArcPath)) { Directory.CreateDirectory(tempMapPath); } DumpContents(archiveRoot, tempArcPath); } LoadProject(tempMapPath, dirPath); // This will signal that we loaded from archives, and that there is no valid path to save the map yet. MainWorld.Map.SavePath = null; m_sourceDataPath = tempMapPath; WSettingsManager.GetSettings().LastStagePath.FilePath = dirPath; WSettingsManager.SaveSettings(); } }
public void OnApplicationRequestOpenProject() { var ofd = new CommonOpenFileDialog() { Title = "Choose Directory", IsFolderPicker = true, AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, EnsureValidNames = true, Multiselect = false, ShowPlacesList = true }; if (WSettingsManager.GetSettings().LastStagePath.FilePath != "") { ofd.InitialDirectory = WSettingsManager.GetSettings().LastStagePath.FilePath; } if (ofd.ShowDialog() == CommonFileDialogResult.Ok) { List <string> files = new List <string>(Directory.GetFiles(ofd.FileName)); List <string> dirs = new List <string>(Directory.GetDirectories(ofd.FileName)); // There are directories here, and one of them is an unpacked Stage folder, so try to load all of these instead of loading the .arcs. if (dirs.Count != 0 && File.Exists(Path.Combine(ofd.FileName, "Stage/dzs/stage.dzs"))) { LoadProject(ofd.FileName, ofd.FileName); m_sourceDataPath = ofd.FileName; } // We'll have to dump the contents of the arcs else { string tempMapPath = HandleTempPath(ofd.FileName); foreach (var arc in files) { var filename = Path.GetFileName(arc); Regex reg = new Regex(@"(Stage|Room\d+).arc", RegexOptions.Compiled | RegexOptions.IgnoreCase); if (!reg.IsMatch(filename)) { continue; } VirtualFilesystemDirectory archiveRoot = ArchiveUtilities.LoadArchive(arc); if (archiveRoot == null) { continue; } string tempArcPath = $"{tempMapPath}\\{archiveRoot.Name}"; if (!Directory.Exists(tempArcPath)) { Directory.CreateDirectory(tempMapPath); } DumpContents(archiveRoot, tempArcPath); } LoadProject(tempMapPath, ofd.FileName); // This will signal that we loaded from archives, and that there is no valid path to save the map yet. MainWorld.Map.SavePath = null; m_sourceDataPath = tempMapPath; WSettingsManager.GetSettings().LastStagePath.FilePath = ofd.FileName; WSettingsManager.SaveSettings(); } } }
private static J3D LoadModelFromResource(WActorResource.ModelResource res, string archive) { J3D j3d = null; if (string.IsNullOrEmpty(res.Path) || string.IsNullOrEmpty(archive)) { return(null); } string archivePath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", archive + ".arc"); if (!File.Exists(archivePath)) { return(null); } VirtualFilesystemDirectory model_arc = ArchiveUtilities.LoadArchive(archivePath); VirtualFilesystemFile archiveFile = model_arc.GetFileAtPath(res.Path); if (archiveFile == null) { Console.WriteLine("LoadActorByName failed because the specified path \"{0}\" does not exist in archive \"{1}\"!", res.Path, archive); return(null); } byte[] j3dData = archiveFile.Data; j3d = new J3D(archiveFile.Name); using (EndianBinaryReader reader = new EndianBinaryReader(j3dData, Endian.Big)) j3d.LoadFromStream(reader, WSettingsManager.GetSettings().DumpTextures, WSettingsManager.GetSettings().DumpShaders); if (res.Position != null) { j3d.SetOffsetTranslation((Vector3)res.Position); } if (res.Rotation != null) { j3d.SetOffsetRotation((Vector3)res.Rotation); } if (res.Scale != null) { j3d.SetOffsetScale((Vector3)res.Scale); } j3d.SetHardwareLight(0, m_mainLight); j3d.SetHardwareLight(1, m_secondaryLight); j3d.SetTextureOverride("ZBtoonEX", "resources/textures/ZBtoonEX.png"); j3d.SetTextureOverride("ZAtoon", "resources/textures/ZAtoon.png"); if (res.Animations == null) { res.Animations = new WActorResource.AnimationResource[0]; } foreach (var anim in res.Animations) { VirtualFilesystemDirectory anim_arc = model_arc; if (!string.IsNullOrEmpty(anim.ArchiveName)) { string anim_arc_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", anim.ArchiveName + ".arc"); if (!File.Exists(anim_arc_path)) { return(null); } anim_arc = ArchiveUtilities.LoadArchive(anim_arc_path); } VirtualFilesystemFile anim_file = anim_arc.GetFileAtPath(anim.Path); if (anim_file == null) { continue; } byte[] anim_data = anim_file.Data; // Decompress the file if necessary if (anim_data[0] == 'Y') { MemoryStream decompressed_data = null; using (EndianBinaryReader decompressor = new EndianBinaryReader(anim_data, Endian.Big)) { decompressed_data = Yaz0.Decode(decompressor); } anim_data = decompressed_data.ToArray(); } switch (anim.Type) { case "bck": BCK loaded_bck = new BCK(anim_file.Name); using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big)) loaded_bck.LoadFromStream(reader); j3d.BoneAnimations.Add(loaded_bck); j3d.SetBoneAnimation(anim_file.Name); loaded_bck.Tick(anim.StartTime); if (anim.PausedOnLoad) { loaded_bck.Pause(); } break; case "btk": BTK loaded_btk = new BTK(anim_file.Name); using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big)) loaded_btk.LoadFromStream(reader); j3d.MaterialAnimations.Add(loaded_btk); j3d.SetMaterialAnimation(anim_file.Name); loaded_btk.Tick(anim.StartTime); if (anim.PausedOnLoad) { loaded_btk.Pause(); } break; case "brk": BRK loaded_brk = new BRK(anim_file.Name); using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big)) loaded_brk.LoadFromStream(reader); j3d.RegisterAnimations.Add(loaded_brk); j3d.SetRegisterAnimation(anim_file.Name); loaded_brk.Tick(anim.StartTime); if (anim.PausedOnLoad) { loaded_brk.Pause(); } break; case "bmt": BMT loaded_bmt = new BMT(anim_file.Name); using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big)) loaded_bmt.LoadFromStream(reader); j3d.ExternalMaterials.Add(loaded_bmt); j3d.SetExternalMaterial(anim_file.Name); if (loaded_bmt.MAT3 != null) { // a hack to get bmts working Material dummyMat = null; j3d.AssignVertexAttributesToMaterialsRecursive(j3d.INF1Tag.HierarchyRoot, ref dummyMat, loaded_bmt.MAT3); j3d.GenerateShadersForMaterials(loaded_bmt.MAT3); } break; default: break; } } j3d.Tick(1 / (float)60); if (res.ChildModels == null) { res.ChildModels = new WActorResource.ModelResource[0]; } foreach (var childRes in res.ChildModels) { var childJ3d = LoadModelFromResource(childRes, archive); j3d.AddChildModel(childJ3d, childRes.ParentJointName); } return(j3d); }
public static List <J3D> LoadActorResource(string name) { List <J3D> models = new List <J3D>(); if (!m_actorResources.ContainsKey(name)) { return(null); } WActorResource res = m_actorResources[name]; foreach (var model in res.Models) { string model_arc_name = res.ArchiveName; if (!string.IsNullOrEmpty(model.ArchiveName)) { model_arc_name = model.ArchiveName; string model_arc_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", model_arc_name + ".arc"); if (!File.Exists(model_arc_path)) { continue; } } string arc_and_file_path = Path.Combine(model_arc_name, model.Path); TSharedRef <J3D> existRef = null;//m_j3dList.Find(x => string.Compare(x.FilePath, arc_and_file_path, StringComparison.InvariantCultureIgnoreCase) == 0); if (existRef != null) { existRef.ReferenceCount++; models.Add(existRef.Asset); continue; } J3D loaded_model = LoadModelFromResource(model, model_arc_name); if (loaded_model == null) { continue; } existRef = new TSharedRef <J3D>(); existRef.FilePath = arc_and_file_path; existRef.Asset = loaded_model; existRef.ReferenceCount++; m_j3dList.Add(existRef); models.Add(loaded_model); } if (models.Count > 0 && (name == "Link" || name == "Tetra" || name == "Zelda")) { models[0].SetColorWriteOverride("eyeLdamA", false); models[0].SetColorWriteOverride("eyeLdamB", false); models[0].SetColorWriteOverride("mayuLdamA", false); models[0].SetColorWriteOverride("mayuLdamB", false); models[0].SetColorWriteOverride("eyeRdamA", false); models[0].SetColorWriteOverride("eyeRdamB", false); models[0].SetColorWriteOverride("mayuRdamA", false); models[0].SetColorWriteOverride("mayuRdamB", false); models[0].SetColorWriteOverride("m_pz_eyeLdamA", false); models[0].SetColorWriteOverride("m_pz_eyeLdamB", false); models[0].SetColorWriteOverride("m_pz_eyeRdamA", false); models[0].SetColorWriteOverride("m_pz_eyeRdamB", false); models[0].SetColorWriteOverride("m_pz_mayuLdamA", false); models[0].SetColorWriteOverride("m_pz_mayuLdamB", false); models[0].SetColorWriteOverride("m_pz_mayuRdamA", false); models[0].SetColorWriteOverride("m_pz_mayuRdamB", false); foreach (var material in models[0].MAT3Tag.MaterialList) { if (material.BlendModeIndex.SourceFactor == GXBlendModeControl.DstAlpha && material.BlendModeIndex.DestinationFactor == GXBlendModeControl.InverseDstAlpha) { material.BlendModeIndex.SourceFactor = GXBlendModeControl.SrcAlpha; material.BlendModeIndex.DestinationFactor = GXBlendModeControl.InverseSrcAlpha; } } } if (models.Count > 0 && (name == "Wizzrobe")) { foreach (var material in models[0].MAT3Tag.MaterialList) { material.ZModeIndex.UpdateEnable = true; } } return(models); }
private void StartPlaytest(WMap map, MapLayer active_layer) { string dolphinPath = Path.Combine(WSettingsManager.GetSettings().DolphinDirectory.FilePath, "Dolphin.exe"); if (!File.Exists(dolphinPath)) { MessageBox.Show("You must specify the path to Dolphin in the options menu before you can playtest.", "Dolphin not found", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Console.WriteLine($"Stage name: { map.MapName }, Room Name: { map.FocusedSceneLabel }"); string map_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "stage", map.MapName); map.ExportToDirectory(map_path); List <string> filesToBackUp = new List <string> { "sys/main.dol" }; if (WSettingsManager.GetSettings().HeapDisplay) { filesToBackUp.Add("sys/boot.bin"); } m_BackedUpFilePaths = new List <string>(); foreach (string filePath in filesToBackUp) { string fullPath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, filePath); m_BackedUpFilePaths.Add(fullPath); } string dolPath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "sys", "main.dol"); m_DolphinStartInfo = new ProcessStartInfo(dolphinPath); m_DolphinStartInfo.Arguments = $"-b -e \"{ dolPath }\""; int room_no = 0; int spawn_id = 0; GetRoomAndSpawnID(map.FocusedScene, out room_no, out spawn_id); if (!File.Exists(dolPath)) { Console.WriteLine("ISO root has no executable!"); return; } foreach (string filePath in m_BackedUpFilePaths) { string backupPath = filePath + ".bak"; if (File.Exists(backupPath)) { File.Delete(backupPath); } File.Copy(filePath, backupPath); } Patch testRoomPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\test_room_diff.json")); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x8022CFF8, new List <byte>(Encoding.ASCII.GetBytes(map.MapName)))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531E3, new List <byte>(new byte[] { (byte)spawn_id }))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531E7, new List <byte>(new byte[] { (byte)room_no }))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531EB, new List <byte>(new byte[] { (byte)(active_layer - 1) }))); testRoomPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); Patch devModePatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\developer_mode_diff.json")); devModePatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); Patch particleIdsPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\missing_particle_ids_diff.json")); particleIdsPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); if (WSettingsManager.GetSettings().HeapDisplay) { Patch heapDisplayPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\heap_display_diff.json")); heapDisplayPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); } m_DolphinInstance = Process.Start(m_DolphinStartInfo); m_DolphinInstance.EnableRaisingEvents = true; m_DolphinInstance.Exited += OnDolphinExited; }
private void StartPlaytest(WMap map, MapLayer active_layer) { string dolphinPath = Path.Combine(WSettingsManager.GetSettings().DolphinDirectory.FilePath, "Dolphin.exe"); if (!File.Exists(dolphinPath)) { MessageBox.Show("You must specify the path to Dolphin in the options menu before you can playtest.", "Dolphin not found", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (map.MapName.Length > 7) { string error = ""; error += "The name of the stage you are trying to playtest is too long.\n"; error += "Stage names must be 7 characters or shorter.\n"; error += "The game would crash if you loaded this map without shortening its name.\n"; error += "Aborting playtest."; MessageBox.Show(error, "Warning"); return; } Console.WriteLine($"Stage name: { map.MapName }, Room Name: { map.FocusedSceneLabel }"); string map_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "stage", map.MapName); map.ExportToDirectory(map_path); BackupSystemFiles(); string dolPath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "sys", "main.dol"); m_DolphinStartInfo = new ProcessStartInfo(dolphinPath); m_DolphinStartInfo.Arguments = $"-b -e \"{ dolPath }\""; int room_no = 0; int spawn_id = 0; GetRoomAndSpawnID(map.FocusedScene, out room_no, out spawn_id); int numMatchingSpawns = 0; foreach (var scn in map.SceneList) { numMatchingSpawns += scn.GetChildrenOfType <SpawnPoint>().Where(x => x.Room == room_no && x.SpawnID == spawn_id).Count(); } if (numMatchingSpawns == 0) { MessageBox.Show($"No spawns found with room number {room_no} and spawn ID {spawn_id}.", "Warning"); return; } if (numMatchingSpawns > 1) { MessageBox.Show($"There are {numMatchingSpawns} duplicate spawns with room number {room_no} and spawn ID {spawn_id}.", "Warning"); return; } if (!File.Exists(dolPath)) { Console.WriteLine("ISO root has no executable!"); return; } Patch testRoomPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\test_room_diff.json")); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x8022D034, new List <byte>(Encoding.ASCII.GetBytes(map.MapName)))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531E3, new List <byte>(new byte[] { (byte)spawn_id }))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531E7, new List <byte>(new byte[] { (byte)room_no }))); testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x800531EB, new List <byte>(new byte[] { (byte)(active_layer - 1) }))); // Starting items list is at 0x8022D03C and can contain a maximum of 256 item IDs List <byte> ItemIDs = m_InventorySettings.ViewModel.ItemIDs; for (int i = 0; i < ItemIDs.Count; i++) { testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x8022D03C + i, new List <byte>(new byte[] { ItemIDs[i] }))); } // Save slot testRoomPatch.Files[0].Patchlets.Add(new Patchlet(0x8022CFDF, new List <byte>(new byte[] { m_InventorySettings.ViewModel.SaveFileIndex }))); testRoomPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); Patch devModePatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\developer_mode_diff.json")); devModePatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); Patch particleIdsPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\missing_particle_ids_diff.json")); particleIdsPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); if (WSettingsManager.GetSettings().HeapDisplay) { Patch heapDisplayPatch = JsonConvert.DeserializeObject <Patch>(File.ReadAllText(@"resources\patches\heap_display_diff.json")); heapDisplayPatch.Apply(WSettingsManager.GetSettings().RootDirectoryPath); } m_DolphinInstance = Process.Start(m_DolphinStartInfo); m_DolphinInstance.EnableRaisingEvents = true; m_DolphinInstance.Exited += OnDolphinExited; }