diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2022-09-17 06:48:15 -0400 | 
|---|---|---|
| committer | Star Rauchenberger <fefferburbia@gmail.com> | 2022-09-17 06:48:15 -0400 | 
| commit | cf3873ca22738b04f0136dab81f1ba077fa62972 (patch) | |
| tree | e8b08a6615018cf92521087fea8ca3967da8a176 | |
| parent | a94643909b30596fc890ca8227270c54f08f40d6 (diff) | |
| download | autosplitters-cf3873ca22738b04f0136dab81f1ba077fa62972.tar.gz autosplitters-cf3873ca22738b04f0136dab81f1ba077fa62972.tar.bz2 autosplitters-cf3873ca22738b04f0136dab81f1ba077fa62972.zip | |
[Taiji] Rewrote using magic autosplitter array
Major thanks for mvandevander for adding this in!
| -rw-r--r-- | Taiji.asl | 122 | 
1 files changed, 98 insertions, 24 deletions
| diff --git a/Taiji.asl b/Taiji.asl index 080dbd9..dffc3c4 100644 --- a/Taiji.asl +++ b/Taiji.asl | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | state("Taiji") | 1 | // Autosplitter script for Taiji, by hatkirby. | 
| 2 | { | 2 | // | 
| 3 | // v9.10.2022, v9.12.2022.6 | 3 | // Requires v9.17.2022 or later. | 
| 4 | int solveCount: "GameAssembly.dll", 0x0168ED88, 0x80, 0x100, 0xD94; | 4 | // | 
| 5 | byte10 worldsCompleted: "GameAssembly.dll", 0x015C8010, 0x48, 0x40, 0x80, 0x290, 0xB8, 0x10, 0x20; | 5 | // Massive thanks to the game developer, mvandevander, for working with me to | 
| 6 | } | 6 | // make this possible. | 
| 7 | |||
| 8 | state("Taiji") {} | ||
| 7 | 9 | ||
| 8 | startup | 10 | startup | 
| 9 | { | 11 | { | 
| @@ -13,34 +15,106 @@ startup | |||
| 13 | 15 | ||
| 14 | settings.Add("solveCount", true, "Split on solve count increasing"); | 16 | settings.Add("solveCount", true, "Split on solve count increasing"); | 
| 15 | settings.Add("world", false, "Split on completing a world"); | 17 | settings.Add("world", false, "Split on completing a world"); | 
| 18 | settings.Add("tutorial", false, "Split on Tutorial completion"); | ||
| 19 | settings.Add("black", true, "Split on Black ending"); | ||
| 20 | settings.Add("white", false, "Split on White ending"); | ||
| 16 | 21 | ||
| 17 | vars.log("Autosplitter loaded"); | 22 | vars.log("Autosplitter loaded"); | 
| 18 | } | 23 | } | 
| 19 | 24 | ||
| 20 | onStart | 25 | init | 
| 26 | { | ||
| 27 | // magic byte array format: | ||
| 28 | // [0-7]: 7b 08 ec f9 87 1d b7 d6 (random bytes used for sigscanning) | ||
| 29 | // [8]: New file flag. Gets set to 1 when "start a new game" is selected. | ||
| 30 | // Gets reset to 0 when the pause menu is opened. | ||
| 31 | // [9-17]: A copy of the world completion flags. | ||
| 32 | // [18]: Solve count / 256. | ||
| 33 | // [19]: Solve count % 256. | ||
| 34 | // [20]: Tutorial completion flag. | ||
| 35 | // [21]: Black ending flag. Gets set to 1 when the square that starts the | ||
| 36 | // interactive ending is clicked. | ||
| 37 | // [22]: White ending flag. Gets set to 1 when the square that enables the | ||
| 38 | // prison is clicked. | ||
| 39 | // [23]: Loading flag. Set to 1 during loads, 0 otherwise. | ||
| 40 | IntPtr ptr = IntPtr.Zero; | ||
| 41 | foreach (var page in game.MemoryPages(true).Reverse()) { | ||
| 42 | var scanner = new SignatureScanner(game, page.BaseAddress, (int)page.RegionSize); | ||
| 43 | ptr = scanner.Scan(new SigScanTarget(0, "7b 08 ec f9 87 1d b7 d6")); | ||
| 44 | if (ptr != IntPtr.Zero) { | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | if (ptr == IntPtr.Zero) { | ||
| 49 | throw new Exception("Could not find magic autosplitter array!"); | ||
| 50 | } | ||
| 51 | vars.newFileFlag = new MemoryWatcher<byte>(ptr + 8); | ||
| 52 | vars.worldCompletion = new List<MemoryWatcher<byte>>(); | ||
| 53 | for (int i = 0; i < 9; i++) { | ||
| 54 | vars.worldCompletion.Add(new MemoryWatcher<byte>(ptr + 9 + i)); | ||
| 55 | } | ||
| 56 | vars.solveCountHigh = new MemoryWatcher<byte>(ptr + 18); | ||
| 57 | vars.solveCountLow = new MemoryWatcher<byte>(ptr + 19); | ||
| 58 | vars.tutorialCompletion = new MemoryWatcher<byte>(ptr + 20); | ||
| 59 | vars.blackEnding = new MemoryWatcher<byte>(ptr + 21); | ||
| 60 | vars.whiteEnding = new MemoryWatcher<byte>(ptr + 22); | ||
| 61 | vars.loadingFlag = new MemoryWatcher<byte>(ptr + 23); | ||
| 62 | |||
| 63 | vars.log(String.Format("Magic autosplitter array: {0}", ptr.ToString("X"))); | ||
| 64 | } | ||
| 65 | |||
| 66 | update | ||
| 67 | { | ||
| 68 | vars.newFileFlag.Update(game); | ||
| 69 | vars.tutorialCompletion.Update(game); | ||
| 70 | vars.blackEnding.Update(game); | ||
| 71 | vars.whiteEnding.Update(game); | ||
| 72 | vars.loadingFlag.Update(game); | ||
| 73 | |||
| 74 | vars.solveCountHigh.Update(game); | ||
| 75 | vars.solveCountLow.Update(game); | ||
| 76 | current.solveCount = vars.solveCountHigh.Current * 256 + vars.solveCountLow.Current; | ||
| 77 | |||
| 78 | int curWorlds = 0; | ||
| 79 | for (int i = 0; i < 9; i++) { | ||
| 80 | vars.worldCompletion[i].Update(game); | ||
| 81 | if (vars.worldCompletion[i].Current == 1) { | ||
| 82 | curWorlds++; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | current.numWorlds = curWorlds; | ||
| 86 | } | ||
| 87 | |||
| 88 | start | ||
| 21 | { | 89 | { | 
| 22 | vars.maxSolve = 0; | 90 | return vars.newFileFlag.Old == 0 && vars.newFileFlag.Current == 1; | 
| 23 | vars.numWorlds = 0; | ||
| 24 | } | 91 | } | 
| 25 | 92 | ||
| 26 | split | 93 | split | 
| 27 | { | 94 | { | 
| 28 | if (settings["solveCount"] && current.solveCount > vars.maxSolve) { | 95 | if (settings["solveCount"] && current.solveCount > old.solveCount) { | 
| 29 | vars.log(String.Format("Solve count increased from {0} to {1}", vars.maxSolve, current.solveCount)); | 96 | vars.log(String.Format("Solve count increased from {0} to {1}", old.solveCount, current.solveCount)); | 
| 30 | vars.maxSolve = current.solveCount; | ||
| 31 | return true; | 97 | return true; | 
| 32 | } | 98 | } | 
| 33 | if (settings["world"]) { | 99 | if (settings["world"] && current.numWorlds > old.numWorlds) { | 
| 34 | int curWorlds = 0; | 100 | vars.log(String.Format("World count increased from {0} to {1}", old.numWorlds, current.numWorlds)); | 
| 35 | foreach (byte b in current.worldsCompleted) { | 101 | return true; | 
| 36 | if (b == 1) { | 102 | } | 
| 37 | curWorlds += 1; | 103 | if (settings["tutorial"] && vars.tutorialCompletion.Old == 0 && vars.tutorialCompletion.Current == 1) { | 
| 38 | } | 104 | vars.log("Split on tutorial completion"); | 
| 39 | } | 105 | return true; | 
| 40 | if (curWorlds > vars.numWorlds) { | ||
| 41 | vars.log(String.Format("World count increased from {0} to {1}", vars.numWorlds, curWorlds)); | ||
| 42 | vars.numWorlds = curWorlds; | ||
| 43 | return true; | ||
| 44 | } | ||
| 45 | } | 106 | } | 
| 107 | if (settings["black"] && vars.blackEnding.Old == 0 && vars.blackEnding.Current == 1) { | ||
| 108 | vars.log("Split on Black ending"); | ||
| 109 | return true; | ||
| 110 | } | ||
| 111 | if (settings["white"] && vars.whiteEnding.Old == 0 && vars.whiteEnding.Current == 1) { | ||
| 112 | vars.log("Split on White ending"); | ||
| 113 | return true; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | isLoading | ||
| 118 | { | ||
| 119 | return vars.loadingFlag.Current == 1; | ||
| 46 | } | 120 | } | 
