Skip to content
Beta: this is a preview of the new SplitScreen.Me. Data may be reset before launch.

Final Fantasy XIV Online · handler “Final Fantasy XIV - A Realm Reborn”

Version 3

Release notes

added document config path and fixed a mutex problem.

Released
Size
8.7 MB
Downloads
76
Check
Verified
SHA-256
4590ae38675172207f486b479d4f81e5aae5ac0d08607d12f69947ae0f798bb3
Download v3 (.nc)All versions

Files 5

PathSize
handler/d3d11.ini6.4 KB
handler/FFXIV.cfg4.8 KB
handler/osd.ini4.6 KB
handler/SpecialK64.dll15.5 MB
handler.js17 KB

handler.js

Plain text
Hub.Handler.Version = 3; // Released at https://hub.splitscreen.me/ on Mon Apr 25 2022 00:57:28 GMT+0000 (Coordinated Universal Time).
Hub.Handler.Id = "QsaJgmhmanM7YCRMD";
Hub.Maintainer.Name = "Perserveruz";
Hub.Maintainer.Id = "nFAYvHKj75jAFRAgt";

Game.MutexProcessExe = "ffxiv_dx11.exe";
Game.KillMutexType = "Mutant";
Game.KillMutexProcess = ["ffxiv_game_common", "ffxiv_game00"];
Game.PartialMutexSearchProcess = true;
var answers = ["No", "Yes"];
var answers1 = ["Yes", "No"];
Game.AddOption("First time login/setup?", "Enable process prompts", "log", answers);
Game.AddOption("Enable background music only in the first instance?", "", "Music", answers1);
Game.FileSymlinkExclusions = ["XInputPlus.ini", "xinput1_4.dll", "d3d11.dll", "d3d11.ini"];
Game.FileSymlinkCopyInstead = ["steam_api.dll", "steam_api64.dll"];
Game.DirSymlinkCopyInstead = ["boot"];
Game.HandlerInterval = 100;
Game.SymlinkExe = false;
Game.SymlinkGame = true;
Game.SymlinkFolders = false;
Game.KeepSymLinkOnExit = true;
Game.UseNucleusEnvironment = true;
Game.SupportsKeyboard = true;
Game.ExecutableName = "ffxiv_dx11.exe";
Game.LauncherExe = "XIVLauncher.exe";
Game.BinariesFolder = "game";
Game.SteamID = "39210";
Game.GUID = "Final Fantasy XIV";
Game.GameName = "Final Fantasy XIV";
Game.MaxPlayersOneMonitor = 4;
Game.MaxPlayers = 4;
Game.Hook.ForceFocus = true;
Game.Hook.ForceFocusWindowName = "FINAL FANTASY XIV";
Game.HookFocus = false;
Game.FakeFocus = false;
Game.Hook.DInputEnabled = false;
Game.Hook.DInputForceDisable = true;
Game.Hook.XInputEnabled = true;
Game.Hook.XInputReroute = false;
Game.Hook.CustomDllEnabled = false;
Game.Hook.UseAlpha8CustomDll = false;
Game.XInputPlusDll = ["xinput1_4.dll"];
Game.InjectHookXinput = true;
Game.PauseBetweenStarts = 15;
Game.PromptBetweenInstances = false;
Game.PauseBetweenProcessGrab = 15;
Game.DontRemoveBorders = true;
Game.DontResize = true;
Game.ResetWindows = true;
Game.DocumentsConfigPath = "My Games\\FINAL FANTASY XIV - A Realm Reborn";
Game.Description = "Please refer to the handler description for details on how to get FFXIV working in split screen";

Game.SupportsMultipleKeyboardsAndMice = true;

// Deprecated options
Game.HookSetCursorPos = false;
Game.HookGetCursorPos = false;
Game.HookGetKeyState = false;
Game.HookGetAsyncKeyState = false;
Game.HookGetKeyboardState = false;
Game.HookFilterRawInput = false;
Game.HookFilterMouseMessages = false;
Game.HookUseLegacyInput = false;
Game.HookDontUpdateLegacyInMouseMsg = false;
Game.HookMouseVisibility = false;
Game.SendNormalMouseInput = false;
Game.SendNormalKeyboardInput = false;
Game.SendScrollWheel = false;
Game.ForwardRawKeyboardInput = false;
Game.ForwardRawMouseInput = false;
Game.DrawFakeMouseCursor = false;
Game.DontRemoveBorders = true;
Game.LockInputAtStart = false;
Game.LockInputSuspendsExplorer = false;
Game.LockInputToggleKey = 0x23;

Game.ProtoInput.InjectStartup = false;
Game.ProtoInput.InjectRuntime_RemoteLoadMethod = false;
Game.ProtoInput.InjectRuntime_EasyHookMethod = true;
Game.ProtoInput.InjectRuntime_EasyHookStealthMethod = false;
Game.ProtoInput.RegisterRawInputHook = true;
Game.ProtoInput.GetRawInputDataHook = true;
Game.ProtoInput.MessageFilterHook = true;
Game.ProtoInput.GetCursorPosHook = false;
Game.ProtoInput.SetCursorPosHook = false;
Game.ProtoInput.GetKeyStateHook = false;
Game.ProtoInput.GetAsyncKeyStateHook = false;
Game.ProtoInput.GetKeyboardStateHook = false;
Game.ProtoInput.CursorVisibilityHook = false;
Game.ProtoInput.ClipCursorHook = false;
Game.ProtoInput.FocusHooks = true;
Game.ProtoInput.DrawFakeCursor = false;
Game.ProtoInput.ClipCursorHookCreatesFakeClip = true;
Game.ProtoInput.RawInputFilter = false;
Game.ProtoInput.MouseMoveFilter = false;
Game.ProtoInput.MouseActivateFilter = false;
Game.ProtoInput.WindowActivateFilter = true;
Game.ProtoInput.WindowActvateAppFilter = true;
Game.ProtoInput.MouseWheelFilter = false;
Game.ProtoInput.MouseButtonFilter = false;
Game.ProtoInput.KeyboardButtonFilter = true;
Game.ProtoInput.SendMouseWheelMessages = true;
Game.ProtoInput.SendMouseButtonMessages = true;
Game.ProtoInput.SendMouseMovementMessages = true;
Game.ProtoInput.SendKeyboardButtonMessages = true;

Game.ProtoInput.EnableFocusMessageLoop = false;
Game.ProtoInput.FocusLoopIntervalMilliseconds = 0;
Game.ProtoInput.FocusLoop_WM_ACTIVATE = true;
Game.ProtoInput.FocusLoop_WM_ACTIVATEAPP = true;
Game.ProtoInput.FocusLoop_WM_NCACTIVATE = true;
Game.ProtoInput.FocusLoop_WM_SETFOCUS = true;
Game.ProtoInput.FocusLoop_WM_MOUSEACTIVATE = true;
Game.ProtoInput.BlockedMessages = [];
Game.ProtoInput.RenameHandlesHook = false;
Game.ProtoInput.RenameHandles = [];
Game.ProtoInput.RenameNamedPipes = [];

Game.Play = function() {
  var log = Context.Options["log"];
  if (log == "No") {
    Game.PromptBetweenInstances = false;
    Game.ProcessChangesAtEnd = false;
    Game.PromptProcessChangesAtEnd = false;
  }
  if (log == "Yes") {
    Game.PromptBetweenInstances = true;
    Game.ProcessChangesAtEnd = true;
    Game.PromptProcessChangesAtEnd = true;
  }

  var filePath = Context.EnvironmentPlayer + "\\Documents";
  System.IO.Directory.CreateDirectory(filePath);

  var filePath = Context.EnvironmentPlayer + "\\Documents\\My Games";
  System.IO.Directory.CreateDirectory(filePath);

  var filePath = Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn";
  System.IO.Directory.CreateDirectory(filePath);

  var filePath = Context.EnvironmentPlayer + "\\Documents\\My Mods";
  System.IO.Directory.CreateDirectory(filePath);

  var filePath = Context.EnvironmentPlayer + "\\Documents\\My Mods\\SpecialK";
  System.IO.Directory.CreateDirectory(filePath);

  var filePath = Context.EnvironmentPlayer + "\\Documents\\My Mods\\SpecialK\\Global";
  System.IO.Directory.CreateDirectory(filePath);

  if (!System.IO.File.Exists(Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg")) {
    var savePath = (Context.SavePath = Context.EnvironmentPlayer + "Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg");
    var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "FFXIV.cfg");
    System.IO.File.Copy(savePkgOrigin, savePath, true);
  }
  var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\game\\d3d11.dll");
  var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "SpecialK64.dll");
  System.IO.File.Copy(savePkgOrigin, savePath, true);

  var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\game\\d3d11.ini");
  var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "d3d11.ini");
  System.IO.File.Copy(savePkgOrigin, savePath, true);

  var savePath = (Context.SavePath = Context.EnvironmentPlayer + "\\Documents\\My Mods\\SpecialK\\Global\\osd.ini");
  var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "osd.ini");
  System.IO.File.Copy(savePkgOrigin, savePath, true);

  var txtPath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\game\\d3d11.ini";
  Context.ReplaceLinesInTextFile(
    txtPath,
    [
      Context.FindLineNumberInTextFile(txtPath, "OverrideRes=", Nucleus.SearchType.StartsWith) + "|OverrideRes=" + Context.Width + "x" + Context.Height + "",
      Context.FindLineNumberInTextFile(txtPath, "MinRes=", Nucleus.SearchType.StartsWith) + "|MinRes=" + Context.Width + "x" + Context.Height + "",
      Context.FindLineNumberInTextFile(txtPath, "MaxRes=", Nucleus.SearchType.StartsWith) + "|MaxRes=" + Context.Width + "x" + Context.Height + ""
    ],
    "utf-8"
  );

  var Music = Context.Options["Music"];

  if (Music == "Yes") {
    if (Context.PlayerID == 0) {
      var txtPath = Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg";
      var dict = [
        Context.FindLineNumberInTextFile(txtPath, "ScreenWidth", Nucleus.SearchType.StartsWith) + "|ScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenHeight", Nucleus.SearchType.StartsWith) + "|ScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenMode", Nucleus.SearchType.StartsWith) + "|ScreenMode	2",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenWidth", Nucleus.SearchType.StartsWith) + "|FullScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenHeight", Nucleus.SearchType.StartsWith) + "|FullScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "FPSInActive", Nucleus.SearchType.StartsWith) + "|FPSInActive	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundDisable", Nucleus.SearchType.StartsWith) + "|IsSoundDisable	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundAlways", Nucleus.SearchType.StartsWith) + "|IsSoundAlways	1",
        Context.FindLineNumberInTextFile(txtPath, "SoundBgm", Nucleus.SearchType.StartsWith) + "|SoundBgm	100"
      ];
      Context.ReplaceLinesInTextFile(txtPath, dict);
    } else {
      var txtPath = Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg";
      var dict = [
        Context.FindLineNumberInTextFile(txtPath, "ScreenWidth", Nucleus.SearchType.StartsWith) + "|ScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenHeight", Nucleus.SearchType.StartsWith) + "|ScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenMode", Nucleus.SearchType.StartsWith) + "|ScreenMode	2",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenWidth", Nucleus.SearchType.StartsWith) + "|FullScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenHeight", Nucleus.SearchType.StartsWith) + "|FullScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "FPSInActive", Nucleus.SearchType.StartsWith) + "|FPSInActive	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundDisable", Nucleus.SearchType.StartsWith) + "|IsSoundDisable	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundAlways", Nucleus.SearchType.StartsWith) + "|IsSoundAlways	1",
        Context.FindLineNumberInTextFile(txtPath, "SoundBgm", Nucleus.SearchType.StartsWith) + "|SoundBgm	0"
      ];
      Context.ReplaceLinesInTextFile(txtPath, dict);
    }
  }

  if (Music == "No") {
    if (Context.PlayerID == 0) {
      var txtPath = Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg";
      var dict = [
        Context.FindLineNumberInTextFile(txtPath, "ScreenWidth", Nucleus.SearchType.StartsWith) + "|ScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenHeight", Nucleus.SearchType.StartsWith) + "|ScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenMode", Nucleus.SearchType.StartsWith) + "|ScreenMode	2",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenWidth", Nucleus.SearchType.StartsWith) + "|FullScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenHeight", Nucleus.SearchType.StartsWith) + "|FullScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "FPSInActive", Nucleus.SearchType.StartsWith) + "|FPSInActive	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundDisable", Nucleus.SearchType.StartsWith) + "|IsSoundDisable	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundAlways", Nucleus.SearchType.StartsWith) + "|IsSoundAlways	1",
        Context.FindLineNumberInTextFile(txtPath, "SoundBgm", Nucleus.SearchType.StartsWith) + "|SoundBgm	100"
      ];
      Context.ReplaceLinesInTextFile(txtPath, dict);
    } else {
      var txtPath = Context.EnvironmentPlayer + "\\Documents\\My Games\\FINAL FANTASY XIV - A Realm Reborn\\FFXIV.cfg";
      var dict = [
        Context.FindLineNumberInTextFile(txtPath, "ScreenWidth", Nucleus.SearchType.StartsWith) + "|ScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenHeight", Nucleus.SearchType.StartsWith) + "|ScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "ScreenMode", Nucleus.SearchType.StartsWith) + "|ScreenMode	2",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenWidth", Nucleus.SearchType.StartsWith) + "|FullScreenWidth	" + Context.Width + "",
        Context.FindLineNumberInTextFile(txtPath, "FullScreenHeight", Nucleus.SearchType.StartsWith) + "|FullScreenHeight	" + Context.Height + "",
        Context.FindLineNumberInTextFile(txtPath, "FPSInActive", Nucleus.SearchType.StartsWith) + "|FPSInActive	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundDisable", Nucleus.SearchType.StartsWith) + "|IsSoundDisable	0",
        Context.FindLineNumberInTextFile(txtPath, "IsSoundAlways", Nucleus.SearchType.StartsWith) + "|IsSoundAlways	1",
        Context.FindLineNumberInTextFile(txtPath, "SoundBgm", Nucleus.SearchType.StartsWith) + "|SoundBgm	100"
      ];
      Context.ReplaceLinesInTextFile(txtPath, dict);
    }
  }

  if (Context.HasKeyboardPlayer == true) {
    Game.ProtoInput.KeyboardButtonFilter = true;
  } else {
    Game.ProtoInput.KeyboardButtonFilter = false;
  }
  Game.ProtoInput.OnInputLocked = function() {
    if (Context.HasKeyboardPlayer) {
      for (var i = 0; i < PlayerList.Count; i++) {
        var player = PlayerList[i];
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.FocusHooksHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetCursorPosHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.SetCursorPosHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.CursorVisibilityStateHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.ClipCursorHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyStateHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyboardStateHookID);
        ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetAsyncKeyStateHookID);

        ProtoInput.StartFocusMessageLoop(player.ProtoInputInstanceHandle, 15, true, true, true, true, true);
        ProtoInput.SetDrawFakeCursor(player.ProtoInputInstanceHandle, true);
        ProtoInput.SetRawInputBypass(player.ProtoInputInstanceHandle, false);

        ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.RawInputFilterID);
        ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.KeyboardButtonFilterID);
        ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseButtonFilterID);

        ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseWheelFilterID);
        ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseActivateFilterID);
        ProtoInput.EnableMessageBlock(player.ProtoInputInstanceHandle, 0x0008);
      }
    }
  };
  Game.ProtoInput.OnInputUnlocked = function() {
    for (var i = 0; i < PlayerList.Count; i++) {
      var player = PlayerList[i];
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.FocusHooksHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetCursorPosHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.SetCursorPosHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.CursorVisibilityStateHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.ClipCursorHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyStateHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyboardStateHookID);
      ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetAsyncKeyStateHookID);

      ProtoInput.SetDrawFakeCursor(player.ProtoInputInstanceHandle, false);
      ProtoInput.SetRawInputBypass(player.ProtoInputInstanceHandle, true);

      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.RawInputFilterID);
      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.KeyboardButtonFilterID);
      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseButtonFilterID);
      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseMoveFilterID);
      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseWheelFilterID);
      ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseActivateFilterID);
    }
  };
};