public string Play() { if (!SteamUtil.IsSteamRunning()) { MessageBox.Show("Steam must be opened to play Portal 2 splitScreen. Open it then click OK."); } // minimize everything User32.MinimizeEverything(); // copy the correct xinput to the bin folder byte[] xdata = GamesResources.Portal_xinput1_3; xinputPath = Path.Combine(binFolder, "xinput1_3.dll"); using (MemoryStream stream = new MemoryStream(xdata)) { // write to bin folder using (FileStream file = new FileStream(xinputPath, FileMode.Create)) { stream.WriteTo(file); } } int pid = StartGameUtil.StartGame(executablePlace, "-novid", 0); proc = Process.GetProcessById(pid); loaded = true; return(string.Empty); }
private void ScanDrivesThread(object state) { List <SearchStorageInfo> storage = (List <SearchStorageInfo>)state; string[] result = StartGameUtil.ScanGames(storage.ToArray()); bool shouldUpdate = false; for (int i = 0; i < result.Length; i++) { string path = result[i]; #if false UserGameInfo uinfo = GameManager.Instance.TryAddGame(path); if (uinfo != null) { Log.WriteLine($"> Found new game ID {uinfo.GameID}"); shouldUpdate = true; } #endif } if (shouldUpdate) { MainForm.Instance.Invoke((Action)MainForm.Instance.RefreshGames); } Invoke(new Action(() => { btn_search.Text = "Scan"; btn_search.Enabled = true; })); }
public override void PlayPlayer(int index, HandlerContext context) { ProcessInfo procData = Player.ProcessData; List <PlayerInfo> players = profile.PlayerData; ProcessInfo pdata = Player.ProcessData; for (int j = 0; j < handlerData.KillMutex.Length; j++) { string mutex = handlerData.KillMutex[j]; StartGameUtil.KillMutex(pdata.Process, mutex); } }
public override void PrePlayPlayer(PlayerInfo player, int index, HandlerContext context) { ProcessInfo procData = player.ProcessData; bool hasSetted = procData != null && procData.Setted; List <PlayerInfo> players = profile.PlayerData; if (index > 0 && (handlerData.KillMutex?.Length > 0 || !hasSetted)) { PlayerInfo before = players[index - 1]; for (; ;) { Thread.Sleep(1000); if (handlerData.KillMutex != null) { if (handlerData.KillMutex.Length > 0 && !before.ProcessData.KilledMutexes) { // check for the existence of the mutexes // before invoking our StartGame app to kill them ProcessInfo pdata = before.ProcessData; if (StartGameUtil.MutexExists(pdata.Process, handlerData.KillMutex)) { // mutexes still exist, must kill StartGameUtil.KillMutex(pdata.Process, handlerData.KillMutex); //pdata.KilledMutexes = true; break; } else { // mutexes dont exist anymore break; } } } else { break; } } } for (int i = 0; i < players.Count; i++) { } }
public void Update(int delayMS) { if (profile == null) { return; } exited = 0; List <PlayerInfo> players = profile.PlayerData; timer += delayMS; for (int i = 0; i < players.Count; i++) { PlayerInfo p = players[i]; ProcessData data = p.ProcessData; if (data == null) { continue; } if (p.SteamEmu) { List <int> children = ProcessUtil.GetChildrenProcesses(data.Process); // catch the game process, that was spawned from Smart Steam Emu if (children.Count > 0) { for (int j = 0; j < children.Count; j++) { int id = children[j]; Process child = Process.GetProcessById(id); try { if (child.ProcessName.Contains("conhost")) { continue; } } catch { continue; } data.AssignProcess(child); p.SteamEmu = child.ProcessName.Contains("SmartSteamLoader") || child.ProcessName.Contains("cmd"); } } } else { if (data.Setted) { if (data.Process.HasExited) { exited++; continue; } if (!p.ProcessData.KilledMutexes && gen.KillMutex.Length > 0) { StartGameUtil.KillMutex(data.Process, gen.KillMutex); p.ProcessData.KilledMutexes = true; } uint lStyle = User32Interop.GetWindowLong(data.HWnd.NativePtr, User32_WS.GWL_STYLE); if (lStyle != data.RegLong) { uint toRemove = User32_WS.WS_CAPTION; lStyle = lStyle & (~toRemove); User32Interop.SetWindowLong(data.HWnd.NativePtr, User32_WS.GWL_STYLE, lStyle); data.RegLong = lStyle; data.HWnd.Location = data.Position; } data.HWnd.TopMost = true; if (p.IsKeyboardPlayer) { Rectangle r = p.MonitorBounds; Cursor.Clip = r; User32Interop.SetForegroundWindow(data.HWnd.NativePtr); } } else { data.Process.Refresh(); if (data.Process.HasExited) { if (p.GotLauncher) { if (p.GotGame) { exited++; } else { List <int> children = ProcessUtil.GetChildrenProcesses(data.Process); if (children.Count > 0) { for (int j = 0; j < children.Count; j++) { int id = children[j]; Process pro = Process.GetProcessById(id); if (!attached.Contains(pro)) { attached.Add(pro); data.HWnd = null; p.GotGame = true; data.AssignProcess(pro); } } } } } else { // Steam showing a launcher, need to find our game process string launcher = gen.LauncherExe; if (launcher.ToLower().EndsWith(".exe")) { launcher = launcher.Remove(launcher.Length - 4, 4); } Process[] procs = Process.GetProcessesByName(launcher); for (int j = 0; j < procs.Length; j++) { Process pro = procs[j]; if (!attached.Contains(pro)) { attached.Add(pro); data.AssignProcess(pro); p.GotLauncher = true; } } } } else { if (data.HWNDRetry || data.HWnd == null || data.HWnd.NativePtr != data.Process.MainWindowHandle) { data.HWnd = new HwndObject(data.Process.MainWindowHandle); Point pos = data.HWnd.Location; if (String.IsNullOrEmpty(data.HWnd.Title) || pos.X == -32000 || data.HWnd.Title.ToLower() == gen.LauncherTitle.ToLower()) { data.HWNDRetry = true; } else { Size s = data.Size; data.Setted = true; data.HWnd.TopMost = true; data.HWnd.Size = data.Size; data.HWnd.Location = data.Position; } } } } } } if (exited == players.Count) { if (!hasEnded) { End(); } } }
public string Play() { List <PlayerInfo> players = profile.PlayerData; Screen[] all = Screen.AllScreens; string backupDir = GameManager.Instance.GetBackupFolder(this.userGame.Game); string binFolder = Path.GetDirectoryName(userGame.ExePath); string rootFolder = ReplaceCaseInsensitive(binFolder, gen.BinariesFolder, ""); int gamePadId = 0; bool first = true; hidetaskbar = false; bool keyboard = false; if (gen.SupportsKeyboard) { // make sure the keyboard player is the last to be started, // so it will get the focus by default KeyboardPlayer player = (KeyboardPlayer)profile.Options["KeyboardPlayer"]; if (player.Value != -1) { keyboard = true; List <PlayerInfo> newPlayers = new List <PlayerInfo>(); for (int i = 0; i < players.Count; i++) { PlayerInfo p = players[i]; if (i == player.Value) { continue; } newPlayers.Add(p); } newPlayers.Add(players[player.Value]); players = newPlayers; } } for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; if (i > 0 && gen.KillMutex.Length > 0) { PlayerInfo before = players[i - 1]; for (;;) { if (exited > 0) { return(""); } Thread.Sleep(100); if (before.ProcessData.KilledMutexes) { break; } } } Rectangle playerBounds = player.MonitorBounds; // find the monitor that has this screen Screen owner = null; for (int j = 0; j < all.Length; j++) { Screen s = all[j]; if (s.Bounds.Contains(playerBounds)) { owner = s; break; } } int width = playerBounds.Width; int height = playerBounds.Height; bool isFullscreen = false; if (owner != null) { Rectangle ob = owner.Bounds; if (playerBounds.X == ob.X && playerBounds.Y == ob.Y && playerBounds.Width == ob.Width && playerBounds.Height == ob.Height) { isFullscreen = true; } } GenericContext context = gen.CreateContext(profile, player, this); context.PlayerID = i; context.IsFullscreen = isFullscreen; context.IsKeyboardPlayer = keyboard && i == players.Count - 1; gen.PrePlay(context); player.IsKeyboardPlayer = context.IsKeyboardPlayer; string saveFile = context.SavePath; if (gen.SaveType != SaveType.None && first) { GameManager.Instance.BeginBackup(gen); GameManager.Instance.BackupFile(gen, saveFile); } // symlink the game folder // find out the folder that contains the game executable string root = GetRootFolder(gen.BinariesFolder); string linkFolder = Path.Combine(backupDir, "Instance" + i); Directory.CreateDirectory(linkFolder); int exitCode; CmdUtil.LinkDirectories(rootFolder, linkFolder, out exitCode, root.ToLower()); string linkBin = Path.Combine(linkFolder, gen.BinariesFolder); if (!string.IsNullOrEmpty(gen.BinariesFolder)) { // this needs fixing, if there are several folder to the exe and they have important files inside, this won't work! TODO Directory.CreateDirectory(linkBin); CmdUtil.LinkDirectories(binFolder, linkBin, out exitCode); } string exePath = Path.Combine(linkBin, this.userGame.Game.ExecutableName); if (context.SymlinkExe) { CmdUtil.LinkFiles(binFolder, linkBin, out exitCode, "xinput", "ncoop"); } else { CmdUtil.LinkFiles(binFolder, linkBin, out exitCode, "xinput", "ncoop", Path.GetFileNameWithoutExtension(gen.ExecutableName.ToLower())); File.Copy(userGame.ExePath, exePath, true); } // some games have save files inside their game folder, so we need to access them inside the loop this.data[Folder.GameFolder.ToString()] = linkFolder; IniFile file = new IniFile(saveFile); switch (context.SaveType) { case SaveType.INI: for (int j = 0; j < context.ModifySave.Length; j++) { SaveInfo save = context.ModifySave[j]; if (save is IniSaveInfo) { IniSaveInfo ini = (IniSaveInfo)save; file.IniWriteValue(ini.Section, ini.Key, ini.Value); } } break; } string startArgs = context.StartArguments; if (context.CustomXinput) { byte[] xdata = null; if (context.IsKeyboardPlayer) { // TODO: need to make an xinput that answers to no gamepad? xdata = Properties.Resources.xinput4; } else { switch (gamePadId) { case 0: xdata = Properties.Resources.xinput1; break; case 1: xdata = Properties.Resources.xinput2; break; case 2: xdata = Properties.Resources.xinput3; break; case 3: default: xdata = Properties.Resources.xinput4; break; } gamePadId++; } using (Stream str = File.OpenWrite(Path.Combine(linkBin, "xinput1_3.dll"))) { str.Write(xdata, 0, xdata.Length); } string ncoopIni = Path.Combine(linkBin, "ncoop.ini"); using (Stream str = File.OpenWrite(ncoopIni)) { byte[] ini = Properties.Resources.ncoop; str.Write(ini, 0, ini.Length); } IniFile x360 = new IniFile(ncoopIni); x360.IniWriteValue("Options", "HookWindows", context.HookWindows.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "HookGameWindow", context.HookGameWindow.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "HookNeeded", context.HookNeeded.ToString(CultureInfo.InvariantCulture)); } Process proc; if (context.NeedsSteamEmulation) { string steamEmu = GameManager.Instance.ExtractSteamEmu(); if (string.IsNullOrEmpty(steamEmu)) { return("Extraction of SmartSteamEmu failed!"); } string emuExe = Path.Combine(steamEmu, "SmartSteamLoader.exe"); string emuIni = Path.Combine(steamEmu, "SmartSteamEmu.ini"); IniFile emu = new IniFile(emuIni); emu.IniWriteValue("Launcher", "Target", exePath); emu.IniWriteValue("Launcher", "StartIn", Path.GetDirectoryName(exePath)); emu.IniWriteValue("Launcher", "CommandLine", startArgs); emu.IniWriteValue("Launcher", "SteamClientPath", Path.Combine(steamEmu, "SmartSteamEmu.dll")); emu.IniWriteValue("Launcher", "SteamClientPath64", Path.Combine(steamEmu, "SmartSteamEmu64.dll")); emu.IniWriteValue("Launcher", "InjectDll", "0"); emu.IniWriteValue("SmartSteamEmu", "AppId", context.SteamID); if (context.KillMutex.Length > 0) { // to kill the mutexes we need to orphanize the process proc = ProcessUtil.RunOrphanProcess(emuExe); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = emuExe; proc = Process.Start(startInfo); } player.SteamEmu = true; } else { if (context.KillMutex.Length > 0) { proc = Process.GetProcessById(StartGameUtil.StartGame(exePath, startArgs)); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = exePath; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.Arguments = startArgs; startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Path.GetDirectoryName(exePath); proc = Process.Start(startInfo); } if (proc == null) { for (int times = 0; times < 200; times++) { Thread.Sleep(50); Process[] procs = Process.GetProcesses(); string proceName = Path.GetFileNameWithoutExtension(context.ExecutableName).ToLower(); string launcherName = Path.GetFileNameWithoutExtension(context.LauncherExe).ToLower(); for (int j = 0; j < procs.Length; j++) { Process p = procs[j]; string lowerP = p.ProcessName.ToLower(); if (((lowerP == proceName) || lowerP == launcherName) && !attached.Contains(p)) { attached.Add(p); proc = p; break; } } if (proc != null) { break; } } } else { attached.Add(proc); } } ProcessData data = new ProcessData(proc); data.Position = new Point(playerBounds.X, playerBounds.Y); data.Size = new Size(playerBounds.Width, playerBounds.Height); data.KilledMutexes = context.KillMutex.Length == 0; player.ProcessData = data; if (first) { if (context.HideTaskbar) { hidetaskbar = true; } } first = false; } //if (hidetaskbar) //{ // User32.HideTaskbar(); //} return(string.Empty); }
public string Play() { if (handlerData.ForceFinishOnPlay) { ProcessUtil.ForceKill(Path.GetFileNameWithoutExtension(handlerData.ExecutableName.ToLower())); } List <PlayerInfo> players = profile.PlayerData; for (int i = 0; i < players.Count; i++) { players[i].PlayerID = i; } UserScreen[] all = ScreensUtil.AllScreens(); string nucleusRootFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string tempDir = GameManager.Instance.GempTempFolder(handlerData); string exeFolder = Path.GetDirectoryName(userGame.ExePath).ToLower(); string rootFolder = exeFolder; string workingFolder = exeFolder; if (!string.IsNullOrEmpty(handlerData.BinariesFolder)) { rootFolder = StringUtil.ReplaceCaseInsensitive(exeFolder, handlerData.BinariesFolder.ToLower(), ""); } if (!string.IsNullOrEmpty(handlerData.WorkingFolder)) { workingFolder = Path.Combine(exeFolder, handlerData.WorkingFolder.ToLower()); } bool first = true; bool keyboard = false; //if (handlerData.SupportsKeyboard) //{ // // make sure the keyboard player is the last to be started, // // so it will get the focus by default // KeyboardPlayer player = (KeyboardPlayer)profile.Options["KeyboardPlayer"]; // if (player.Value != -1) // { // keyboard = true; // List<PlayerInfo> newPlayers = new List<PlayerInfo>(); // for (int i = 0; i < players.Count; i++) // { // PlayerInfo p = players[i]; // if (i == player.Value) // { // continue; // } // newPlayers.Add(p); // } // newPlayers.Add(players[player.Value]); // players = newPlayers; // } //} for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; ProcessInfo procData = player.ProcessData; bool hasSetted = procData != null && procData.Setted; if (i > 0 && (handlerData.KillMutex?.Length > 0 || !hasSetted)) { PlayerInfo before = players[i - 1]; for (; ;) { if (exited > 0) { return(""); } Thread.Sleep(1000); if (handlerData.KillMutex != null) { if (handlerData.KillMutex.Length > 0 && !before.ProcessData.KilledMutexes) { // check for the existence of the mutexes // before invoking our StartGame app to kill them ProcessInfo pdata = before.ProcessData; if (StartGameUtil.MutexExists(pdata.Process, handlerData.KillMutex)) { // mutexes still exist, must kill StartGameUtil.KillMutex(pdata.Process, handlerData.KillMutex); pdata.KilledMutexes = true; break; } else { // mutexes dont exist anymore break; } } } else { break; } } } Rectangle playerBounds = player.MonitorBounds; UserScreen owner = player.Owner; int width = playerBounds.Width; int height = playerBounds.Height; bool isFullscreen = owner.Type == UserScreenType.FullScreen; string exePath; string linkFolder; string linkBinFolder; if (handlerData.SymlinkGame || handlerData.HardcopyGame) { List <string> dirExclusions = new List <string>(); List <string> fileExclusions = new List <string>(); List <string> fileCopies = new List <string>(); // symlink the game folder (and not the bin folder, if we have one) linkFolder = Path.Combine(tempDir, "Instance" + i); Directory.CreateDirectory(linkFolder); linkBinFolder = linkFolder; if (!string.IsNullOrEmpty(handlerData.BinariesFolder)) { linkBinFolder = Path.Combine(linkFolder, handlerData.BinariesFolder); dirExclusions.Add(handlerData.BinariesFolder); } exePath = Path.Combine(linkBinFolder, Path.GetFileName(this.userGame.ExePath)); if (!string.IsNullOrEmpty(handlerData.WorkingFolder)) { linkBinFolder = Path.Combine(linkFolder, handlerData.WorkingFolder); dirExclusions.Add(handlerData.WorkingFolder); } // some games have save files inside their game folder, so we need to access them inside the loop jsData[Folder.InstancedGameFolder.ToString()] = linkFolder; if (handlerData.Hook.CustomDllEnabled) { fileExclusions.Add("xinput1_3.dll"); fileExclusions.Add("ncoop.ini"); } if (!handlerData.SymlinkExe) { fileCopies.Add(handlerData.ExecutableName.ToLower()); } // additional ignored files by the generic info if (handlerData.FileSymlinkExclusions != null) { string[] symlinkExclusions = handlerData.FileSymlinkExclusions; for (int k = 0; k < symlinkExclusions.Length; k++) { string s = symlinkExclusions[k]; // make sure it's lower case fileExclusions.Add(s.ToLower()); } } if (handlerData.FileSymlinkCopyInstead != null) { string[] fileSymlinkCopyInstead = handlerData.FileSymlinkCopyInstead; for (int k = 0; k < fileSymlinkCopyInstead.Length; k++) { string s = fileSymlinkCopyInstead[k]; // make sure it's lower case fileCopies.Add(s.ToLower()); } } if (handlerData.DirSymlinkExclusions != null) { string[] symlinkExclusions = handlerData.DirSymlinkExclusions; for (int k = 0; k < symlinkExclusions.Length; k++) { string s = symlinkExclusions[k]; // make sure it's lower case dirExclusions.Add(s.ToLower()); } } string[] fileExclusionsArr = fileExclusions.ToArray(); string[] fileCopiesArr = fileCopies.ToArray(); if (handlerData.HardcopyGame) { // copy the directory //int exitCode; //FileUtil.CopyDirectory(rootFolder, new DirectoryInfo(rootFolder), linkFolder, out exitCode, dirExclusions.ToArray(), fileExclusionsArr, true); } else { int exitCode; CmdUtil.LinkDirectory(rootFolder, new DirectoryInfo(rootFolder), linkFolder, out exitCode, dirExclusions.ToArray(), fileExclusionsArr, fileCopiesArr, true); if (!handlerData.SymlinkExe) { //File.Copy(userGame.ExePath, exePath, true); } } } else { exePath = userGame.ExePath; linkBinFolder = rootFolder; linkFolder = workingFolder; } HandlerContext context = handlerData.CreateContext(profile, player); context.PlayerID = player.PlayerID; context.IsFullscreen = isFullscreen; context.ExePath = exePath; context.RootInstallFolder = exeFolder; context.RootFolder = linkFolder; handlerData.PrePlay(context, player); string startArgs = context.StartArguments; if (context.Hook.CustomDllEnabled) { byte[] xdata = Properties.Resources.xinput1_3; if (context.Hook.XInputNames == null) { using (Stream str = File.OpenWrite(Path.Combine(linkBinFolder, "xinput1_3.dll"))) { str.Write(xdata, 0, xdata.Length); } } else { string[] xinputs = context.Hook.XInputNames; for (int z = 0; z < xinputs.Length; z++) { string xinputName = xinputs[z]; using (Stream str = File.OpenWrite(Path.Combine(linkBinFolder, xinputName))) { str.Write(xdata, 0, xdata.Length); } } } string ncoopIni = Path.Combine(linkBinFolder, "ncoop.ini"); using (Stream str = File.OpenWrite(ncoopIni)) { byte[] ini = Properties.Resources.ncoop; str.Write(ini, 0, ini.Length); } IniFile x360 = new IniFile(ncoopIni); x360.IniWriteValue("Options", "ForceFocus", handlerData.Hook.ForceFocus.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "ForceFocusWindowName", handlerData.Hook.ForceFocusWindowName.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "WindowX", playerBounds.X.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "WindowY", playerBounds.Y.ToString(CultureInfo.InvariantCulture)); if (context.Hook.SetWindowSize) { x360.IniWriteValue("Options", "ResWidth", context.Width.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "ResHeight", context.Height.ToString(CultureInfo.InvariantCulture)); } else { x360.IniWriteValue("Options", "ResWidth", "0"); x360.IniWriteValue("Options", "ResHeight", "0"); } x360.IniWriteValue("Options", "RerouteInput", context.Hook.XInputReroute.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "RerouteJoystickTemplate", JoystickDatabase.GetID(player.GamepadProductGuid.ToString()).ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "EnableMKBInput", player.IsKeyboardPlayer.ToString(CultureInfo.InvariantCulture)); // windows events x360.IniWriteValue("Options", "BlockInputEvents", context.Hook.BlockInputEvents.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "BlockMouseEvents", context.Hook.BlockMouseEvents.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "BlockKeyboardEvents", context.Hook.BlockKeyboardEvents.ToString(CultureInfo.InvariantCulture)); // xinput x360.IniWriteValue("Options", "XInputEnabled", context.Hook.XInputEnabled.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "XInputPlayerID", player.GamepadId.ToString(CultureInfo.InvariantCulture)); // dinput x360.IniWriteValue("Options", "DInputEnabled", context.Hook.DInputEnabled.ToString(CultureInfo.InvariantCulture)); x360.IniWriteValue("Options", "DInputGuid", player.GamepadGuid.ToString().ToUpper()); x360.IniWriteValue("Options", "DInputForceDisable", context.Hook.DInputForceDisable.ToString()); } Process proc; if (context.NeedsSteamEmulation) { string steamEmu = GameManager.Instance.ExtractSteamEmu(Path.Combine(linkFolder, "SmartSteamLoader")); //string steamEmu = GameManager.Instance.ExtractSteamEmu(); if (string.IsNullOrEmpty(steamEmu)) { return("Extraction of SmartSteamEmu failed!"); } string emuExe = Path.Combine(steamEmu, "SmartSteamLoader.exe"); string emuIni = Path.Combine(steamEmu, "SmartSteamEmu.ini"); IniFile emu = new IniFile(emuIni); emu.IniWriteValue("Launcher", "Target", exePath); emu.IniWriteValue("Launcher", "StartIn", Path.GetDirectoryName(exePath)); emu.IniWriteValue("Launcher", "CommandLine", startArgs); emu.IniWriteValue("Launcher", "SteamClientPath", Path.Combine(steamEmu, "SmartSteamEmu.dll")); emu.IniWriteValue("Launcher", "SteamClientPath64", Path.Combine(steamEmu, "SmartSteamEmu64.dll")); emu.IniWriteValue("Launcher", "InjectDll", "1"); emu.IniWriteValue("SmartSteamEmu", "AppId", context.SteamID); //emu.IniWriteValue("SmartSteamEmu", "SteamIdGeneration", "Static"); //string userName = $"Player { context.PlayerID }"; //emu.IniWriteValue("SmartSteamEmu", "PersonaName", userName); //emu.IniWriteValue("SmartSteamEmu", "ManualSteamId", userName); //emu.IniWriteValue("SmartSteamEmu", "Offline", "False"); //emu.IniWriteValue("SmartSteamEmu", "MasterServer", ""); //emu.IniWriteValue("SmartSteamEmu", "MasterServerGoldSrc", ""); handlerData.SetupSse?.Invoke(); if (context.KillMutex?.Length > 0) { // to kill the mutexes we need to orphanize the process proc = ProcessUtil.RunOrphanProcess(emuExe); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = emuExe; proc = Process.Start(startInfo); } player.SteamEmu = true; } else { if (context.KillMutex?.Length > 0) { proc = Process.GetProcessById(StartGameUtil.StartGame( new DirectoryInfo(exePath).GetRelativePath(nucleusRootFolder), startArgs, new DirectoryInfo(linkFolder).GetRelativePath(nucleusRootFolder))); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = exePath; //startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.Arguments = startArgs; startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Path.GetDirectoryName(exePath); proc = Process.Start(startInfo); } if (proc == null) { for (int times = 0; times < 200; times++) { Thread.Sleep(50); Process[] procs = Process.GetProcesses(); string proceName = Path.GetFileNameWithoutExtension(context.ExecutableName).ToLower(); string launcherName = Path.GetFileNameWithoutExtension(context.LauncherExe).ToLower(); for (int j = 0; j < procs.Length; j++) { Process p = procs[j]; string lowerP = p.ProcessName.ToLower(); if (((lowerP == proceName) || lowerP == launcherName) && !attached.Contains(p)) { attached.Add(p); proc = p; break; } } if (proc != null) { break; } } } else { attached.Add(proc); } } ProcessInfo data = new ProcessInfo(proc); data.Position = new Point(playerBounds.X, playerBounds.Y); data.Size = new Size(playerBounds.Width, playerBounds.Height); data.KilledMutexes = context.KillMutex?.Length == 0; player.ProcessData = data; first = false; Thread.Sleep(TimeSpan.FromSeconds(handlerData.PauseBetweenStarts)); } return(string.Empty); }
public string Play() { if (!SteamUtil.IsSteamRunning()) { return("Steam must be opened to play Left 4 Dead 2 splitScreen"); } using (Stream videoStream = new FileStream(videoFile, FileMode.Open)) { videoCfg = new SourceCfgFile(videoStream); } string originalCFG = String.Copy(videoCfg.RawData); // minimize everything User32.MinimizeEverything(); Screen[] allScreens = Screen.AllScreens; string folder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string l4dFolder = Path.GetDirectoryName(executablePlace); int gamePadId = 0; if (instances) { for (int i = 0; i < players.Count; i++) { PlayerInfo p = players[i]; Screen screen = allScreens[p.ScreenIndex]; int width = 0; int height = 0; Rectangle bounds = screen.Bounds; Point location = new Point(); ViewportUtil.GetPlayerViewport(p, 0, out width, out height, out location); CultureInfo c = CultureInfo.InvariantCulture; UpdateVideoCfg(width.ToString(c), height.ToString(c), "0", "1"); if (i == 0) { MakeAutoExecServer(); } else { MakeAutoExecClient(); } MakeMakeSplit(); string execPlace = executablePlace; string l4dBinFolder; if (i == 0) { l4dBinFolder = Path.Combine(l4dFolder, "bin"); } else { string l4d = Path.Combine(folder, "L4D2_" + (i + 1)); Directory.CreateDirectory(l4d); int exitCode; #region mklink CmdUtil.ExecuteCommand(l4d, out exitCode, "mklink /d \"" + Path.Combine(l4d, "config") + "\" \"" + Path.Combine(l4dFolder, "config") + "\"", "mklink /d \"" + Path.Combine(l4d, "hl2") + "\" \"" + Path.Combine(l4dFolder, "hl2") + "\"", "mklink /d \"" + Path.Combine(l4d, "left4dead2") + "\" \"" + Path.Combine(l4dFolder, "left4dead2") + "\"", "mklink /d \"" + Path.Combine(l4d, "left4dead2_dlc1") + "\" \"" + Path.Combine(l4dFolder, "left4dead2_dlc1") + "\"", "mklink /d \"" + Path.Combine(l4d, "left4dead2_dlc2") + "\" \"" + Path.Combine(l4dFolder, "left4dead2_dlc2") + "\"", "mklink /d \"" + Path.Combine(l4d, "left4dead2_dlc3") + "\" \"" + Path.Combine(l4dFolder, "left4dead2_dlc3") + "\"", "mklink /d \"" + Path.Combine(l4d, "platform") + "\" \"" + Path.Combine(l4dFolder, "platform") + "\"", "mklink /d \"" + Path.Combine(l4d, "RemStorage") + "\" \"" + Path.Combine(l4dFolder, "RemStorage") + "\"", "mklink /d \"" + Path.Combine(l4d, "update") + "\" \"" + Path.Combine(l4dFolder, "update") + "\""); #endregion // copy executable File.Copy(Path.Combine(l4dFolder, "left4dead2.exe"), Path.Combine(l4d, "left4dead2.exe"), true); // make bin folder now l4dBinFolder = Path.Combine(l4d, "bin"); string originalBinFolder = Path.Combine(l4dFolder, "bin"); Directory.CreateDirectory(l4dBinFolder); #region mklink CmdUtil.ExecuteCommand(l4d, out exitCode, "mklink /d \"" + Path.Combine(l4dBinFolder, "dedicated") + "\" \"" + Path.Combine(originalBinFolder, "dedicated") + "\"", "mklink /d \"" + Path.Combine(l4dBinFolder, "linux32") + "\" \"" + Path.Combine(originalBinFolder, "linux32") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "addoninstaller.exe") + "\" \"" + Path.Combine(originalBinFolder, "addoninstaller.exe") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "addoninstaller_osx") + "\" \"" + Path.Combine(originalBinFolder, "addoninstaller_osx") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "adminserver.dll") + "\" \"" + Path.Combine(originalBinFolder, "adminserver.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "binkw32.dll") + "\" \"" + Path.Combine(originalBinFolder, "binkw32.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "bsppack.dll") + "\" \"" + Path.Combine(originalBinFolder, "bsppack.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "bugreporter.dll") + "\" \"" + Path.Combine(originalBinFolder, "bugreporter.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "bugreporter_public.dll") + "\" \"" + Path.Combine(originalBinFolder, "bugreporter_public.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "chromehtml.dll") + "\" \"" + Path.Combine(originalBinFolder, "chromehtml.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "config.SoftTHconfig") + "\" \"" + Path.Combine(originalBinFolder, "config.SoftTHconfig") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "crashhandler.dll") + "\" \"" + Path.Combine(originalBinFolder, "crashhandler.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "datacache.dll") + "\" \"" + Path.Combine(originalBinFolder, "datacache.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "dxsupport.cfg") + "\" \"" + Path.Combine(originalBinFolder, "dxsupport.cfg") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "dxsupport_episodic.cfg") + "\" \"" + Path.Combine(originalBinFolder, "dxsupport_episodic.cfg") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "dxsupport_mac.cfg") + "\" \"" + Path.Combine(originalBinFolder, "dxsupport_mac.cfg") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "engine.dll") + "\" \"" + Path.Combine(originalBinFolder, "engine.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "export_entity_group.pl") + "\" \"" + Path.Combine(originalBinFolder, "export_entity_group.pl") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "export_entity_layer.pl") + "\" \"" + Path.Combine(originalBinFolder, "export_entity_layer.pl") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "filesystemopendialog.dll") + "\" \"" + Path.Combine(originalBinFolder, "filesystemopendialog.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "filesystem_stdio.dll") + "\" \"" + Path.Combine(originalBinFolder, "filesystem_stdio.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "GameOverlayRenderer.log") + "\" \"" + Path.Combine(originalBinFolder, "GameOverlayRenderer.log") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "gameui.dll") + "\" \"" + Path.Combine(originalBinFolder, "gameui.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "hl_ent.cnt") + "\" \"" + Path.Combine(originalBinFolder, "hl_ent.cnt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "icudt.dll") + "\" \"" + Path.Combine(originalBinFolder, "icudt.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "icudt42.dll") + "\" \"" + Path.Combine(originalBinFolder, "icudt42.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "inputsystem.dll") + "\" \"" + Path.Combine(originalBinFolder, "inputsystem.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "launcher.dll") + "\" \"" + Path.Combine(originalBinFolder, "launcher.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "libcef.dll") + "\" \"" + Path.Combine(originalBinFolder, "libcef.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "libmysql.dll") + "\" \"" + Path.Combine(originalBinFolder, "libmysql.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "maplist_terror.txt") + "\" \"" + Path.Combine(originalBinFolder, "maplist_terror.txt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "materialsystem.dll") + "\" \"" + Path.Combine(originalBinFolder, "materialsystem.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mdllib.dll") + "\" \"" + Path.Combine(originalBinFolder, "mdllib.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mss32.dll") + "\" \"" + Path.Combine(originalBinFolder, "mss32.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mssdolby.flt") + "\" \"" + Path.Combine(originalBinFolder, "mssdolby.flt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mssds3d.flt") + "\" \"" + Path.Combine(originalBinFolder, "mssds3d.flt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mssdsp.flt") + "\" \"" + Path.Combine(originalBinFolder, "mssdsp.flt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "msseax.flt") + "\" \"" + Path.Combine(originalBinFolder, "msseax.flt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "mssmp3.asi") + "\" \"" + Path.Combine(originalBinFolder, "mssmp3.asi") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "msssrs.flt") + "\" \"" + Path.Combine(originalBinFolder, "msssrs.flt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "msvcr71.dll") + "\" \"" + Path.Combine(originalBinFolder, "msvcr71.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "parsifal.dll") + "\" \"" + Path.Combine(originalBinFolder, "parsifal.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "rdmwin32.dll") + "\" \"" + Path.Combine(originalBinFolder, "rdmwin32.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "scenefilecache.dll") + "\" \"" + Path.Combine(originalBinFolder, "scenefilecache.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "serverbrowser.dll") + "\" \"" + Path.Combine(originalBinFolder, "serverbrowser.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "serverplugin_empty.dll") + "\" \"" + Path.Combine(originalBinFolder, "serverplugin_empty.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "shaderapidx10.dll") + "\" \"" + Path.Combine(originalBinFolder, "shaderapidx10.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "shaderapidx9.dll") + "\" \"" + Path.Combine(originalBinFolder, "shaderapidx9.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "shaderapiempty.dll") + "\" \"" + Path.Combine(originalBinFolder, "shaderapiempty.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "soundemittersystem.dll") + "\" \"" + Path.Combine(originalBinFolder, "soundemittersystem.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "soundsystem.dll") + "\" \"" + Path.Combine(originalBinFolder, "soundsystem.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "stats.bin") + "\" \"" + Path.Combine(originalBinFolder, "stats.bin") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "stdshader_dbg.dll") + "\" \"" + Path.Combine(originalBinFolder, "stdshader_dbg.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "stdshader_dx9.dll") + "\" \"" + Path.Combine(originalBinFolder, "stdshader_dx9.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "Steam.dll") + "\" \"" + Path.Combine(originalBinFolder, "Steam.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "steamclient.dll") + "\" \"" + Path.Combine(originalBinFolder, "steamclient.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "steamclient_l4d2.dll") + "\" \"" + Path.Combine(originalBinFolder, "steamclient_l4d2.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "steam_api.dll") + "\" \"" + Path.Combine(originalBinFolder, "steam_api.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "steam_appid.txt") + "\" \"" + Path.Combine(originalBinFolder, "steam_appid.txt") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "Steam_l4d2.dll") + "\" \"" + Path.Combine(originalBinFolder, "Steam_l4d2.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "studiorender.dll") + "\" \"" + Path.Combine(originalBinFolder, "studiorender.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "texturecompile_dll.dll") + "\" \"" + Path.Combine(originalBinFolder, "texturecompile_dll.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "tier0.dll") + "\" \"" + Path.Combine(originalBinFolder, "tier0.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "tier0_s.dll") + "\" \"" + Path.Combine(originalBinFolder, "tier0_s.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "unicode.dll") + "\" \"" + Path.Combine(originalBinFolder, "unicode.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "unicows.dll") + "\" \"" + Path.Combine(originalBinFolder, "unicows.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "unitlib.dll") + "\" \"" + Path.Combine(originalBinFolder, "unitlib.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "valve_avi.dll") + "\" \"" + Path.Combine(originalBinFolder, "valve_avi.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vaudio_miles.dll") + "\" \"" + Path.Combine(originalBinFolder, "vaudio_miles.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vaudio_speex.dll") + "\" \"" + Path.Combine(originalBinFolder, "vaudio_speex.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vgui2.dll") + "\" \"" + Path.Combine(originalBinFolder, "vgui2.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vguimatsurface.dll") + "\" \"" + Path.Combine(originalBinFolder, "vguimatsurface.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vidcfg.bin") + "\" \"" + Path.Combine(originalBinFolder, "vidcfg.bin") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vphysics.dll") + "\" \"" + Path.Combine(originalBinFolder, "vphysics.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vscript.dll") + "\" \"" + Path.Combine(originalBinFolder, "vscript.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vstdlib.dll") + "\" \"" + Path.Combine(originalBinFolder, "vstdlib.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vstdlib_s.dll") + "\" \"" + Path.Combine(originalBinFolder, "vstdlib_s.dll") + "\"", "mklink \"" + Path.Combine(l4dBinFolder, "vtex_dll.dll") + "\" \"" + Path.Combine(originalBinFolder, "vtex_dll.dll") + "\""); #endregion execPlace = Path.Combine(l4d, "left4dead2.exe"); } if ((int)keyboardId == i) { // delete if there are any xinput string xinputPath = Path.Combine(l4dBinFolder, "xinput1_3.dll"); if (File.Exists(xinputPath)) { File.Delete(xinputPath); } } else { // copy the correct xinput to the bin folder byte[] xdata = null; switch (gamePadId) { case 0: xdata = Nucleus.Coop.Games.GamesResources._1_xinput1_3; break; case 1: xdata = Nucleus.Coop.Games.GamesResources._2_xinput1_3; break; case 2: xdata = Nucleus.Coop.Games.GamesResources._3_xinput1_3; break; case 3: xdata = Nucleus.Coop.Games.GamesResources._4_xinput1_3; break; default: xdata = Nucleus.Coop.Games.GamesResources._4_xinput1_3; break; } string xinputPath = Path.Combine(l4dBinFolder, "xinput1_3.dll"); using (MemoryStream stream = new MemoryStream(xdata)) { // write to bin folder using (FileStream file = new FileStream(xinputPath, FileMode.Create)) { stream.CopyTo(file); } } gamePadId++; } int pid = StartGameUtil.StartGame(execPlace, "-novid -insecure", delayTime, "hl2_singleton_mutex", "steam_singleton_mutext"); Process proc = Process.GetProcessById(pid); HwndObject hwnd = new HwndObject(proc.Handle); ScreenData data = new ScreenData(); data.Position = location; data.HWND = hwnd; data.Size = new Size(width, height); p.Process = proc; p.Tag = data; Thread.Sleep(delayTime); //uint processHandle; //IntPtr windowHandle = proc.MainWindowHandle; //uint threadID = User32.GetWindowThreadProcessId(windowHandle, out processHandle); //bool installed = InstallHook(threadID); } } else { List <DuetPlayerInfo> duets = ViewportUtil.GetPlayerDuets(players); for (int i = 0; i < duets.Count; i++) { DuetPlayerInfo duet = duets[i]; } } int screenIndex = -1; bool twoScreens = false; int fullWidth = 0; int fullHeight = 0; for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; Screen scr = allScreens[player.ScreenIndex]; if (screenIndex == -1) { screenIndex = player.ScreenIndex; fullWidth = scr.Bounds.Width; fullHeight = scr.Bounds.Height; } else { if (screenIndex != player.ScreenIndex) { twoScreens = true; // Add 2nd monitor fullWidth += scr.Bounds.Width; } } } loaded = true; return(""); string fWidth = fullWidth.ToString(); string fHeight = fullHeight.ToString(); string fullScr = (0).ToString(); string noWindowBorderStr = (1).ToString(); //if (players.Count == 1) //{ // // 1 monitor // Screen monitor = allScreens[players.First().Key]; // fWidth = monitor.Bounds.Width.ToString(CultureInfo.InvariantCulture); // fHeight = monitor.Bounds.Height.ToString(CultureInfo.InvariantCulture); // fullScr = (0).ToString(); // noWindowBorderStr = (1).ToString(); //} //else //{ // // 2 or more monitors // //?? // fullScr = (1).ToString(); // noWindowBorderStr = (0).ToString(); //} fWidth = "1920";// 960x540 fHeight = "540"; string d3d9Path = binFolder + @"\d3d9.dll"; // SoftTH if (twoScreens) { // Copy SoftTH to the game folder // Get the SoftTH stream if (!File.Exists(d3d9Path)) { using (MemoryStream stream = new MemoryStream(Nucleus.Coop.Games.GamesResources.d3d9)) { // write to bin folder using (FileStream file = new FileStream(d3d9Path, FileMode.Create)) { stream.CopyTo(file); } } } } else { // Delete SoftTH from the game folder FileInfo file = new FileInfo(d3d9Path); // Only delete if it's not read only if (File.Exists(d3d9Path)) { File.Delete(d3d9Path); } } // PAK hex edit if (twoScreens) { FileInfo f = new FileInfo(pak01_000_path); if (!f.IsReadOnly) { // make a backup of pak01_000, if it isn't already made string dir = Path.GetDirectoryName(backupPak); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (!File.Exists(backupPak)) { File.Copy(pak01_000_path, backupPak); } using (FileStream str = File.OpenRead(backupPak)) { // Now modify some stuff // Eat Point that comes at 29.664.480 // The 8 is at position 29.664.483 // 29.675.904 byte one = 49; byte six = 54; using (FileStream stream = new FileStream(pak01_000_path, FileMode.Create)) { byte[] buff = new byte[4096]; int point = 29664480; while (str.Position < point) { int length = 4096; if (point - str.Position < length) { length = (int)(point - str.Position); } str.Read(buff, 0, length); stream.Write(buff, 0, length); } // Jumps 1 byte str.Position += 1; str.Read(buff, 0, 2); stream.Write(buff, 0, 2); // Jumps the 8 str.Position += 1; buff[0] = one; buff[1] = six; stream.Write(buff, 0, 2); while (stream.Position < str.Length) { int length = 4096; if (str.Length - str.Position < length) { length = (int)(str.Length - str.Position); } str.Read(buff, 0, length); stream.Write(buff, 0, length); } } } f.IsReadOnly = true; } } //else //{ // if (File.Exists(backupPak)) // { // if (File.Exists(pak01_000)) // { // FileInfo f = new FileInfo(pak01_000); // f.IsReadOnly = false; // File.Delete(pak01_000); // } // File.Copy(backupPak, pak01_000); // } //} int splitMode = 1; for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; if (player.ScreenType == ScreenType.HorizontalBottom || player.ScreenType == ScreenType.HorizontalTop) { splitMode = 1; } else { splitMode = 2; } } MakeAutoExecSplitscreen(splitMode.ToString(CultureInfo.InvariantCulture)); MakeMakeSplit(); /* if (player.ScreenType == ScreenType.VerticalLeft || * player.ScreenType == ScreenType.VerticalRight)*/ //ss_splitmode 1 = horizontal //ss_splitmode 2 = vertical //ProcessStartInfo startInfo = new ProcessStartInfo(); //startInfo.FileName = executablePlace; //startInfo.WindowStyle = ProcessWindowStyle.Hidden; //MessageBox.Show("Press the F8 key after the game is loaded to begin splitscreen!"); //proc = Process.Start(startInfo); return(string.Empty); }
public RequestResult <string> Play() { List <PlayerInfo> players = profile.PlayerData; for (int i = 0; i < players.Count; i++) { players[i].PlayerID = i; } RequestResult <String> result = new RequestResult <String>(); List <HandlerContext> contexts = new List <HandlerContext>(); for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; HandlerContext context = handlerManager.HandlerData.CreateContext(profile, player, hasKeyboardPlayer); contexts.Add(context); context.PlayerID = player.PlayerID; List <HandlerModule> modules = player.Modules; for (int j = 0; j < modules.Count; j++) { modules[j].PrePlayPlayer(i, context); } } // get all the SymlinkData from each players IOModule // and start the StartGame application to symlink them List <SymlinkGameData> symData = new List <SymlinkGameData>(); for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; IOModule mod = GetModule <IOModule>(player); SymlinkGameData data = mod.SymlinkData; symData.Add(data); } StartGameData symStartData = StartGameUtil.BuildSymlinkGameData(symData.ToArray()); // check if we need to kill mutexes bool killingMutexes = false; if (handlerManager.HandlerData.KillMutex?.Length > 0) { // need to also kill mutexes killingMutexes = true; StartGameData scanKillData = StartGameUtil.BuildScanKillMutexData(Path.GetFileNameWithoutExtension(userGame.ExePath), players.Count, handlerManager.HandlerData.KillMutex); StartGameUtil.RunMultipleTasks(new StartGameData[] { symStartData, scanKillData }, true); // wait for confirmation file that the folders were symlinked // (RunMultipleTasks doesnt wait for process to finish) string dataFile = StartGameUtil.GetStartDataPath(); for (; ;) { if (File.Exists(dataFile)) { try { string txt = File.ReadAllText(dataFile); bool res; if (bool.TryParse(txt, out res)) { break; } } catch { } } Thread.Sleep(250); } File.Delete(dataFile); } else { // just symlink the folders StartGameUtil.RunPreBuiltData(symStartData, true); } for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; HandlerContext context = contexts[i]; handlerManager.Play(context, player); List <HandlerModule> modules = player.Modules; for (int j = 0; j < modules.Count; j++) { modules[j].PlayPlayer(i, context); } Thread.Sleep(TimeSpan.FromMilliseconds(handlerManager.HandlerData.PauseBetweenStarts)); IGameProcessModule procModule = GetModule <IGameProcessModule>(player); if (handlerManager.HandlerData.WaitFullWindowLoad) { for (; ;) { Thread.Sleep(100); // check for window status if (procModule.HasWindowSetup(player)) { break; } } } if (killingMutexes) { // wait for StartGame confirmation that mutexes were killed string dataFile = StartGameUtil.GetStartDataPath(); for (; ;) { if (File.Exists(dataFile)) { try { string txt = File.ReadAllText(dataFile); bool res; if (bool.TryParse(txt, out res)) { break; } } catch { } } Thread.Sleep(250); } File.Delete(dataFile); } } return(result); }
public override void PlayPlayer(int index, HandlerContext context) { Process proc; IOModule ioModule = handler.GetModule <IOModule>(Player); string startArgs = context.StartArguments; string startingApp = ioModule.LinkedExePath; if (!string.IsNullOrEmpty(context.OverrideStartProcess)) { startingApp = context.OverrideStartProcess; } if (context.KillMutex?.Length > 0) { int processId = StartGameUtil.StartGame(startingApp, startArgs, ioModule.LinkedWorkingDir); proc = Process.GetProcessById(processId); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = startingApp; startInfo.Arguments = startArgs; startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Path.GetDirectoryName(ioModule.LinkedExePath); proc = Process.Start(startInfo); } if (proc == null) { for (int times = 0; times < 200; times++) { Thread.Sleep(50); Process[] procs = Process.GetProcesses(); string proceName = Path.GetFileNameWithoutExtension(context.ExecutableName).ToLower(); string launcherName = string.IsNullOrEmpty(context.LauncherExe) ? string.Empty : Path.GetFileNameWithoutExtension(context.LauncherExe).ToLower(); for (int j = 0; j < procs.Length; j++) { Process p = procs[j]; string lowerP = p.ProcessName.ToLower(); if (((lowerP == proceName) || lowerP == launcherName) && !attached.Contains(p)) { attached.Add(p); proc = p; break; } } if (proc != null) { break; } } } else { attached.Add(proc); } ProcessInfo data = new ProcessInfo(proc); Rectangle playerBounds = Player.MonitorBounds; UserScreen owner = Player.Owner; int width = playerBounds.Width; int height = playerBounds.Height; data.Position = new Point(playerBounds.X, playerBounds.Y); data.Size = new Size(playerBounds.Width, playerBounds.Height); data.KilledMutexes = context.KillMutex?.Length == 0; Player.ProcessData = data; }
private static void ExecuteTask(StartGameData data) { switch (data.Task) { case GameStarterTask.StartGame: { string gamePath = data.Parameters[0]; string gameArgs = data.Parameters[1]; string gameWorkingDir = data.Parameters[2]; ConsoleU.WriteLine($"Start game: EXE: {gamePath} ARGS: {gameArgs} WORKDIR: {gameWorkingDir}", Palette.Feedback); StartGame(gamePath, gameArgs, gameWorkingDir); } break; case GameStarterTask.KillMutex: { Log.WriteLine($"Kill Mutex Task"); string procId = data.Parameters[0]; string[] mutexes = new string[data.Parameters.Length - 1]; for (int j = 1; j < data.Parameters.Length; j++) { string m = data.Parameters[j]; mutexes[j - 1] = m; } KillMutex(procId, mutexes); WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString()); } break; case GameStarterTask.RenameMutex: { Log.WriteLine($"Rename Mutex Task"); string procId = data.Parameters[0]; string[] mutexes = new string[data.Parameters.Length - 1]; for (int j = 1; j < data.Parameters.Length; j++) { string m = data.Parameters[j]; mutexes[j - 1] = m; } KillMutex(procId, mutexes); WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString()); } break; case GameStarterTask.ScanKillMutex: { Log.WriteLine($"Scan Kill Mutex"); List <int> processIds = new List <int>(); for (int j = 0; j < data.Parameters.Length; j++) { string scanMutexDataRaw = data.Parameters[j]; ScanMutexData scanMutex = JsonConvert.DeserializeObject <ScanMutexData>(scanMutexDataRaw); Log.WriteLine($"Kill Mutex for process {scanMutex.ProcessName}"); for (; ;) { Process[] procs = Process.GetProcessesByName(scanMutex.ProcessName); if (procs == null || procs.Length == 0) { Thread.Sleep(250); } else { // kill mutexes bool killedMutexes = false; for (int k = 0; k < procs.Length; k++) { Process p = procs[k]; if (processIds.Contains(p.Id)) { continue; } // start other process, as the mutexes are only truly killed // when the process is ended if (scanMutex.ShouldRename) { StartGameUtil.RenameMutex(p, scanMutex.Mutexes); } else { StartGameUtil.KillMutex(p, scanMutex.Mutexes); } //KillMutex(p.Id.ToString(), scanMutex.Mutexes); processIds.Add(p.Id); killedMutexes = true; break; } if (killedMutexes) { Log.WriteLine($"Killed all mutexes for process {scanMutex.ProcessName}"); WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString()); break; } } } } } break; case GameStarterTask.MultipleTasks: { Log.WriteLine($"Multiple tasks"); for (int j = 0; j < data.Parameters.Length; j++) { string taskDataRaw = data.Parameters[j]; StartGameData taskData = JsonConvert.DeserializeObject <StartGameData>(taskDataRaw); Log.WriteLine($"Executing task {j + 1}"); ExecuteTask(taskData); } } break; case GameStarterTask.QueryMutex: { string procId = data.Parameters[0]; string[] mutexes = new string[data.Parameters.Length - 1]; for (int j = 1; j < data.Parameters.Length; j++) { string m = data.Parameters[j]; mutexes[j - 1] = m; } } break; case GameStarterTask.ListMonitors: break; case GameStarterTask.ScanGames: { // initialize game manager to read available handlers GameManager gameManager = new GameManager(); List <string> games = new List <string>(); for (int j = 0; j < data.Parameters.Length; j++) { string driveName = data.Parameters[j]; //SearchStorageInfo info = JsonConvert.DeserializeObject<SearchStorageInfo>(storageData); DriveInfo drive = new DriveInfo(driveName); if (!drive.IsReady) { continue; } Log.WriteLine($"> Searching drive {drive.Name} for game executables"); Dictionary <ulong, FileNameAndParentFrn> allExes = new Dictionary <ulong, FileNameAndParentFrn>(); MFTReader mft = new MFTReader(); mft.Drive = drive.RootDirectory.FullName; // TODO: search only for specific games? mft.EnumerateVolume(out allExes, new string[] { ".exe" }); foreach (KeyValuePair <UInt64, FileNameAndParentFrn> entry in allExes) { FileNameAndParentFrn file = (FileNameAndParentFrn)entry.Value; string name = file.Name; string lower = name.ToLower(); string path = mft.GetFullPath(file); if (path.Contains("$Recycle.Bin") || path.Contains(@"\Instance")) { // noope continue; } if (GameManager.Instance.AnyGame(lower)) { Log.WriteLine($"Found game at path: {path}"); games.Add(path); } } } WriteToDataFile(Assembly.GetEntryAssembly().Location, JsonConvert.SerializeObject(games)); } break; case GameStarterTask.SymlinkFolders: for (int j = 0; j < data.Parameters.Length; j++) { string symData = data.Parameters[j]; Log.WriteLine($"Symlink game instance {j + 1}"); SymlinkGameData gameData = JsonConvert.DeserializeObject <SymlinkGameData>(symData); int exitCode; WinDirectoryUtil.LinkDirectory(gameData.SourcePath, new DirectoryInfo(gameData.SourcePath), gameData.DestinationPath, out exitCode, gameData.DirExclusions, gameData.FileExclusions, gameData.FileCopies, true); } WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString()); break; } }
public string Play() { if (!SteamUtil.IsSteamRunning()) { return("Steam must be opened to play Left 4 Dead splitscreen"); } using (Stream videoStream = new FileStream(videoFile, FileMode.Open)) { videoCfg = new SourceCfgFile(videoStream); } string originalCFG = String.Copy(videoCfg.RawData); // minimize everything User32.MinimizeEverything(); Screen[] allScreens = Screen.AllScreens; string folder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string l4dFolder = Path.GetDirectoryName(executablePlace); int gamePadId = 0; if (instances) { for (int i = 0; i < players.Count; i++) { PlayerInfo p = players[i]; Screen screen = allScreens[p.ScreenIndex]; int width = 0; int height = 0; Rectangle bounds = screen.Bounds; Point location = new Point(); ViewportUtil.GetPlayerViewport(p, 0, out width, out height, out location); CultureInfo c = CultureInfo.InvariantCulture; UpdateVideoCfg(width.ToString(c), height.ToString(c), "0", "1"); if (i == 0) { MakeAutoExecServer(); } else { MakeAutoExecClient(); } MakeMakeSplit(); string execPlace = executablePlace; string l4dBinFolder = Path.Combine(l4dFolder, "bin"); if (i != 0) { string l4d = Path.Combine(folder, "L4D_" + (i + 1)); Directory.CreateDirectory(l4d); FolderUtil.MkLink(l4dFolder, l4d, "bin", "left4dead.exe"); // copy executable execPlace = Path.Combine(l4d, "left4dead.exe"); File.Copy(Path.Combine(l4dFolder, "left4dead.exe"), execPlace, true); // make bin folder now l4dBinFolder = Path.Combine(l4d, "bin"); string originalBinFolder = Path.Combine(l4dFolder, "bin"); Directory.CreateDirectory(l4dBinFolder); FolderUtil.MkLink(originalBinFolder, l4dBinFolder, "xinput1_3.dll"); // add exec to firewall FirewallUtil.AuthorizeProgram("Left 4 Dead", execPlace); } // copy the correct xinput to the bin folder byte[] xdata = null; if (firstKeyboard) { switch (gamePadId) { case 0: xdata = GamesResources._4_xinput1_3; break; case 1: xdata = GamesResources._1_xinput1_3; break; case 2: xdata = GamesResources._2_xinput1_3; break; case 3: xdata = GamesResources._3_xinput1_3; break; } } else { switch (gamePadId) { case 0: xdata = GamesResources._1_xinput1_3; break; case 1: xdata = GamesResources._2_xinput1_3; break; case 2: xdata = GamesResources._3_xinput1_3; break; case 3: xdata = GamesResources._4_xinput1_3; break; } } string xinputPath = Path.Combine(l4dBinFolder, "xinput1_3.dll"); using (MemoryStream stream = new MemoryStream(xdata)) { // write to bin folder using (FileStream file = new FileStream(xinputPath, FileMode.Create)) { stream.WriteTo(file); } } gamePadId++; int pid = StartGameUtil.StartGame(execPlace, "-novid -insecure", delayTime, "hl2_singleton_mutex", "steam_singleton_mutext"); Process proc = Process.GetProcessById(pid); HwndObject hwnd = new HwndObject(proc.Handle); ScreenData data = new ScreenData(); data.Position = location; data.HWND = hwnd; data.Size = new Size(width, height); p.Process = proc; p.Tag = data; Thread.Sleep(delayTime); } loaded = true; } else { int screenIndex = -1; int fullWidth = 0; int fullHeight = 0; for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; Screen scr = allScreens[player.ScreenIndex]; if (screenIndex == -1) { screenIndex = player.ScreenIndex; fullWidth = scr.Bounds.Width; fullHeight = scr.Bounds.Height; } else { if (screenIndex != player.ScreenIndex) { //twoScreens = true; // Add 2nd monitor fullWidth += scr.Bounds.Width; } } } loaded = true; string fWidth = fullWidth.ToString(); string fHeight = fullHeight.ToString(); string fullScr = (0).ToString(); string noWindowBorderStr = (1).ToString(); int splitMode = 1; for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; if (player.ScreenType == ScreenType.HorizontalBottom || player.ScreenType == ScreenType.HorizontalTop) { splitMode = 1; } else { splitMode = 2; } } MakeAutoExecSplitscreen(splitMode.ToString(CultureInfo.InvariantCulture)); MakeMakeSplit(); StartGameUtil.StartGame(executablePlace, "-novid -insecure", delayTime, "hl2_singleton_mutex", "steam_singleton_mutext"); } return(string.Empty); }
public void Update(int delayMS) { if (profile == null) { return; } exited = 0; List <PlayerInfo> players = profile.PlayerData; timer += delayMS; for (int i = 0; i < players.Count; i++) { PlayerInfo p = players[i]; if (p.screenData == null || p.Process == null) { continue; } if (p.SteamEmu) { List <int> children = ProcessUtil.GetChildrenProcesses(p.Process); if (children.Count > 0) { for (int j = 0; j < children.Count; j++) { int id = children[j]; Process child = Process.GetProcessById(id); try { if (child.ProcessName.Contains("conhost")) { continue; } } catch { continue; } p.Process = child; p.SteamEmu = child.ProcessName.Contains("SmartSteamLoader") || child.ProcessName.Contains("cmd"); } } } else { ScreenData data = p.screenData; if (data.Set) { if (p.Process.HasExited) { exited++; continue; } if (!p.screenData.KilledMutexes && gen.KillMutex.Length > 0) { StartGameUtil.KillMutex(p.Process, gen.KillMutex); p.screenData.KilledMutexes = true; } uint lStyle = User32Interop.GetWindowLong(data.HWND.Hwnd, User32_WS.GWL_STYLE); if (lStyle != data.RegLong) { uint toRemove = User32_WS.WS_CAPTION; lStyle = lStyle & (~toRemove); User32Interop.SetWindowLong(data.HWND.Hwnd, User32_WS.GWL_STYLE, lStyle); data.RegLong = lStyle; data.HWND.Location = data.Position; } } else { p.Process.Refresh(); if (p.Process.HasExited) { if (p.GotLauncher) { if (p.GotGame) { exited++; } else { List <int> children = ProcessUtil.GetChildrenProcesses(p.Process); if (children.Count > 0) { for (int j = 0; j < children.Count; j++) { int id = children[j]; Process pro = Process.GetProcessById(id); if (!attached.Contains(pro)) { attached.Add(pro); data.HWND = null; p.GotGame = true; p.Process = pro; } } } } } else { // Steam showing a launcher, need to find our game process string launcher = gen.LauncherExe; if (launcher.ToLower().EndsWith(".exe")) { launcher = launcher.Remove(launcher.Length - 4, 4); } Process[] procs = Process.GetProcessesByName(launcher); for (int j = 0; j < procs.Length; j++) { Process pro = procs[j]; if (!attached.Contains(pro)) { attached.Add(pro); p.Process = pro; p.GotLauncher = true; } } } } else { if (data.HWNDRetry || data.HWND == null || data.HWND.Hwnd != p.Process.MainWindowHandle) { data.HWND = new HwndObject(p.Process.MainWindowHandle); Point pos = data.HWND.Location; if (String.IsNullOrEmpty(data.HWND.Title) || pos.X == -32000 || data.HWND.Title.ToLower() == gen.LauncherTitle.ToLower()) { data.HWNDRetry = true; } else { Size s = data.Size; data.Set = true; data.HWND.TopMost = true; data.HWND.Size = data.Size; data.HWND.Location = data.Position; } } } } } if (exited == players.Count) { if (!hasEnded) { hasEnded = true; GameManager.Instance.ExecuteBackup(this.userGame.Game); if (Ended != null) { Ended(); } } } } }
public string Play() { List <PlayerInfo> players = profile.PlayerData; Screen[] all = Screen.AllScreens; string backupDir = GameManager.Instance.GetBackupFolder(this.userGame.Game); string binFolder = Path.GetDirectoryName(userGame.ExePath); string rootFolder = ReplaceCaseInsensitive(binFolder, gen.BinariesFolder, ""); int gamePadId = 0; for (int i = 0; i < players.Count; i++) { PlayerInfo player = players[i]; if (i > 0 && gen.KillMutex.Length > 0) { PlayerInfo before = players[i - 1]; for (;;) { if (exited > 0) { return(""); } Thread.Sleep(100); if (before.screenData.KilledMutexes) { break; } } } Rectangle playerBounds = player.monitorBounds; // find the monitor that has this screen Screen owner = null; for (int j = 0; j < all.Length; j++) { Screen s = all[j]; if (s.Bounds.Contains(playerBounds)) { owner = s; break; } } int width = playerBounds.Width; int height = playerBounds.Height; bool isFullscreen = false; if (owner != null) { Rectangle ob = owner.Bounds; if (playerBounds.X == ob.X && playerBounds.Y == ob.Y && playerBounds.Width == ob.Width && playerBounds.Height == ob.Height) { isFullscreen = true; } } engine.SetValue("Id", i.ToString(CultureInfo.InvariantCulture)); engine.SetValue("Width", width.ToString(CultureInfo.InvariantCulture)); engine.SetValue("Height", height.ToString(CultureInfo.InvariantCulture)); engine.SetValue("IsFullscreen", isFullscreen); // symlink the game folder // find out the folder that contains the game executable string root = GetRootFolder(gen.BinariesFolder); string linkFolder = Path.Combine(backupDir, "Instance" + i); Directory.CreateDirectory(linkFolder); int exitCode; CmdUtil.LinkDirectories(rootFolder, linkFolder, out exitCode, root.ToLower()); string linkBin = Path.Combine(linkFolder, gen.BinariesFolder); if (!string.IsNullOrEmpty(gen.BinariesFolder)) { // this needs fixing, if there are several folder to the exe and they have important files inside, this won't work! TODO Directory.CreateDirectory(linkBin); CmdUtil.LinkDirectories(binFolder, linkBin, out exitCode); } string exePath = Path.Combine(linkBin, this.userGame.Game.ExecutableName); if (gen.SymlinkExe) { CmdUtil.LinkFiles(binFolder, linkBin, out exitCode, "xinput"); } else { CmdUtil.LinkFiles(binFolder, linkBin, out exitCode, "xinput", Path.GetFileNameWithoutExtension(gen.ExecutableName.ToLower())); File.Copy(userGame.ExePath, exePath, true); } // some games have save files inside their game folder, so we need to access them inside the loop this.data[NucleusFolderEnum.GameFolder.ToString()] = linkFolder; string saveFile = ProcessPath(gen.SavePath); IniFile file = new IniFile(saveFile); switch (gen.SaveType) { case GenericGameSaveType.INI: foreach (var modPair in gen.ModifySave) { string key = modPair.Key; string[] keys = key.Split('/'); engine.Execute(modPair.Value); string val = engine.GetCompletionValue().ToString(); file.IniWriteValue(keys[0], keys[1], val); } break; } string startArgs = gen.StartArguments; byte[] xdata = null; if (gen.SupportsKeyboard && i == (int)profile.Options["KeyboardPlayer"]) { engine.SetValue("Keyboard", true); // need to make an xinput that answers to no gamepad? xdata = Properties.Resources.xinput4; } else { engine.SetValue("Keyboard", false); switch (gamePadId) { case 0: xdata = Properties.Resources.xinput1; break; case 1: xdata = Properties.Resources.xinput2; break; case 2: xdata = Properties.Resources.xinput3; break; case 3: xdata = Properties.Resources.xinput4; break; default: xdata = Properties.Resources.xinput4; break; } gamePadId++; } using (Stream str = File.OpenWrite(Path.Combine(linkBin, "xinput1_3.dll"))) { str.Write(xdata, 0, xdata.Length); } if (!string.IsNullOrEmpty(startArgs)) { startArgs = engine.Execute(startArgs).GetCompletionValue().AsString(); } if (gen.NeedsSteamEmulation) { string steamEmu = GameManager.Instance.ExtractSteamEmu(); string emuExe = Path.Combine(steamEmu, "SmartSteamLoader.exe"); string emuIni = Path.Combine(steamEmu, "SmartSteamEmu.ini"); IniFile emu = new IniFile(emuIni); emu.IniWriteValue("Launcher", "Target", exePath); emu.IniWriteValue("Launcher", "StartIn", Path.GetDirectoryName(exePath)); emu.IniWriteValue("Launcher", "CommandLine", startArgs); emu.IniWriteValue("Launcher", "SteamClientPath", Path.Combine(steamEmu, "SmartSteamEmu.dll")); emu.IniWriteValue("Launcher", "SteamClientPath64", Path.Combine(steamEmu, "SmartSteamEmu64.dll")); emu.IniWriteValue("Launcher", "InjectDll", "0"); emu.IniWriteValue("SmartSteamEmu", "AppId", gen.SteamID); Process proc; if (gen.KillMutex.Length > 0) { // to kill the mutexes we need to orphanize the process proc = ProcessUtil.RunOrphanProcess(emuExe); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = emuExe; proc = Process.Start(startInfo); } player.Process = proc; player.SteamEmu = true; } else { Process proc; if (gen.KillMutex.Length > 0) { proc = Process.GetProcessById(StartGameUtil.StartGame(exePath, startArgs)); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = exePath; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.Arguments = startArgs; startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Path.GetDirectoryName(exePath); proc = Process.Start(startInfo); } if (proc == null) { for (int times = 0; times < 200; times++) { Thread.Sleep(50); Process[] procs = Process.GetProcesses(); string proceName = Path.GetFileNameWithoutExtension(gen.ExecutableName).ToLower(); string launcherName = Path.GetFileNameWithoutExtension(gen.LauncherExe).ToLower(); for (int j = 0; j < procs.Length; j++) { Process p = procs[j]; string lowerP = p.ProcessName.ToLower(); if (((lowerP == proceName) || lowerP == launcherName) && !attached.Contains(p)) { attached.Add(p); proc = p; break; } } if (proc != null) { break; } } } else { attached.Add(proc); } player.Process = proc; } ScreenData data = new ScreenData(); data.Position = new Point(playerBounds.X, playerBounds.Y); data.Size = new Size(playerBounds.Width, playerBounds.Height); data.KilledMutexes = gen.KillMutex.Length == 0; player.screenData = data; } return(string.Empty); }
public override void PlayPlayer(PlayerInfo playerInfo, int index, HandlerContext context) { Process proc; IOModule ioModule = handler.GetModule <IOModule>(); string startArgs = context.StartArguments; if (context.KillMutex?.Length > 0) { //DirectoryInfo exeFolderDir = new DirectoryInfo(Path.GetDirectoryName(ioModule.ExePath)); //DirectoryInfo linkedFolderDir = new DirectoryInfo(ioModule.LinkedFolder); //string exePath = Path.Combine(exeFolderDir.GetRelativePath(ioModule.NucleusRootFolder), Path.GetFileName(ioModule.ExePath)); //string exeRoot = linkedFolderDir.GetRelativePath(ioModule.NucleusRootFolder); proc = Process.GetProcessById(StartGameUtil.StartGame(ioModule.ExePath, startArgs, ioModule.WorkingFolder)); } else { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = ioModule.ExePath; //startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.Arguments = startArgs; startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Path.GetDirectoryName(ioModule.ExePath); proc = Process.Start(startInfo); } if (proc == null) { for (int times = 0; times < 200; times++) { Thread.Sleep(50); Process[] procs = Process.GetProcesses(); string proceName = Path.GetFileNameWithoutExtension(context.ExecutableName).ToLower(); string launcherName = Path.GetFileNameWithoutExtension(context.LauncherExe).ToLower(); for (int j = 0; j < procs.Length; j++) { Process p = procs[j]; string lowerP = p.ProcessName.ToLower(); if (((lowerP == proceName) || lowerP == launcherName) && !attached.Contains(p)) { attached.Add(p); proc = p; break; } } if (proc != null) { break; } } } else { attached.Add(proc); } ProcessInfo data = new ProcessInfo(proc); Rectangle playerBounds = playerInfo.MonitorBounds; UserScreen owner = playerInfo.Owner; int width = playerBounds.Width; int height = playerBounds.Height; bool isFullscreen = owner.Type == UserScreenType.FullScreen; data.Position = new Point(playerBounds.X, playerBounds.Y); data.Size = new Size(playerBounds.Width, playerBounds.Height); data.KilledMutexes = context.KillMutex?.Length == 0; playerInfo.ProcessData = data; }