From cf3873ca22738b04f0136dab81f1ba077fa62972 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 17 Sep 2022 06:48:15 -0400 Subject: [Taiji] Rewrote using magic autosplitter array Major thanks for mvandevander for adding this in! --- Taiji.asl | 122 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 24 deletions(-) (limited to 'Taiji.asl') diff --git a/Taiji.asl b/Taiji.asl index 080dbd9..dffc3c4 100644 --- a/Taiji.asl +++ b/Taiji.asl @@ -1,9 +1,11 @@ -state("Taiji") -{ - // v9.10.2022, v9.12.2022.6 - int solveCount: "GameAssembly.dll", 0x0168ED88, 0x80, 0x100, 0xD94; - byte10 worldsCompleted: "GameAssembly.dll", 0x015C8010, 0x48, 0x40, 0x80, 0x290, 0xB8, 0x10, 0x20; -} +// Autosplitter script for Taiji, by hatkirby. +// +// Requires v9.17.2022 or later. +// +// Massive thanks to the game developer, mvandevander, for working with me to +// make this possible. + +state("Taiji") {} startup { @@ -13,34 +15,106 @@ startup settings.Add("solveCount", true, "Split on solve count increasing"); settings.Add("world", false, "Split on completing a world"); + settings.Add("tutorial", false, "Split on Tutorial completion"); + settings.Add("black", true, "Split on Black ending"); + settings.Add("white", false, "Split on White ending"); vars.log("Autosplitter loaded"); } -onStart +init +{ + // magic byte array format: + // [0-7]: 7b 08 ec f9 87 1d b7 d6 (random bytes used for sigscanning) + // [8]: New file flag. Gets set to 1 when "start a new game" is selected. + // Gets reset to 0 when the pause menu is opened. + // [9-17]: A copy of the world completion flags. + // [18]: Solve count / 256. + // [19]: Solve count % 256. + // [20]: Tutorial completion flag. + // [21]: Black ending flag. Gets set to 1 when the square that starts the + // interactive ending is clicked. + // [22]: White ending flag. Gets set to 1 when the square that enables the + // prison is clicked. + // [23]: Loading flag. Set to 1 during loads, 0 otherwise. + IntPtr ptr = IntPtr.Zero; + foreach (var page in game.MemoryPages(true).Reverse()) { + var scanner = new SignatureScanner(game, page.BaseAddress, (int)page.RegionSize); + ptr = scanner.Scan(new SigScanTarget(0, "7b 08 ec f9 87 1d b7 d6")); + if (ptr != IntPtr.Zero) { + break; + } + } + if (ptr == IntPtr.Zero) { + throw new Exception("Could not find magic autosplitter array!"); + } + vars.newFileFlag = new MemoryWatcher(ptr + 8); + vars.worldCompletion = new List>(); + for (int i = 0; i < 9; i++) { + vars.worldCompletion.Add(new MemoryWatcher(ptr + 9 + i)); + } + vars.solveCountHigh = new MemoryWatcher(ptr + 18); + vars.solveCountLow = new MemoryWatcher(ptr + 19); + vars.tutorialCompletion = new MemoryWatcher(ptr + 20); + vars.blackEnding = new MemoryWatcher(ptr + 21); + vars.whiteEnding = new MemoryWatcher(ptr + 22); + vars.loadingFlag = new MemoryWatcher(ptr + 23); + + vars.log(String.Format("Magic autosplitter array: {0}", ptr.ToString("X"))); +} + +update +{ + vars.newFileFlag.Update(game); + vars.tutorialCompletion.Update(game); + vars.blackEnding.Update(game); + vars.whiteEnding.Update(game); + vars.loadingFlag.Update(game); + + vars.solveCountHigh.Update(game); + vars.solveCountLow.Update(game); + current.solveCount = vars.solveCountHigh.Current * 256 + vars.solveCountLow.Current; + + int curWorlds = 0; + for (int i = 0; i < 9; i++) { + vars.worldCompletion[i].Update(game); + if (vars.worldCompletion[i].Current == 1) { + curWorlds++; + } + } + current.numWorlds = curWorlds; +} + +start { - vars.maxSolve = 0; - vars.numWorlds = 0; + return vars.newFileFlag.Old == 0 && vars.newFileFlag.Current == 1; } split { - if (settings["solveCount"] && current.solveCount > vars.maxSolve) { - vars.log(String.Format("Solve count increased from {0} to {1}", vars.maxSolve, current.solveCount)); - vars.maxSolve = current.solveCount; + if (settings["solveCount"] && current.solveCount > old.solveCount) { + vars.log(String.Format("Solve count increased from {0} to {1}", old.solveCount, current.solveCount)); return true; } - if (settings["world"]) { - int curWorlds = 0; - foreach (byte b in current.worldsCompleted) { - if (b == 1) { - curWorlds += 1; - } - } - if (curWorlds > vars.numWorlds) { - vars.log(String.Format("World count increased from {0} to {1}", vars.numWorlds, curWorlds)); - vars.numWorlds = curWorlds; - return true; - } + if (settings["world"] && current.numWorlds > old.numWorlds) { + vars.log(String.Format("World count increased from {0} to {1}", old.numWorlds, current.numWorlds)); + return true; + } + if (settings["tutorial"] && vars.tutorialCompletion.Old == 0 && vars.tutorialCompletion.Current == 1) { + vars.log("Split on tutorial completion"); + return true; } + if (settings["black"] && vars.blackEnding.Old == 0 && vars.blackEnding.Current == 1) { + vars.log("Split on Black ending"); + return true; + } + if (settings["white"] && vars.whiteEnding.Old == 0 && vars.whiteEnding.Current == 1) { + vars.log("Split on White ending"); + return true; + } +} + +isLoading +{ + return vars.loadingFlag.Current == 1; } -- cgit 1.4.1