<?xml version='1.0' encoding='utf-8'?>
<CheatTable CheatEngineTableVersion="45">
  <CheatEntries>
    <CheatEntry>
      <ID>1</ID>
      <Description>"Auto-Attach and Version Check"</Description>
      <GroupHeader>1</GroupHeader>
    </CheatEntry>
    <CheatEntry>
      <ID>2</ID>
      <Description>"☕ Fuel the Cheats — Tip Katzy (Toggle to open my Ko-fi page)"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>3</ID>
      <Description>"How to use"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>4</ID>
      <Description>"Clear All"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>5</ID>
      <Description>"[MAIN] Like a Dragon: Infinite Wealth"</Description>
      <Options moHideChildren="1" />
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
      <CheatEntries>
        <CheatEntry>
          <ID>6</ID>
          <Description>"Infinite Health"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>8</ID>
          <Description>"Infinite Mana"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>11</ID>
          <Description>"Infinite Items"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>7</ID>
          <Description>"Infinite Money"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>9</ID>
          <Description>"Always Perfect Guard"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>10</ID>
          <Description>"Always Skill Bonus"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>39</ID>
          <Description>"Infinite Tag Gauge"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>36</ID>
          <Description>"Max Bond"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>23</ID>
          <Description>"Max Job Rank"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>22</ID>
          <Description>"Max Level"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>40</ID>
          <Description>"No Random Encounters"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>15</ID>
          <Description>"Personality"</Description>
          <Options moHideChildren="1" />
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>16</ID>
              <Description>"Max Charisma (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>17</ID>
              <Description>"Max Confidence (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>18</ID>
              <Description>"Max Intellect (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>19</ID>
              <Description>"Max Kindness (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>20</ID>
              <Description>"Max Passion (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>21</ID>
              <Description>"Max Style (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>75</ID>
          <Description>"Sujimon"</Description>
          <Options moHideChildren="1" />
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>98</ID>
              <Description>"Infinite Sujimon Points"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>76</ID>
              <Description>"Infinite SP"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>77</ID>
              <Description>"Infinite MP"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>78</ID>
              <Description>"Always Best Roulette Result"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>79</ID>
              <Description>"Best Recruitment Effort"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>80</ID>
              <Description>"Auto Encouragement Presses"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>82</ID>
              <Description>"Max Friendship (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>81</ID>
              <Description>"Max Level (One-shot)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>88</ID>
          <Description>"Dondoko Islands"</Description>
          <Options moHideChildren="1" moDeactivateChildrenAsWell="1" />
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>89</ID>
              <Description>"Infinite Dokobucks"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>90</ID>
              <Description>"Infinite Materials"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>91</ID>
              <Description>"Max Building Talent"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>92</ID>
              <Description>"Max Satisfaction"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>93</ID>
              <Description>"Max Popularity"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>94</ID>
              <Description>"Freeze Time of Day"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>95</ID>
              <Description>"Infinite HP"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>71</ID>
          <Description>"Arcade"</Description>
          <Options moHideChildren="1" />
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>31</ID>
              <Description>"Sega Bass Fishing"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>32</ID>
                  <Description>"Always Green Tension"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>33</ID>
                  <Description>"Infinite Timer"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>34</ID>
                  <Description>"Max Points"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>63</ID>
              <Description>"SpikeOut"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>64</ID>
                  <Description>"Infinite Health"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>67</ID>
                  <Description>"Infinite Super Gauge"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>66</ID>
                  <Description>"Max Charge"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>65</ID>
                  <Description>"Set Enemy Health to 1"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>68</ID>
              <Description>"UFO Catcher"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>70</ID>
                  <Description>"Sticky Claw"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>27</ID>
              <Description>"Virtua Fighter"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>28</ID>
                  <Description>"Infinite Health"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>30</ID>
                  <Description>"Infinite Timer"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>29</ID>
                  <Description>"Set Enemy Health to 1"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>85</ID>
          <Description>"Gambles"</Description>
          <Options moHideChildren="1" />
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>58</ID>
              <Description>"Infinite Wooden Tags"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>24</ID>
              <Description>"Infinite Poker Chips"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>61</ID>
              <Description>"Auto Play Koi-Koi"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>62</ID>
              <Description>"Max Round Points (Koi-Koi)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>60</ID>
              <Description>"Always Win Oicho-Kabu"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>14</ID>
              <Description>"Win Mahjong Match"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>25</ID>
              <Description>"Win Poker Hand"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>83</ID>
          <Description>"MiniGames"</Description>
          <Options moHideChildren="1" />
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>37</ID>
              <Description>"Aloha-Link Friendship"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>26</ID>
              <Description>"Always Perfect Darts"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>35</ID>
              <Description>"Always Perfect Notes"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>72</ID>
              <Description>"Anaconda Escape"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>73</ID>
                  <Description>"Auto Answer Quizzes"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>74</ID>
                  <Description>"Infinite Timer"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>50</ID>
              <Description>"Crazy Eats"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>51</ID>
                  <Description>"Always Extreme"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>55</ID>
                  <Description>"Infinite Delivery Points"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>52</ID>
                  <Description>"Infinite Food Items"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>53</ID>
                  <Description>"Infinite Timer"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>54</ID>
                  <Description>"Max Stage Rank"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>48</ID>
              <Description>"Miss Match"</Description>
              <Options moHideChildren="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>46</ID>
                  <Description>"Always Best Emoji Result"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>44</ID>
                  <Description>"Always Excellent Replies"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>45</ID>
                  <Description>"Auto Miss Match Inputs"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>56</ID>
              <Description>"Lemonade Stand Timer"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>38</ID>
              <Description>"Overworld Fishing"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>47</ID>
              <Description>"Overworld Chase QTEs"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>87</ID>
              <Description>"Shogi"</Description>
              <Options moHideChildren="1" />
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>12</ID>
                  <Description>"Win Shogi Match (One-shot)"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>13</ID>
                  <Description>"Infinite Shogi Points"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>86</ID>
              <Description>"Sicko Snap"</Description>
              <Options moHideChildren="1" />
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>42</ID>
                  <Description>"Always Perfect Sicko Snap"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>43</ID>
                  <Description>"Infinite Sicko Snap Points"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>96</ID>
              <Description>"Vocational School"</Description>
              <Options moHideChildren="1" moDeactivateChildrenAsWell="1" />
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>97</ID>
                  <Description>"Auto Correct Answers"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>99</ID>
                  <Description>"Infinite Timer"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
// Table Lua handles this entry before activation.
[DISABLE]
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols />
  <Comments>Table identification: Katzy. Like a Dragon: Infinite Wealth 1.20, Steam build 17233673. See How to use for option behavior.</Comments>
  <LuaScript>--[[
Table identification: Katzy
Like a Dragon: Infinite Wealth | 1.20 | Steam build 17233673 | v1.94
Original derivation from the user's installed executable.
Published code pages are reused and retained until process exit: restoring
entry points cannot prove that a suspended thread has left a code page.
Unpublished allocations are freed on failure. Inventory enrollment checks
twice per second and refills at most eight owned stacks per batch.
]]
local old=rawget(_G,'KatzyIW')
if old and not old.unload() then
  showMessage('The previous table still has a hook to restore. Remove the conflicting cheat and use Clear All before reloading.')
  return
end
local S={active={},closing=false,dead=false}
local cancelShogi, cancelMahjong
local friendshipRestore,friendshipEnable
KatzyIW=S
KatzyIWPages=KatzyIWPages or {}
local list=getAddressList()
local main=list.getMemoryRecordByID(5)
local missMatchGroup=list.getMemoryRecordByID(48)
local gamblingGroup=list.getMemoryRecordByID(85)
local crazyGroup=list.getMemoryRecordByID(50)
local ufoGroup=list.getMemoryRecordByID(68)
local spikeGroup=list.getMemoryRecordByID(63)
local personality=list.getMemoryRecordByID(15)
local records={health=list.getMemoryRecordByID(6),mana=list.getMemoryRecordByID(8),money=list.getMemoryRecordByID(7),guard=list.getMemoryRecordByID(9),skill=list.getMemoryRecordByID(10),items=list.getMemoryRecordByID(11),shogipoints=list.getMemoryRecordByID(13)}
records.crazyextreme=list.getMemoryRecordByID(51)
records.crazyfood=list.getMemoryRecordByID(52)
records.crazytimer=list.getMemoryRecordByID(53)
records.koiauto=list.getMemoryRecordByID(61)
records.koipoints=list.getMemoryRecordByID(62)
records.oichowin=list.getMemoryRecordByID(60)
records.sujimonpoints=list.getMemoryRecordByID(98)
records.woodentags=list.getMemoryRecordByID(58)
local schoolGroup=list.getMemoryRecordByID(96)
records.schoolanswer=list.getMemoryRecordByID(97)
records.schooltimer=list.getMemoryRecordByID(99)
local dondokoGroup=list.getMemoryRecordByID(88)
records.dokomoney=list.getMemoryRecordByID(89)
records.dokomaterials=list.getMemoryRecordByID(90)
records.dokotalent=list.getMemoryRecordByID(91)
records.dokosatisfaction=list.getMemoryRecordByID(92)
records.dokopopularity=list.getMemoryRecordByID(93)
records.dokotime=list.getMemoryRecordByID(94)
records.dokohp=list.getMemoryRecordByID(95)
local sujimonGroup=list.getMemoryRecordByID(75)
records.recruiteffort=list.getMemoryRecordByID(79)
records.recruitauto=list.getMemoryRecordByID(80)
records.sujimonmp=list.getMemoryRecordByID(77)
records.sujimonroulette=list.getMemoryRecordByID(78)
records.sujimonsp=list.getMemoryRecordByID(76)
local anacondaGroup=list.getMemoryRecordByID(72)
records.anacondatimer=list.getMemoryRecordByID(74)
records.anacondaquiz=list.getMemoryRecordByID(73)
records.lemontimer=list.getMemoryRecordByID(56)
records.crazyrank=list.getMemoryRecordByID(54)
records.level=list.getMemoryRecordByID(22)
records.job=list.getMemoryRecordByID(23)
records.pokerchips=list.getMemoryRecordByID(24)
records.pokerwin=list.getMemoryRecordByID(25)
records.chase=list.getMemoryRecordByID(47)
records.emoji=list.getMemoryRecordByID(46)
records.match=list.getMemoryRecordByID(44)
records.matchauto=list.getMemoryRecordByID(45)
records.snap=list.getMemoryRecordByID(42)
records.deliverypoints=list.getMemoryRecordByID(55)
records.snappoints=list.getMemoryRecordByID(43)
records.encounter=list.getMemoryRecordByID(40)
records.tag=list.getMemoryRecordByID(39)
records.fishing=list.getMemoryRecordByID(38)
records.friendship=list.getMemoryRecordByID(37)
records.bond=list.getMemoryRecordByID(36)
records.karaoke=list.getMemoryRecordByID(35)
records.darts=list.getMemoryRecordByID(26)
records.vfhealth=list.getMemoryRecordByID(28)
records.vftimer=list.getMemoryRecordByID(30)
records.vfenemy=list.getMemoryRecordByID(29)
records.basstension=list.getMemoryRecordByID(32)
records.basstimer=list.getMemoryRecordByID(33)
records.basspoints=list.getMemoryRecordByID(34)
records.spikehealth=list.getMemoryRecordByID(64)
records.spikeenemy=list.getMemoryRecordByID(65)
records.spikecharge=list.getMemoryRecordByID(66)
records.spikesuper=list.getMemoryRecordByID(67)
local itemTargets={[189]=998,[190]=998,[191]=998,[192]=998,[193]=998,[194]=998,[195]=998,[196]=998,[197]=998,[198]=998,[199]=998,[200]=998,[201]=998,[202]=998,[203]=998,[204]=998,[205]=998,[206]=998,[207]=998,[208]=998,[209]=998,[210]=998,[211]=998,[212]=998,[213]=998,[214]=998,[215]=998,[216]=998,[217]=998,[218]=998,[219]=998,[220]=998,[221]=998,[222]=998,[223]=998,[224]=998,[225]=998,[226]=998,[227]=998,[228]=998,[229]=998,[230]=998,[231]=998,[232]=998,[233]=998,[234]=998,[235]=998,[236]=998,[237]=998,[238]=998,[239]=998,[240]=998,[241]=998,[242]=998,[243]=998,[244]=998,[245]=998,[246]=998,[247]=998,[248]=998,[249]=998,[250]=998,[251]=998,[252]=998,[253]=998,[254]=998,[255]=998,[256]=998,[257]=998,[258]=998,[259]=998,[260]=998,[261]=998,[262]=998,[263]=998,[264]=998,[265]=998,[266]=998,[267]=998,[268]=998,[269]=998,[270]=998,[271]=998,[272]=998,[273]=998,[274]=998,[275]=998,[276]=998,[277]=998,[278]=998,[279]=998,[280]=998,[281]=998,[282]=998,[283]=998,[284]=998,[285]=998,[286]=998,[287]=998,[288]=998,[289]=998,[290]=998,[291]=998,[292]=998,[293]=998,[294]=998,[295]=998,[296]=998,[297]=998,[298]=998,[299]=998,[300]=998,[301]=998,[302]=998,[303]=998,[304]=998,[305]=998,[306]=998,[307]=998,[308]=998,[309]=998,[310]=998,[311]=998,[312]=998,[313]=998,[314]=998,[315]=998,[316]=998,[317]=998,[318]=998,[319]=998,[320]=998,[321]=998,[322]=998,[323]=998,[324]=998,[325]=998,[326]=998,[327]=998,[328]=998,[329]=998,[330]=998,[331]=998,[332]=998,[333]=998,[334]=998,[335]=998,[336]=998,[337]=998,[338]=998,[339]=998,[340]=998,[341]=998,[342]=998,[343]=998,[344]=998,[345]=998,[346]=998,[347]=998,[348]=998,[349]=998,[350]=998,[351]=998,[353]=998,[354]=998,[355]=998,[356]=998,[357]=998,[358]=998,[359]=998,[360]=998,[361]=998,[362]=998,[363]=998,[364]=998,[365]=998,[366]=998,[367]=998,[368]=998,[369]=998,[370]=998,[371]=998,[372]=998,[373]=998,[374]=998,[375]=998,[376]=998,[377]=998,[378]=998,[379]=998,[380]=998,[381]=998,[382]=998,[383]=998,[384]=998,[385]=998,[386]=998,[387]=998,[388]=998,[389]=998,[390]=998,[391]=998,[392]=998,[393]=998,[394]=998,[395]=998,[396]=998,[397]=998,[398]=998,[399]=998,[400]=998,[401]=998,[402]=998,[403]=998,[404]=998,[405]=998,[406]=998,[407]=998,[408]=998,[409]=998,[410]=998,[411]=998,[412]=998,[413]=998,[414]=998,[415]=998,[416]=998,[417]=998,[418]=998,[419]=998,[420]=998,[421]=998,[422]=998,[423]=998,[424]=998,[425]=998,[426]=998,[427]=998,[428]=998,[429]=998,[430]=998,[431]=998,[432]=998,[433]=998,[434]=998,[435]=998,[436]=998,[437]=998,[438]=998,[439]=998,[440]=998,[441]=998,[442]=998,[443]=998,[444]=998,[445]=998,[446]=998,[447]=998,[448]=998,[449]=998,[450]=998,[451]=998,[452]=998,[453]=998,[454]=998,[455]=998,[456]=998,[457]=998,[458]=998,[459]=998,[460]=998,[461]=998,[462]=998,[463]=998,[464]=998,[465]=998,[466]=998,[467]=998,[468]=998,[469]=998,[470]=998,[471]=998,[472]=998,[473]=998,[474]=998,[475]=998,[476]=998,[477]=998,[478]=998,[479]=998,[480]=998,[481]=998,[482]=998,[483]=998,[484]=998,[485]=998,[486]=998,[487]=998,[488]=998,[489]=998,[490]=998,[491]=998,[492]=998,[493]=998,[494]=998,[495]=998,[496]=998,[497]=998,[498]=998,[499]=998,[500]=998,[501]=998,[502]=998,[503]=998,[504]=998,[505]=998,[506]=998,[507]=998,[508]=998,[509]=998,[510]=998,[511]=998,[512]=998,[513]=998,[514]=998,[515]=998,[516]=998,[517]=998,[518]=998,[519]=998,[520]=998,[521]=998,[522]=998,[523]=998,[524]=998,[525]=998,[526]=998,[527]=998,[528]=998,[529]=998,[530]=998,[531]=998,[532]=998,[533]=998,[534]=998,[535]=998,[536]=998,[537]=998,[538]=998,[539]=998,[540]=998,[541]=998,[542]=998,[543]=998,[544]=998,[545]=998,[546]=998,[547]=998,[548]=998,[549]=998,[550]=998,[551]=998,[552]=998,[553]=998,[554]=998,[555]=998,[556]=998,[557]=998,[558]=998,[559]=998,[560]=998,[561]=998,[562]=998,[563]=998,[564]=998,[565]=998,[566]=998,[567]=998,[568]=998,[569]=998,[570]=998,[571]=998,[572]=998,[573]=998,[574]=998,[575]=998,[576]=998,[577]=998,[578]=998,[579]=998,[580]=998,[581]=998,[582]=998,[583]=998,[584]=998,[585]=998,[586]=998,[587]=998,[588]=998,[589]=998,[590]=998,[591]=998,[592]=998,[593]=998,[594]=998,[595]=998,[596]=998,[597]=998,[598]=998,[599]=998,[600]=998,[601]=998,[602]=998,[603]=998,[604]=998,[605]=998,[606]=998,[607]=998,[608]=998,[609]=998,[610]=998,[611]=998,[612]=998,[613]=998,[614]=998,[615]=998,[616]=998,[617]=998,[618]=998,[619]=998,[620]=998,[621]=998,[622]=998,[623]=998,[624]=998,[625]=998,[626]=998,[627]=998,[628]=998,[629]=998,[630]=998,[631]=998,[632]=998,[633]=998,[634]=998,[635]=998,[636]=998,[637]=998,[638]=998,[639]=998,[640]=998,[641]=998,[642]=998,[643]=998,[644]=998,[645]=998,[646]=998,[647]=998,[648]=998,[649]=998,[650]=998,[651]=998,[652]=998,[653]=998,[654]=998,[655]=998,[656]=998,[657]=998,[658]=998,[659]=998,[660]=998,[661]=998,[662]=998,[663]=998,[664]=998,[665]=998,[666]=998,[667]=998,[668]=998,[669]=998,[670]=998,[671]=998,[672]=998,[673]=998,[674]=998,[675]=998,[676]=998,[677]=998,[678]=998,[679]=998,[680]=998,[681]=998,[682]=998,[683]=998,[684]=998,[685]=998,[686]=998,[687]=998,[688]=998,[689]=998,[690]=998,[691]=998,[692]=998,[693]=998,[694]=998,[695]=998,[696]=998,[697]=998,[698]=998,[699]=998,[700]=998,[701]=998,[702]=998,[703]=998,[704]=998,[705]=998,[706]=998,[707]=998,[708]=998,[709]=998,[710]=998,[711]=998,[712]=998,[713]=998,[714]=998,[715]=998,[716]=998,[717]=998,[718]=998,[719]=998,[720]=998,[721]=998,[722]=998,[723]=998,[724]=998,[725]=998,[726]=998,[727]=998,[728]=998,[729]=998,[730]=998,[731]=998,[732]=998,[733]=998,[734]=998,[735]=998,[736]=998,[737]=998,[738]=998,[739]=998,[740]=998,[741]=998,[742]=998,[743]=998,[744]=998,[745]=998,[746]=998,[747]=998,[748]=998,[749]=998,[750]=998,[751]=998,[752]=998,[753]=998,[754]=998,[755]=998,[756]=998,[757]=998,[758]=998,[759]=998,[760]=998,[761]=998,[762]=998,[763]=998,[764]=998,[765]=998,[766]=998,[767]=998,[768]=998,[769]=998,[770]=998,[1163]=9,[1164]=9,[1165]=9,[1166]=9,[1167]=9,[1168]=9,[1169]=9,[1170]=9,[1171]=9,[1172]=9,[1173]=4,[1174]=9,[1175]=9,[1176]=9,[1177]=9,[1178]=9,[1179]=9,[1180]=9,[1181]=9,[1182]=9,[1183]=9,[1184]=9,[1186]=9,[1187]=9,[1188]=9,[1191]=29,[1192]=29,[1193]=29,[1194]=9,[1195]=4,[1196]=4,[1197]=4,[1198]=9,[1199]=4,[1200]=4,[1201]=4,[1202]=9,[1203]=4,[1204]=4,[1205]=4,[1206]=4,[1207]=29,[1208]=29,[1209]=29,[1210]=29,[1211]=9,[1212]=9,[1213]=9,[1214]=9,[1215]=9,[1216]=9,[1217]=9,[1218]=9,[1219]=9,[1220]=9,[1221]=9,[1222]=9,[1223]=9,[1224]=29,[1225]=9,[1226]=29,[1227]=29,[1243]=499,[1244]=499,[1245]=9,[1246]=9,[1247]=9,[1248]=9,[1249]=9,[1250]=9,[1251]=9,[1252]=9,[1253]=9,[1254]=9,[1255]=9,[1256]=9,[1257]=9,[1258]=9,[1259]=9,[1260]=9,[1261]=9,[1262]=9,[1263]=9,[1264]=9,[1265]=9,[1266]=9,[1267]=9,[1268]=9,[1269]=9,[1270]=9,[1271]=9,[1272]=9,[1273]=9,[1274]=9,[1275]=9,[1276]=4,[1277]=9,[1278]=9,[1279]=4,[1280]=4,[1281]=4,[1282]=4,[1283]=4,[1284]=4,[1285]=4,[1286]=4,[1287]=4,[1289]=1,[1290]=1,[1291]=1,[1292]=4,[1293]=4,[1294]=4,[1295]=4,[1296]=4,[1297]=4,[1298]=4,[1299]=4,[1300]=4,[1301]=4,[1302]=4,[1303]=4,[1304]=4,[1305]=4,[1306]=4,[1307]=4,[1308]=4,[1309]=4,[1310]=4,[1311]=4,[1312]=499,[1314]=499,[1316]=499,[1317]=499,[1319]=499,[1321]=499,[1322]=499,[1324]=499,[1326]=499,[1327]=499,[1329]=499,[1331]=499,[1332]=998,[1333]=998,[1334]=998,[1335]=998,[1336]=998,[1337]=499,[1338]=499,[1339]=499,[1342]=499,[1343]=499,[1344]=499,[1345]=499,[1346]=499,[1347]=499,[1357]=9,[1358]=9,[1359]=9,[1360]=9,[1361]=9,[1363]=9,[1365]=9,[1366]=49,[1388]=499,[1393]=2,[1394]=2,[1395]=2,[1397]=499,[1398]=499,[1399]=499,[1400]=499,[1401]=499,[1402]=499,[1403]=998,[1404]=499,[1405]=499,[1406]=499,[1407]=499,[1408]=499,[1409]=499,[1410]=499,[1411]=499,[1412]=499,[1413]=499,[1414]=499,[1415]=499,[1416]=499,[1417]=499,[1418]=499,[1419]=499,[1420]=499,[1421]=499,[1422]=499,[1423]=499,[1424]=499,[1425]=499,[1426]=499,[1427]=499,[1428]=499,[1429]=499,[1430]=499,[1431]=499,[1432]=499,[1433]=499,[1434]=499,[1435]=499,[1436]=499,[1437]=499,[1438]=499,[1439]=499,[1528]=998,[1529]=998,[1530]=998,[1531]=998,[1532]=998,[1533]=998,[1534]=8,[1535]=8,[1536]=8,[1537]=8,[1538]=8,[1539]=8,[1540]=8,[1542]=998,[1543]=998,[1544]=998,[1545]=998,[1546]=998,[1547]=998,[1548]=998,[1549]=998,[1550]=998,[1551]=998,[1552]=998,[1553]=998,[1554]=998,[1555]=998,[1561]=998,[1562]=998,[1564]=998,[1565]=998,[1577]=998,[1581]=998,[1582]=998,[1583]=998,[1584]=998,[1585]=998,[1586]=998,[1587]=998,[1601]=9,[1602]=9,[1603]=9,[1604]=9,[1605]=9,[1606]=9,[1607]=9,[1610]=9,[1620]=9,[1623]=9,[1624]=9,[1625]=9,[1626]=9,[1627]=9,[1628]=9,[1629]=9,[1630]=9,[1631]=9,[1632]=9,[1633]=9,[1635]=9,[1636]=9,[1637]=9,[1638]=9,[1639]=9,[1640]=9,[1641]=9,[1642]=9,[1643]=9,[1644]=9,[1645]=9,[1646]=9,[1647]=9,[1648]=9,[1649]=9,[1650]=9,[1651]=9,[1652]=9,[1653]=9,[1654]=9,[1655]=9,[1656]=9,[1657]=9,[1658]=9,[1659]=9,[1660]=9,[1661]=9,[1662]=4,[1663]=9,[1664]=9,[1665]=9,[1668]=9,[1669]=9,[1670]=9,[1671]=4,[1672]=9,[1673]=9,[1674]=9,[1675]=9,[1676]=9,[1677]=9,[1678]=9,[1679]=9,[1680]=9,[1681]=9,[1682]=9,[1683]=9,[1684]=4,[1685]=9,[1686]=9,[1687]=9,[1688]=9,[1689]=9,[1690]=9,[1691]=9,[1692]=9,[1693]=4,[1694]=4,[1695]=4,[1696]=4,[1697]=9,[1698]=9,[1699]=9,[1700]=9,[1701]=9,[1702]=4,[1703]=499,[1704]=499,[1705]=499,[1708]=4,[1709]=4,[1710]=4,[1711]=29,[1712]=29,[1713]=9,[1714]=9,[1715]=9,[1716]=9,[1717]=9,[1718]=9,[1719]=9,[1720]=9,[1721]=9,[1722]=9,[1723]=499,[1724]=499,[1725]=9,[1726]=9,[1727]=9,[1728]=9,[1729]=9,[1730]=9,[1731]=9,[1732]=49,[1733]=49,[1734]=49,[1735]=49,[1736]=49,[1737]=49,[1738]=49,[1739]=49,[1740]=49,[1741]=49,[1742]=49,[1743]=49,[1744]=49,[1745]=49,[1746]=49,[1747]=49,[1748]=49,[1749]=49,[1750]=49,[1751]=49,[1752]=49,[1753]=49,[1754]=49,[1755]=49,[1756]=49,[1757]=49,[1758]=49,[1759]=2,[1760]=2,[1761]=2,[1762]=2,[1763]=2,[1764]=2,[1765]=2,[1766]=2,[1767]=2,[1768]=2,[1769]=2,[1770]=2,[1771]=2,[1772]=2,[1773]=499,[1774]=499,[1775]=499,[1776]=499,[1777]=499,[1778]=499,[1779]=499,[1780]=499,[1781]=499,[1782]=499,[1821]=998,[1822]=998,[1823]=998,[1824]=998,[1825]=998,[1826]=998,[1827]=998,[1828]=998,[1829]=998,[1830]=998,[1831]=998,[1832]=998,[1833]=998,[1834]=998,[1835]=998,[1836]=499,[1837]=499,[1838]=499,[1841]=29,[1842]=4,[1843]=998,[1844]=998,[1845]=998,[1846]=4,[1847]=4,[1848]=8,[1849]=8,[1850]=8,[1876]=1,[1877]=9,[1888]=9,[1889]=9,[1890]=9,[1891]=9,[1892]=9,[1893]=9,[1894]=499,[1895]=499,[1896]=499,[1897]=499,[1898]=499,[1899]=499,[1900]=499,[1901]=499,[1902]=9,[1908]=499,[1911]=998,[1912]=998,[1913]=998,[1914]=998,[1915]=998,[1942]=9,[1943]=9,[1957]=998,[1962]=8,[1963]=8,[1964]=8,[1974]=998,[1975]=998,[1976]=998,[1980]=998,[2034]=998,[2035]=998,[2036]=998,[2037]=998,[2038]=998,[2039]=998,[2060]=9,[2065]=499,[2067]=499,[2070]=4,[2071]=4,[2072]=4,[2073]=4,[2074]=4,[2078]=499,[2079]=499,[2080]=499,[2081]=499,[2102]=29,[2103]=29,[2104]=499,[2107]=499,[2108]=499,[2171]=4,[2182]=199,[2183]=99,[2184]=49,[2185]=199,[2186]=99,[2187]=49,[2188]=199,[2189]=99,[2190]=49,[2191]=199,[2192]=99,[2193]=49,[2194]=199,[2195]=199,[2196]=149,[2197]=9,[2198]=19,[2199]=4,[2200]=4,[2201]=2,[2202]=2,[2203]=2,[2204]=2,[2205]=2,[2206]=2,[2234]=2,[2235]=2,[2236]=2,[2237]=299,[2238]=149,[2239]=99,[2240]=9,[2241]=99,[2258]=199,[2259]=199,[2277]=29,[2315]=2,[2316]=4,[2317]=4,[2318]=2,[2319]=998,[2320]=998,[2321]=998,[2322]=1,[2323]=2,[2324]=4,[2325]=1,[2326]=2,[2327]=4,[2328]=1,[2329]=2,[2330]=4,[2331]=1,[2332]=2,[2333]=4,[2334]=1,[2335]=2,[2336]=4,[2337]=1,[2338]=2,[2339]=4,[2340]=1,[2341]=2,[2342]=4,[2343]=1,[2344]=2,[2345]=4,[2346]=9,[2347]=14,[2348]=19,[2349]=5,[2350]=9,[2351]=2,[2352]=5,[2353]=9,[2354]=2,[2355]=5,[2356]=9,[2357]=2,[2358]=5,[2359]=9,[2360]=2,[2361]=5,[2362]=9,[2363]=2,[2364]=5,[2365]=9,[2366]=2,[2367]=1,[2368]=2,[2369]=1,[2370]=2,[2371]=1,[2372]=2,[2373]=1,[2374]=2,[2375]=1,[2376]=2,[2377]=1,[2378]=2,[2379]=1,[2380]=2,[2381]=1,[2382]=2,[2383]=1,[2384]=2,[2385]=1,[2386]=2,[2387]=1,[2388]=2,[2389]=1,[2390]=2,[2391]=1,[2392]=2,[2393]=1,[2394]=2,[2395]=1,[2396]=2,[2397]=1,[2398]=2,[2399]=1,[2400]=2,[2401]=1,[2402]=2,[2403]=1,[2404]=2,[2405]=1,[2406]=2,[2407]=1,[2408]=2,[2409]=1,[2410]=2,[2411]=1,[2412]=2,[2413]=1,[2414]=2,[2415]=1,[2416]=2,[2417]=1,[2418]=2,[2419]=1,[2420]=2,[2421]=5,[2422]=9,[2423]=5,[2424]=9,[2425]=5,[2426]=9,[2449]=4,[2450]=4,[2451]=2,[2452]=2,[2453]=2,[2454]=2,[2455]=2,[2456]=2,[2458]=1,[2460]=1,[2462]=1,[2464]=1,[2466]=1,[2468]=1,[2470]=1,[2472]=1,[2474]=1,[2476]=1,[2478]=1,[2480]=1,[2482]=1,[2484]=1,[2486]=1,[2488]=1,[2490]=1,[2492]=1,[2494]=1,[2496]=1,[2498]=1,[2500]=1,[2502]=1,[2504]=1,[2506]=1,[2508]=1,[2510]=1,[2511]=2,[2512]=2,[2513]=2}
local exe='likeadragon8.exe'
local expectedHash='8814e7c07caad4079f82461e4d5c7e26'
local function equal(a,b)
  if not a or not b or #a~=#b then return false end
  for i=1,#a do if a[i]~=b[i] then return false end end
  return true
end
local function bytes(a,n) return readBytes(a,n,true) end
local function tell(message)
  S.error=message
  if not S.closing then showMessage(message) end
  return false
end
local function module(pid)
  for _,m in ipairs(enumModules(pid) or {}) do
    if m.Name:lower()==exe then return m end
  end
end
records.ufosticky=list.getMemoryRecordByID(70)
local function anyActive()
  if S.shogiPending or S.mahjongPending or S.mahjongWait or S.sujimonGrowthTimer then return true end
  for _,active in pairs(S.active) do if active then return true end end
  return false
end
local function identity(pid)
  local m=module(pid)
  if not m then return nil,'Start Like a Dragon: Infinite Wealth first.' end
  local path=m.PathToFile:gsub('/','\\'):lower()
  if not path:match('\\likeadragon8\\runtime\\media\\likeadragon8%.exe$') then
    return nil,'Use the supported Steam installation of Like a Dragon: Infinite Wealth.'
  end
  local _,v=getFileVersion(m.PathToFile)
  if not v or v.major~=1 or v.minor~=0 or v.release~=0 or v.build~=0 or m.Size~=0x1326D000 or md5file(m.PathToFile)~=expectedHash then
    return nil,'This table supports version 1.20, Steam build 17233673. The executable does not match.'
  end
  return {pid=pid,base=m.Address,path=m.PathToFile}
end
local function attach()
  if anyActive() then return getOpenedProcessID()==S.context.pid end
  local candidates={}
  for pid,name in pairs(getProcesslist()) do
    if name:lower()==exe then candidates[#candidates+1]=tonumber(pid) end
  end
  if #candidates~=1 then
    schoolGroup.Active=false;dondokoGroup.Active=false;sujimonGroup.Active=false
    S.context=nil
    S.attachError=#candidates==0 and 'Start Like a Dragon: Infinite Wealth first.' or 'Close the extra game instance before using this table.'
    return false
  end
  local pid=candidates[1]
  local m=module(pid)
  if not m then return false end
  if not S.context or S.context.pid~=pid or S.context.base~=m.Address then
    local c,reason=identity(pid)
    if not c then S.attachError=reason;return false end
    S.context=c
  end
  if getOpenedProcessID()~=pid then openProcess(pid) end
  S.attachError=nil
  return getOpenedProcessID()==pid
end
local function ready()
  if not attach() then return tell(S.attachError or 'Select the supported game process before enabling this option.') end
  local c=S.context
  local p=readQword(c.base+0x38C8750)
  if not p or p==0 or readQword(p)~=c.base+0x2B03680 or readQword(p+0x3A0)~=c.base+0x2B0AA00 then
    return tell('Load your save before enabling MAIN.')
  end
  return true
end
local function put(a,b)
  if not writeBytes(a,b) or not equal(bytes(a,#b),b) then error('Memory write did not verify') end
end
local function paused(action)
  local ok,reason=pcall(pause)
  if not ok then return false,reason end
  local success,result=pcall(action)
  local resumed,resumeError=pcall(unpause)
  if not resumed then return false,resumeError end
  return success and result~=false,success and nil or result
end
local function branch(address,target,length)
  local delta=target-address-5
  assert(delta&gt;=-0x80000000 and delta&lt;=0x7FFFFFFF,'Code page is too far away')
  local b={0xE9}
  for i=0,3 do b[#b+1]=(delta &gt;&gt; (8*i)) &amp; 255 end
  while #b&lt;length do b[#b+1]=0x90 end
  return b
end
local assembly=[==[define(sujimonPointsFlag,SUJIMON_POINTS_FLAG)
label(sujimonCurrency)
define(woodenTagsFlag,WOODEN_TAGS_FLAG)
label(woodenCurrency)
define(deliveryPointsFlag,DELIVERY_POINTS_FLAG)
label(deliveryCurrency)
define(chaseEntry,CHASE_ENTRY)
define(chaseInputEntry,CHASE_INPUT_ENTRY)
define(chaseFlag,CHASE_FLAG)
define(chaseReturn,CHASE_RETURN)
define(chaseButtonPath,CHASE_BUTTON_PATH)
define(chaseInputReturn,CHASE_INPUT_RETURN)
label(chaseNormal)
label(chaseInputNormal)
label(KatzyIWChaseEnd)
label(KatzyIWChaseInputEnd)
registersymbol(KatzyIWChaseEnd)
registersymbol(KatzyIWChaseInputEnd)
define(emojiEntry,EMOJI_ENTRY)
define(emojiFlag,EMOJI_FLAG)
define(emojiReturn,EMOJI_RETURN)
label(emojiNormal)
label(KatzyIWEmojiEnd)
registersymbol(KatzyIWEmojiEnd)
define(matchEntry,MATCH_ENTRY)
define(matchFlag,MATCH_FLAG)
define(matchReturn,MATCH_RETURN)
define(matchAutoEntry,MATCH_AUTO_ENTRY)
define(matchComboEntry,MATCH_COMBO_ENTRY)
define(matchAutoFlag,MATCH_AUTO_FLAG)
define(matchAutoReturn,MATCH_AUTO_RETURN)
define(matchComboReturn,MATCH_COMBO_RETURN)
define(matchInput,MATCH_INPUT)
label(matchNormal)
label(matchScoreReady)
label(matchAutoNormal)
label(matchComboNormal)
label(KatzyIWMatchEnd)
label(KatzyIWMatchAutoEnd)
label(KatzyIWMatchComboEnd)
registersymbol(KatzyIWMatchEnd)
registersymbol(KatzyIWMatchAutoEnd)
registersymbol(KatzyIWMatchComboEnd)
define(encounterEntry,ENCOUNTER_ENTRY)
define(snapEntry,SNAP_ENTRY)
define(snapFlag,SNAP_FLAG)
define(snapReturn,SNAP_RETURN)
define(snapPointsFlag,SNAP_POINTS_FLAG)
label(snapNormal)
label(snapCurrency)
label(snapAllowanceDone)
label(KatzyIWSnapEnd)
registersymbol(KatzyIWSnapEnd)
define(encounterFlag,ENCOUNTER_FLAG)
define(encounterReturn,ENCOUNTER_RETURN)
label(encounterNormal)
label(KatzyIWEncounterEnd)
registersymbol(KatzyIWEncounterEnd)
define(tagEntry,TAG_ENTRY)
define(tagFlag,TAG_FLAG)
define(tagReturn,TAG_RETURN)
label(tagNormal)
label(tagDone)
label(KatzyIWTagEnd)
registersymbol(KatzyIWTagEnd)
define(fishingEntry,FISHING_ENTRY)
define(fishingFlag,FISHING_FLAG)
define(fishingReturn,FISHING_RETURN)
define(fishingWait,FISHING_WAIT)
define(fishingHalf,FISHING_HALF)
label(fishingOriginal)
label(fishingNegative)
label(fishingPress)
label(fishingRestore)
label(KatzyIWFishingEnd)
registersymbol(KatzyIWFishingEnd)
define(bondEntry,BOND_ENTRY)
define(bondFlag,BOND_FLAG)
define(bondReturn,BOND_RETURN)
label(bondOriginal)
label(KatzyIWBondEnd)
registersymbol(KatzyIWBondEnd)
define(karaokeEntry,KARAOKE_ENTRY)
define(karaokeFlag,KARAOKE_FLAG)
define(karaokeReturn,KARAOKE_RETURN)
define(karaokeDone,KARAOKE_DONE)
define(karaokeHit,KARAOKE_HIT)
define(karaokeScore,KARAOKE_SCORE)
label(karaokeOriginal)
label(karaokeExit)
label(karaokeTime)
label(KatzyIWKaraokeEnd)
registersymbol(KatzyIWKaraokeEnd)
define(healthEntry,%X)
define(percentEntry,%X)
define(partyGuard,%X)
define(moneyEntry,%X)
define(healthFlag,%X)
define(moneyFlag,%X)
define(manager,%X)
define(managerType,%X)
define(partyType,%X)
define(healthReturn,%X)
define(percentReturn,%X)
define(manaEntry,%X)
define(manaPercentEntry,%X)
define(manaGuard,%X)
define(manaFlag,%X)
define(manaReturn,%X)
define(manaPercentReturn,%X)
define(combatHealthEntry,%X)
define(combatManaEntry,%X)
define(perfectGuardEntry,%X)
define(playerFighterType,%X)
define(combatHealthReturn,%X)
define(combatManaReturn,%X)
define(perfectGuardFlag,%X)
define(perfectGuardReturn,%X)
define(perfectGuardEligible,%X)
define(skillMashEntry,%X)
define(skillTimedEntry,%X)
define(skillParty,%X)
define(skillFlag,%X)
define(skillMashReturn,%X)
define(skillMashSkip,%X)
define(skillTimedReturn,%X)
define(skillTimedSkip,%X)
define(battleRoster,%X)
define(battleRosterType,%X)
define(itemEntry,%X)
define(itemFlag,%X)
define(itemOwner,%X)
define(itemTargets,%X)
define(itemReturn,%X)
define(shogiPointsFlag,%X)
define(skillIdentityEntry,IDENTITY_ENTRY)
define(skillActorIdentity,ACTOR_IDENTITY)
define(actorRegistry,ACTOR_REGISTRY)
define(levelEntry,LEVEL_ENTRY)
define(levelFlag,LEVEL_FLAG)
define(levelReturn,LEVEL_RETURN)
define(characterIds,CHARACTER_IDS)
define(jobEntry,JOB_ENTRY)
define(jobFlag,JOB_FLAG)
define(jobReturn,JOB_RETURN)
define(pokerChipsFlag,POKER_CHIPS_FLAG)
define(pokerWinEntry,POKER_WIN_ENTRY)
define(pokerWinFlag,POKER_WIN_FLAG)
define(pokerManager,POKER_MANAGER)
define(pokerWinReturn,POKER_WIN_RETURN)
define(pokerSpendEntry,POKER_SPEND_ENTRY)
define(pokerSpendReturn,POKER_SPEND_RETURN)
define(dartsEntry,DARTS_ENTRY)
define(dartsFlag,DARTS_FLAG)
define(dartsReturn,DARTS_RETURN)
label(dartsDone)
label(KatzyIWDartsEnd)
registersymbol(KatzyIWDartsEnd)
label(pokerSpendOriginal)
label(pokerSpendExit)
label(pokerSpendAllowed)
label(KatzyIWSpendEnd)
registersymbol(KatzyIWSpendEnd)
label(pokerCurrency)
label(pokerCurrencySelected)
label(pokerDone)
label(pokerValidateLoop)
label(pokerRankLoop)
label(KatzyIWMoneyEnd)
label(KatzyIWPokerEnd)
registersymbol(KatzyIWMoneyEnd)
registersymbol(KatzyIWPokerEnd)
label(jobDone)
label(jobPartyLoop)
label(jobFound)
label(KatzyIWLevelEnd)
label(KatzyIWJobEnd)
registersymbol(KatzyIWLevelEnd)
registersymbol(KatzyIWJobEnd)
label(levelDone)
label(levelPartyLoop)
label(levelSlot)
label(levelSlotLoop)
label(levelFound)
label(moneySelect)
label(moneyValidate)
label(itemOriginal)
label(skillMashOriginal)
label(skillMashContinue)
label(skillTimedOriginal)
label(skillTimedContinue)
label(skillPartyDone)
label(skillPartyLoop)
label(skillPartyFound)
label(skillPartyNext)
label(combatHealthDone)
label(combatManaDone)
label(perfectGuardOriginal)
label(healthDone)
label(percentDone)
label(guardDone)
label(guardLoop)
label(guardFound)
label(moneyOriginal)
label(moneyPool)
label(moneyRead)
label(moneyDone)
label(manaDone)
label(manaPercentDone)
label(manaGuardDone)
label(manaGuardLoop)
label(manaGuardFound)
jobEntry:
mov edx,r14d
mov rcx,r13
pushfq
push rax
push r8
push r9
cmp byte ptr [jobFlag],1
jne jobDone
mov rax,[manager]
test rax,rax
jz jobDone
mov r8,managerType
cmp [rax],r8
jne jobDone
mov r8,partyType
cmp [rax+3A0],r8
jne jobDone
mov r8d,[rax+6364]
test r8d,r8d
jz jobDone
cmp r8d,A
ja jobDone
mov r9,[rax+6358]
test r9,r9
jz jobDone
jobPartyLoop:
cmp [r9],ebp
je jobFound
add r9,04
dec r8d
jnz jobPartyLoop
jmp jobDone
jobFound:
cmp byte ptr [rcx+02],1
jb jobDone
cmp byte ptr [rcx+02],63
jae jobDone
mov r8d,[rcx+04]
test r8d,r8d
js jobDone
mov eax,118CCF54
sub eax,r8d
cmp edx,eax
cmovl edx,eax
jobDone:
pop r9
pop r8
pop rax
popfq
jmp jobReturn
KatzyIWJobEnd:
levelEntry:
mov rdx,r15
mov r15,[rsp+20]
pushfq
push rax
push rcx
push r8
push r9
cmp byte ptr [levelFlag],1
jne levelDone
mov rax,[manager]
test rax,rax
jz levelDone
mov rcx,managerType
cmp [rax],rcx
jne levelDone
mov rcx,partyType
cmp [rax+3A0],rcx
jne levelDone
mov r8d,[rax+6364]
test r8d,r8d
jz levelDone
cmp r8d,A
ja levelDone
mov rcx,[rax+6358]
test rcx,rcx
jz levelDone
levelPartyLoop:
cmp [rcx],r13d
je levelSlot
add rcx,04
dec r8d
jnz levelPartyLoop
jmp levelDone
levelSlot:
mov rcx,characterIds
lea r9,[rax+3D8]
mov r8d,A
levelSlotLoop:
cmp [rcx],r13d
je levelFound
add rcx,04
add r9,7F8
dec r8d
jnz levelSlotLoop
jmp levelDone
levelFound:
cmp r9,r15
jne levelDone
cmp byte ptr [r15+08],1
jb levelDone
cmp byte ptr [r15+08],63
jae levelDone
mov rcx,[r15]
test rcx,rcx
js levelDone
mov eax,9B41A592
sub rax,rcx
cmp rdx,rax
cmovl rdx,rax
levelDone:
pop r9
pop r8
pop rcx
pop rax
popfq
jmp levelReturn
KatzyIWLevelEnd:
healthEntry:
pushfq
push r9
call partyGuard
test r9,r9
jz healthDone
cmp rdx,[rcx]
cmovl rdx,[rcx]
healthDone:
pop r9
popfq
mov r8,[rcx+08]
cmp rdx,r8
jmp healthReturn
percentEntry:
test r8,r8
cmovg rax,r8
pushfq
push r9
call partyGuard
test r9,r9
jz percentDone
cmp rax,[rcx]
cmovl rax,[rcx]
percentDone:
pop r9
popfq
jmp percentReturn
partyGuard:
push rax
push r8
xor r9d,r9d
cmp byte ptr [healthFlag],1
jne guardDone
mov rax,[manager]
test rax,rax
jz guardDone
mov r8,managerType
cmp [rax],r8
jne guardDone
mov r8,partyType
cmp [rax+3A0],r8
jne guardDone
add rax,3A8
mov r8d,A
guardLoop:
cmp rcx,rax
je guardFound
add rax,7F8
dec r8d
jnz guardLoop
jmp guardDone
guardFound:
cmp qword ptr [rcx],0
jle guardDone
mov r9d,1
guardDone:
pop r8
pop rax
ret
moneyEntry:
push r9
push r10
xor r10d,r10d
cmp edx,1
je moneySelect
cmp edx,9D
jne pokerCurrency
cmp byte ptr [shogiPointsFlag],1
jne moneyOriginal
jmp moneyValidate
pokerCurrency:
cmp edx,249
je sujimonCurrency
cmp edx,75
je woodenCurrency
cmp edx,239
je deliveryCurrency
cmp edx,24B
je snapCurrency
cmp edx,76
je pokerCurrencySelected
cmp edx,252
jne moneyOriginal
pokerCurrencySelected:
cmp byte ptr [pokerChipsFlag],1
jne moneyOriginal
jmp moneyValidate
sujimonCurrency:
cmp byte ptr [sujimonPointsFlag],1
jne moneyOriginal
jmp moneyValidate
woodenCurrency:
cmp byte ptr [woodenTagsFlag],1
jne moneyOriginal
jmp moneyValidate
deliveryCurrency:
cmp byte ptr [deliveryPointsFlag],1
jne moneyOriginal
jmp moneyValidate
snapCurrency:
cmp byte ptr [snapPointsFlag],1
jne moneyOriginal
jmp moneyValidate
moneySelect:
cmp byte ptr [moneyFlag],1
jne moneyOriginal
moneyValidate:
mov rax,[manager]
test rax,rax
jz moneyOriginal
mov r9,managerType
cmp [rax],r9
jne moneyOriginal
mov r9,partyType
cmp [rax+3A0],r9
jne moneyOriginal
add rax,6890
cmp rcx,rax
jne moneyOriginal
mov r10d,55D4A80
cmp edx,1
je moneyOriginal
mov r10d,15F90
cmp edx,24B
jne snapAllowanceDone
mov r10d,DBBA0
snapAllowanceDone:
moneyOriginal:
cmp r8d,3
jb moneyPool
mov rax,rcx
jmp moneyRead
moneyPool:
mov eax,r8d
lea rax,[rax+rax*2]
shl rax,4
add rax,rcx
moneyRead:
mov ecx,edx
mov rax,[rax]
mov rax,[rax+rcx*8]
test r10,r10
jz moneyDone
add rax,r10
moneyDone:
pop r10
pop r9
ret
KatzyIWMoneyEnd:
manaEntry:
pushfq
push r9
call manaGuard
test r9,r9
jz manaDone
cmp edx,[rcx]
cmovl edx,[rcx]
manaDone:
pop r9
popfq
mov r8d,[rcx+04]
cmp edx,r8d
jmp manaReturn
manaPercentEntry:
test edx,edx
cmovg eax,edx
pushfq
push r9
call manaGuard
test r9,r9
jz manaPercentDone
cmp eax,[rcx]
cmovl eax,[rcx]
manaPercentDone:
pop r9
popfq
jmp manaPercentReturn
manaGuard:
push rax
push r8
xor r9d,r9d
cmp byte ptr [manaFlag],1
jne manaGuardDone
mov rax,[manager]
test rax,rax
jz manaGuardDone
mov r8,managerType
cmp [rax],r8
jne manaGuardDone
mov r8,partyType
cmp [rax+3A0],r8
jne manaGuardDone
add rax,3B8
mov r8d,A
manaGuardLoop:
cmp rcx,rax
je manaGuardFound
add rax,7F8
dec r8d
jnz manaGuardLoop
jmp manaGuardDone
manaGuardFound:
mov r9d,1
manaGuardDone:
pop r8
pop rax
ret
combatHealthEntry:
pushfq
push rax
cmp byte ptr [healthFlag],1
jne combatHealthDone
mov rax,playerFighterType
cmp [rcx],rax
jne combatHealthDone
cmp qword ptr [rcx+1FB8],0
jle combatHealthDone
cmp rdx,[rcx+1FB8]
cmovl rdx,[rcx+1FB8]
combatHealthDone:
pop rax
popfq
mov [rsp+10],rbx
jmp combatHealthReturn
combatManaEntry:
pushfq
push rax
cmp byte ptr [manaFlag],1
jne combatManaDone
mov rax,playerFighterType
cmp [rcx],rax
jne combatManaDone
cmp edx,[rcx+2138]
cmovl edx,[rcx+2138]
combatManaDone:
pop rax
popfq
mov [rsp+08],rbx
jmp combatManaReturn
perfectGuardEntry:
pushfq
cmp byte ptr [perfectGuardFlag],1
jne perfectGuardOriginal
popfq
jmp perfectGuardEligible
perfectGuardOriginal:
popfq
mov r9d,[rsp+58]
jmp perfectGuardReturn
skillMashEntry:
pushfq
push r9
call skillParty
test r9,r9
jz skillMashOriginal
push rax
mov eax,[rsi+30]
dec eax
mov [rsi+58],eax
pop rax
pop r9
popfq
jmp skillMashReturn
skillMashOriginal:
pop r9
popfq
test eax,eax
jnz skillMashContinue
jmp skillMashSkip
skillMashContinue:
jmp skillMashReturn
skillTimedEntry:
pushfq
push r9
call skillParty
test r9,r9
pop r9
jz skillTimedOriginal
popfq
mov ebx,edi
jmp skillTimedContinue
skillTimedOriginal:
popfq
test eax,eax
jnz skillTimedContinue
jmp skillTimedSkip
skillTimedContinue:
mov [rsi+54],ebx
jmp skillTimedReturn
skillParty:
push rax
push r8
push r10
xor r9d,r9d
cmp byte ptr [skillFlag],1
jne skillPartyDone
mov rax,[battleRoster]
test rax,rax
jz skillPartyDone
mov r8,battleRosterType
cmp [rax],r8
jne skillPartyDone
mov r10d,[rsi+18]
test r10d,r10d
jz skillPartyDone
mov eax,r10d
and eax,FFFFF
cmp eax,80000
jae skillPartyDone
shl rax,5
mov r8,actorRegistry
add rax,r8
shr r10d,14
cmp word ptr [rax+08],r10w
jne skillPartyDone
cmp word ptr [rax+0C],3
jne skillPartyDone
mov rax,[rax]
test rax,rax
jz skillPartyDone
call skillIdentityEntry
mov r10d,[rsi+18]
mov rax,[battleRoster]
add rax,158
mov r8d,4
skillPartyLoop:
cmp [rax],r10d
je skillPartyFound
test r9d,r9d
jz skillPartyNext
cmp [rax],r9d
je skillPartyFound
skillPartyNext:
add rax,160
dec r8d
jnz skillPartyLoop
xor r9d,r9d
jmp skillPartyDone
skillPartyFound:
mov r9d,1
skillPartyDone:
pop r10
pop r8
pop rax
ret
skillIdentityEntry:
push rcx
push rdx
push r11
sub rsp,90
movups [rsp+30],xmm0
movups [rsp+40],xmm1
movups [rsp+50],xmm2
movups [rsp+60],xmm3
movups [rsp+70],xmm4
movups [rsp+80],xmm5
mov rcx,rax
lea rdx,[rsp+20]
mov dword ptr [rsp+20],0
call skillActorIdentity
mov r9d,[rsp+20]
movups xmm0,[rsp+30]
movups xmm1,[rsp+40]
movups xmm2,[rsp+50]
movups xmm3,[rsp+60]
movups xmm4,[rsp+70]
movups xmm5,[rsp+80]
add rsp,90
pop r11
pop rdx
pop rcx
ret
itemEntry:
pushfq
push rax
push r10
cmp byte ptr [itemFlag],1
jne itemOriginal
mov rax,[manager]
test rax,rax
jz itemOriginal
cmp [itemOwner],rax
jne itemOriginal
add rax,6950
cmp rcx,rax
jne itemOriginal
test r9d,r9d
jnz itemOriginal
cmp edx,9D3
jae itemOriginal
mov r10,itemTargets
mov eax,edx
mov eax,[r10+rax*4]
test eax,eax
jz itemOriginal
mov r8d,eax
itemOriginal:
pop r10
pop rax
popfq
mov [rsp+08],rbx
jmp itemReturn
pokerWinEntry:
pushfq
push rdx
push r8
push r9
push r10
push r11
cmp byte ptr [pokerWinFlag],1
jne pokerDone
test byte ptr [rdi+24],4
jnz pokerDone
cmp [pokerManager],rax
jne pokerDone
cmp [rax+18],rdi
jne pokerDone
mov r8,[rax+28]
test r8,r8
jz pokerDone
test byte ptr [r8+2AC],0C
jnz pokerDone
mov r9,[rax+20]
test r9,r9
jz pokerDone
mov r10,[r9+18]
test r10,r10
jz pokerDone
cmp [r10+08],r8
jne pokerDone
xor edx,edx
pokerValidateLoop:
mov r11,rdx
shl r11,4
mov r11,[r10+r11+08]
test r11,r11
jz pokerDone
cmp [r11+2B0],edx
jne pokerDone
inc edx
cmp edx,4
jb pokerValidateLoop
xor edx,edx
pokerRankLoop:
mov r11,rdx
shl r11,4
mov r11,[r10+r11+08]
mov dword ptr [r11+2A8],2
inc edx
cmp edx,4
jb pokerRankLoop
mov dword ptr [r8+2A8],0
mov [r9+28],r8
mov dword ptr [r9+48],1
pokerDone:
pop r11
pop r10
pop r9
pop r8
pop rdx
popfq
mov rcx,[rax+20]
mov r12d,[rcx+48]
jmp pokerWinReturn
KatzyIWPokerEnd:
pokerSpendEntry:
push r8
cmp byte ptr [pokerChipsFlag],1
jne pokerSpendOriginal
mov r8,pokerManager
mov r8,[r8]
test r8,r8
jz pokerSpendOriginal
mov r8,[r8+28]
test r8,r8
jz pokerSpendOriginal
add r8,278
cmp rcx,r8
jne pokerSpendOriginal
mov eax,[rcx+08]
cmp eax,edx
jb pokerSpendOriginal
sub eax,edx
cmp eax,15F90
jae pokerSpendExit
pokerSpendAllowed:
mov eax,15F90
pokerSpendExit:
mov [rcx+08],eax
mov al,1
pop r8
ret
pokerSpendOriginal:
pop r8
mov eax,[rcx+08]
cmp eax,edx
jmp pokerSpendReturn
KatzyIWSpendEnd:
dartsEntry:
vmovss xmm1,[rax+3BC]
pushfq
cmp byte ptr [dartsFlag],1
jne dartsDone
push rax
mov eax,3F000000
vmovd xmm1,eax
pop rax
dartsDone:
popfq
jmp dartsReturn
KatzyIWDartsEnd:

// Each native note update owns a valid note and its feedback handles.
// Complete taps at their start, sustained notes at their end. Until due,
// bypass manual judgement so incidental input cannot spoil automatic play.
karaokeEntry:
cmp byte ptr [karaokeFlag],1
jne karaokeOriginal
cmp dword ptr [rbx+14],3
jne karaokeDone
cmp dword ptr [rbx+10],2
ja karaokeOriginal
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
sub rsp,80
movdqu [rsp+20],xmm0
movdqu [rsp+30],xmm1
movdqu [rsp+40],xmm2
movdqu [rsp+50],xmm3
movdqu [rsp+60],xmm4
movdqu [rsp+70],xmm5
movss xmm0,[rbx]
cmp dword ptr [rbx+10],0
je karaokeTime
maxss xmm0,[rbx+04]
karaokeTime:
movss xmm1,[rbx+24]
ucomiss xmm1,xmm0
jp karaokeExit
jb karaokeExit
mov dword ptr [rbx+14],2
mov rcx,rbx
call karaokeHit
mov rcx,rbx
call karaokeScore
karaokeExit:
movdqu xmm0,[rsp+20]
movdqu xmm1,[rsp+30]
movdqu xmm2,[rsp+40]
movdqu xmm3,[rsp+50]
movdqu xmm4,[rsp+60]
movdqu xmm5,[rsp+70]
add rsp,80
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
jmp karaokeDone
karaokeOriginal:
cmp dword ptr [rbx+14],3
jne karaokeDone
jmp karaokeReturn
KatzyIWKaraokeEnd:

// Current trust award, after native companion eligibility checks.
bondEntry:
mov r14,[rbp+5F]
cmp byte ptr [bondFlag],1
jne bondOriginal
test r14,r14
jle bondOriginal
cmp dword ptr [rbp-45],64
jae bondOriginal
cmp r14,E10
jge bondOriginal
mov r14d,E10
mov [rbp+5F],r14
bondOriginal:
test r14,r14
jmp bondReturn
KatzyIWBondEnd:

// Only the ordinary fishing prompt, after native actor and prompt resolution.
fishingEntry:
cmp byte ptr [fishingFlag],1
jne fishingOriginal
cmp dword ptr [rsi+30],2
jne fishingOriginal
sub rsp,10
movdqu [rsp],xmm0
xor eax,eax
movss xmm0,[rsi+4C]
mulss xmm0,[fishingHalf]
test dword ptr [rsi+3C],80000000
jnz fishingNegative
comiss xmm0,[rsi+48]
jp fishingRestore
ja fishingRestore
jmp fishingPress
fishingNegative:
comiss xmm0,[rsi+48]
jp fishingRestore
jb fishingRestore
fishingPress:
movss [rsi+48],xmm0
mov eax,[rsi+34]
fishingRestore:
movdqu xmm0,[rsp]
add rsp,10
fishingOriginal:
test eax,eax
je fishingWait
jmp fishingReturn
KatzyIWFishingEnd:

// Dedicated current Tag gauge reader, after the native party meter resolver.
tagEntry:
cmp byte ptr [tagFlag],1
jne tagNormal
mov eax,[rax+04]
jmp tagDone
tagNormal:
mov eax,[rax]
tagDone:
add rsp,20
jmp tagReturn
KatzyIWTagEnd:

// Street encounter AI: suppress gradual and close-range detection alike.
// Keep the sensor result in memory unchanged; route this update through
// its native undetected branch so the UI and attention state also clear.
encounterEntry:
pushfq
cmp byte ptr [encounterFlag],1
jne encounterNormal
mov dword ptr [rsi+2F0],0
mov ecx,0
popfq
jmp encounterReturn
encounterNormal:
popfq
mov ecx,[rsi+2E0]
jmp encounterReturn
KatzyIWEncounterEnd:

// The native shutter path has already selected a new eligible target.
// Supply best quality and chance timing; retain its type and native scoring.
snapEntry:
cmp byte ptr [snapFlag],1
jne snapNormal
mov dil,1
mov r15b,1
snapNormal:
mov ecx,13FA
test dil,dil
jmp snapReturn
KatzyIWSnapEnd:

// Player reply judgement only; NPC text bypasses this native branch.
// Preserve better earned scores; native rating and subsequent award consume
// the same pending gain and penalty fields. Never write the mood gauge.
matchEntry:
mov rax,[rdi+78]
pushfq
cmp byte ptr [matchFlag],1
jne matchNormal
cmp dword ptr [rax+08],14
jae matchScoreReady
mov dword ptr [rax+08],14
matchScoreReady:
mov dword ptr [rax+0C],0
matchNormal:
popfq
mov r12d,[rax+08]
jmp matchReturn
KatzyIWMatchEnd:

// Native expected-button query, once per sequence update; the caller advances
// and completes the input through its ordinary success branch.
matchAutoEntry:
cmp byte ptr [matchAutoFlag],1
jne matchAutoNormal
mov eax,1
jmp matchAutoReturn
matchAutoNormal:
call matchInput
jmp matchAutoReturn
KatzyIWMatchAutoEnd:

matchComboEntry:
cmp byte ptr [matchAutoFlag],1
jne matchComboNormal
mov eax,1
jmp matchComboReturn
matchComboNormal:
call matchInput
jmp matchComboReturn
KatzyIWMatchComboEnd:

// Roulette result dispatch after the native stop/timeout resolution.
// Emoji 99 selects Excellent, and timing band 0 selects its best multiplier.
// Native reward, reaction and result-message construction remain in charge.
emojiEntry:
cmp byte ptr [emojiFlag],1
jne emojiNormal
mov r12d,63
mov dword ptr [r13+24],0
emojiNormal:
mov ecx,r12d
sub ecx,61
jmp emojiReturn
KatzyIWEmojiEnd:

// The native dispatcher has already excluded resolved/inactive prompts.
// Type A is the chase-specific input resolver, including directional prompts.
chaseEntry:
mov rcx,rbx
cmp byte ptr [chaseFlag],1
jne chaseNormal
cmp dword ptr [rbx+30],0A
jne chaseNormal
jmp chaseButtonPath
chaseNormal:
test al,8
jmp chaseReturn
KatzyIWChaseEnd:

// Slot zero is the requested input, the other three are incorrect alternatives.
// Retain native UI ownership, one-shot completion and success callbacks.
chaseInputEntry:
cmp byte ptr [chaseFlag],1
jne chaseInputNormal
cmp dword ptr [rbx+30],0A
jne chaseInputNormal
test rdi,rdi
sete al
movzx eax,al
chaseInputNormal:
mov [rsp+rdi*4+20],eax
inc rdi
jmp chaseInputReturn
KatzyIWChaseInputEnd:

define(crazyRankFlag,CRAZY_RANK_FLAG)
define(crazyRankBorders,CRAZY_RANK_BORDERS)
label(crazyRankDone)
define(crazyEntry,CRAZY_ENTRY)
define(crazyTimerEntry,CRAZY_TIMER_ENTRY)
define(crazyExtremeFlag,CRAZY_EXTREME_FLAG)
define(crazyFoodFlag,CRAZY_FOOD_FLAG)
define(crazyTimerFlag,CRAZY_TIMER_FLAG)
define(crazyHandle,CRAZY_HANDLE)
define(crazyRegistry,CRAZY_REGISTRY)
define(crazyType,CRAZY_TYPE)
define(crazyReturn,CRAZY_RETURN)
define(crazyDone,CRAZY_DONE)
define(crazyExtreme,CRAZY_EXTREME)
define(crazyBonus,CRAZY_BONUS)
define(crazyTimerReturn,CRAZY_TIMER_RETURN)
define(crazyTimerDone,CRAZY_TIMER_DONE)
label(crazyRestore)
label(crazyFoodNext)
label(crazyFoodFind)
label(crazyFoodRight)
label(crazyFoodChild)
label(crazyFoodFound)
label(crazyBonusCheck)
label(crazyBonusFill)
label(crazyExtremeCheck)
label(crazyNormal)
label(crazyTimerNormal)
label(crazyTimerSkip)
label(KatzyIWCrazyEnd)
label(KatzyIWCrazyTimerEnd)
registersymbol(KatzyIWCrazyEnd)
registersymbol(KatzyIWCrazyTimerEnd)

crazyEntry:
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
sub rsp,80
movdqu [rsp+20],xmm0
movdqu [rsp+30],xmm1
movdqu [rsp+40],xmm2
movdqu [rsp+50],xmm3
movdqu [rsp+60],xmm4
movdqu [rsp+70],xmm5
mov rax,crazyType
cmp [r8],rax
jne crazyRestore
cmp [r8+118],rbx
jne crazyRestore
mov eax,[r8+1F8]
sub eax,3
cmp eax,1
ja crazyRestore
mov eax,[r8+0C]
mov [crazyHandle],eax
cmp byte ptr [crazyRankFlag],1
jne crazyRankDone
mov eax,[r8+0CC]
cmp eax,9
ja crazyRankDone
test eax,eax
jz crazyRankDone
mov r10,crazyRankBorders
mov eax,[r10+rax*4]
test eax,eax
jz crazyRankDone
cmp [r8+0D4],eax
jae crazyRankDone
mov [r8+0D4],eax
crazyRankDone:
mov eax,[r8+0C]
cmp byte ptr [crazyFoodFlag],1
jne crazyBonusCheck
mov rdx,[r8+120]
test rdx,rdx
jz crazyBonusCheck
cmp [rdx],eax
jne crazyBonusCheck
mov r9d,1
crazyFoodNext:
mov r10,[rdx+10]
mov r11d,10
crazyFoodFind:
test r10,r10
jz crazyFoodChild
movsx rax,word ptr [r10+0E]
add rax,r10
cmp [rax+10],r9d
je crazyFoodFound
jb crazyFoodRight
mov r10,[r10]
jmp crazyFoodChild
crazyFoodRight:
mov r10,[r10+8]
crazyFoodChild:
shl r10,10
shr r10,10
dec r11d
jz crazyFoodFound
test r10,r10
jnz crazyFoodFind
xor eax,eax
crazyFoodFound:
test r10,r10
jz crazyExtremeCheck
test r11d,r11d
jz crazyExtremeCheck
cmp [rax+14],r9d
jne crazyExtremeCheck
cmp dword ptr [rax+18],64
ja crazyExtremeCheck
mov dword ptr [rax+18],64
crazyExtremeCheck:
add r9d,2
cmp r9d,5
jbe crazyFoodNext
crazyBonusCheck:
cmp byte ptr [crazyExtremeFlag],1
jne crazyRestore
mov r8,[rsp+98]
cmp dword ptr [r8+0D8],0
jg crazyBonusFill
mov rcx,r8
call crazyBonus
crazyBonusFill:
mov r8,[rsp+98]
mov dword ptr [r8+0D8],41A00000
cmp dword ptr [rbx+0C],3
je crazyRestore
mov rcx,rbx
call crazyExtreme
crazyRestore:
movdqu xmm0,[rsp+20]
movdqu xmm1,[rsp+30]
movdqu xmm2,[rsp+40]
movdqu xmm3,[rsp+50]
movdqu xmm4,[rsp+60]
movdqu xmm5,[rsp+70]
add rsp,80
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
cmp byte ptr [crazyExtremeFlag],1
jne crazyNormal
cmp dword ptr [r8+1F8],3
jb crazyNormal
cmp dword ptr [r8+1F8],4
ja crazyNormal
cmp dword ptr [rbx+0C],3
jne crazyNormal
jmp crazyDone
crazyNormal:
cmp dword ptr [rcx+2B0],1
jmp crazyReturn
KatzyIWCrazyEnd:

crazyTimerEntry:
pushfq
push rax
push rdx
push r8
cmp byte ptr [crazyTimerFlag],1
jne crazyTimerNormal
mov eax,[crazyHandle]
test eax,eax
jz crazyTimerNormal
mov edx,eax
and eax,FFFFF
cmp eax,80000
jae crazyTimerNormal
shl rax,5
mov r8,crazyRegistry
add r8,rax
shr edx,14
cmp word ptr [r8+8],dx
jne crazyTimerNormal
cmp word ptr [r8+0C],3
jne crazyTimerNormal
mov r8,[r8]
test r8,r8
jz crazyTimerNormal
mov rax,crazyType
cmp [r8],rax
jne crazyTimerNormal
mov eax,[r8+1F8]
sub eax,3
cmp eax,1
ja crazyTimerNormal
mov eax,[r8+0D0]
mov edx,eax
and eax,FFFFF
cmp eax,80000
jae crazyTimerNormal
shl rax,5
mov r8,crazyRegistry
add r8,rax
shr edx,14
cmp word ptr [r8+8],dx
jne crazyTimerNormal
cmp word ptr [r8+0C],4
jne crazyTimerNormal
cmp [r8],rcx
je crazyTimerSkip
crazyTimerNormal:
pop r8
pop rdx
pop rax
popfq
cmp byte ptr [rcx+98],0
jmp crazyTimerReturn
crazyTimerSkip:
pop r8
pop rdx
pop rax
popfq
jmp crazyTimerDone
KatzyIWCrazyTimerEnd:

// Lemonade timer entities from the installed Hawaii event data.
// Only suppress the native decrement; preserve expiry, UI and event handling.
define(lemonEntry,LEMON_ENTRY)
define(lemonFlag,LEMON_FLAG)
define(lemonType,LEMON_TYPE)
define(lemonReturn,LEMON_RETURN)
define(anacondaTimerFlag,ANACONDA_TIMER_FLAG)
label(anacondaTimer)
label(lemonNormal)
label(lemonSkip)
label(KatzyIWLemonEnd)
registersymbol(KatzyIWLemonEnd)

lemonEntry:
pushfq
push rax
mov rax,lemonType
cmp [r15],rax
jne lemonNormal
mov rax,08AF014D00000A03
cmp [r15+30],rax
je anacondaTimer
cmp byte ptr [lemonFlag],1
jne lemonNormal
mov rax,08BB014D00000AA9
cmp [r15+30],rax
je lemonSkip
mov rax,092E014D0000078F
cmp [r15+30],rax
je lemonSkip
mov rax,092E014D00000790
cmp [r15+30],rax
je lemonSkip
jmp lemonNormal
anacondaTimer:
cmp byte ptr [anacondaTimerFlag],1
jne lemonNormal
cmp dword ptr [r15+0C0],0
je lemonNormal
mov dword ptr [r15+0C0],107AC0
jmp lemonSkip
lemonNormal:
pop rax
popfq
mov [r15+0C0],eax
jmp lemonReturn
lemonSkip:
pop rax
popfq
jmp lemonReturn
KatzyIWLemonEnd:

define(oichoEntry,OICHO_ENTRY)
define(oichoFlag,OICHO_FLAG)
define(oichoHandle,OICHO_HANDLE)
define(oichoRegistry,OICHO_REGISTRY)
define(oichoType,OICHO_TYPE)
define(oichoPlayerType,OICHO_PLAYER_TYPE)
define(oichoReturn,OICHO_RETURN)
label(oichoDone)
label(oichoPlayerChallenger)
label(oichoReverse)
label(KatzyIWOichoEnd)
registersymbol(KatzyIWOichoEnd)
oichoEntry:
pushfq
push rax
push r8
push r9
push r10
push r11
cmp byte ptr [oichoFlag],1
jne oichoDone
mov eax,[oichoHandle]
test eax,eax
jz oichoDone
mov r8d,eax
and r8d,FFFFF
cmp r8d,80000
jae oichoDone
shl r8,5
mov r9,oichoRegistry
add r8,r9
shr eax,14
cmp [r8+08],ax
jne oichoDone
cmp word ptr [r8+0C],3
jne oichoDone
mov r8,[r8]
test r8,r8
jz oichoDone
mov r9,oichoType
cmp [r8],r9
jne oichoDone
test rcx,rcx
jz oichoDone
mov eax,[rcx+14]
cmp eax,4
jae oichoDone
cmp [r8+rax*8+720],rcx
jne oichoDone
mov eax,[r8+768]
cmp eax,4
jae oichoDone
mov r9,[r8+rax*8+720]
test r9,r9
jz oichoDone
cmp r9,rcx
je oichoDone
test byte ptr [r9+10],1
jz oichoDone
mov r8,[r8+720]
test r8,r8
jz oichoDone
mov r10,oichoPlayerType
cmp [r8],r10
jne oichoDone
cmp r8,rcx
je oichoPlayerChallenger
cmp r8,r9
jne oichoDone
cmp dl,1
jne oichoDone
movsxd r10,dword ptr [rcx+44]
test r10,r10
jle oichoDone
jmp oichoReverse
oichoPlayerChallenger:
test dl,dl
jnz oichoDone
movsxd r10,dword ptr [rcx+44]
test r10,r10
jge oichoDone
oichoReverse:
mov r11d,r10d
neg r11d
jo oichoDone
movsxd rax,dword ptr [r9+44]
lea rax,[rax+r10*2]
movsxd r8,eax
cmp rax,r8
jne oichoDone
mov [r9+44],eax
mov [rcx+44],r11d
xor dl,1
oichoDone:
pop r11
pop r10
pop r9
pop r8
pop rax
popfq
mov [rsp+08],rbx
jmp oichoReturn
KatzyIWOichoEnd:

define(koiPointsEntry,KOI_POINTS_ENTRY)
define(koiPointsFlag,KOI_POINTS_FLAG)
define(koiPointsReturn,KOI_POINTS_RETURN)
define(koiPointsType,KOI_POINTS_TYPE)
define(koiEvaluate,KOI_EVALUATE)
define(koiPointTable,KOI_POINT_TABLE)
label(koiPointsDone)
label(koiMaximum)
label(koiRemove)
label(koiScoreLoop)
label(koiScoreAdd)
label(koiScoreNext)
label(koiAnimals)
label(koiRibbons)
label(koiJunk)
label(koiCount)
label(koiCountLoop)
label(koiMaximumDone)
label(KatzyIWKoiPointsEnd)
registersymbol(KatzyIWKoiPointsEnd)
koiPointsEntry:
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
cmp byte ptr [koiPointsFlag],1
jne koiPointsDone
cmp dword ptr [rbx+88],0
jne koiPointsDone
cmp [rbx+28],rbp
jne koiPointsDone
mov rax,koiPointsType
cmp [rbp],rax
jne koiPointsDone
sub rsp,28
mov rcx,rbx
call koiMaximum
cmp edi,eax
cmovb edi,eax
add rsp,28
koiPointsDone:
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
cmp byte ptr [rbx+12E],1
jmp koiPointsReturn
koiMaximum:
push rbx
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
sub rsp,C8
mov rsi,[rcx+20]
lea r12,[rsp+30]
mov rdi,r12
mov ecx,13
rep movsq
mov r13,FFFFFFFFFFFF
mov rax,[r12+70]
mov rdx,FFFFFFF7FFFFFFFF
and rax,rdx
mov rdx,[r12+88]
not rdx
and rax,rdx
mov ecx,0C
xor r15d,r15d
koiRemove:
test rax,rax
jz koiMaximumDone
mov rdx,rax
neg rdx
and rdx,rax
xor r13,rdx
xor rax,rdx
dec ecx
jnz koiRemove
mov rcx,r12
mov rdx,r13
call koiEvaluate
mov ebx,eax
mov ebp,1
mov r14,koiPointTable
koiScoreLoop:
mov ecx,1F
sub ecx,ebp
bt ebx,ecx
jnc koiScoreNext
mov edx,[r14+rbp*4]
cmp ebp,0A
je koiAnimals
cmp ebp,0B
je koiRibbons
cmp ebp,0C
je koiJunk
jmp koiScoreAdd
koiAnimals:
mov rax,[r12+60]
sub edx,5
jmp koiCount
koiRibbons:
mov rax,[r12+68]
sub edx,5
jmp koiCount
koiJunk:
mov rax,[r12+70]
sub edx,0A
koiCount:
and rax,r13
test rax,rax
jz koiScoreAdd
koiCountLoop:
lea rcx,[rax-1]
inc edx
and rax,rcx
jnz koiCountLoop
koiScoreAdd:
add r15d,edx
koiScoreNext:
inc ebp
cmp ebp,10
jb koiScoreLoop
koiMaximumDone:
mov eax,r15d
add rsp,C8
pop r15
pop r14
pop r13
pop r12
pop rdi
pop rsi
pop rbp
pop rbx
ret
KatzyIWKoiPointsEnd:

define(koiFlag,KOI_FLAG)
define(koiType,KOI_TYPE)
define(koiAiHand,KOI_AI_HAND)
define(koiAiField,KOI_AI_FIELD)
define(koiBankBranch,KOI_BANK_BRANCH)
define(koiHandEntry,KOI_HAND_ENTRY)
define(koiHandReturn,KOI_HAND_RETURN)
define(koiFieldEntry,KOI_FIELD_ENTRY)
define(koiFieldReturn,KOI_FIELD_RETURN)
define(koiInputEntry,KOI_INPUT_ENTRY)
define(koiInputReturn,KOI_INPUT_RETURN)
define(koiBankEntry,KOI_BANK_ENTRY)
define(koiBankReturn,KOI_BANK_RETURN)
define(koiConfirm0,KOI_CONFIRM_0)
define(koiConfirm1,KOI_CONFIRM_1)
define(koiConfirm2,KOI_CONFIRM_2)
define(koiConfirm3,KOI_CONFIRM_3)
define(koiConfirm4,KOI_CONFIRM_4)
define(koiConfirm5,KOI_CONFIRM_5)
label(koiHandNormal)
label(KatzyIWKoiHandEnd)
registersymbol(KatzyIWKoiHandEnd)
koiHandEntry:
pushfq
push rax
cmp byte ptr [koiFlag],1
jne koiHandNormal
mov rax,koiType
cmp [rcx],rax
jne koiHandNormal
cmp dword ptr [rcx+08],0
jne koiHandNormal
pop rax
popfq
push rbx
sub rsp,30
mov rbx,rcx
mov eax,[rbx+5C]
mov [rsp+20],eax
mov eax,[rbx+0C]
mov [rsp+24],eax
mov dword ptr [rbx+5C],FE000000
mov dword ptr [rbx+0C],3
call koiAiHand
mov ecx,[rsp+20]
mov [rbx+5C],ecx
mov ecx,[rsp+24]
mov [rbx+0C],ecx
add rsp,30
pop rbx
ret
koiHandNormal:
pop rax
popfq
push rbx
sub rsp,40
jmp koiHandReturn
KatzyIWKoiHandEnd:
label(koiFieldNormal)
label(KatzyIWKoiFieldEnd)
registersymbol(KatzyIWKoiFieldEnd)
koiFieldEntry:
pushfq
push rax
cmp byte ptr [koiFlag],1
jne koiFieldNormal
mov rax,koiType
cmp [rcx],rax
jne koiFieldNormal
cmp dword ptr [rcx+08],0
jne koiFieldNormal
pop rax
popfq
jmp koiAiField
koiFieldNormal:
pop rax
popfq
push rbx
sub rsp,50
jmp koiFieldReturn
KatzyIWKoiFieldEnd:
label(koiInputNormal)
label(koiInputConfirm)
label(KatzyIWKoiInputEnd)
registersymbol(KatzyIWKoiInputEnd)
koiInputEntry:
pushfq
push r11
cmp byte ptr [koiFlag],1
jne koiInputNormal
mov r11,koiConfirm0
cmp [rsp+10],r11
je koiInputConfirm
mov r11,koiConfirm1
cmp [rsp+10],r11
je koiInputConfirm
mov r11,koiConfirm2
cmp [rsp+10],r11
je koiInputConfirm
mov r11,koiConfirm3
cmp [rsp+10],r11
je koiInputConfirm
mov r11,koiConfirm4
cmp [rsp+10],r11
je koiInputConfirm
mov r11,koiConfirm5
cmp [rsp+10],r11
je koiInputConfirm
koiInputNormal:
pop r11
popfq
push rbx
sub rsp,20
jmp koiInputReturn
koiInputConfirm:
pop r11
popfq
mov eax,1
ret
KatzyIWKoiInputEnd:
label(koiBankNormal)
label(KatzyIWKoiBankEnd)
registersymbol(KatzyIWKoiBankEnd)
koiBankEntry:
cmp byte ptr [koiFlag],1
jne koiBankNormal
cmp dword ptr [rbx+88],0
jne koiBankNormal
mov eax,1
koiBankNormal:
test eax,eax
jne koiBankBranch
jmp koiBankReturn
KatzyIWKoiBankEnd:

define(stickyEntry,STICKY_ENTRY)
define(stickyFlag,STICKY_FLAG)
define(stickyState,STICKY_STATE)
define(stickyReturn,STICKY_RETURN)
define(stickyCallback,UFO_CALLBACK)
define(stickyActors,STICKY_ACTORS)
define(stickyPhysics,STICKY_PHYSICS)
define(stickyBodyType,STICKY_BODY_TYPE)
define(stickyMove,STICKY_MOVE)
define(stickyWake,STICKY_WAKE)
label(stickyExit)
label(stickyClear)
label(stickyReady)
label(stickyContacts)
label(stickyArmLoop)
label(stickyContactArray)
label(stickyContactLoop)
label(stickyNextArm)
label(stickyFollow)
label(stickyFollowLoop)
label(stickyNextSlot)
label(stickyDiscard)
label(stickyActor)
label(stickyActorNull)
label(stickyBody)
label(stickyBodyNull)
label(stickyAccept)
label(stickyAcceptLoop)
label(stickyAcceptNext)
label(stickyAcceptFound)
label(stickyAcceptSlot)
label(stickyAcceptFree)
label(stickyAcceptDone)
label(KatzyIWStickyEnd)
registersymbol(KatzyIWStickyEnd)
stickyEntry:
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
push rbx
push rdi
push r12
push r13
push r14
push r15
sub rsp,100
vmovdqu [rsp+40],ymm0
vmovdqu [rsp+60],ymm1
vmovdqu [rsp+80],ymm2
vmovdqu [rsp+A0],ymm3
vmovdqu [rsp+C0],ymm4
vmovdqu [rsp+E0],ymm5
mov rax,stickyFlag
cmp byte ptr [rax],1
jne stickyExit
mov rax,stickyCallback
cmp [rsi+1D0],rax
jne stickyExit
cmp dword ptr [rsi+1E0],0
jne stickyExit
mov rbx,stickyState
mov rax,[rsi+1C8]
test rax,rax
jz stickyClear
mov rax,[rax-8]
test rax,rax
jz stickyClear
mov rdi,[rax+8]
test rdi,rdi
jz stickyClear
movzx eax,byte ptr [rdi+1FC]
cmp eax,1
ja stickyClear
imul eax,eax,1A0
cmp [rdi+rax+2F0],rsi
jne stickyClear
cmp byte ptr [rdi+559],24
jne stickyClear
movzx ecx,byte ptr [rsi+14E]
cmp ecx,3
jb stickyClear
cmp ecx,4
ja stickyClear
cmp [rbx],rsi
je stickyReady
mov [rbx],rsi
mov qword ptr [rbx+8],0
mov qword ptr [rbx+50],0
mov qword ptr [rbx+90],0
mov qword ptr [rbx+D0],0
mov qword ptr [rbx+110],0
mov qword ptr [rbx+150],0
mov qword ptr [rbx+190],0
mov qword ptr [rbx+1D0],0
mov qword ptr [rbx+210],0
stickyReady:
mov ecx,[rdi+rax+31C]
call stickyActor
test rax,rax
jz stickyClear
mov r12,[rax+E0]
mov r13d,[rax+EC]
test r12,r12
jz stickyClear
cmp r13d,40
ja stickyClear
test r13d,r13d
jz stickyClear
mov rax,[rsi+150]
test rax,rax
jz stickyClear
mov rax,[rax]
test rax,rax
jz stickyClear
movups xmm0,[rax+80]
movups [rsp+20],xmm0
cmp byte ptr [rsi+14E],3
jne stickyFollow
xor r14d,r14d
stickyArmLoop:
mov rax,[rsi+r14*8+160]
test rax,rax
jz stickyNextArm
mov r15,[rax+20]
test r15,r15
jz stickyNextArm
mov rax,[r15+60]
test rax,rax
jz stickyNextArm
mov rax,[rax+90]
test rax,rax
jz stickyContactArray
mov ecx,[rax+18]
call stickyAccept
stickyContactArray:
mov eax,[r15+158]
cmp eax,40
ja stickyNextArm
mov [rsp+30],eax
mov rax,[r15+150]
mov [rsp+38],rax
test rax,rax
jz stickyNextArm
xor r15d,r15d
stickyContactLoop:
cmp r15d,[rsp+30]
jae stickyNextArm
mov rax,[rsp+38]
mov rcx,[rax+r15*8]
mov rax,rcx
shr rax,20
and eax,F0000000
cmp eax,10000000
jne stickyContacts
call stickyAccept
stickyContacts:
inc r15d
jmp stickyContactLoop
stickyNextArm:
inc r14d
cmp r14d,2
jb stickyArmLoop
stickyFollow:
lea r14,[rbx+50]
mov r15d,8
stickyFollowLoop:
mov ecx,[r14]
test ecx,ecx
jz stickyNextSlot
call stickyBody
test rax,rax
jz stickyDiscard
mov rdi,rax
mov rcx,[r14+8]
cmp [rax+28],rcx
jne stickyDiscard
mov ecx,[r14+4]
call stickyActor
test rax,rax
jz stickyDiscard
mov rcx,[r14+8]
cmp [rax+30],rcx
jne stickyDiscard
mov rax,stickyFlag
cmp byte ptr [rax],1
jne stickyExit
movups xmm0,[rsp+20]
addps xmm0,[r14+10]
movups [rsp+30],xmm0
mov rcx,rdi
lea rdx,[rsp+30]
lea r8,[r14+20]
mov r9d,1
call stickyMove
mov rcx,rdi
xor edx,edx
call stickyWake
jmp stickyNextSlot
stickyDiscard:
mov qword ptr [r14],0
stickyNextSlot:
add r14,40
dec r15d
jnz stickyFollowLoop
jmp stickyExit
stickyClear:
mov qword ptr [rbx],0
stickyExit:
vmovdqu ymm0,[rsp+40]
vmovdqu ymm1,[rsp+60]
vmovdqu ymm2,[rsp+80]
vmovdqu ymm3,[rsp+A0]
vmovdqu ymm4,[rsp+C0]
vmovdqu ymm5,[rsp+E0]
add rsp,100
pop r15
pop r14
pop r13
pop r12
pop rdi
pop rbx
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
lea rcx,[rsi+1C0]
jmp stickyReturn

// Resolve a current entity handle; never follow stale registry entries.
stickyActor:
mov eax,ecx
and eax,FFFFF
cmp eax,80000
jae stickyActorNull
shl rax,5
mov rdx,stickyActors
add rdx,rax
shr ecx,14
cmp [rdx+8],cx
jne stickyActorNull
cmp word ptr [rdx+C],3
jne stickyActorNull
mov rax,[rdx]
ret
stickyActorNull:
xor eax,eax
ret

// Physics registry encoding derived from native 2822470.
stickyBody:
mov rdx,stickyPhysics
mov rdx,[rdx]
test rdx,rdx
jz stickyBodyNull
mov eax,ecx
and eax,FFFFF
cmp eax,[rdx+78]
jae stickyBodyNull
mov rdx,[rdx+70]
mov rax,[rdx+rax*8]
mov edx,eax
and edx,FFF
shr ecx,14
cmp edx,ecx
jne stickyBodyNull
shr rax,8
mov rdx,FFFFFFFFFFF0
and rax,rdx
test rax,rax
jz stickyBodyNull
mov rdx,stickyBodyType
cmp [rax],rdx
jne stickyBodyNull
ret
stickyBodyNull:
xor eax,eax
ret

// Accept only a real prize from this cabinet, not the arms or environment.
stickyAccept:
push rdi
sub rsp,20
call stickyBody
test rax,rax
jz stickyAcceptDone
mov rdi,rax
xor r10d,r10d
stickyAcceptLoop:
cmp r10d,r13d
jae stickyAcceptDone
mov ecx,[r12+r10*4]
call stickyActor
test rax,rax
jz stickyAcceptNext
mov rdx,[rax+30]
cmp [rdi+28],rdx
je stickyAcceptFound
stickyAcceptNext:
inc r10d
jmp stickyAcceptLoop
stickyAcceptFound:
mov r11d,[rdi+8]
lea r9,[rbx+50]
xor r8d,r8d
stickyAcceptSlot:
cmp [r9],r11d
je stickyAcceptDone
cmp dword ptr [r9],0
jne stickyAcceptFree
test r8,r8
cmovz r8,r9
stickyAcceptFree:
add r9,40
lea rax,[rbx+250]
cmp r9,rax
jb stickyAcceptSlot
test r8,r8
jz stickyAcceptDone
mov [r8],r11d
mov eax,[r12+r10*4]
mov [r8+4],eax
mov [r8+8],rdx
movups xmm0,[rdi+80]
subps xmm0,[rsp+50]
movups [r8+10],xmm0
movups xmm0,[rdi+90]
movups [r8+20],xmm0
stickyAcceptDone:
add rsp,20
pop rdi
ret
KatzyIWStickyEnd:

// Complete the two specific laptop choices after native menu initialization
// Native result uses zero-based valid-answer ordinals, not database row IDs.
// and after its lock is released. Use the game's normal submission handler.
define(anacondaQuizEntry,ANACONDA_QUIZ_ENTRY)
define(anacondaQuizFlag,ANACONDA_QUIZ_FLAG)
define(anacondaQuizReturn,ANACONDA_QUIZ_RETURN)
define(anacondaCommit,ANACONDA_COMMIT)
label(anacondaQuizExit)
label(anacondaQuizFind)
label(anacondaQuizLoop)
label(anacondaQuizSubmit)
label(KatzyIWAnacondaQuizEnd)
registersymbol(KatzyIWAnacondaQuizEnd)
anacondaQuizEntry:
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
sub rsp,100
vmovdqu [rsp+40],ymm0
vmovdqu [rsp+60],ymm1
vmovdqu [rsp+80],ymm2
vmovdqu [rsp+A0],ymm3
vmovdqu [rsp+C0],ymm4
vmovdqu [rsp+E0],ymm5
cmp byte ptr [anacondaQuizFlag],1
jne anacondaQuizExit
cmp dword ptr [rax+100],9
jne anacondaQuizExit
test dword ptr [rax+F8],120
jne anacondaQuizExit
xor edx,edx
cmp dword ptr [rax+1A0],124
je anacondaQuizFind
mov edx,1
cmp dword ptr [rax+1A0],16F
jne anacondaQuizExit
anacondaQuizFind:
xor r8d,r8d
anacondaQuizLoop:
cmp [rax+r8*4+11C],edx
je anacondaQuizSubmit
inc r8d
cmp r8d,20
jb anacondaQuizLoop
jmp anacondaQuizExit
anacondaQuizSubmit:
mov rcx,rax
xor edx,edx
call anacondaCommit
anacondaQuizExit:
vmovdqu ymm0,[rsp+40]
vmovdqu ymm1,[rsp+60]
vmovdqu ymm2,[rsp+80]
vmovdqu ymm3,[rsp+A0]
vmovdqu ymm4,[rsp+C0]
vmovdqu ymm5,[rsp+E0]
add rsp,100
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
mov rcx,[rbp+70]
xor rcx,rsp
jmp anacondaQuizReturn
KatzyIWAnacondaQuizEnd:

// SP refresh routine has already validated its party handle and entity.
define(sujimonEntry,SUJIMON_ENTRY)
define(sujimonFlag,SUJIMON_FLAG)
define(sujimonReturn,SUJIMON_RETURN)
define(sujimonPartyType,SUJIMON_PARTY_TYPE)
label(sujimonNormal)
label(KatzyIWSujimonEnd)
registersymbol(KatzyIWSujimonEnd)
sujimonEntry:
pushfq
push rax
cmp byte ptr [sujimonFlag],1
jne sujimonNormal
mov rax,sujimonPartyType
cmp [rdx],rax
jne sujimonNormal
cmp dword ptr [rdx+E0],1
jne sujimonNormal
cmp [rdx+F8],r8
jne sujimonNormal
mov eax,[r8+0C]
test eax,eax
jle sujimonNormal
cmp eax,7F800000
jae sujimonNormal
mov [r8+08],eax
sujimonNormal:
pop rax
popfq
mov ecx,[rdx+D0]
jmp sujimonReturn
KatzyIWSujimonEnd:


define(sujimonMpEntry,SUJIMON_MP_ENTRY)
define(sujimonMpFlag,SUJIMON_MP_FLAG)
define(sujimonMpReturn,SUJIMON_MP_RETURN)
define(sujimonTrainerType,SUJIMON_TRAINER_TYPE)
label(sujimonMpNormal)
label(KatzyIWSujimonMpEnd)
registersymbol(KatzyIWSujimonMpEnd)
sujimonMpEntry:
pushfq
push rax
push rdx
cmp byte ptr [sujimonMpFlag],1
jne sujimonMpNormal
mov rax,sujimonTrainerType
cmp [rcx],rax
jne sujimonMpNormal
cmp byte ptr [rcx+F0],1
jne sujimonMpNormal
mov rdx,[rcx+E0]
test rdx,rdx
je sujimonMpNormal
mov eax,[rcx+0C]
cmp [rdx],eax
jne sujimonMpNormal
mov eax,[rdx+10]
test eax,eax
jle sujimonMpNormal
cmp eax,7F800000
jae sujimonMpNormal
mov [rdx+08],eax
sujimonMpNormal:
pop rdx
pop rax
popfq
mov rcx,[rcx+E0]
jmp sujimonMpReturn
KatzyIWSujimonMpEnd:

define(sujimonRouletteEntry,SUJIMON_ROULETTE_ENTRY)
define(sujimonRouletteFlag,SUJIMON_ROULETTE_FLAG)
define(sujimonRouletteReturn,SUJIMON_ROULETTE_RETURN)
define(sujimonRouletteType,SUJIMON_ROULETTE_TYPE)
label(sujimonRouletteNormal)
label(KatzyIWSujimonRouletteEnd)
registersymbol(KatzyIWSujimonRouletteEnd)
sujimonRouletteEntry:
pushfq
push rdx
cmp byte ptr [sujimonRouletteFlag],1
jne sujimonRouletteNormal
mov rdx,sujimonRouletteType
cmp [rcx],rdx
jne sujimonRouletteNormal
cmp dword ptr [rcx+D4],0C
jne sujimonRouletteNormal
mov rdx,[rcx+C8]
test rdx,rdx
je sujimonRouletteNormal
mov rdx,[rdx+18]
test rdx,rdx
je sujimonRouletteNormal
cmp dword ptr [rdx],3
jne sujimonRouletteNormal
// Native angle zero selects pocket 3, whose installed result is LV_2.
mov dword ptr [rcx+130],0
sujimonRouletteNormal:
pop rdx
popfq
vmovss xmm3,[rcx+130]
jmp sujimonRouletteReturn
KatzyIWSujimonRouletteEnd:

define(recruitEffortEntry,RECRUIT_EFFORT_ENTRY)
define(recruitEffortFlag,RECRUIT_EFFORT_FLAG)
define(recruitEffortReturn,RECRUIT_EFFORT_RETURN)
label(recruitEffortNormal)
label(KatzyIWRecruitEffortEnd)
registersymbol(KatzyIWRecruitEffortEnd)
recruitEffortEntry:
pushfq
cmp byte ptr [recruitEffortFlag],1
jne recruitEffortNormal
mov dword ptr [rdx+48],3F800000
recruitEffortNormal:
popfq
mov eax,[rdx+48]
mov [r8+188],eax
jmp recruitEffortReturn
KatzyIWRecruitEffortEnd:

define(recruitTimeoutEntry,RECRUIT_TIMEOUT_ENTRY)
define(recruitTimeoutReturn,RECRUIT_TIMEOUT_RETURN)
label(recruitTimeoutNormal)
label(KatzyIWRecruitTimeoutEnd)
registersymbol(KatzyIWRecruitTimeoutEnd)
recruitTimeoutEntry:
pushfq
cmp byte ptr [recruitEffortFlag],1
jne recruitTimeoutNormal
mov dword ptr [rbx+48],3F800000
vmovss xmm0,[rbx+48]
recruitTimeoutNormal:
popfq
vmovss [rdi+188],xmm0
jmp recruitTimeoutReturn
KatzyIWRecruitTimeoutEnd:

define(recruitAutoEntry,RECRUIT_AUTO_ENTRY)
define(recruitAutoFlag,RECRUIT_AUTO_FLAG)
define(recruitAutoReturn,RECRUIT_AUTO_RETURN)
define(recruitPress,RECRUIT_PRESS)
define(recruitDelta,RECRUIT_DELTA)
label(recruitAutoNormal)
label(recruitAutoLoop)
label(recruitAutoDone)
label(KatzyIWRecruitAutoEnd)
registersymbol(KatzyIWRecruitAutoEnd)
recruitAutoEntry:
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
cmp byte ptr [recruitAutoFlag],1
jne recruitAutoNormal
// Native input opens at 0.25 seconds; the update clamps this clock at 0.5.
cmp byte ptr [rbx+54],0
jne recruitAutoNormal
cmp dword ptr [rbx+48],3E800000
jb recruitAutoNormal
cmp dword ptr [rbx+48],3F000000
ja recruitAutoNormal
// Validate the native countdown handle and require time remaining.
mov eax,[rbx+30]
test eax,eax
je recruitAutoNormal
mov ecx,eax
and ecx,FFFFF
cmp ecx,80000
jae recruitAutoNormal
shl rcx,5
shr eax,14
cmp [rcx+r12+8],ax
jne recruitAutoNormal
cmp word ptr [rcx+r12+0C],4
jne recruitAutoNormal
mov rax,[rcx+r12]
test rax,rax
je recruitAutoNormal
mov eax,[rax+78]
test eax,eax
jle recruitAutoNormal
cmp eax,7F800000
jae recruitAutoNormal
// Preserve volatile state and provide Windows x64 shadow space.
sub rsp,B0
movdqu [rsp+20],xmm0
movdqu [rsp+30],xmm1
movdqu [rsp+40],xmm2
movdqu [rsp+50],xmm3
movdqu [rsp+60],xmm4
movdqu [rsp+70],xmm5
mov [rsp+80],rbx
mov dword ptr [rsp+88],2
recruitAutoLoop:
mov eax,[rbx+4C]
cmp eax,[rbx+6C]
jae recruitAutoDone
cmp qword ptr [rbx+60],0
je recruitAutoDone
lea rcx,[rsp+80]
xor edx,edx
xor r8d,r8d
call recruitPress
dec dword ptr [rsp+88]
jne recruitAutoLoop
recruitAutoDone:
movdqu xmm0,[rsp+20]
movdqu xmm1,[rsp+30]
movdqu xmm2,[rsp+40]
movdqu xmm3,[rsp+50]
movdqu xmm4,[rsp+60]
movdqu xmm5,[rsp+70]
add rsp,B0
recruitAutoNormal:
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
vmovss xmm0,[recruitDelta]
jmp recruitAutoReturn
KatzyIWRecruitAutoEnd:

// Dondoko-only native resource, score, clock and heart paths. No polling.
define(dokoDelta,DOKO_DELTA)
define(dokoMoneyEntry,DOKO_MONEY_ENTRY)
define(dokoMoneyFlag,DOKO_MONEY_FLAG)
define(dokoMoneyReturn,DOKO_MONEY_RETURN)
label(dokoMoneyNormal)
label(KatzyIWDokoMoneyEnd)
registersymbol(KatzyIWDokoMoneyEnd)
dokoMoneyEntry:
mov rax,[rbx+98]
mov rbx,[rax+08]
pushfq
cmp byte ptr [dokoMoneyFlag],1
jne dokoMoneyNormal
add rbx,895440
dokoMoneyNormal:
popfq
jmp dokoMoneyReturn
KatzyIWDokoMoneyEnd:

define(dokoMaterialReadEntry,DOKO_MATERIALREAD_ENTRY)
define(dokoMaterialReadFlag,DOKO_MATERIALREAD_FLAG)
define(dokoMaterialReadReturn,DOKO_MATERIALREAD_RETURN)
label(dokoMaterialReadNormal)
label(KatzyIWDokoMaterialReadEnd)
registersymbol(KatzyIWDokoMaterialReadEnd)
dokoMaterialReadEntry:
mov rax,[rsi+38]
pushfq
cmp byte ptr [dokoMaterialReadFlag],1
jne dokoMaterialReadNormal
cmp r8d,6
ja dokoMaterialReadNormal
mov dword ptr [rax+r8*4],270F
dokoMaterialReadNormal:
popfq
mov edi,[rax+r8*4]
jmp dokoMaterialReadReturn
KatzyIWDokoMaterialReadEnd:

define(dokoMaterialCheckEntry,DOKO_MATERIALCHECK_ENTRY)
define(dokoMaterialCheckFlag,DOKO_MATERIALCHECK_FLAG)
define(dokoMaterialCheckReturn,DOKO_MATERIALCHECK_RETURN)
label(dokoMaterialCheckNormal)
label(KatzyIWDokoMaterialCheckEnd)
registersymbol(KatzyIWDokoMaterialCheckEnd)
dokoMaterialCheckEntry:
mov rax,[r13+38]
pushfq
cmp byte ptr [dokoMaterialCheckFlag],1
jne dokoMaterialCheckNormal
cmp edx,6
ja dokoMaterialCheckNormal
mov dword ptr [rax+rdx*4],270F
dokoMaterialCheckNormal:
popfq
mov r14d,[rax+rdx*4]
jmp dokoMaterialCheckReturn
KatzyIWDokoMaterialCheckEnd:

define(dokoMaterialSpendEntry,DOKO_MATERIALSPEND_ENTRY)
define(dokoMaterialSpendFlag,DOKO_MATERIALSPEND_FLAG)
define(dokoMaterialSpendReturn,DOKO_MATERIALSPEND_RETURN)
label(dokoMaterialSpendNormal)
label(KatzyIWDokoMaterialSpendEnd)
registersymbol(KatzyIWDokoMaterialSpendEnd)
dokoMaterialSpendEntry:
mov rax,[r14+38]
pushfq
cmp byte ptr [dokoMaterialSpendFlag],1
jne dokoMaterialSpendNormal
cmp r15d,6
ja dokoMaterialSpendNormal
mov dword ptr [rax+r15*4],270F
dokoMaterialSpendNormal:
popfq
mov esi,[rax+r15*4]
jmp dokoMaterialSpendReturn
KatzyIWDokoMaterialSpendEnd:

define(dokoTalentEntry,DOKO_TALENT_ENTRY)
define(dokoTalentFlag,DOKO_TALENT_FLAG)
define(dokoTalentReturn,DOKO_TALENT_RETURN)
label(dokoTalentNormal)
label(KatzyIWDokoTalentEnd)
registersymbol(KatzyIWDokoTalentEnd)
dokoTalentEntry:
mov eax,[rcx+1C]
pushfq
cmp byte ptr [dokoTalentFlag],1
jne dokoTalentNormal
mov eax,7616
dokoTalentNormal:
popfq
ret
KatzyIWDokoTalentEnd:

define(dokoSatisfactionEntry,DOKO_SATISFACTION_ENTRY)
define(dokoSatisfactionFlag,DOKO_SATISFACTION_FLAG)
define(dokoSatisfactionReturn,DOKO_SATISFACTION_RETURN)
label(dokoSatisfactionNormal)
label(KatzyIWDokoSatisfactionEnd)
registersymbol(KatzyIWDokoSatisfactionEnd)
dokoSatisfactionEntry:
lea eax,[rsi+rdi]
mov rcx,[rsp+B0]
pushfq
cmp byte ptr [dokoSatisfactionFlag],1
jne dokoSatisfactionNormal
mov eax,F423F
dokoSatisfactionNormal:
popfq
jmp dokoSatisfactionReturn
KatzyIWDokoSatisfactionEnd:

define(dokoPopularityEntry,DOKO_POPULARITY_ENTRY)
define(dokoPopularityFlag,DOKO_POPULARITY_FLAG)
define(dokoPopularityReturn,DOKO_POPULARITY_RETURN)
label(dokoPopularityNormal)
label(KatzyIWDokoPopularityEnd)
registersymbol(KatzyIWDokoPopularityEnd)
dokoPopularityEntry:
mov eax,esi
mov rcx,[rbp+12C0]
pushfq
cmp byte ptr [dokoPopularityFlag],1
jne dokoPopularityNormal
mov eax,1869F
dokoPopularityNormal:
popfq
jmp dokoPopularityReturn
KatzyIWDokoPopularityEnd:

define(dokoPopularityReadEntry,DOKO_POPULARITYREAD_ENTRY)
define(dokoPopularityReadFlag,DOKO_POPULARITYREAD_FLAG)
define(dokoPopularityReadReturn,DOKO_POPULARITYREAD_RETURN)
label(dokoPopularityReadNormal)
label(KatzyIWDokoPopularityReadEnd)
registersymbol(KatzyIWDokoPopularityReadEnd)
dokoPopularityReadEntry:
mov eax,[rax+1B4]
pushfq
cmp byte ptr [dokoPopularityReadFlag],1
jne dokoPopularityReadNormal
mov eax,1869F
dokoPopularityReadNormal:
popfq
jmp dokoPopularityReadReturn
KatzyIWDokoPopularityReadEnd:

define(dokoPopularityRankEntry,DOKO_POPULARITYRANK_ENTRY)
define(dokoPopularityRankFlag,DOKO_POPULARITYRANK_FLAG)
define(dokoPopularityRankReturn,DOKO_POPULARITYRANK_RETURN)
label(dokoPopularityRankNormal)
label(KatzyIWDokoPopularityRankEnd)
registersymbol(KatzyIWDokoPopularityRankEnd)
dokoPopularityRankEntry:
mov eax,[rax+1B4]
pushfq
cmp byte ptr [dokoPopularityRankFlag],1
jne dokoPopularityRankNormal
mov eax,1869F
dokoPopularityRankNormal:
popfq
jmp dokoPopularityRankReturn
KatzyIWDokoPopularityRankEnd:

define(dokoTimeEntry,DOKO_TIME_ENTRY)
define(dokoTimeFlag,DOKO_TIME_FLAG)
define(dokoTimeReturn,DOKO_TIME_RETURN)
label(dokoTimeNormal)
label(KatzyIWDokoTimeEnd)
registersymbol(KatzyIWDokoTimeEnd)
dokoTimeEntry:
pushfq
cmp byte ptr [dokoTimeFlag],1
jne dokoTimeNormal
popfq
jmp dokoTimeReturn
dokoTimeNormal:
popfq
vaddss xmm0,xmm0,dword ptr [dokoDelta]
jmp dokoTimeReturn
KatzyIWDokoTimeEnd:

define(dokoHealthEntry,DOKO_HEALTH_ENTRY)
define(dokoHealthFlag,DOKO_HEALTH_FLAG)
define(dokoHealthReturn,DOKO_HEALTH_RETURN)
label(dokoHealthNormal)
label(KatzyIWDokoHealthEnd)
registersymbol(KatzyIWDokoHealthEnd)
dokoHealthEntry:
pushfq
cmp byte ptr [dokoHealthFlag],1
jne dokoHealthNormal
mov [rax+30],ebx
dokoHealthNormal:
popfq
cmp [rax+30],ebx
cmovb ebx,[rax+30]
jmp dokoHealthReturn
KatzyIWDokoHealthEnd:


// Stored ingredients used by installed DIY and souvenir recipes; each native cap is 9,999.
define(dokoGoldOreEntry,DOKO_GOLDORE_ENTRY)
define(dokoGoldOreFlag,DOKO_GOLDORE_FLAG)
define(dokoGoldOreReturn,DOKO_GOLDORE_RETURN)
label(dokoGoldOreNormal)
label(dokoMaterialFill)
label(KatzyIWDokoGoldOreEnd)
registersymbol(KatzyIWDokoGoldOreEnd)
label(dokoMaterialCat1)
label(dokoMaterialCat2)
label(dokoMaterialCat5)
label(dokoMaterialCat6)
label(dokoMaterialCat7)
label(dokoMaterialCat8)
label(dokoMaterialCat12)
label(dokoMaterialCat13)
dokoGoldOreEntry:
mov ecx,[rax+rcx*8+08]
pushfq
cmp byte ptr [dokoGoldOreFlag],1
jne dokoGoldOreNormal
cmp ecx,1
je dokoMaterialCat1
cmp ecx,2
je dokoMaterialCat2
cmp ecx,5
je dokoMaterialCat5
cmp ecx,6
je dokoMaterialCat6
cmp ecx,7
je dokoMaterialCat7
cmp ecx,8
je dokoMaterialCat8
cmp ecx,C
je dokoMaterialCat12
cmp ecx,D
je dokoMaterialCat13
jmp dokoGoldOreNormal
dokoMaterialCat1:
cmp edx,6
je dokoMaterialFill
cmp edx,C
je dokoMaterialFill
cmp edx,20
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat2:
cmp edx,B
je dokoMaterialFill
cmp edx,C
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat5:
test edx,edx
jz dokoGoldOreNormal
cmp edx,9
jbe dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat6:
cmp edx,1
je dokoMaterialFill
cmp edx,A
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat7:
cmp edx,1
je dokoMaterialFill
cmp edx,2
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat8:
test edx,edx
jz dokoGoldOreNormal
cmp edx,8
jbe dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat12:
cmp edx,1
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialCat13:
cmp edx,1
je dokoMaterialFill
jmp dokoGoldOreNormal
dokoMaterialFill:
mov dword ptr [rdi+10],270F
dokoGoldOreNormal:
popfq
mov ebx,[rdi+10]
jmp dokoGoldOreReturn
KatzyIWDokoGoldOreEnd:

// Dondoko condition 14: dusk/night rest eligibility. Earlier busy, null-clock,
// and transition checks remain native. Only the local phase comparison changes.
define(dokoSleepEntry,DOKO_SLEEP_ENTRY)
define(dokoSleepFlag,DOKO_SLEEP_FLAG)
define(dokoSleepReturn,DOKO_SLEEP_RETURN)
label(dokoSleepNormal)
label(KatzyIWDokoSleepEnd)
registersymbol(KatzyIWDokoSleepEnd)
dokoSleepEntry:
mov ecx,[rcx+34]
cmp byte ptr [dokoSleepFlag],1
jne dokoSleepNormal
mov ecx,2
dokoSleepNormal:
sub ecx,2
jmp dokoSleepReturn
KatzyIWDokoSleepEnd:

// Select through the school UI, wait one second, then confirm normally.
define(schoolEntry,SCHOOL_ENTRY)
define(schoolFlag,SCHOOL_FLAG)
define(schoolReturn,SCHOOL_RETURN)
define(schoolState,SCHOOL_STATE)
define(schoolGet,SCHOOL_GET)
define(schoolSelect,SCHOOL_SELECT)
define(schoolBusy,SCHOOL_BUSY)
define(schoolConfirm,SCHOOL_CONFIRM)
define(schoolDelta,SCHOOL_DELTA)
label(schoolDone)
label(schoolReset)
label(schoolLoop)
label(schoolFound)
label(schoolIndexReady)
label(schoolNew)
label(schoolCheckSelection)
label(schoolWait)
label(KatzyIWSchoolEnd)
registersymbol(KatzyIWSchoolEnd)
schoolEntry:
pushfq
push rax
push rcx
push rdx
push r8
push r9
push r10
push r11
sub rsp,A0
movdqu [rsp+40],xmm0
movdqu [rsp+50],xmm1
movdqu [rsp+60],xmm2
movdqu [rsp+70],xmm3
movdqu [rsp+80],xmm4
movdqu [rsp+90],xmm5
cmp byte ptr [schoolFlag],1
jne schoolReset
mov r10,[rdi+28]
mov r11,[r10+58]
cmp dword ptr [r11],4
jne schoolReset
lea rcx,[r10+68]
mov edx,1133
call schoolBusy
test al,al
jnz schoolReset
mov rcx,[rdi+28]
add rcx,68
mov edx,1134
call schoolBusy
test al,al
jnz schoolReset
mov r10,[rdi+28]
mov edx,[rdi+80]
cmp edx,[r10+74]
jae schoolReset
cmp edx,40
jae schoolReset
mov r10,[r10+40]
test r10,r10
jz schoolReset
imul rdx,rdx,38
add r10,rdx
mov r8d,[r10+2C]
test r8d,r8d
jz schoolReset
cmp r8d,4
ja schoolReset
mov r11,[r10+20]
test r11,r11
jz schoolReset
xor edx,edx
schoolLoop:
mov r9d,edx
shl r9,5
cmp byte ptr [r11+r9+18],0
jne schoolFound
inc edx
cmp edx,r8d
jb schoolLoop
jmp schoolReset
schoolFound:
cmp byte ptr [r10+1C],0
je schoolIndexReady
dec r8d
sub r8d,edx
mov edx,r8d
schoolIndexReady:
mov [rsp+28],edx
mov rax,[rdi+38]
test rax,rax
jz schoolReset
cmp [schoolState],rdi
jne schoolNew
cmp [schoolState+8],rax
jne schoolNew
mov ecx,[rdi+80]
cmp [schoolState+10],ecx
je schoolCheckSelection
schoolNew:
mov [schoolState],rdi
mov [schoolState+8],rax
mov ecx,[rdi+80]
mov [schoolState+10],ecx
mov dword ptr [schoolState+14],0
mov dword ptr [schoolState+18],0
schoolCheckSelection:
cmp dword ptr [schoolState+18],0
jne schoolDone
lea rcx,[rdi+38]
call schoolGet
cmp eax,[rsp+28]
je schoolWait
lea rcx,[rdi+38]
mov edx,[rsp+28]
mov r8d,1
call schoolSelect
mov dword ptr [schoolState+14],0
jmp schoolDone
schoolWait:
movss xmm0,[schoolDelta]
xorps xmm1,xmm1
ucomiss xmm0,xmm1
jbe schoolDone
jp schoolDone
// A loading hitch must not consume the entire visible selection delay.
mov eax,3DCCCCCD
movd xmm1,eax
minss xmm0,xmm1
addss xmm0,[schoolState+14]
movss [schoolState+14],xmm0
mov eax,3F800000
movd xmm1,eax
ucomiss xmm0,xmm1
jb schoolDone
mov dword ptr [schoolState+18],1
mov [rsp+30],rdi
lea rcx,[rsp+30]
lea rdx,[rdi+38]
xor r8d,r8d
mov r9d,1
call schoolConfirm
test al,al
jnz schoolDone
schoolReset:
mov qword ptr [schoolState],0
schoolDone:
movdqu xmm0,[rsp+40]
movdqu xmm1,[rsp+50]
movdqu xmm2,[rsp+60]
movdqu xmm3,[rsp+70]
movdqu xmm4,[rsp+80]
movdqu xmm5,[rsp+90]
add rsp,A0
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rax
popfq
mov rbx,[rsp+90]
jmp schoolReturn
KatzyIWSchoolEnd:

define(schoolTimerEntry,SCHOOL_TIMER_ENTRY)
define(schoolTimerFlag,SCHOOL_TIMER_FLAG)
define(schoolTimerReturn,SCHOOL_TIMER_RETURN)
label(schoolTimerNormal)
label(schoolTimerDone)
label(KatzyIWSchoolTimerEnd)
registersymbol(KatzyIWSchoolTimerEnd)
schoolTimerEntry:
pushfq
cmp byte ptr [schoolTimerFlag],1
jne schoolTimerNormal
vmovss xmm1,dword ptr [rdi+88]
jmp schoolTimerDone
schoolTimerNormal:
vaddss xmm1,xmm0,dword ptr [rdi+88]
schoolTimerDone:
popfq
jmp schoolTimerReturn
KatzyIWSchoolTimerEnd:

// Cinematic button/mash prompts: native code has validated the timeline
// window and active input owner before this hook. Keep its normal commit.
define(cinematicSkillEntry,CINEMATIC_SKILL_ENTRY)
define(cinematicSkillReturn,CINEMATIC_SKILL_RETURN)
label(cinematicSkillNormal)
label(KatzyIWCinematicSkillEnd)
registersymbol(KatzyIWCinematicSkillEnd)
cinematicSkillEntry:
pushfq
push r9
push rsi
push rax
mov rsi,rdi
call skillParty
pop rax
pop rsi
test r9d,r9d
pop r9
jz cinematicSkillNormal
mov edx,[rdi+30]
dec edx
cmp edx,4
ja cinematicSkillNormal
mov edx,[rdi+38]
test edx,edx
jle cinematicSkillNormal
dec edx
mov [rdi+54],edx
mov eax,1
cinematicSkillNormal:
popfq
mov edx,[rdi+30]
test eax,eax
jmp cinematicSkillReturn
KatzyIWCinematicSkillEnd:
]==]
local specs={
  {kind='health',offset=0,entry=0,original={0x4C,0x8B,0x41,0x08,0x4C,0x39,0xC2},pattern='4C 8B 41 08 4C 39 C2 4C 0F 4C C2 31 C0 4D 85 C0 49 0F 4F C0 48 89 01 C3'},
  {kind='health',offset=0x2E,entry=0x100,original={0x4D,0x85,0xC0,0x49,0x0F,0x4F,0xC0},pattern='4C 8B 41 08 C5 F8 57 C0 C4 C1 FA 2A C0 C5 FA 59 D1 C5 FA 2D C2 48 63 D0 4C 89 C0 48 03 11 4C 39 C2 48 0F 4C C2 4C 39 C0 4C 0F 4C C0 31 C0 4D 85 C0 49 0F 4F C0 48 89 01 C3'},
  {kind='money',offset=0,entry=0x4000,original={0x41,0x83,0xF8,0x03,0x73,0x18},pattern='41 83 F8 03 73 18 44 89 C0 48 8D 04 40 48 C1 E0 04 48 01 C8 89 D1 48 8B 00 48 8B 04 C8 C3 48 89 C8 89 D1 48 8B 00 48 8B 04 C8 C3'},
  {kind='mana',offset=0,entry=0x400,original={0x44,0x8B,0x41,0x04,0x44,0x39,0xC2},pattern='44 8B 41 04 44 39 C2 44 0F 4C C2 31 C0 45 85 C0 41 0F 4F C0 89 01 C3'},
  {kind='mana',offset=0x1C,entry=0x500,original={0x85,0xD2,0x0F,0x4F,0xC2},pattern='8B 51 04 C5 F8 57 C0 C5 FA 2A C2 C5 FA 59 D1 C5 FA 2D C2 03 01 3B C2 0F 4C D0 33 C0 85 D2 0F 4F C2 89 01 C3'},
  {kind='health',offset=0,entry=0x700,original={0x48,0x89,0x5C,0x24,0x10},pattern='48 89 5C 24 10 57 48 83 EC 20 48 8B 81 80 00 00 00 48 89 D7 48 89 CB 8B 90 40 04 00 00 85 D2'},
  {kind='mana',offset=0,entry=0x800,original={0x48,0x89,0x5C,0x24,0x08},pattern='48 89 5C 24 08 48 89 74 24 18 57 48 83 EC 20 48 8B 81 80 00 00 00 31 FF 85 D2 89 FB 48 89 CE 0F 4F DA'},
  {kind='guard',offset=0,entry=0x900,original={0x44,0x8B,0x4C,0x24,0x58},pattern='44 8B 4C 24 58 48 8D 8E 00 04 00 00 BF 20 00 00 00 45 31 C0 0F AB C7 89 FA'},
  {kind='skill',offset=0,entry=0xA00,original={0x85,0xC0,0x0F,0x84,0x99,0x01,0x00,0x00},pattern='85 C0 0F 84 99 01 00 00 FF 46 58 8B 46 58 3B 46 30 0F 82 8A 01 00 00'},
  {kind='skill',offset=0,entry=0xB00,original={0x85,0xC0,0x74,0x52,0x89,0x5E,0x54},pattern='85 C0 74 52 89 5E 54 48 8D 4E 78 3B DF 7F 3A BA 2B 15 00 00 C6 46 68 01'},
  {kind='items',offset=0,entry=0xD00,original={0x48,0x89,0x5C,0x24,0x08},pattern='48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 83 EC 40 44 89 CF 44 89 C3 41 89 D6 48 89 CD'}
}
-- Hints belong to the exact executable fingerprint checked on attachment.
-- Validate the entire signature at each hint; retain AOB discovery on mismatch.
specs[#specs+1]={kind='level',offset=0,entry=0x3800,original={0x49,0x8B,0xD7,0x4C,0x8B,0x7C,0x24,0x20},pattern='49 8B D7 4C 8B 7C 24 20 49 8B CF E8 1D 99 4A FF 45 85 E4 0F 84 75 01 00 00'}
specs[#specs+1]={kind='job',offset=0,entry=0x3C00,original={0x41,0x8B,0xD6,0x49,0x8B,0xCD},pattern='41 8B D6 49 8B CD E8 6D 9F 4A FF 41 83 FC 63 75 4C'}
specs[#specs+1]={kind='pokerwin',offset=0,entry=0x4400,original={0x48,0x8B,0x48,0x20,0x44,0x8B,0x61,0x48},pattern='48 8B 48 20 44 8B 61 48 8B 4F 24 8B C1 C1 E8 02 A8 01'}
specs[#specs+1]={kind='pokerchips',offset=0,entry=0x4800,original={0x8B,0x41,0x08,0x3B,0xC2},pattern='8B 41 08 3B C2 73 03 32 C0 C3 2B C2 89 41 08 B0 01 C3'}
specs[#specs+1]={kind='darts',offset=0,entry=0x4C00,original={0xC5,0xFA,0x10,0x88,0xBC,0x03,0x00,0x00},pattern='C5 FA 10 88 BC 03 00 00 4C 8D 80 B8 03 00 00 48 8D 90 B4 03 00 00 C5 FA 11 74 24 30 C5 FA 11 44 24 28 C5 FA 11 4C 24 20 C5 F8 28 DF'}
specs[#specs+1]={kind='karaoke',offset=0,entry=0x5000,original={0x83,0x7B,0x14,0x03,0x0F,0x85,0xBF,0x01,0x00,0x00},pattern='83 7B 14 03 0F 85 BF 01 00 00 C5 FA 10 5B 04 C5 D8 57 E4 C5 F8 2E DC 7A 22 75 20'}
specs[#specs+1]={kind='bond',offset=0,entry=0x5400,original={0x4C,0x8B,0x75,0x5F,0x4D,0x85,0xF6},pattern='4C 8B 75 5F 4D 85 F6 7F 09 45 84 ED 0F 84 59 06 00 00 48 8B D6'}
specs[#specs+1]={kind='fishing',offset=0,entry=0x5800,original={0x85,0xC0,0x0F,0x84,0xED,0x01,0x00,0x00},pattern='85 C0 0F 84 ED 01 00 00 C5 FA 10 46 4C C5 FA 59 15 0A 28 A6 00 C5 EA 5C 5E 40 C5 EA 58 66 40 3B 46 34'}
specs[#specs+1]={kind='tag',offset=15,entry=0x5C00,original={0x8B,0x00,0x48,0x83,0xC4,0x20},pattern='89 DA 48 89 C1 E8 AF 9D 8B F5 48 85 C0 74 08 8B 00 48 83 C4 20 5B C3 31 C0 48 83 C4 20 5B C3'}
specs[#specs+1]={kind='encounter',offset=0,entry=0x5D00,original={0x8B,0x8E,0xE0,0x02,0x00,0x00},pattern='8B 8E E0 02 00 00 4C 8B AC 24 A8 00 00 00 44 89 B6 18 03 00 00 85 C9 0F 84 94 01 00 00'}
specs[#specs+1]={kind='snap',offset=0,entry=0x5E00,original={0xB9,0xFA,0x13,0x00,0x00,0x40,0x84,0xFF},pattern='B9 FA 13 00 00 40 84 FF 0F 85 81 00 00 00 C7 45 83 02 00 00 00'}
specs[#specs+1]={kind='match',offset=0,entry=0x5F20,original={0x48,0x8B,0x47,0x78,0x44,0x8B,0x60,0x08},pattern='48 8B 47 78 44 8B 60 08 44 2B 60 0C B9 45 13 00 00 41 BF 05 00 00 00'}
specs[#specs+1]={kind='matchauto',offset=0,entry=0x5F80,original={0xE8,0x3C,0x15,0x0C,0xFF},pattern='E8 3C 15 0C FF 85 C0 74 04 FF C7 EB 41 BA 02 00 00 00'}
specs[#specs+1]={kind='matchauto',offset=0,entry=0x5FC0,original={0xE8,0x37,0xFD,0x0B,0xFF},pattern='E8 37 FD 0B FF 85 C0 75 41 8D 50 02 49 8B CF E8 28 FD 0B FF'}
specs[#specs+1]={kind='emoji',offset=0,entry=0x6000,original={0x41,0x8B,0xCC,0x83,0xE9,0x61},pattern='41 8B CC 83 E9 61 0F 84 B8 00 00 00 41 2B CF 74 7E 41 2B CF 74 44'}
specs[#specs+1]={kind='chase',offset=0,entry=0x6100,original={0x48,0x8B,0xCB,0xA8,0x08},pattern='48 8B CB A8 08 74 0F 48 8B 7C 24 40 48 83 C4 30 5B E9 6C 09 00 00'}
specs[#specs+1]={kind='chase',offset=0,entry=0x6200,original={0x89,0x44,0xBC,0x20,0x48,0xFF,0xC7},pattern='89 44 BC 20 48 FF C7 48 83 FF 04 7C DA 83 7C 24 24 00 48 8B 74 24'}
specs[#specs+1]={kind='crazy',offset=0,entry=0x6300,original={0x83,0xB9,0xB0,0x02,0x00,0x00,0x01},pattern='83 B9 B0 02 00 00 01 75 0D 48 8B CB 48 83 C4 30 5B E9 1E 05 00 00'}
specs[#specs+1]={kind='crazy',offset=0,entry=0x6800,original={0x80,0xB9,0x98,0x00,0x00,0x00,0x00},pattern='80 B9 98 00 00 00 00 75 48 80 B9 84 00 00 00 00 C5 FA 10 0D 8A AD'}
specs[#specs+1]={kind='lemontimer',offset=0,entry=0x6C00,original={0x41,0x89,0x87,0xC0,0x00,0x00,0x00},pattern='41 89 87 C0 00 00 00 EB 17 FF D2 0F B6 C8 48 8D 05 51 1D D8 02'}
specs[#specs+1]={kind='oichowin',offset=0,entry=0x6E00,original={0x48,0x89,0x5C,0x24,0x08},pattern='48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 8B 41 10 33 FF 83 E0 BF 44 0F B6 C2 41 83 C8 02 4C 8B E1 41 C1 E0 06 41 B5 01 44 0B C0 8B DF 44 89 41 10'}
specs[#specs+1]={kind='koipoints',offset=0,entry=0x7000,original={0x80,0xBB,0x2E,0x01,0x00,0x00,0x01},pattern='80 BB 2E 01 00 00 01 75 0D 83 FF 07 72 08 8D 04 3F 01 45 58 EB 03 01 7D 58 BA 00 02 00 00 49 8B'}
specs[#specs+1]={kind='koiauto',offset=0,entry=0x7800,original={0x40,0x53,0x48,0x83,0xEC,0x40},pattern='40 53 48 83 EC 40 48 8B D9 B9 08 00 00 00 E8 7D 94 E7 FF 85 C0 0F 85 F9 02 00 00 48 89 6C 24 50'}
specs[#specs+1]={kind='koiauto',offset=0,entry=0x7900,original={0x40,0x53,0x48,0x83,0xEC,0x50},pattern='40 53 48 83 EC 50 48 89 6C 24 60 48 8B D9 48 89 74 24 70 33 F6 48 89 7C 24 78 4C 89 64 24 48 4C'}
specs[#specs+1]={kind='koiauto',offset=0,entry=0x7A00,original={0x40,0x53,0x48,0x83,0xEC,0x20},pattern='40 53 48 83 EC 20 8B D9 48 8B 0D D1 60 3D 01 48 85 C9 75 08 33 C0 48 83 C4 20 5B C3 E8 BF 47 14'}
specs[#specs+1]={kind='koiauto',offset=0,entry=0x7C00,original={0x85,0xC0,0x0F,0x85,0x4B,0x01,0x00,0x00},pattern='85 C0 0F 85 4B 01 00 00 44 89 B3 F4 00 00 00 39 6B 50 75 14 BA 09 00 40 05 48 8D 4C 24 60 E8 60'}
specs[#specs+1]={kind='ufosticky',offset=0,entry=0x8000,original={0x48,0x8D,0x8E,0xC0,0x01,0x00,0x00},pattern='48 8D 8E C0 01 00 00 4C 8B 09 C5 78 28 6C 24 70 4D 85 C9 74 1A'}
specs[#specs+1]={kind='anacondaquiz',offset=0,entry=0x7D00,original={0x48,0x8B,0x4D,0x70,0x48,0x33,0xCC},pattern='48 8B 4D 70 48 33 CC E8 1A 26 58 FE 48 8B 9C 24 D8 01 00 00'}
specs[#specs+1]={kind='sujimonsp',offset=0,entry=0x9400,original={0x8B,0x8A,0xD0,0x00,0x00,0x00},pattern='8B 8A D0 00 00 00 85 C9 0F 84 D1 00 00 00 8B C1 25 FF FF 0F 00'}
specs[#specs+1]={kind='sujimonmp',offset=0,entry=0x9600,original={0x48,0x8B,0x89,0xE0,0,0,0},pattern='48 8B 89 E0 00 00 00 48 85 C9 74 05 E8 36 1A 00 00 48 8B 87 E8 00'}
specs[#specs+1]={kind='sujimonroulette',offset=0,entry=0x9700,original={0xC5,0xFA,0x10,0x99,0x30,1,0,0},pattern='C5 FA 10 99 30 01 00 00 C5 FA 10 2D 2D 8E ED 01 C5 F8 29 70 E8 45 32 C0'}
specs[#specs+1]={kind='recruiteffort',offset=0,entry=0x9800,original={0x8B,0x42,0x48,0x41,0x89,0x80,0x88,0x01,0x00,0x00},pattern='8B 42 48 41 89 80 88 01 00 00 48 8B 4B 08 48 83 C1 38 BA 36 22 00 00 E8'}
specs[#specs+1]={kind='recruiteffort',offset=0,entry=0x9880,original={0xC5,0xFA,0x11,0x87,0x88,0x01,0x00,0x00},pattern='C5 FA 11 87 88 01 00 00 C5 FA 10 4B 48 48 8D 4B 38 E8 2C F0 88 00 48 8B'}
specs[#specs+1]={kind='recruitauto',offset=0,entry=0x9900,original={0xC5,0xFA,0x10,0x05,0x03,0x54,0xA4,0x03},pattern='C5 FA 10 05 03 54 A4 03 C5 FA 58 53 48 C5 FA 10 0D D6 A6 DE 01 48 8B 43'}
specs[#specs+1]={kind='dokomoney',offset=0,entry=0xA000,original={0x48,0x8B,0x83,0x98,0x00,0x00,0x00,0x48,0x8B,0x58,0x08},pattern='48 8B 83 98 00 00 00 48 8B 58 08 48 8D 0D BD 4A C4 01 E8 24 F6 80 FE 90 48'}
specs[#specs+1]={kind='dokomaterials',offset=0,entry=0xA100,original={0x48,0x8B,0x46,0x38,0x42,0x8B,0x3C,0x80},pattern='48 8B 46 38 42 8B 3C 80 E8 B3 9F 03 FF 85 C0 74 24 48 8D 8E 90 15 00 00 8B'}
specs[#specs+1]={kind='dokomaterials',offset=0,entry=0xA200,original={0x49,0x8B,0x45,0x38,0x44,0x8B,0x34,0x90},pattern='49 8B 45 38 44 8B 34 90 E8 A6 8C 03 FF 85 C0 74 15 49 8D 8D 90 15 00 00 8B'}
specs[#specs+1]={kind='dokomaterials',offset=0,entry=0xA300,original={0x49,0x8B,0x46,0x38,0x42,0x8B,0x34,0xB8},pattern='49 8B 46 38 42 8B 34 B8 E8 9E 8A 03 FF 85 C0 74 14 49 8D 8E 90 15 00 00 8B'}
specs[#specs+1]={kind='dokotalent',offset=0,entry=0xA400,original={0x8B,0x41,0x1C,0xC3,0xCC},pattern='8B 41 1C C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24 10 48 89 74 24'}
specs[#specs+1]={kind='dokosatisfaction',offset=0,entry=0xA500,original={0x8D,0x04,0x3E,0x48,0x8B,0x8C,0x24,0xB0,0x00,0x00,0x00},pattern='8D 04 3E 48 8B 8C 24 B0 00 00 00 48 33 CC E8 70 5F 66 FF 4C 8D 9C 24 C0 00'}
specs[#specs+1]={kind='dokopopularity',offset=0,entry=0xA600,original={0x8B,0xC6,0x48,0x8B,0x8D,0xC0,0x12,0x00,0x00},pattern='8B C6 48 8B 8D C0 12 00 00 48 33 CC E8 AF 4E 66 FF 4C 8D 9C 24 D0 13 00 00'}
specs[#specs+1]={kind='dokopopularity',offset=0,entry=0xA700,original={0x8B,0x80,0xB4,0x01,0x00,0x00},pattern='8B 80 B4 01 00 00 C3 E9 84 00 00 00 CC CC CC CC CC CC CC CC CC CC CC CC CC'}
specs[#specs+1]={kind='dokopopularity',offset=0,entry=0xA800,original={0x8B,0x80,0xB4,0x01,0x00,0x00},pattern='8B 80 B4 01 00 00 8B C8 48 83 C4 28 E9 AB 63 FB FF E8 16 00 00 00 8B C8 48'}
specs[#specs+1]={kind='dokotime',offset=0,entry=0xA900,original={0xC5,0xFA,0x58,0x05,0x91,0x7F,0xA2,0x03},pattern='C5 FA 58 05 91 7F A2 03 C5 FA 11 41 24 C6 41 3C 00 C5 F8 29 7C 24 50 E8 D9'}
specs[#specs+1]={kind='dokohp',offset=0,entry=0xAA00,original={0x39,0x58,0x30,0x0F,0x42,0x58,0x30},pattern='39 58 30 0F 42 58 30 8B C3 48 83 C4 20 5B C3 CC CC CC CC CC CC CC CC CC CC'}
specs[#specs+1]={kind='dokomaterials',offset=0,entry=0xAD00,original={0x8B,0x4C,0xC8,0x08,0x8B,0x5F,0x10},pattern='8B 4C C8 08 8B 5F 10 E8 18 F3 03 FF 84 C0 74 2B 8B 57 0C 8B 4F 08 E8 99 F6'}
specs[#specs+1]={kind='dokotime',offset=0,entry=0xAC00,original={0x8B,0x49,0x34,0x83,0xE9,0x02},pattern='8B 49 34 83 E9 02 0F 84 3A 08 00 00 83 F9 01 0F 84 31 08 00 00 32 C0 48 8B'}
specs[#specs+1]={kind='schoolanswer',offset=0,entry=0xAF00,original={0x48,0x8B,0x9C,0x24,0x90,0x00,0x00,0x00},pattern='48 8B 9C 24 90 00 00 00 C5 F8 28 74 24 60 C5 F8 28 7C 24 50 C5 78 28 44 24 40 48 83 C4 70 5F C3 CC CC CC CC CC CC CC CC'}
specs[#specs+1]={kind='skill',offset=0,entry=0xB300,original={0x8B,0x57,0x30,0x85,0xC0},pattern='8B 57 30 85 C0 0F 84 FF 00 00 00 83 FA 0C 0F 85 E3 00 00 00 C5 FA 10 47 74'}
specs[#specs+1]={kind='schooltimer',offset=0,entry=0xB400,original={0xC5,0xFA,0x58,0x8F,0x88,0x00,0x00,0x00},pattern='C5 FA 58 8F 88 00 00 00 C5 FA 11 8F 88 00 00 00 C5 D2 5C D1 C4 C1 6A C2'}
local signatureHints={0xBD35B20,0xBD3E7D0,0xBDAD970,0xBD3ECA0,0x14DB3E0,0x118C2D90,0x118C7E90,0x1204FA0A,0x22327BD,0x2232902,0xBDBFCD0,0x2031D53,0x2032078,0x266A293,0x269B090,0x24CC932,0x24E9098,0x1D575FD,0x222D4A5,0xBC2F107,0x97C5C8,0xDA3CAF,0x25AFD2C,0x258975F,0x258AF64,0x258B962,0x21DF3DE,0x21DFB99,0xDD594C,0x64FC42,0x1B68C7A,0x2637620,0x262C26A,0x268EBC0,0x268EF70,0x2508050,0x2628D9D,0x2056A97,0x1DE926A,0xB5B157,0xBBFE39,0xBC4817,0xEA80A9,0xEA65EE,0xEA55D9,0x1C88C95,0x1C89020,0x1C8A32D,0x1C8A535,0x1C88DA0,0xD0590D,0xD069D0,0xD062C0,0xD06324,0xEC2A4B,0xD06BC7,0x1C75A9C,0xC956C6,0x2520204,0x21E081F,0x2520001}
local codeBounds={
  KatzyIWCinematicSkillEnd={0xB300,0xB400},
  KatzyIWSchoolEnd={0xAF00,0xB300},
  KatzyIWSchoolTimerEnd={0xB400,0xB500},
  KatzyIWDokoGoldOreEnd={0xAD00,0xAF00},
  KatzyIWDokoSleepEnd={0xAC00,0xAD00},
  KatzyIWDokoMoneyEnd={0xA000,0xA100},
  KatzyIWDokoMaterialReadEnd={0xA100,0xA200},
  KatzyIWDokoMaterialCheckEnd={0xA200,0xA300},
  KatzyIWDokoMaterialSpendEnd={0xA300,0xA400},
  KatzyIWDokoTalentEnd={0xA400,0xA500},
  KatzyIWDokoSatisfactionEnd={0xA500,0xA600},
  KatzyIWDokoPopularityEnd={0xA600,0xA700},
  KatzyIWDokoPopularityReadEnd={0xA700,0xA800},
  KatzyIWDokoPopularityRankEnd={0xA800,0xA900},
  KatzyIWDokoTimeEnd={0xA900,0xAA00},
  KatzyIWDokoHealthEnd={0xAA00,0xAB00},
  KatzyIWRecruitEffortEnd={0x9800,0x9880},
  KatzyIWRecruitTimeoutEnd={0x9880,0x9900},
  KatzyIWRecruitAutoEnd={0x9900,0x9C00},
  KatzyIWSujimonMpEnd={0x9600,0x9700},
  KatzyIWSujimonRouletteEnd={0x9700,0x9800},
  KatzyIWSujimonEnd={0x9400,0x9500},
  KatzyIWAnacondaQuizEnd={0x7D00,0x8000},
  KatzyIWStickyEnd={0x8000,0x9000},
  KatzyIWKoiHandEnd={0x7800,0x7900},
  KatzyIWKoiFieldEnd={0x7900,0x7A00},
  KatzyIWKoiInputEnd={0x7A00,0x7C00},
  KatzyIWKoiBankEnd={0x7C00,0x7D00},
  KatzyIWKoiPointsEnd={0x7000,0x7800},
  KatzyIWOichoEnd={0x6E00,0x7000},
  KatzyIWLemonEnd={0x6C00,0x6D00},
  KatzyIWCrazyEnd={0x6300,0x6800},
  KatzyIWCrazyTimerEnd={0x6800,0x6B00},
  KatzyIWChaseEnd={0x6100,0x6200},
  KatzyIWChaseInputEnd={0x6200,0x6300},
  KatzyIWEmojiEnd={0x6000,0x6100},
  KatzyIWMatchEnd={0x5F20,0x5F80},
  KatzyIWMatchAutoEnd={0x5F80,0x5FC0},
  KatzyIWMatchComboEnd={0x5FC0,0x6000},
  KatzyIWSnapEnd={0x5E00,0x5F00,'Sicko Snap code exceeds its reserved space'},
  KatzyIWEncounterEnd={0x5D00,0x5E00,'Encounter code exceeds its reserved space'},
  KatzyIWTagEnd={0x5C00,0x5D00,'Tag Gauge code exceeds its reserved space'},
  KatzyIWFishingEnd={0x5800,0x5C00,'Fishing code exceeds its reserved space'},
  KatzyIWBondEnd={0x5400,0x5800,'Bond code exceeds its reserved space'},
  KatzyIWKaraokeEnd={0x5000,0x5400,'Karaoke code exceeds its reserved space'},
  KatzyIWDartsEnd={0x4C00,0x5000,'Darts code exceeds its reserved space'},
  KatzyIWSpendEnd={0x4800,0x4C00,'Poker spending code exceeds its reserved space'},
  KatzyIWMoneyEnd={0x4000,0x4400,'Currency code exceeds its reserved space'},
  KatzyIWPokerEnd={0x4400,0x4800,'Poker code exceeds its reserved space'},
  KatzyIWLevelEnd={0x3800,0x3C00,'Level code exceeds its reserved space'},
  KatzyIWJobEnd={0x3C00,0x4000,'Job code exceeds its reserved space'}
}
local function prepare()
  local c=S.context
  local key=c.pid..':'..c.base..':1.94'
  local cached=KatzyIWPages[key]
  if cached and equal(bytes(cached.address+0xF00,#cached.marker),cached.marker) then return cached end
  local hooks={}
  for index,s in ipairs(specs) do
    local expected={}
    for value in s.pattern:gmatch('%x%x') do expected[#expected+1]=tonumber(value,16) end
    local a=c.base+signatureHints[index]
    if not equal(bytes(a,#expected),expected) then a=AOBScanModuleUnique(exe,s.pattern,'+X') end
    if not a then error('A supported code signature was not found') end
    hooks[#hooks+1]={address=a+s.offset,kind=s.kind,original=s.original,entry=s.entry}
  end
  local a=allocateMemory(49152,hooks[1].address)
  assert(a and a~=0,'Could not allocate code page')
  local p={address=a,hooks=hooks,marker={75,97,116,122,121,73,87,33},context=c,flags={schooltimer=a+0xBF09,sujimonpoints=a+0xBF08,schoolanswer=a+0xBF07,dokomoney=a+0xBF00,dokomaterials=a+0xBF01,dokotalent=a+0xBF02,dokosatisfaction=a+0xBF03,dokopopularity=a+0xBF04,dokotime=a+0xBF05,dokohp=a+0xBF06,recruiteffort=a+0x5F1E,recruitauto=a+0x5F1F,sujimonmp=a+0x5F1C,sujimonroulette=a+0x5F1D,sujimonsp=a+0x5F1B,anacondatimer=a+0x5F19,anacondaquiz=a+0x5F1A,ufosticky=a+0x5F18,health=a+0xF10,money=a+0xF11,mana=a+0xF12,guard=a+0xF13,skill=a+0xF14,items=a+0xF15,shogipoints=a+0xF16,level=a+0xF17,job=a+0xF18,pokerchips=a+0xF19,pokerwin=a+0xF1A,darts=a+0xF1B,karaoke=a+0xF1C,bond=a+0xF1D,fishing=a+0xF1E,tag=a+0xF1F,encounter=a+0x5F00,snap=a+0x5F02,snappoints=a+0x5F03,match=a+0x5F04,matchauto=a+0x5F05,emoji=a+0x5F06,chase=a+0x5F07,crazyextreme=a+0x5F08,crazyfood=a+0x5F09,crazytimer=a+0x5F0A,crazyrank=a+0x5F0B,deliverypoints=a+0x5F0C,lemontimer=a+0x5F0D,woodentags=a+0x5F0F,oichowin=a+0x5F14,koipoints=a+0x5F16,koiauto=a+0x5F15}}
  local ok,reason=pcall(function()
    for _,h in ipairs(hooks) do h.patch=branch(h.address,a+h.entry,#h.original) end
    local code=assembly:format(a,a+0x100,a+0x200,a+0x4000,p.flags.health,p.flags.money,c.base+0x38C8750,c.base+0x2B03680,c.base+0x2B0AA00,hooks[1].address+7,hooks[2].address+7,a+0x400,a+0x500,a+0x600,p.flags.mana,hooks[4].address+7,hooks[5].address+5,a+0x700,a+0x800,a+0x900,c.base+0x2C10C38,hooks[6].address+5,hooks[7].address+5,p.flags.guard,hooks[8].address+5,hooks[8].address+0x4B,a+0xA00,a+0xB00,a+0xC00,p.flags.skill,hooks[9].address+8,hooks[9].address+0x1A1,hooks[10].address+7,hooks[10].address+0x56,c.base+0x38DCCA0,c.base+0x2C20DD0,a+0xD00,p.flags.items,a+0xF20,a+0x1000,hooks[11].address+5,p.flags.shogipoints)
    local bindings={
      IDENTITY_ENTRY=a+0xE00,
      ACTOR_IDENTITY=c.base+0x21914B0,
      ACTOR_REGISTRY=c.base+0x38E6300,
      LEVEL_ENTRY=a+0x3800,
      LEVEL_FLAG=p.flags.level,
      LEVEL_RETURN=hooks[12].address+8,
      CHARACTER_IDS=c.base+0x2B0A378,
      JOB_ENTRY=a+0x3C00,
      JOB_FLAG=p.flags.job,
      JOB_RETURN=hooks[13].address+6,
      POKER_CHIPS_FLAG=p.flags.pokerchips,
      POKER_WIN_ENTRY=a+0x4400,
      POKER_WIN_FLAG=p.flags.pokerwin,
      POKER_MANAGER=c.base+0x38DEF00,
      POKER_WIN_RETURN=hooks[14].address+8,
      POKER_SPEND_ENTRY=a+0x4800,
      POKER_SPEND_RETURN=hooks[15].address+5,
      DARTS_ENTRY=a+0x4C00,
      DARTS_FLAG=p.flags.darts,
      DARTS_RETURN=hooks[16].address+8,
      KARAOKE_ENTRY=a+0x5000,
      KARAOKE_FLAG=p.flags.karaoke,
      KARAOKE_RETURN=hooks[17].address+10,
      KARAOKE_DONE=hooks[17].address+0x1C9,
      KARAOKE_HIT=c.base+0x24E99D0,
      KARAOKE_SCORE=c.base+0x24E9B00,
      BOND_ENTRY=a+0x5400,
      BOND_FLAG=p.flags.bond,
      BOND_RETURN=hooks[18].address+7,
      FISHING_ENTRY=a+0x5800,
      FISHING_FLAG=p.flags.fishing,
      FISHING_RETURN=hooks[19].address+8,
      FISHING_WAIT=hooks[19].address+0x1F5,
      FISHING_HALF=c.base+0x2C8FCC4,
      TAG_ENTRY=a+0x5C00,
      TAG_FLAG=p.flags.tag,
      TAG_RETURN=hooks[20].address+6,
      ENCOUNTER_ENTRY=a+0x5D00,
      ENCOUNTER_FLAG=p.flags.encounter,
      ENCOUNTER_RETURN=hooks[21].address+6,
      SUJIMON_POINTS_FLAG=p.flags.sujimonpoints,
      WOODEN_TAGS_FLAG=p.flags.woodentags,
      DELIVERY_POINTS_FLAG=p.flags.deliverypoints,
      SNAP_ENTRY=a+0x5E00,
      SNAP_FLAG=p.flags.snap,
      SNAP_RETURN=hooks[22].address+8,
      SNAP_POINTS_FLAG=p.flags.snappoints,
      MATCH_ENTRY=a+0x5F20,
      MATCH_FLAG=p.flags.match,
      MATCH_RETURN=hooks[23].address+8,
      MATCH_AUTO_ENTRY=a+0x5F80,
      MATCH_COMBO_ENTRY=a+0x5FC0,
      MATCH_AUTO_FLAG=p.flags.matchauto,
      MATCH_AUTO_RETURN=hooks[24].address+5,
      MATCH_COMBO_RETURN=hooks[25].address+5,
      MATCH_INPUT=hooks[24].address+5+readInteger(hooks[24].address+1,true),
      EMOJI_ENTRY=a+0x6000,
      EMOJI_FLAG=p.flags.emoji,
      EMOJI_RETURN=hooks[26].address+6,
      CHASE_ENTRY=a+0x6100,
      CHASE_INPUT_ENTRY=a+0x6200,
      CHASE_FLAG=p.flags.chase,
      CHASE_RETURN=hooks[27].address+5,
      CHASE_BUTTON_PATH=hooks[27].address+0x16,
      CHASE_INPUT_RETURN=hooks[28].address+7,
      ANACONDA_TIMER_FLAG=p.flags.anacondatimer,
      LEMON_ENTRY=a+0x6C00,
      LEMON_FLAG=p.flags.lemontimer,
      LEMON_TYPE=c.base+0x2B45668,
      LEMON_RETURN=hooks[31].address+7,
      UFO_CALLBACK=c.base+0x24963F0,
      SCHOOL_ENTRY=a+0xAF00,
      SCHOOL_FLAG=p.flags.schoolanswer,
      SCHOOL_RETURN=hooks[59].address+8,
      SCHOOL_STATE=a+0xB500,
      SCHOOL_GET=c.base+0x173E520,
      SCHOOL_SELECT=c.base+0x173E480,
      SCHOOL_BUSY=c.base+0x1732CB0,
      SCHOOL_CONFIRM=c.base+0x251A5C0,
      SCHOOL_DELTA=c.base+0x48EA9E4,
      SCHOOL_TIMER_ENTRY=a+0xB400,
      SCHOOL_TIMER_FLAG=p.flags.schooltimer,
      SCHOOL_TIMER_RETURN=hooks[61].address+8,
      CINEMATIC_SKILL_ENTRY=a+0xB300,
      CINEMATIC_SKILL_RETURN=hooks[60].address+5,
      CRAZY_RANK_FLAG=p.flags.crazyrank,
      CRAZY_RANK_BORDERS=a+0x6B00,
      CRAZY_ENTRY=a+0x6300,
      CRAZY_TIMER_ENTRY=a+0x6800,
      CRAZY_EXTREME_FLAG=p.flags.crazyextreme,
      CRAZY_FOOD_FLAG=p.flags.crazyfood,
      CRAZY_TIMER_FLAG=p.flags.crazytimer,
      CRAZY_HANDLE=a+0x5F10,
      CRAZY_REGISTRY=c.base+0x38E6300,
      CRAZY_TYPE=c.base+0x2AA44E0,
      CRAZY_RETURN=hooks[29].address+7,
      CRAZY_DONE=c.base+0xDD5A3A,
      CRAZY_EXTREME=c.base+0xDD5DA0,
      CRAZY_BONUS=c.base+0xDB79A0,
      CRAZY_TIMER_RETURN=hooks[30].address+7,
      CRAZY_TIMER_DONE=c.base+0x64FC93,
      RECRUIT_EFFORT_ENTRY=a+0x9800,
      RECRUIT_EFFORT_FLAG=p.flags.recruiteffort,
      RECRUIT_EFFORT_RETURN=hooks[43].address+10,
      RECRUIT_TIMEOUT_ENTRY=a+0x9880,
      RECRUIT_TIMEOUT_RETURN=hooks[44].address+8,
      RECRUIT_AUTO_ENTRY=a+0x9900,
      RECRUIT_AUTO_FLAG=p.flags.recruitauto,
      RECRUIT_AUTO_RETURN=hooks[45].address+8,
      RECRUIT_PRESS=c.base+0xEA3F40,
      RECRUIT_DELTA=c.base+0x48EA9E4,
      SUJIMON_MP_ENTRY=a+0x9600,
      SUJIMON_MP_FLAG=p.flags.sujimonmp,
      SUJIMON_MP_RETURN=hooks[41].address+7,
      SUJIMON_TRAINER_TYPE=c.base+0x2A99088,
      SUJIMON_ROULETTE_ENTRY=a+0x9700,
      SUJIMON_ROULETTE_FLAG=p.flags.sujimonroulette,
      SUJIMON_ROULETTE_RETURN=hooks[42].address+8,
      SUJIMON_ROULETTE_TYPE=c.base+0x2A99258,
      SUJIMON_ENTRY=a+0x9400,
      SUJIMON_FLAG=p.flags.sujimonsp,
      SUJIMON_RETURN=hooks[40].address+6,
      SUJIMON_PARTY_TYPE=c.base+0x2A987A8,
      ANACONDA_QUIZ_ENTRY=a+0x7D00,
      ANACONDA_QUIZ_FLAG=p.flags.anacondaquiz,
      ANACONDA_QUIZ_RETURN=hooks[39].address+7,
      ANACONDA_COMMIT=c.base+0x1DEA060,
      OICHO_ENTRY=a+0x6E00,
      OICHO_FLAG=p.flags.oichowin,
      OICHO_HANDLE=c.base+0x38DE17C,
      OICHO_REGISTRY=c.base+0x38E6300,
      OICHO_TYPE=c.base+0x2C359F0,
      OICHO_PLAYER_TYPE=c.base+0x2C46788,
      OICHO_RETURN=hooks[32].address+5,
      KOI_POINTS_ENTRY=a+0x7000,
      KOI_POINTS_FLAG=p.flags.koipoints,
      KOI_POINTS_TYPE=c.base+0x2C4A7E8,
      KOI_POINTS_RETURN=hooks[33].address+7,
      KOI_EVALUATE=c.base+0x268A630,
      KOI_POINT_TABLE=c.base+0x2C460C0,
      KOI_FLAG=p.flags.koiauto,
      KOI_TYPE=c.base+0x2C4A7E8,
      KOI_AI_HAND=c.base+0x268BCC0,
      KOI_AI_FIELD=c.base+0x268BE70,
      KOI_BANK_BRANCH=c.base+0x2628EF0,
      KOI_HAND_ENTRY=a+0x7800,
      KOI_HAND_RETURN=hooks[34].address+6,
      KOI_FIELD_ENTRY=a+0x7900,
      KOI_FIELD_RETURN=hooks[35].address+6,
      KOI_INPUT_ENTRY=a+0x7A00,
      KOI_INPUT_RETURN=hooks[36].address+6,
      KOI_BANK_ENTRY=a+0x7C00,
      KOI_BANK_RETURN=hooks[37].address+8,
      KOI_CONFIRM_0=c.base+0x2625D9E,
      KOI_CONFIRM_1=c.base+0x2626268,
      KOI_CONFIRM_2=c.base+0x2626B43,
      KOI_CONFIRM_3=c.base+0x2628D4F,
      KOI_CONFIRM_4=c.base+0x262C2A2,
      KOI_CONFIRM_5=c.base+0x262C6F2,
      STICKY_ENTRY=a+0x8000,
      STICKY_FLAG=p.flags.ufosticky,
      STICKY_STATE=a+0x9000,
      STICKY_RETURN=hooks[38].address+7,
      STICKY_ACTORS=c.base+0x38E6300,
      STICKY_PHYSICS=c.base+0x31206E8,
      STICKY_BODY_TYPE=c.base+0x2C89258,
      STICKY_MOVE=c.base+0x282CCF0,
      STICKY_WAKE=c.base+0x282C170,
      DOKO_GOLDORE_ENTRY=a+0xAD00,
      DOKO_GOLDORE_FLAG=p.flags.dokomaterials,
      DOKO_GOLDORE_RETURN=hooks[57].address+7,
      DOKO_SLEEP_ENTRY=a+0xAC00,
      DOKO_SLEEP_FLAG=p.flags.dokotime,
      DOKO_SLEEP_RETURN=hooks[58].address+6,
      DOKO_DELTA=c.base+0x48EA9E4,
      DOKO_MONEY_ENTRY=a+0xA000,
      DOKO_MONEY_FLAG=p.flags.dokomoney,
      DOKO_MONEY_RETURN=hooks[46].address+11,
      DOKO_MATERIALREAD_ENTRY=a+0xA100,
      DOKO_MATERIALREAD_FLAG=p.flags.dokomaterials,
      DOKO_MATERIALREAD_RETURN=hooks[47].address+8,
      DOKO_MATERIALCHECK_ENTRY=a+0xA200,
      DOKO_MATERIALCHECK_FLAG=p.flags.dokomaterials,
      DOKO_MATERIALCHECK_RETURN=hooks[48].address+8,
      DOKO_MATERIALSPEND_ENTRY=a+0xA300,
      DOKO_MATERIALSPEND_FLAG=p.flags.dokomaterials,
      DOKO_MATERIALSPEND_RETURN=hooks[49].address+8,
      DOKO_TALENT_ENTRY=a+0xA400,
      DOKO_TALENT_FLAG=p.flags.dokotalent,
      DOKO_TALENT_RETURN=hooks[50].address+5,
      DOKO_SATISFACTION_ENTRY=a+0xA500,
      DOKO_SATISFACTION_FLAG=p.flags.dokosatisfaction,
      DOKO_SATISFACTION_RETURN=hooks[51].address+11,
      DOKO_POPULARITY_ENTRY=a+0xA600,
      DOKO_POPULARITY_FLAG=p.flags.dokopopularity,
      DOKO_POPULARITY_RETURN=hooks[52].address+9,
      DOKO_POPULARITYREAD_ENTRY=a+0xA700,
      DOKO_POPULARITYREAD_FLAG=p.flags.dokopopularity,
      DOKO_POPULARITYREAD_RETURN=hooks[53].address+6,
      DOKO_POPULARITYRANK_ENTRY=a+0xA800,
      DOKO_POPULARITYRANK_FLAG=p.flags.dokopopularity,
      DOKO_POPULARITYRANK_RETURN=hooks[54].address+6,
      DOKO_TIME_ENTRY=a+0xA900,
      DOKO_TIME_FLAG=p.flags.dokotime,
      DOKO_TIME_RETURN=hooks[55].address+8,
      DOKO_HEALTH_ENTRY=a+0xAA00,
      DOKO_HEALTH_FLAG=p.flags.dokohp,
      DOKO_HEALTH_RETURN=hooks[56].address+7,
    }
    code=code:gsub("%f[%w_][A-Z][A-Z_0-9]*%f[^%w_]",function(token)
      local value=bindings[token]
      if value~=nil then return string.format("%X",value) end
      return token
    end)
    local compiled,details=autoAssemble(code)
    assert(compiled,tostring(details))
    for name,bounds in pairs(codeBounds) do
      local ending=getAddressSafe(name)
      unregisterSymbol(name)
      assert(ending and ending&gt;a+bounds[1] and ending&lt;=a+bounds[2],bounds[3] or name..' is missing or exceeds its reserved space')
    end
    put(p.flags.encounter,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})
    put(a+0x6B00,{0,0,0,0,152,58,0,0,63,66,15,0,48,117,0,0,48,117,0,0,80,70,0,0,120,105,0,0,200,175,0,0,216,214,0,0,44,1,0,0})
    put(a+0xBF00,{0,0,0,0,0,0,0,0,0,0})
    put(a+0xB500,{0,0,0,0,0,0,0,0})
    put(a+0xF00,p.marker)
    put(a+0xF10,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})
  end)
  if not ok then
    for name in pairs(codeBounds) do unregisterSymbol(name) end
    deAlloc(a);error(reason)
  end
  KatzyIWPages[key]=p
  return p
end
local function crazyKind(kind) return kind=='crazyextreme' or kind=='crazyfood' or kind=='crazytimer' or kind=='crazyrank' end
local function otherCrazyActive(kind)
  for _,other in ipairs({'crazyextreme','crazyfood','crazytimer','crazyrank'}) do if other~=kind and S.active[other] then return true end end
  return false
end
local function usesHook(h,kind)
  return (h.kind=='lemontimer' and kind=='anacondatimer') or (h.kind=='crazy' and crazyKind(kind)) or h.kind==kind or (h.kind=='money' and (kind=='shogipoints' or kind=='pokerchips' or kind=='snappoints' or kind=='deliverypoints' or kind=='woodentags' or kind=='sujimonpoints'))
end
local function otherTimerActive(kind)
  return (kind=='lemontimer' and S.active.anacondatimer) or (kind=='anacondatimer' and S.active.lemontimer)
end
local function otherCurrencyActive(kind)
  if kind~='money' and kind~='shogipoints' and kind~='pokerchips' and kind~='snappoints' and kind~='deliverypoints' and kind~='woodentags' and kind~='sujimonpoints' then return false end
  for _,other in ipairs({'money','shogipoints','pokerchips','snappoints','deliverypoints','woodentags','sujimonpoints'}) do
    if other~=kind and S.active[other] then return true end
  end
  return false
end
local function pokerStackChange(c,adding)
  local m=readQword(c.base+0x38DEF00)
  if not m or m==0 then return nil end
  local point=readInteger(m+0x12C)
  if point~=118 and point~=594 then return nil end
  local player=readQword(m+0x28)
  if not player or player==0 or readQword(player)~=c.base+0x2C49850 then return nil end
  local address=player+0x280
  local value=readInteger(address)
  if not value or value&lt;0 or value&gt;10899999 then return nil end
  local after=adding and value+90000 or math.max(0,value-90000)
  local b={};for i=0,3 do b[#b+1]=(after &gt;&gt; (i*8)) &amp; 255 end
  return {address=address,before=bytes(address,4),after=b}
end
-- Virtua Fighter 3tb: independently derived PPC RAM and native interpreter.
-- CPU+8 is the current guest PC (16540); GPRs start at CPU+10.
-- Guest 12668 subtracts damage; ring-out stores at 61CC0/61CD0 are separate.
local vfName='pre3-pxd-w64-d3d12_retail.dll'
local vfOriginal={0x41,0x2B,0x44,0x90,0x10}
local vfDamage={0x74,0x1F,0x8E,0xB0,0x56,0x00,0x4E,0xA1}
local vfSubtract={0x51,0x50,0x44,0x7D,0x14,0x00,0x81,0x41}
local vfTimerOriginal={0x44,0x03,0x44,0x82,0x10}
local vfTimerGuest={0x14,0xE0,0x6D,0x80,0xFF,0xFF,0x63,0x38,0x00,0x00,0x03,0x2C,0x14,0xE0,0x6D,0x90}
KatzyIWVFPages=KatzyIWVFPages or {}
local function vfFailure(reason,fallback)
  S.detail=reason
  local text=tostring(reason)
  if text:find('Unsupported',1,true) then return tell('This Virtua Fighter build does not match the table. Use the supported Steam version 1.20.') end
  if text:find('another patch',1,true) then return tell('Another cheat has changed the Virtua Fighter code. Disable that cheat and retry.') end
  if text:find('reserved space',1,true) or text:find('code space',1,true) then return tell('The Virtua Fighter code could not be prepared safely. The option was left off.') end
  return tell(fallback)
end
local function vfModule(pid)
  for _,m in ipairs(enumModules(pid) or {}) do
    if m.Name:lower()==vfName then return m end
  end
end
local function vfResolve(needHealth)
  local c=S.context
  assert(c and getOpenedProcessID()==c.pid,'Game attachment changed')
  local m=vfModule(c.pid)
  assert(m and m.Size==0x639000 and m.PathToFile:gsub('/','\\'):lower():match('\\likeadragon8\\runtime\\media\\pre3\\pre3%-pxd%-w64%-d3d12_retail%.dll$'), 'Virtua Fighter is not loaded')
  assert(md5file(m.PathToFile)=='eea947d1435b3016eb16671e3d945247','Unsupported arcade emulator')
  local owner=readQword(m.Address+0x52AA80)
  assert(owner and owner~=0 and readQword(owner)==m.Address+0x10BC50,'Arcade owner changed')
  local ram=readQword(owner+8)
  local cpu=readQword(m.Address+0x52AA88)
  assert(ram and cpu and ram~=0 and cpu~=0  ,'Arcade RAM is not ready')
  assert(equal(bytes(ram+0x1261C,#vfDamage),vfDamage) and equal(bytes(ram+0x12668,#vfSubtract),vfSubtract),'Unsupported guest code')
  assert(equal(bytes(ram+0x2CFD4,#vfTimerGuest),vfTimerGuest),'Unsupported round clock')
  local result={context=c,base=m.Address,owner=owner,ram=ram,cpu=cpu}
  if not needHealth then return result end
  local p1=readInteger(ram+0x102108)
  local function fighter(p,side)
    assert(p and p&gt;=0x100000 and p&lt;=0x1FD000 and p%4==0,'Invalid fighter')
    assert(equal(bytes(ram+((p+4)~3),1),{side}),'Fighter side changed')
    local hp=readSmallInteger(ram+((p+0x56)~2))
    local maximum=readSmallInteger(ram+((p+0xCEA)~2))
    local flags=readInteger(ram+p)
    assert(hp and maximum and hp&gt;0 and maximum&gt;0 and maximum&lt;=1000 and hp&lt;=maximum and flags and (flags &amp; 0x04000000)==0,'No living fighter in this round')
    return hp,maximum
  end
  result.hp,result.maximum=fighter(p1,0)
  result.p1=p1
  return result
end
local function vfSame(p)
  local m=vfModule(p.context.pid)
  return getOpenedProcessID()==p.context.pid and m and m.Address==p.base
    and readQword(p.base+0x52AA80)==p.owner and readQword(p.owner)==p.base+0x10BC50
    and readQword(p.owner+8)==p.ram and readQword(p.base+0x52AA88)==p.cpu
end
local vfAssembly=[==[
label(vfNormal)
label(vfReturn)
label(KatzyIWVFEnd)
registersymbol(KatzyIWVFEnd)
%X:
cmp dword ptr [r8+08],00012668
jne vfNormal
cmp byte ptr [%X],1
jne vfNormal
cmp dword ptr [r8+44],00108000
jne vfNormal
cmp ecx,0A
jne vfNormal
cmp edx,04
jne vfNormal
test eax,eax
jle vfNormal
push r11
mov r11,%X
cmp r8,r11
jne vfReturn
mov r11,%X
mov r11,[r11]
test r11,r11
jz vfReturn
mov r11,[r11+08]
push r10
mov r10,%X
cmp r11,r10
pop r10
jne vfReturn
mov r11d,[r11+102108]
cmp r11d,[r8+48]
jne vfReturn
pop r11
jmp %X
vfReturn:
pop r11
vfNormal:
sub eax,[r8+rdx*4+10]
jmp %X
KatzyIWVFEnd:
]==]
local vfTimerAssembly=[==[
label(vfNormal)
label(vfReturn)
label(KatzyIWVFEnd)
registersymbol(KatzyIWVFEnd)
%X:
cmp dword ptr [rdx+08],0002CFD8
jne vfNormal
cmp byte ptr [%X],1
jne vfNormal
cmp dword ptr [rdx+44],00108000
jne vfNormal
cmp eax,03
jne vfNormal
cmp ecx,03
jne vfNormal
cmp r8d,-1
jne vfNormal
cmp dword ptr [rdx+1C],0
jle vfNormal
push r11
mov r11,%X
cmp rdx,r11
jne vfReturn
mov r11,%X
mov r11,[r11]
test r11,r11
jz vfReturn
mov r11,[r11+08]
push r10
mov r10,%X
cmp r11,r10
pop r10
jne vfReturn
mov r8d,0
vfReturn:
pop r11
vfNormal:
add r8d,[rdx+rax*4+10]
jmp %X
KatzyIWVFEnd:
]==]
local function vfPrepare(v,kind)
  local timer=kind=='vftimer'
  local offset=timer and 0x17D2C or 0x25967
  local original=timer and vfTimerOriginal or vfOriginal
  local key=string.format('%d:%X:%X:%X:1.24:%s',v.context.pid,v.base,v.ram,v.cpu,kind)
  local cached=KatzyIWVFPages[key]
  if cached and equal(bytes(cached.address+0x810,8),cached.marker) then return cached end
  assert(equal(bytes(v.base+offset,5),original),'Arcade instruction has another patch')
  local a=allocateMemory(4096,v.base+offset)
  assert(a and a~=0,'No nearby arcade code space')
  v.address=a;v.hook=v.base+offset;v.flag=a+0x800;v.marker={75,97,116,122,121,86,70,timer and 25 or 24};v.original=original
  local ok,why=pcall(function()
    v.patch=branch(v.hook,a,5)
    local assembly=timer and vfTimerAssembly or vfAssembly
    local compiled,reason=autoAssemble(assembly:format(a,v.flag,v.cpu,v.base+0x52AA80,v.ram,v.hook+5,v.hook+5))
    assert(compiled,tostring(reason))
    local ending=getAddressSafe('KatzyIWVFEnd')
    unregisterSymbol('KatzyIWVFEnd')
    assert(ending and ending&gt;a and ending&lt;=a+0x800,'Arcade code exceeds its reserved space')
    put(v.flag,{0});put(a+0x810,v.marker)
  end)
  if not ok then unregisterSymbol('KatzyIWVFEnd');deAlloc(a);error(why) end
  KatzyIWVFPages[key]=v
  return v
end
local function vfRestore(kind)
  if kind=='vfenemy' then
    S.active.vfenemy=false
    if S.vfEnemyTimer then S.vfEnemyTimer.destroy();S.vfEnemyTimer=nil end
    S.vfEnemy=nil
    return true
  end
  if not S.active[kind] then return true end
  local p=S.vfPages[kind]
  local selected=getOpenedProcessID()
  local m=module(p.context.pid)
  if not m or m.Address~=p.context.base then S.active[kind]=false;return true end
  if selected~=p.context.pid then openProcess(p.context.pid) end
  if getOpenedProcessID()~=p.context.pid then return false end
  local ok,why=paused(function()
    assert(equal(bytes(p.address+0x810,8),p.marker),'Arcade code ownership changed')
    put(p.flag,{0})
    local current=vfModule(p.context.pid)
    if current and current.Address==p.base then
      local code=bytes(p.hook,5)
      assert(equal(code,p.patch) or equal(code,p.original),'Another patch owns arcade instruction')
      if equal(code,p.patch) then put(p.hook,p.original) end
    end
  end)
  if selected~=p.context.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=why
  if ok then S.active[kind]=false end
  return ok
end
local function vfEnable(kind)
  if not main.Active or not list.getMemoryRecordByID(27).Active then return tell('Enable MAIN and Virtua Fighter first.') end
  if not ready() then return false end
  if S.active[kind] then return true end
  local ok,why=paused(function()
    local v=vfResolve(kind=='vfhealth')
    local p=vfPrepare(v,kind)
    assert(vfSame(p) and equal(bytes(p.hook,5),p.original),'Arcade context changed')
    if kind=='vftimer' then local ticks=readInteger(v.ram+0x106014);assert(ticks and ticks&gt;0 and ticks&lt;=36000,'The round clock has expired') end
    local hpAddress,oldHP
    if kind=='vfhealth' then hpAddress=v.ram+((v.p1+0x56)~2);oldHP=bytes(hpAddress,2) end
    S.vfPages=S.vfPages or {};S.vfPages[kind]=p;S.active[kind]=true
    local installed,reason=pcall(function()
      if kind=='vfhealth' then put(hpAddress,{v.maximum &amp; 255,v.maximum &gt;&gt; 8}) end
      put(p.flag,{1});put(p.hook,p.patch)
    end)
    if not installed then
      put(p.flag,{0});put(p.hook,p.original)
      if kind=='vfhealth' then put(hpAddress,oldHP) end
      S.active[kind]=false;error(reason)
    end
  end)
  if not ok then
    if not vfRestore(kind) then return tell('The arcade hook could not be restored. Keep this table open, remove conflicting cheats, and use Clear All.') end
    return vfFailure(why,'For Infinite Health, wait until your fighter is alive. For Infinite Timer, wait until round time remains, then retry. Disable other arcade cheats if it still cannot activate.')
  end
  return true
end
local function vfSetEnemy()
  if not main.Active or not list.getMemoryRecordByID(27).Active then return tell('Enable MAIN and Virtua Fighter first.') end
  if not ready() then return false end
  if S.active.vfenemy then return true end
  local ok,v=pcall(vfResolve)
  if not ok then return vfFailure(v,'Open Virtua Fighter 3tb, then enable Set Enemy Health to 1 again.') end
  S.vfEnemy=v;S.active.vfenemy=true
  local function target()
    if not vfSame(v) then return nil end
    local p=readInteger(v.ram+0x10210C)
    if not p or p&lt;0x100000 or p&gt;0x1FD000 or p%4~=0 or p==readInteger(v.ram+0x102108) then return nil end
    if not equal(bytes(v.ram+((p+4)~3),1),{1}) then return nil end
    local flags=readInteger(v.ram+p)
    local a=v.ram+((p+0x56)~2)
    local hp=readSmallInteger(a)
    local maximum=readSmallInteger(v.ram+((p+0xCEA)~2))
    if not flags or (flags &amp; 0x04000000)~=0 or not hp or not maximum or hp&lt;=1 or hp&gt;maximum or maximum&gt;1000 then return nil end
    return a
  end
  local function tick()
    if not S.active.vfenemy then return end
    if not vfSame(v) then vfRestore('vfenemy');records.vfenemy.Active=false;return end
    -- Idle checks never pause. Re-resolve inside the transaction so a new
    -- opponent or a knockout between reads cannot receive an old write.
    if not target() then return end
    local success,reason=paused(function()
      local a=target()
      if not a then return end
      local before=bytes(a,2)
      local wrote,why=pcall(put,a,{1,0})
      if not wrote then put(a,before);error(why) end
    end)
    if not success then
      vfRestore('vfenemy');records.vfenemy.Active=false
      if module(v.context.pid) then vfFailure(reason,'Enemy health could not be updated. The option stopped; enable it again during a round.') end
    end
  end
  S.vfEnemyTimer=createTimer(nil,false)
  S.vfEnemyTimer.Interval=500
  S.vfEnemyTimer.OnTimer=tick
  tick()
  if not S.active.vfenemy then return false end
  S.vfEnemyTimer.Enabled=true
  return true
end

-- SpikeOut Final Edition: guest 22680 subtracts damage, actors are 4000 bytes.
-- Players occupy 1A0000..1AC000; 16 enemy slots occupy 1B0000..1EC000.
-- Guest halfwords use host offset XOR 2; energy is +3F02, maximum +3F04.
KatzyIWSpikePages=KatzyIWSpikePages or {}
local function spikeSame(p)
  return vfSame(p) and readInteger(p.ram+0x22680)==0x7E248851
    and readInteger(p.ram+0x227B8)==0xB22E3F02
end
local function spikeResolve()
  local c=S.context
  assert(c and getOpenedProcessID()==c.pid,'Game attachment changed')
  local m=vfModule(c.pid)
  assert(m and m.Size==0x639000 and m.PathToFile:gsub('/','\\'):lower():match('\\likeadragon8\\runtime\\media\\pre3\\pre3%-pxd%-w64%-d3d12_retail%.dll$'),'SpikeOut is not loaded')
  assert(md5file(m.PathToFile)=='eea947d1435b3016eb16671e3d945247','Unsupported arcade emulator')
  local owner=readQword(m.Address+0x52AA80)
  assert(owner and owner~=0 and readQword(owner)==m.Address+0x10BC50,'Arcade owner changed')
  local p={context=c,base=m.Address,owner=owner,ram=readQword(owner+8),cpu=readQword(m.Address+0x52AA88)}
  assert(p.ram and p.cpu and p.ram~=0 and p.cpu~=0 and spikeSame(p),'Start SpikeOut first')
  return p
end
local function spikeActor(p,slot)
  if readBytes(p.ram+(0x104008~3),1)~=7 then return end
  local actor=0x1A0000+slot*0x4000
  local flags=readInteger(p.ram+actor)
  if not flags or flags&amp;1==0 or flags&amp;0x04000000~=0 then return end
  if readInteger(p.ram+actor+8)~=0x4000 or readInteger(p.ram+actor+12)~=0x1E94C then return end
  if readBytes(p.ram+((actor+0x72)~3),1)~=slot then return end
  if slot&lt;4 and flags&amp;4==0 or slot&gt;=4 and flags&amp;2==0 then return end
  local hp=readSmallInteger(p.ram+((actor+0x3F02)~2))
  local maximum=readSmallInteger(p.ram+((actor+0x3F04)~2))
  if not hp or not maximum or hp&lt;=0 or maximum&lt;=0 or maximum&gt;10000 or hp&gt;maximum then return end
  return actor,hp,maximum
end
local spikeAssembly=[==[
label(spikeNormal)
label(spikePop)
label(KatzyIWSpikeEnd)
registersymbol(KatzyIWSpikeEnd)
%X:
cmp dword ptr [r8+08],00022680
jne spikeNormal
cmp byte ptr [%X],1
jne spikeNormal
cmp dword ptr [r8+44],00108000
jne spikeNormal
cmp ecx,11
jne spikeNormal
cmp edx,04
jne spikeNormal
test eax,eax
jle spikeNormal
push r10
push r11
mov r11,%X
cmp r8,r11
jne spikePop
mov r11,%X
mov r11,[r11]
test r11,r11
jz spikePop
mov r11,[r11+08]
mov r10,%X
cmp r11,r10
jne spikePop
cmp byte ptr [r11+10400B],7
jne spikePop
mov r10d,[r8+48]
cmp r10d,001A0000
jb spikePop
cmp r10d,001B0000
jae spikePop
test r10d,3FFF
jnz spikePop
test dword ptr [r11+r10],4
jz spikePop
pop r11
pop r10
jmp %X
spikePop:
pop r11
pop r10
spikeNormal:
sub eax,[r8+rdx*4+10]
jmp %X
KatzyIWSpikeEnd:
]==]
local function spikePrepare(v)
  local key=string.format('%d:%X:%X:%X:1.63',v.context.pid,v.base,v.ram,v.cpu)
  local cached=KatzyIWSpikePages[key]
  if cached and equal(bytes(cached.address+0x810,8),cached.marker) then return cached end
  local original={0x41,0x2B,0x44,0x90,0x10}
  assert(equal(bytes(v.base+0x25967,5),original),'Arcade instruction has another patch')
  local a=allocateMemory(4096,v.base+0x25967)
  assert(a and a~=0,'No nearby code space')
  v.address=a;v.hook=v.base+0x25967;v.flag=a+0x800
  v.original=original;v.marker={75,97,116,122,121,83,80,1}
  local ok,why=pcall(function()
    v.patch=branch(v.hook,a,5)
    local compiled,reason=autoAssemble(spikeAssembly:format(a,v.flag,v.cpu,v.base+0x52AA80,v.ram,v.hook+5,v.hook+5))
    assert(compiled,tostring(reason))
    local ending=getAddressSafe('KatzyIWSpikeEnd');unregisterSymbol('KatzyIWSpikeEnd')
    assert(ending and ending&gt;a and ending&lt;=a+0x800,'SpikeOut code exceeds reserved space')
    put(v.flag,{0});put(a+0x810,v.marker)
  end)
  if not ok then unregisterSymbol('KatzyIWSpikeEnd');deAlloc(a);error(why) end
  KatzyIWSpikePages[key]=v
  return v
end
local function spikeRestore(kind)
  if kind=='spikesuper' then
    S.active[kind]=false
    if S.spikeStockTimer then S.spikeStockTimer.destroy();S.spikeStockTimer=nil end
    local v=S.spikeStock
    if not v then return true end
    local ok,why=true,nil
    if spikeSame(v) and next(v.saved) then
      ok,why=paused(function()
        for slot,item in pairs(v.saved) do
          if spikeActor(v,slot) and readBytes(item.address,1)==5 then put(item.address,{item.before}) end
        end
      end)
    end
    S.detail=why
    if ok then S.spikeStock=nil else S.active[kind]=true end
    return ok
  end
  if kind=='spikecharge' then
    S.active[kind]=false
    if S.spikeChargeTimer then S.spikeChargeTimer.destroy();S.spikeChargeTimer=nil end
    local v=S.spikeCharge
    if not v then return true end
    local ok,why=true,nil
    if spikeSame(v) and next(v.saved) then
      ok,why=paused(function()
        for slot,item in pairs(v.saved) do
          local actor=spikeActor(v,slot)
          if actor and readInteger(v.ram+actor+0x2248)&amp;2~=0 and readSmallInteger(item.address)==item.after then put(item.address,item.before) end
        end
      end)
    end
    S.detail=why
    if ok then S.spikeCharge=nil else S.active[kind]=true end
    return ok
  end
  if kind=='spikeenemy' then
    S.active[kind]=false
    if S.spikeEnemyTimer then S.spikeEnemyTimer.destroy();S.spikeEnemyTimer=nil end
    S.spikeEnemy=nil
    return true
  end
  if not S.active[kind] then return true end
  local p=S.spikePage
  local m=module(p.context.pid)
  if not m or m.Address~=p.context.base then S.active[kind]=false;return true end
  local selected=getOpenedProcessID()
  if selected~=p.context.pid then openProcess(p.context.pid) end
  if getOpenedProcessID()~=p.context.pid then return false end
  local ok,why=paused(function()
    assert(equal(bytes(p.address+0x810,8),p.marker),'SpikeOut ownership changed')
    put(p.flag,{0})
    local current=vfModule(p.context.pid)
    if current and current.Address==p.base then
      local code=bytes(p.hook,5)
      assert(equal(code,p.patch) or equal(code,p.original),'Another patch owns the instruction')
      if equal(code,p.patch) then put(p.hook,p.original) end
    end
  end)
  if selected~=p.context.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=why
  if ok then S.active[kind]=false end
  return ok
end
local function spikeEnable(kind)
  if not main.Active or not list.getMemoryRecordByID(63).Active then return tell('Enable MAIN and SpikeOut first.') end
  if not ready() then return false end
  if S.active[kind] then return true end
  local ok,v=pcall(spikeResolve)
  if not ok then S.detail=v;return tell('Start SpikeOut Final Edition, then enable this option again.') end
  if kind=='spikesuper' then
    -- 21FC8 consumes a stock; 54460 grants one (cap 5); 1B8DC reads HUD stock.
    if readInteger(v.ram+0x21FC8)~=0x988E3F25 then return tell('The Super Attack code does not match this table. The option was left off.') end
    v.saved={};S.spikeStock=v;S.active[kind]=true
    local function candidates()
      local result={}
      if not spikeSame(v) then return result end
      for slot=0,3 do
        local actor=spikeActor(v,slot)
        if not actor then v.saved[slot]=nil
        else
          local address=v.ram+((actor+0x3F25)~3)
          local current=readBytes(address,1)
          if current and current&gt;=0 and current&lt;5 then result[#result+1]={slot=slot,address=address,before=current} end
        end
      end
      return result
    end
    local function tick()
      if not S.active[kind] then return end
      if not spikeSame(v) then spikeRestore(kind);records[kind].Active=false;return end
      if #candidates()==0 then return end
      local success,reason=paused(function()
        for _,t in ipairs(candidates()) do
          v.saved[t.slot]=v.saved[t.slot] or t
          local written,why=pcall(put,t.address,{5})
          if not written then put(t.address,{t.before});error(why) end
        end
      end)
      if not success then
        S.detail=reason
        if spikeRestore(kind) then records[kind].Active=false end
        if module(v.context.pid) then tell('Super Attack stock could not be updated. Disable and re-enable the option during SpikeOut.') end
      end
    end
    S.spikeStockTimer=createTimer(nil,false);S.spikeStockTimer.Interval=250;S.spikeStockTimer.OnTimer=tick
    tick();if S.active[kind] then S.spikeStockTimer.Enabled=true end
    return S.active[kind]==true
  end
  if kind=='spikecharge' then
    v.saved={};S.spikeCharge=v;S.active[kind]=true
    local function candidates()
      local result={}
      if not spikeSame(v) then return result end
      for slot=0,3 do
        local actor=spikeActor(v,slot)
        local held=actor and readInteger(v.ram+actor+0x2248)
        if not held or held&amp;2==0 then v.saved[slot]=nil
        else
          local address=v.ram+((actor+0x224E)~2)
          local current=readSmallInteger(address)
          local peak=readSmallInteger(v.ram+((actor+0x1E70)~2))
          local timeout=readSmallInteger(v.ram+((actor+0x1E84)~2))
          if current and peak and timeout and peak&gt;0 and peak&lt;timeout and timeout&lt;=3600 and current~=peak then
            result[#result+1]={slot=slot,address=address,peak=peak}
          end
        end
      end
      return result
    end
    local function tick()
      if not S.active[kind] then return end
      if not spikeSame(v) then spikeRestore(kind);records[kind].Active=false;return end
      if #candidates()==0 then return end
      local success,reason=paused(function()
        for _,t in ipairs(candidates()) do
          local before=bytes(t.address,2)
          local saved=v.saved[t.slot] or {address=t.address,before=before}
          saved.after=t.peak;v.saved[t.slot]=saved
          local written,why=pcall(put,t.address,{t.peak&amp;255,t.peak&gt;&gt;8})
          if not written then put(t.address,before);error(why) end
        end
      end)
      if not success then S.detail=reason;spikeRestore(kind);records[kind].Active=false end
    end
    S.spikeChargeTimer=createTimer(nil,false);S.spikeChargeTimer.Interval=100;S.spikeChargeTimer.OnTimer=tick
    tick();if S.active[kind] then S.spikeChargeTimer.Enabled=true end
    return S.active[kind]==true
  end
  if kind=='spikehealth' then
    local success,reason=paused(function()
      local p=spikePrepare(v)
      assert(spikeSame(p) and equal(bytes(p.hook,5),p.original),'Arcade context changed')
      S.spikePage=p;S.active[kind]=true
      local installed,why=pcall(function() put(p.flag,{1});put(p.hook,p.patch) end)
      if not installed then
        put(p.flag,{0});put(p.hook,p.original);S.active[kind]=false;error(why)
      end
    end)
    if not success then
      S.detail=reason
      local restored=spikeRestore(kind)
      return tell(restored and 'SpikeOut health protection could not start. Disable other arcade health options and retry.' or 'The arcade hook could not be restored. Keep this table open and use Clear All after removing conflicting cheats.')
    end
    return true
  end
  S.spikeEnemy=v;S.active.spikeenemy=true
  local nextSlot=4
  local function targets()
    local result={}
    if not spikeSame(v) then return result end
    -- At most eight writes per batch; visit all sixteen slots without a RAM scan.
    for i=0,15 do
      local slot=4+(nextSlot-4+i)%16
      local actor,hp=spikeActor(v,slot)
      if actor and hp&gt;1 then result[#result+1]={slot=slot,address=v.ram+((actor+0x3F02)~2)} end
      if #result==8 then nextSlot=4+(slot-3)%16;break end
    end
    return result
  end
  local function tick()
    if not S.active.spikeenemy then return end
    if not spikeSame(v) then spikeRestore('spikeenemy');records.spikeenemy.Active=false;return end
    if #targets()==0 then return end
    local success,reason=paused(function()
      for _,t in ipairs(targets()) do
        local before=bytes(t.address,2)
        local written,why=pcall(put,t.address,{1,0})
        if not written then put(t.address,before);error(why) end
      end
    end)
    if not success then
      spikeRestore('spikeenemy');records.spikeenemy.Active=false;S.detail=reason
      if module(v.context.pid) then tell('Enemy health could not be updated. The option stopped; enable it again during SpikeOut.') end
    end
  end
  S.spikeEnemyTimer=createTimer(nil,false);S.spikeEnemyTimer.Interval=500
  S.spikeEnemyTimer.OnTimer=tick;tick()
  if S.active.spikeenemy then S.spikeEnemyTimer.Enabled=true end
  return S.active.spikeenemy==true
end

-- Sega Bass Fishing guest code, independently derived from getbass.par.
-- 143B0 advances the round-clock frame counter. 33F0C computes tension;
-- its result is stored at 1358E4 and passed to the native break classifier.
-- 160 / 16 = band 10 (safe 8..17); the gauge uses model band floor(160/100).
local bassSpecs={
  basstimer={offset=0x17A5C,original={0x41,0x8B,0x44,0x81,0x10},pc=0x143B0,cpu='r9'},
  basstension={offset=0x1B781,original={0xC5,0xF3,0x5A,0xD1,0xC5,0xEA,0x5A,0xDA},pc=0x33F0C,cpu='rdx'}
}
KatzyIWBassPages=KatzyIWBassPages or {}
local function bassSame(p)
  return vfSame(p) and readInteger(p.ram+0x143B0)==0x30000001
    and readInteger(p.ram+0x33F0C)==0xEC210024
end
local function bassResolve()
  local c=S.context
  assert(c and getOpenedProcessID()==c.pid,'Game attachment changed')
  local m=vfModule(c.pid)
  assert(m and m.Size==0x639000 and m.PathToFile:gsub('/','\\'):lower():match('\\likeadragon8\\runtime\\media\\pre3\\pre3%-pxd%-w64%-d3d12_retail%.dll$'),'Fishing arcade is not loaded')
  assert(md5file(m.PathToFile)=='eea947d1435b3016eb16671e3d945247','Unsupported arcade emulator')
  local owner=readQword(m.Address+0x52AA80)
  assert(owner and owner~=0 and readQword(owner)==m.Address+0x10BC50,'Arcade owner changed')
  local p={context=c,base=m.Address,owner=owner,ram=readQword(owner+8),cpu=readQword(m.Address+0x52AA88)}
  assert(p.ram and p.cpu and p.ram~=0 and p.cpu~=0 and bassSame(p),'Start Sega Bass Fishing first')
  assert(readInteger(p.ram+0x143CC)==0x900A0010 and readInteger(p.ram+0x33F14)==0xD02958E4,'Unsupported fishing code')
  return p
end
local function bassPrepare(v,kind)
  local spec=bassSpecs[kind]
  local key=string.format('%d:%X:%X:%X:1.26:%s',v.context.pid,v.base,v.ram,v.cpu,kind)
  local cached=KatzyIWBassPages[key]
  if cached and equal(bytes(cached.address+0x810,8),cached.marker) then return cached end
  assert(equal(bytes(v.base+spec.offset,#spec.original),spec.original),'Another patch owns the fishing instruction')
  local a=allocateMemory(4096,v.base+spec.offset)
  assert(a and a~=0,'No nearby fishing code space')
  v.address=a;v.flag=a+0x800;v.hook=v.base+spec.offset;v.original=spec.original
  v.marker={75,97,116,122,121,66,70,kind=='basstimer' and 1 or 2}
  local ok,why=pcall(function()
    v.patch=branch(v.hook,a,#spec.original)
    local head=([==[
label(bassNormal)
label(bassPop)
label(bassDone)
label(KatzyIWBassEnd)
registersymbol(KatzyIWBassEnd)
%X:
cmp dword ptr [%s+08],%X
jne bassNormal
cmp byte ptr [%X],1
jne bassNormal
push r11
mov r11,%X
cmp %s,r11
jne bassPop
mov r11,%X
mov r11,[r11]
test r11,r11
jz bassPop
mov r11,[r11+08]
push r10
mov r10,%X
cmp r11,r10
pop r10
jne bassPop
cmp dword ptr [r11+143B0],30000001
jne bassPop
cmp dword ptr [r11+33F0C],EC210024
jne bassPop
]==]):format(a,spec.cpu,spec.pc,v.flag,v.cpu,spec.cpu,v.base+0x52AA80,v.ram)
    local body
    if kind=='basstimer' then
      body=([==[
xor r8d,r8d
bassPop:
pop r11
bassNormal:
mov eax,[r9+rax*4+10]
bassDone:
jmp %X
KatzyIWBassEnd:
]==]):format(v.hook+5)
    else
      body=([==[
cmp dword ptr [r11+122A7C],1
jne bassPop
cmp dword ptr [r11+134E98],0
je bassPop
pop r11
vcvtsd2ss xmm2,xmm1,xmm1
vcvtss2sd xmm3,xmm2,xmm2
push r11
mov r11,4064000000000000
vmovq xmm3,r11
pop r11
jmp bassDone
bassPop:
pop r11
bassNormal:
vcvtsd2ss xmm2,xmm1,xmm1
vcvtss2sd xmm3,xmm2,xmm2
bassDone:
jmp %X
KatzyIWBassEnd:
]==]):format(v.hook+8)
    end
    local compiled,reason=autoAssemble(head..body)
    assert(compiled,tostring(reason))
    local ending=getAddressSafe('KatzyIWBassEnd');unregisterSymbol('KatzyIWBassEnd')
    assert(ending and ending&gt;a and ending&lt;=a+0x800,'Fishing code exceeds reserved space')
    put(v.flag,{0});put(a+0x810,v.marker)
  end)
  if not ok then unregisterSymbol('KatzyIWBassEnd');deAlloc(a);error(why) end
  KatzyIWBassPages[key]=v
  return v
end
local function bassRestore(kind)
  if kind=='basspoints' then
    S.active.basspoints=false
    if S.bassPointTimer then S.bassPointTimer.destroy();S.bassPointTimer=nil end
    S.bassPointContext=nil
    return true
  end
  if not S.active[kind] then return true end
  local p=S.bassPages[kind]
  local selected=getOpenedProcessID()
  local m=module(p.context.pid)
  if not m or m.Address~=p.context.base then S.active[kind]=false;return true end
  if selected~=p.context.pid then openProcess(p.context.pid) end
  if getOpenedProcessID()~=p.context.pid then return false end
  local ok,why=paused(function()
    assert(equal(bytes(p.address+0x810,8),p.marker),'Fishing code ownership changed')
    put(p.flag,{0})
    local current=vfModule(p.context.pid)
    if current and current.Address==p.base then
      local code=bytes(p.hook,#p.original)
      assert(equal(code,p.patch) or equal(code,p.original),'Another patch owns fishing instruction')
      if equal(code,p.patch) then put(p.hook,p.original) end
    end
  end)
  if selected~=p.context.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=why
  if ok then S.active[kind]=false end
  return ok
end
local function bassEnable(kind)
  if not main.Active or not list.getMemoryRecordByID(31).Active then return tell('Enable MAIN and Sega Bass Fishing first.') end
  if not ready() then return false end
  if S.active[kind] then return true end
  local ok,why=paused(function()
    local v=bassResolve()
    local p=bassPrepare(v,kind)
    assert(bassSame(p) and equal(bytes(p.hook,#p.original),p.original),'Fishing context changed')
    S.bassPages=S.bassPages or {};S.bassPages[kind]=p;S.active[kind]=true
    local installed,reason=pcall(function()
      put(p.flag,{1});put(p.hook,p.patch)
    end)
    if not installed then
      put(p.flag,{0});put(p.hook,p.original)
      S.active[kind]=false;error(reason)
    end
  end)
  if not ok then
    S.detail=why
    if not bassRestore(kind) then return tell('A fishing hook still needs restoration. Keep this table open and use Clear All after removing conflicting cheats.') end
    return tell('The fishing option could not start. Open Sega Bass Fishing and disable other arcade cheats, then retry.')
  end
  return true
end
local function bassFillPoints()
  if not main.Active or not list.getMemoryRecordByID(31).Active then return tell('Enable MAIN and Sega Bass Fishing first.') end
  if not ready() then return false end
  if S.active.basspoints then return true end
  local valid,p=pcall(bassResolve)
  if not valid then S.detail=p;return tell('Open Sega Bass Fishing before enabling Max Points.') end
  S.bassPointContext=p;S.active.basspoints=true
  local function target()
    if not bassSame(p) or readInteger(p.ram+0x130CD4)~=1 then return nil end
    local required=readSmallInteger(p.ram+(0x13590A~2))
    local address=p.ram+(0x12E5F4~2)
    local current=readSmallInteger(address)
    if not required or not current then return nil end
    required=required &amp; 65535;current=current &amp; 65535
    if required&lt;=100 or current&gt;=required-100 then return nil end
    return address,required-100
  end
  local function tick()
    if not S.active.basspoints then return end
    if not bassSame(p) then bassRestore('basspoints');records.basspoints.Active=false;return end
    if not target() then return end
    local ok,why=paused(function()
      local address,amount=target()
      if not address then return end
      local before=bytes(address,2)
      local wrote,reason=pcall(put,address,{amount &amp; 255,amount &gt;&gt; 8})
      if not wrote then put(address,before);error(reason) end
    end)
    if not ok then
      S.detail=why;bassRestore('basspoints');records.basspoints.Active=false
      if module(p.context.pid) then tell('The fishing score could not be updated. Max Points stopped; enable it again during a stage.') end
    end
  end
  S.bassPointTimer=createTimer(nil,false)
  S.bassPointTimer.Interval=500;S.bassPointTimer.OnTimer=tick
  tick()
  if not S.active.basspoints then return false end
  S.bassPointTimer.Enabled=true
  return true
end

local function finishCrazyClock(p)
  local base=p.context.base
  local function actor(handle,kind)
    if not handle or handle==0 or (handle &amp; 0xFFFFF)&gt;=0x80000 then return nil end
    local entry=base+0x38E6300+(handle &amp; 0xFFFFF)*32
    if readSmallInteger(entry+8)~=(handle &gt;&gt; 20) or readSmallInteger(entry+12)~=kind then return nil end
    local value=readQword(entry)
    return value and value~=0 and value or nil
  end
  local handle=readInteger(p.address+0x5F10)
  local owner=actor(handle,3)
  if not owner or readQword(owner)~=base+0x2AA44E0 then return end
  local state=readInteger(owner+0x1F8)
  if state~=3 and state~=4 then return end
  local timer=actor(readInteger(owner+0xD0),4)
  if not timer or readQword(timer)~=base+0x2A59A40 or readInteger(timer+0x28)~=handle then return end
  local value=readInteger(timer+0x78)
  -- Positive finite float only: an expired run must not be restarted.
  if not value or value&lt;=0 or value&gt;=0x7F800000 then return end
  local before=bytes(timer+0x78,4)
  assert(before and #before==4,'Unreadable delivery clock')
  local ok,why=pcall(put,timer+0x78,{0,0,32,65}) -- 10.0 seconds
  if not ok then put(timer+0x78,before);error(why) end
end
local function restore(kind)
  if kind:sub(1,5)=='spike' then return spikeRestore(kind) end
  if kind=='friendship' then return friendshipRestore() end
  if bassSpecs[kind] or kind=='basspoints' then return bassRestore(kind) end
  if kind=='vfhealth' or kind=='vftimer' or kind=='vfenemy' then return vfRestore(kind) end
  if kind=='items' then
    if S.fillTimer then S.fillTimer.destroy();S.fillTimer=nil end
    S.itemFill=nil
  end
  if not S.active[kind] then return true end
  local p=S.page
  local selected=getOpenedProcessID()
  local m=module(p.context.pid)
  if not m or m.Address~=p.context.base then S.active[kind]=false;return true end
  if selected~=p.context.pid then openProcess(p.context.pid) end
  if getOpenedProcessID()~=p.context.pid then return false end
  local ok,reason=paused(function()
    assert(equal(bytes(p.address+0xF00,#p.marker),p.marker),'Process context changed')
    local stack
    if kind=='pokerchips' then
      S.pokerStackRestore=S.pokerStackRestore or pokerStackChange(p.context,false)
      stack=S.pokerStackRestore
    end
    for _,h in ipairs(p.hooks) do
      if usesHook(h,kind) then
        local current=bytes(h.address,#h.original)
        assert(equal(current,h.original) or equal(current,h.patch),'Another patch owns this entry point')
      end
    end
    if kind=='crazytimer' then finishCrazyClock(p) end
    put(p.flags[kind],{0})
    if stack then put(stack.address,stack.after) end
    for _,h in ipairs(p.hooks) do
      if usesHook(h,kind) and not ((h.kind=='money' and otherCurrencyActive(kind)) or (h.kind=='crazy' and otherCrazyActive(kind)) or (h.kind=='lemontimer' and otherTimerActive(kind))) and equal(bytes(h.address,#h.original),h.patch) then put(h.address,h.original) end
    end
  end)
  if selected~=p.context.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=reason
  if ok then S.active[kind]=false;if kind=='pokerchips' then S.pokerStackRestore=nil end end
  return ok
end
local function restoreKinds(fn,kinds)
  local ok=true
  for _,kind in ipairs(kinds) do
    local restored=fn(kind)
    ok=restored and ok
  end
  return ok
end
local function restoreAll()
  local ok=restoreKinds(restore,{'sujimonpoints','schoolanswer','schooltimer','dokomoney','dokomaterials','dokotalent','dokosatisfaction','dokopopularity','dokotime','dokohp'})
  if S.stopSujimonGrowth then S.stopSujimonGrowth() end
  ok=restoreKinds(restore,{'recruiteffort','recruitauto','sujimonmp','sujimonroulette','sujimonsp','anacondatimer','anacondaquiz','ufosticky','koipoints','koiauto','oichowin','woodentags','lemontimer','crazyrank','crazyextreme','crazyfood','crazytimer'}) and ok
  friendshipRestore()
  local shogiOk=cancelShogi()
  local mahjongOk=cancelMahjong()
  ok=shogiOk and mahjongOk and ok
  ok=restoreKinds(restore,{'health','money','mana','guard','skill','items','shogipoints','level','job','pokerchips','pokerwin','chase','emoji','match','matchauto','snap','deliverypoints','snappoints','encounter','tag','fishing','bond','karaoke','darts'}) and ok
  ok=restoreKinds(spikeRestore,{'spikehealth','spikeenemy','spikecharge','spikesuper'}) and ok
  ok=restoreKinds(vfRestore,{'vfhealth','vftimer','vfenemy'}) and ok
  ok=restoreKinds(bassRestore,{'basstimer','basstension','basspoints'}) and ok
  return ok
end
-- Resolve only the four current party slots; never scan the process or refill
-- enemies. Run while paused so roster handles cannot change between reads.
local function refillChanges(kind,c)
  if kind~='health' and kind~='mana' then return {} end
  local changes,seen={},{}
  local hp=kind=='health'
  local function add(current,maximum,size)
    if seen[current] then return end
    seen[current]=true
    local now=hp and readQword(current) or readInteger(current)
    local full=hp and readQword(maximum) or readInteger(maximum)
    assert(now and full and now&gt;=0 and full&gt;=0,'The party meters could not be read')
    if now&gt;=full or (hp and now==0) then return end
    local before,after=bytes(current,size),bytes(maximum,size)
    assert(before and after and #before==size and #after==size,'The party meters could not be read')
    changes[#changes+1]={address=current,before=before,after=after}
  end
  local manager=readQword(c.base+0x38C8750)
  assert(manager and readQword(manager)==c.base+0x2B03680 and readQword(manager+0x3A0)==c.base+0x2B0AA00,'The party changed')
  local count=readInteger(manager+0x6364)
  local ids=readQword(manager+0x6358)
  assert(count and count&gt;=0 and count&lt;=4 and ids,'The party roster could not be read')
  for i=0,count-1 do
    local id=readInteger(ids+i*4)
    for slot=0,9 do
      if id==readInteger(c.base+0x2B0A378+slot*4) then
        local stat=manager+0x3A8+slot*0x7F8
        if hp then add(stat,stat+8,8) else add(stat+0x10,stat+0x14,4) end
        break
      end
    end
  end
  local function resolve(handle,kind)
    if not handle or handle==0 or (handle &amp; 0xFFFFF)&gt;=0x80000 then return nil end
    local entry=c.base+0x38E6300+(handle &amp; 0xFFFFF)*0x20
    if readSmallInteger(entry+8)~=(handle &gt;&gt; 20) or readSmallInteger(entry+0xC)~=kind then return nil end
    local pointer=readQword(entry)
    return pointer and pointer~=0 and pointer or nil
  end
  local roster=readQword(c.base+0x38DCCA0)
  if roster and roster~=0 and readQword(roster)==c.base+0x2C20DD0 then
    for slot=0,3 do
      local actor=resolve(readInteger(roster+0x158+slot*0x160),3)
      local fighter=actor and resolve(readInteger(actor+0x4DE8),4)
      if fighter and readQword(fighter)==c.base+0x2C10C38 and readQword(fighter+0x80)==actor and readQword(fighter+0x1FA8)==c.base+0x2C10B28 then
        if hp then add(fighter+0x1FB8,fighter+0x1FB0,8)
        else add(fighter+0x2138,fighter+0x213C,4) end
      end
    end
  end
  return changes
end
local function integerBytes(value,size)
  local result={}
  for i=0,size-1 do result[i+1]=(value &gt;&gt; (i*8)) &amp; 255 end
  return result
end
-- Aloha Links: prepare met friends at 999, then let a normal interaction
-- cross 1000 through native 14F6BC0 and its caller 74F6F7. The caller
-- requires a changed result before dispatching the Best Buddy event.
friendshipRestore=function()
  S.active.friendship=false
  if S.friendshipTimer then S.friendshipTimer.destroy();S.friendshipTimer=nil end
  S.friendshipContext=nil
  return true
end
local function friendshipSnapshot(c)
  local m=module(c.pid)
  assert(m and m.Address==c.base and getOpenedProcessID()==c.pid,'Game changed')
  local owner=readQword(c.base+0x38C8750)
  assert(owner and owner~=0 and readQword(owner)==c.base+0x2B03680,'Save changed')
  local state=owner+0x11BD0
  assert(readQword(state)==c.base+0x2B035A8,'Aloha Links state unavailable')
  local data,capacity,count=readQword(state+8),readInteger(state+0x10),readInteger(state+0x14)
  assert(data and data~=0 and count==201 and capacity and capacity&gt;=count and capacity&lt;=4096,'Invalid friend list')
  if c.owner then assert(owner==c.owner and data==c.data,'Friend list changed') end
  local b=bytes(data,count*8)
  assert(b and #b==count*8,'Unreadable friend list')
  local met,best,eligible=0,0,{}
  for id=1,200 do
    local i=id*8+1
    local points=b[i]|(b[i+1]&lt;&lt;8)|(b[i+2]&lt;&lt;16)|(b[i+3]&lt;&lt;24)
    local known=b[i+4]
    assert(points&gt;=0 and points&lt;=1000 and (known==0 or known==1),'Invalid friend entry')
    if known==1 then
      met=met+1
      if points==1000 then best=best+1 elseif points&lt;999 then eligible[#eligible+1]={id=id,address=data+id*8} end
    end
  end
  local storedBest,storedMet=readInteger(state+0x40),readInteger(state+0x44)
  -- A native update can interleave the read-only precheck. Retry next tick.
  if best~=storedBest or met~=storedMet then return nil end
  return {owner=owner,data=data,state=state,best=best,eligible=eligible}
end
local function friendshipBatch(c)
  local v=friendshipSnapshot(c)
  if not v or #v.eligible==0 then return end
  local changes={}
  for _,entry in ipairs(v.eligible) do
    if #changes==3 then break end
    changes[#changes+1]={address=entry.address,after=integerBytes(999,4)}
  end
  for _,change in ipairs(changes) do change.before=bytes(change.address,#change.after) end
  local attempted=0
  local ok,why=pcall(function()
    for index,change in ipairs(changes) do attempted=index;put(change.address,change.after) end
  end)
  if not ok then
    for index=attempted,1,-1 do put(changes[index].address,changes[index].before) end
    error(why)
  end
end
friendshipEnable=function()
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  if S.active.friendship then return true end
  local c={pid=S.context.pid,base=S.context.base}
  local valid,v=pcall(friendshipSnapshot,c)
  if not valid or not v then S.detail=v;return tell('Aloha Links is not ready. Load your save and try again.') end
  c.owner=v.owner;c.data=v.data
  S.friendshipContext=c;S.active.friendship=true
  local function tick()
    if not S.active.friendship then return end
    if S.dead or S.closing then friendshipRestore();return end
    local ok,v=pcall(friendshipSnapshot,c)
    if not ok then S.detail=v;friendshipRestore();records.friendship.Active=false;return end
    if not v or #v.eligible==0 then return end
    local changed,why=paused(function() friendshipBatch(c) end)
    if not changed then S.detail=why;friendshipRestore();records.friendship.Active=false end
  end
  S.friendshipTimer=createTimer(nil,false)
  S.friendshipTimer.Interval=2000;S.friendshipTimer.OnTimer=tick
  tick()
  if not S.active.friendship then return false end
  S.friendshipTimer.Enabled=true
  return true
end

local function maxPersonality(id)
  if not main.Active or not personality.Active then return tell('Enable MAIN and Personality first.') end
  if not ready() then return false end
  local c=S.context
  local ok,reason=paused(function()
    local manager=readQword(c.base+0x38C8750)
    assert(manager and manager~=0 and readQword(manager)==c.base+0x2B03680
      and readQword(manager+0x3A0)==c.base+0x2B0AA00,'Player changed')
    -- The native personality getter explicitly uses the shared point pool (0).
    local vector=manager+0x6890
    local data,count,capacity=readQword(vector),readInteger(vector+12),readInteger(vector+8)
    assert(data and data~=0 and count==695 and capacity and capacity&gt;=count and capacity&lt;=65536,'Invalid point array')
    local address=data+id*8
    local value=readQword(address)
    assert(value and value&gt;=0 and value&lt;=2070,'Invalid personality points')
    if value==2070 then return end
    local before=bytes(address,8)
    assert(before and #before==8,'Unreadable personality points')
    local written,why=pcall(put,address,integerBytes(2070,8))
    if not written then put(address,before);error(why) end
  end)
  if not ok then S.detail=reason;return tell('Personality could not be updated. Load your save and retry.') end
  return true
end
-- Use the existing Mahjong scheduler and bankruptcy settlement. No new code,
-- remote thread, recurring score lock, or keyboard input is needed.
local function mahjongOwner(c,task,parent)
  local b=c.base
  return task and task~=0 and parent and parent~=0
    and readQword(b+0x38DEDA0)==task and readQword(b+0x38DE6C0)==parent
    and readQword(task+0x18)==parent and readQword(parent+8)==task
    and readQword(task-0x30)==b+0x2694A80 and readQword(task-0x28)==b+0x2694A90
    and (readInteger(task-8) &amp; 1)==0 and (readInteger(parent-8) &amp; 1)==0
end
local function stopMahjongTimer()
  if S.mahjongTimer then S.mahjongTimer.destroy();S.mahjongTimer=nil end
end
local function uncheckMahjong()
  S.mahjongUnchecking=true
  local ok,why=pcall(function() list.getMemoryRecordByID(14).Active=false end)
  S.mahjongUnchecking=nil
  if not ok then S.detail=why end
end
cancelMahjong=function()
  S.mahjongWait=nil
  if S.mahjongWaitTimer then S.mahjongWaitTimer.destroy();S.mahjongWaitTimer=nil end
  local p=S.mahjongPending
  if not p then stopMahjongTimer();uncheckMahjong();return true end
  local c=p.context
  local m=module(c.pid)
  if not m or m.Address~=c.base then S.mahjongPending=nil;stopMahjongTimer();uncheckMahjong();return true end
  local selected=getOpenedProcessID()
  if selected~=c.pid then openProcess(c.pid) end
  if getOpenedProcessID()~=c.pid then return false end
  local ok,reason=paused(function()
    if not mahjongOwner(c,p.task,p.parent) then return end
    local callback=readQword(p.task-0x38)
    assert(callback==c.base+0x25F70A0 or callback==c.base+0x2693CD0,'The Mahjong callback changed')
    -- Restore execution first. A completed native settlement owns its scores.
    if callback==c.base+0x25F70A0 then put(p.task-0x38,integerBytes(c.base+0x2693CD0,8)) end
    local consumed=bytes(c.base+0x38DED07,1)[1]~=0 or readInteger(c.base+0x38DEB28)==5 or readQword(c.base+0x38DEDB0)~=0
    if not consumed then
      for i=#p.changes,1,-1 do
        local v=p.changes[i]
        local owner=not v.player or readQword(c.base+0x38DECC8+v.index*8)==v.player
        if owner and equal(bytes(v.address,#v.after),v.after) then put(v.address,v.before) end
      end
    end
  end)
  if selected~=c.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=reason
  if ok then S.mahjongPending=nil;stopMahjongTimer();uncheckMahjong() end
  return ok
end
local mahjongCanStart
local function winMahjong()
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  if S.mahjongPending then return false end
  local c=S.context
  local deferred=false
  local success,reason=paused(function()
    if not mahjongCanStart(c) then deferred=true;return end
    local b=c.base
    local task,parent=readQword(b+0x38DEDA0),readQword(b+0x38DE6C0)
    assert(mahjongOwner(c,task,parent),'No active Mahjong match')
    assert(readQword(task-0x38)==b+0x2693CD0 and readInteger(task+4)==7,'The board is busy')
    assert(readInteger(b+0x38DEB28)==3 and readInteger(b+0x38DEB2C)==6,'Wait for a discard turn')
    assert(readQword(b+0x38DEDB0)==0 and bytes(b+0x38DED07,1)[1]==0 and bytes(b+0x38DED0C,1)[1]==0,'A result is pending')
    local prologue={0x48,0x83,0xEC,0x28,0x83,0x3D,0x15,0x7B,0x2E,0x01,0x00,0x0F,0x85,0xF8,0x00,0x00,0x00}
    assert(equal(bytes(b+0x25F70A0,#prologue),prologue),'The Mahjong code changed')
    local settlement={0x48,0x83,0xEC,0x28,0x80,0x3D,0xE1,0x80,0x2E,0x01,0x00,0x44,0x8B,0xDA,0x0F,0x85,0xC8,0x03,0x00,0x00}
    assert(equal(bytes(b+0x25F6C20,#settlement),settlement),'The Mahjong settlement changed')
    local players,total,human={},0,nil
    for i=0,3 do
      local player=readQword(b+0x38DECC8+i*8)
      assert(player and player~=0 and readInteger(player+8)==i,'The seats changed')
      local kind=readInteger(player)
      assert(kind==0 or kind==1,'Unsupported Mahjong player type')
      if kind==0 then assert(not human,'Multiple human players');human=i end
      local points=readInteger(player+12)
      assert(points and points&gt;=0 and points&lt;=100000 and readInteger(player+16)==points,'Wait for the score animation')
      players[i]=player;total=total+points
    end
    assert(human and bytes(b+0x38DED0D,1)[1]==human and total&gt;0 and total&lt;=100000,'Wait for your turn')
    local p={context=c,task=task,parent=parent,changes={}}
    for i=0,3 do
      local address=players[i]+12
      p.changes[#p.changes+1]={address=address,player=players[i],index=i,before=bytes(address,4),after=integerBytes(i==human and total+300 or -100,4)}
    end
    p.changes[#p.changes+1]={address=b+0x38DEBC0,before=bytes(b+0x38DEBC0,4),after=integerBytes(0,4)}
    S.mahjongPending=p
    local count=0
    local written,why=pcall(function()
      for i,v in ipairs(p.changes) do count=i;put(v.address,v.after) end
      put(task-0x38,integerBytes(b+0x25F70A0,8))
    end)
    if not written then
      put(task-0x38,integerBytes(b+0x2693CD0,8))
      for i=count,1,-1 do put(p.changes[i].address,p.changes[i].before) end
      S.mahjongPending=nil
      error(why)
    end
  end)
  if deferred then return nil end
  if not success then
    S.detail=reason;cancelMahjong()
    return tell('The Mahjong win could not be applied safely. The request was cancelled.')
  end
  S.mahjongTimer=createTimer(nil,false)
  S.mahjongTimer.Interval=250
  S.mahjongTimer.OnTimer=function()
    local p=S.mahjongPending
    if not p then return stopMahjongTimer() end
    -- Wall-clock time keeps advancing while the game is paused. Wait for
    -- actual settlement or loss of the original match, never a tick budget.
    local m=module(p.context.pid)
    local sameProcess=getOpenedProcessID()==p.context.pid and m and m.Address==p.context.base
    local ownerOk,owned=false,false
    if sameProcess then ownerOk,owned=pcall(mahjongOwner,p.context,p.task,p.parent) end
    if not sameProcess or not ownerOk or not owned
      or readInteger(p.context.base+0x38DEB28)==5 then
      local ok,done=pcall(cancelMahjong)
      if not ok or not done then stopMahjongTimer() end
    end
  end
  S.mahjongTimer.Enabled=true
  return true
end
-- A one-shot native state transition, with no executable patch or new thread.
-- The native checkmate handler selects shogi_win (timeline alias 134) when
-- the current controller is sente. In normal matches that is the player.
local function shogiState(c,handle)
  if not handle or handle==0 or (handle &amp; 0xFFFFF)&gt;=0x80000 then return nil end
  local entry=c.base+0x38E6300+(handle &amp; 0xFFFFF)*32
  if readSmallInteger(entry+8)~=(handle &gt;&gt; 20) or readSmallInteger(entry+12)~=3 then return nil end
  local entity=readQword(entry)
  if not entity or readQword(entity)~=c.base+0x2AD2568 then return nil end
  local wrapper=readQword(entity+0xC0)
  if not wrapper or readQword(wrapper)~=c.base+0x2C35550 or readInteger(wrapper+0x38)~=handle then return nil end
  local manager=readQword(wrapper+8)
  if not manager or readQword(manager)~=c.base+0x2C35290 then return nil end
  local state=readQword(manager+0x20)
  if not state or readQword(manager+8)~=state or readQword(state)~=c.base+0x2C45CD8 then return nil end
  if readQword(state+0x15738)~=manager or readInteger(state+0x157AC)~=handle then return nil end
  return state
end
local function findShogi(c)
  local state=shogiState(c,S.shogiHandle)
  if state then return state,S.shogiHandle end
  -- Scan only the game's bounded entity registry, once per uncached match.
  -- Keep each read small and perform discovery before pausing the game.
  for offset=0,0xFFFFFF,0x10000 do
    local data=bytes(c.base+0x38E6300+offset,0x10000)
    assert(data and #data==0x10000,'The entity registry could not be read')
    for i=0,0xFFFF,32 do
      if data[i+13]==3 and data[i+14]==0 then
        local handle=(offset+i)//32 | ((data[i+9] | (data[i+10]&lt;&lt;8))&lt;&lt;20)
        state=shogiState(c,handle)
        if state then S.shogiHandle=handle;return state,handle end
      end
    end
  end
end
cancelShogi=function()
  local p=S.shogiPending
  if not p then return true end
  local m=module(p.context.pid)
  if not m or m.Address~=p.context.base then S.shogiPending=nil;return true end
  local selected=getOpenedProcessID()
  if selected~=p.context.pid then openProcess(p.context.pid) end
  if getOpenedProcessID()~=p.context.pid then return false end
  local ok,reason=paused(function()
    if shogiState(p.context,p.handle)==p.state and equal(bytes(p.state+8,8),p.after) then
      put(p.state+8,p.before)
    end
  end)
  if selected~=p.context.pid and selected~=0 then pcall(openProcess,selected) end
  S.detail=reason
  if ok then S.shogiPending=nil end
  return ok
end
local function winShogi()
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  local c=S.context
  local ok,state,handle=pcall(findShogi,c)
  if not ok then S.detail=state;return tell('The shogi match could not be read. Return to the board and try again.') end
  if not state or readInteger(state+0x15728)~=0 then return tell('Start a regular shogi match and use this option on your turn.') end
  if readQword(state+8)~=c.base+0x2613940 then return tell('Wait until the shogi board is ready for your next move.') end
  local success,reason=paused(function()
    assert(getOpenedProcessID()==c.pid and shogiState(c,handle)==state,'The match changed')
    local player=readQword(state+0x30)
    local ai=readQword(state+0x12248)
    assert(player and player~=0 and ai and ai~=0 and ai~=player,'The match is not ready')
    assert(readQword(state+0x12250)==player and readQword(state+0x12258)==player and readQword(state+0x12260)==ai,'Wait for your turn')
    assert(readQword(state+8)==c.base+0x2613940 and readQword(state+0x10)==c.base+0x2617A70 and readQword(state+0x18)==c.base+0x2613A40,'The board is busy')
    local prologue={0x40,0x55,0x57,0x41,0x54,0x41,0x57,0x48,0x8B,0xEC,0x48,0x83,0xEC,0x58,0x48,0x8B,0x81,0x58,0x22,0x01,0x00}
    assert(equal(bytes(c.base+0x2617A80,#prologue),prologue),'The shogi code changed')
    local p={context=c,handle=handle,state=state,before=bytes(state+8,8),after=integerBytes(c.base+0x2617A80,8)}
    S.shogiPending=p
    local written,why=pcall(put,state+8,p.after)
    if not written then
      put(state+8,p.before)
      S.shogiPending=nil
      error(why)
    end
  end)
  if not success then
    S.detail=reason
    cancelShogi()
    return tell('The win could not be requested. Wait for your turn with the board open, then try again.')
  end
  return true
end
local function inventory(c,owner)
  assert(getOpenedProcessID()==c.pid,'Process changed')
  local manager=readQword(c.base+0x38C8750)
  assert(manager and manager~=0 and (not owner or owner==manager),'Inventory owner changed')
  assert(readQword(manager)==c.base+0x2B03680 and readQword(manager+0x3A0)==c.base+0x2B0AA00,'Inventory owner changed')
  local pointer=readQword(manager+0x6950)
  local capacity,count=readInteger(manager+0x6958),readInteger(manager+0x695C)
  assert(pointer and capacity and count and count&gt;=0 and count&lt;=2515 and capacity&gt;=count and capacity&lt;=65536,'Inventory bounds changed')
  assert(count==0 or pointer~=0,'Inventory unavailable')
  local data=count&gt;0 and bytes(pointer,count*16) or {}
  assert(data and #data==count*16,'Inventory could not be read')
  local result={}
  local function number(offset)
    return data[offset+1]|(data[offset+2]&lt;&lt;8)|(data[offset+3]&lt;&lt;16)|(data[offset+4]&lt;&lt;24)
  end
  for i=0,count-1 do
    local id,quantity=number(i*16),number(i*16+4)
    assert(id&gt;0 and id&lt;2515 and not result[id] and quantity&lt;=65535,'Inventory record changed')
    result[id]={address=pointer+i*16+4,quantity=quantity}
  end
  return manager,result
end
local function itemsNeedUpdate(p)
  local state=S.itemFill
  if not state then return false end
  local _,owned=inventory(p.context,state.owner)
  local enrolled=0
  for id,item in pairs(owned) do
    local target=itemTargets[id]
    if target and item.quantity&gt;0 then
      enrolled=enrolled+1
      if item.quantity~=target or not state.enrolledIDs or not state.enrolledIDs[id] then return true end
    end
  end
  return enrolled~=state.enrolled
end
local function itemBatch(p)
  local state=S.itemFill
  if not state then return {} end
  local _,owned=inventory(p.context,state.owner)
  local data,ids={},{}
  for i=1,2515*4 do data[i]=0 end
  for id,item in pairs(owned) do
    local target=itemTargets[id]
    if target and item.quantity&gt;0 then
      ids[#ids+1]=id
      local b=integerBytes(target,4)
      for i=1,4 do data[id*4+i]=b[i] end
    end
  end
  table.sort(ids)
  state.enrolled=#ids
  state.enrolledIDs={}
  for _,id in ipairs(ids) do state.enrolledIDs[id]=true end
  if not equal(data,state.targets) then put(p.address+0x1000,data);state.targets=data end
  local changes,visited={},0
  while visited&lt;#ids and #changes&lt;8 do
    if state.next&gt;#ids then state.next=1 end
    local id=ids[state.next];state.next=state.next+1;visited=visited+1
    local item=owned[id]
    if item and item.quantity&gt;0 and item.quantity~=itemTargets[id] then
      changes[#changes+1]={address=item.address,before=integerBytes(item.quantity,4),after=integerBytes(itemTargets[id],4)}
    end
  end
  return changes
end
local function prepareItems(p)
  local owner=inventory(p.context)
  put(p.address+0xF20,integerBytes(owner,8))
  S.itemFill={owner=owner,next=1}
  return itemBatch(p)
end
local function continueItems(p)
  local function stopIfExited()
    local current=module(p.context.pid)
    if current and current.Address==p.context.base then return false end
    restore('items')
    records.items.Active=false
    return true
  end
  S.fillTimer=createTimer(nil,false)
  S.fillTimer.Interval=500
  S.fillTimer.OnTimer=function()
    if S.dead or S.closing or not S.active.items then restore('items');return end
    if stopIfExited() then return end
    local checked,needed=pcall(itemsNeedUpdate,p)
    if checked and not needed then return end
    local ok,reason=false,needed
    if checked then ok,reason=paused(function()
      local changes=itemBatch(p)
      local touched={}
      local written,why=pcall(function()
        for _,change in ipairs(changes) do touched[#touched+1]=change;put(change.address,change.after) end
      end)
      if not written then
        for i=#touched,1,-1 do put(touched[i].address,touched[i].before) end
        error(why)
      end
    end) end
    if not ok then
      S.detail=reason
      if stopIfExited() then return end
      local restored=restore('items')
      if restored then records.items.Active=false end
      -- Save unloading also invalidates inventory before the process disappears.
      -- A successfully stopped lock needs no modal notification during teardown.
      if not restored and not stopIfExited() then
        tell('The item lock could not be restored. Keep the table open and use Clear All after removing conflicting cheats.')
      end
    end
  end
  S.fillTimer.Enabled=true
end
local function enable(kind)
  if kind:sub(1,5)=='spike' then return spikeEnable(kind) end
  if kind=='friendship' then return friendshipEnable() end
  if kind=='basspoints' then return bassFillPoints() end
  if bassSpecs[kind] then return bassEnable(kind) end
  if kind=='vfenemy' then return vfSetEnemy() end
  if kind=='vfhealth' or kind=='vftimer' then return vfEnable(kind) end
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  if S.active[kind] then return true end
  local prepared,p=pcall(prepare)
    if not prepared then S.detail=p;return tell('The game code could not be prepared. The option was left off.\n\n'..tostring(p)) end
  S.page=p
  local ok,reason=paused(function()
    local refills=kind=='items' and prepareItems(p) or refillChanges(kind,p.context)
    if kind=='pokerchips' then local stack=pokerStackChange(p.context,true);if stack then refills[#refills+1]=stack end end
    for _,h in ipairs(p.hooks) do
      if usesHook(h,kind) then
        local current=bytes(h.address,#h.original)
        assert(equal(current,h.original) or (((h.kind=='money' and otherCurrencyActive(kind)) or (h.kind=='crazy' and otherCrazyActive(kind)) or (h.kind=='lemontimer' and otherTimerActive(kind))) and equal(current,h.patch)),'Original code was changed')
      end
    end
    S.active[kind]=true
    local touched,filled={},{}
    local installed,installError=pcall(function()
      for _,h in ipairs(p.hooks) do
        if usesHook(h,kind) and not ((h.kind=='money' and otherCurrencyActive(kind)) or (h.kind=='crazy' and otherCrazyActive(kind)) or (h.kind=='lemontimer' and otherTimerActive(kind))) then touched[#touched+1]=h;put(h.address,h.patch) end
      end
      if kind=='ufosticky' then put(p.address+0x9000,{0,0,0,0,0,0,0,0}) end
      if kind=='schoolanswer' then put(p.address+0xB500,{0,0,0,0,0,0,0,0}) end
      put(p.flags[kind],{1})
      for _,change in ipairs(refills) do
        filled[#filled+1]=change
        put(change.address,change.after)
      end
    end)
    if not installed then
      -- Roll back our writes before the paused game can execute a partial jump.
      put(p.flags[kind],{0})
      for i=#filled,1,-1 do put(filled[i].address,filled[i].before) end
      for i=#touched,1,-1 do put(touched[i].address,touched[i].original) end
      S.active[kind]=false
      error(installError)
    end
  end)
  if not ok then
    S.detail=reason
    local undone=restore(kind)
    return tell(undone and 'The option could not be enabled. Its changes were restored.' or 'The option could not be fully restored. Keep the table open, remove the conflicting cheat, and use Clear All.')
  end
  if kind=='items' then continueItems(p) end
  return true
end
local function clear()
  if not restoreAll() then return tell('A hook could not be restored. Remove conflicting cheats and try Clear All again.') end
  for _,record in pairs(records) do record.Active=false end
  for _,id in ipairs({15,48,85,50,63,68,75,72,31,27,88,96}) do list.getMemoryRecordByID(id).Active=false end
  main.Active=false
  return true
end
local sujimonExpCurves={{0,10,21,34,49,66,86,109,136,168,206,251,304,367,442,531,637,764,916,1098,1316,1577,1889,2263,2711,3248,3891,4661,5584,6690,8016,9605,11510,13794,16532,19814,23749,28467,34123,40904,49034,58781,70467,84478,101277,121419,145569,174524,209241,250866},{0,10,21,33,46,61,78,97,119,144,174,211,256,311,378,460,561,685,838,1027,1253,1523,1846,2233,2697,3253,3919,4717,5673,6819,8193,9840,11814,14180,17016,20416,24492,29379,35238,42262,50690,60803,72938,87500,104974,125942,151103,181296,217527,261004},{0,10,22,36,52,71,93,119,150,187,231,283,345,419,507,612,737,886,1064,1277,1526,1817,2157,2554,3018,3560,4194,4935,5801,6814,8033,9500,11266,13392,15951,19032,22741,27206,32581,39052,46817,56135,67316,80733,96833,116153,139337,167157,200541,240601}}
-- Owned save roster: native save-kind 0x1C, 64-byte records.
-- The game's level setter writes EXP at +20 and its derived level at +2F.
-- Friendship is the ushort rehabilitation field at +24, capped at 100.
local sujimonLevelExp={[53]=sujimonExpCurves[1],[54]=sujimonExpCurves[2],[55]=sujimonExpCurves[2],[56]=sujimonExpCurves[2],[57]=sujimonExpCurves[2],[58]=sujimonExpCurves[2],[59]=sujimonExpCurves[2],[60]=sujimonExpCurves[3],[61]=sujimonExpCurves[3],[62]=sujimonExpCurves[3],[68]=sujimonExpCurves[1],[69]=sujimonExpCurves[3],[70]=sujimonExpCurves[3],[71]=sujimonExpCurves[3],[72]=sujimonExpCurves[2],[73]=sujimonExpCurves[2],[74]=sujimonExpCurves[2],[75]=sujimonExpCurves[2],[76]=sujimonExpCurves[2],[77]=sujimonExpCurves[2],[83]=sujimonExpCurves[1],[86]=sujimonExpCurves[1],[87]=sujimonExpCurves[2],[88]=sujimonExpCurves[2],[89]=sujimonExpCurves[2],[93]=sujimonExpCurves[1],[94]=sujimonExpCurves[1],[95]=sujimonExpCurves[1],[98]=sujimonExpCurves[1],[99]=sujimonExpCurves[2],[100]=sujimonExpCurves[2],[101]=sujimonExpCurves[2],[102]=sujimonExpCurves[3],[103]=sujimonExpCurves[3],[104]=sujimonExpCurves[3],[105]=sujimonExpCurves[2],[106]=sujimonExpCurves[2],[107]=sujimonExpCurves[2],[108]=sujimonExpCurves[3],[109]=sujimonExpCurves[3],[110]=sujimonExpCurves[3],[111]=sujimonExpCurves[3],[112]=sujimonExpCurves[3],[113]=sujimonExpCurves[3],[120]=sujimonExpCurves[3],[121]=sujimonExpCurves[3],[122]=sujimonExpCurves[3],[123]=sujimonExpCurves[3],[124]=sujimonExpCurves[3],[125]=sujimonExpCurves[3],[128]=sujimonExpCurves[1],[131]=sujimonExpCurves[3],[134]=sujimonExpCurves[1],[135]=sujimonExpCurves[3],[136]=sujimonExpCurves[3],[137]=sujimonExpCurves[3],[143]=sujimonExpCurves[3],[144]=sujimonExpCurves[2],[145]=sujimonExpCurves[2],[146]=sujimonExpCurves[2],[151]=sujimonExpCurves[1],[155]=sujimonExpCurves[1],[156]=sujimonExpCurves[2],[157]=sujimonExpCurves[2],[158]=sujimonExpCurves[2],[162]=sujimonExpCurves[1],[163]=sujimonExpCurves[1],[164]=sujimonExpCurves[1],[165]=sujimonExpCurves[1],[166]=sujimonExpCurves[1],[167]=sujimonExpCurves[1],[168]=sujimonExpCurves[1],[169]=sujimonExpCurves[1],[170]=sujimonExpCurves[1],[171]=sujimonExpCurves[1],[172]=sujimonExpCurves[1],[173]=sujimonExpCurves[1],[174]=sujimonExpCurves[3],[175]=sujimonExpCurves[3],[176]=sujimonExpCurves[3],[177]=sujimonExpCurves[2],[178]=sujimonExpCurves[2],[179]=sujimonExpCurves[2],[180]=sujimonExpCurves[1],[181]=sujimonExpCurves[1],[182]=sujimonExpCurves[1],[183]=sujimonExpCurves[1],[184]=sujimonExpCurves[1],[185]=sujimonExpCurves[1],[187]=sujimonExpCurves[3],[188]=sujimonExpCurves[3],[189]=sujimonExpCurves[3],[192]=sujimonExpCurves[1],[195]=sujimonExpCurves[1],[196]=sujimonExpCurves[2],[203]=sujimonExpCurves[2],[204]=sujimonExpCurves[2],[205]=sujimonExpCurves[2],[211]=sujimonExpCurves[1],[212]=sujimonExpCurves[1],[219]=sujimonExpCurves[1],[221]=sujimonExpCurves[1],[222]=sujimonExpCurves[1],[224]=sujimonExpCurves[1],[226]=sujimonExpCurves[1],[230]=sujimonExpCurves[1],[234]=sujimonExpCurves[1],[235]=sujimonExpCurves[2],[240]=sujimonExpCurves[2],[245]=sujimonExpCurves[2],[246]=sujimonExpCurves[3],[248]=sujimonExpCurves[1],[249]=sujimonExpCurves[2],[250]=sujimonExpCurves[3],[251]=sujimonExpCurves[1],[252]=sujimonExpCurves[1],[253]=sujimonExpCurves[1],[256]=sujimonExpCurves[1],[257]=sujimonExpCurves[3],[258]=sujimonExpCurves[3],[259]=sujimonExpCurves[3],[260]=sujimonExpCurves[1],[261]=sujimonExpCurves[3],[262]=sujimonExpCurves[2],[263]=sujimonExpCurves[1],[264]=sujimonExpCurves[3],[265]=sujimonExpCurves[2],[266]=sujimonExpCurves[1],[267]=sujimonExpCurves[1],[268]=sujimonExpCurves[3],[269]=sujimonExpCurves[2],[270]=sujimonExpCurves[3],[271]=sujimonExpCurves[3],[272]=sujimonExpCurves[3],[273]=sujimonExpCurves[3],[274]=sujimonExpCurves[3],[275]=sujimonExpCurves[1],[276]=sujimonExpCurves[1],[277]=sujimonExpCurves[1],[278]=sujimonExpCurves[1],[279]=sujimonExpCurves[2],[282]=sujimonExpCurves[1],[283]=sujimonExpCurves[1],[284]=sujimonExpCurves[1],[285]=sujimonExpCurves[3],[286]=sujimonExpCurves[3],[287]=sujimonExpCurves[2],[290]=sujimonExpCurves[1],[291]=sujimonExpCurves[2],[292]=sujimonExpCurves[3],[294]=sujimonExpCurves[2],[295]=sujimonExpCurves[3],[296]=sujimonExpCurves[1],[297]=sujimonExpCurves[1],[298]=sujimonExpCurves[2],[299]=sujimonExpCurves[1],[300]=sujimonExpCurves[2],[301]=sujimonExpCurves[2],[302]=sujimonExpCurves[3],[303]=sujimonExpCurves[1],[304]=sujimonExpCurves[3],[305]=sujimonExpCurves[1],[306]=sujimonExpCurves[2],[307]=sujimonExpCurves[3],[308]=sujimonExpCurves[1],[309]=sujimonExpCurves[1],[310]=sujimonExpCurves[2],[311]=sujimonExpCurves[3],[312]=sujimonExpCurves[1],[313]=sujimonExpCurves[2],[314]=sujimonExpCurves[1],[315]=sujimonExpCurves[3],[316]=sujimonExpCurves[1],[317]=sujimonExpCurves[2],[318]=sujimonExpCurves[1],[319]=sujimonExpCurves[1],[320]=sujimonExpCurves[1],[321]=sujimonExpCurves[1],[322]=sujimonExpCurves[1],[323]=sujimonExpCurves[1],[324]=sujimonExpCurves[1],[325]=sujimonExpCurves[1],[326]=sujimonExpCurves[1],[327]=sujimonExpCurves[1],[328]=sujimonExpCurves[1],[329]=sujimonExpCurves[1],[331]=sujimonExpCurves[1],[333]=sujimonExpCurves[2],[334]=sujimonExpCurves[1],[335]=sujimonExpCurves[1],[336]=sujimonExpCurves[2],[337]=sujimonExpCurves[2],[338]=sujimonExpCurves[1],[339]=sujimonExpCurves[1],[340]=sujimonExpCurves[1],[341]=sujimonExpCurves[1],[342]=sujimonExpCurves[1],[343]=sujimonExpCurves[1],[344]=sujimonExpCurves[2],[345]=sujimonExpCurves[1],[346]=sujimonExpCurves[2]}
local function sujimonLevelCap(c)
  local function entity(handle)
    if not handle or handle==0 or (handle &amp; 0xFFFFF)&gt;=0x80000 then return nil end
    local r=c.base+0x38E6300+(handle &amp; 0xFFFFF)*32
    if readSmallInteger(r+8)~=(handle &gt;&gt; 20) or readSmallInteger(r+12)~=3 then return nil end
    local p=readQword(r)
    return p and p~=0 and p or nil
  end
  local world=readQword(c.base+0x38E2A50)
  if not world or world==0 then return nil end
  local root=entity(readInteger(world+0x38))
  if not root then return nil end
  local timelines=entity(readInteger(root+0x468))
  if not timelines or readQword(timelines)~=c.base+0x2B078D8 then return nil end
  local categories=readQword(timelines+0xC0)
  local count=readInteger(timelines+0xCC)
  if not categories or categories==0 or not count or count&lt;0 or count&gt;256 then return nil end
  -- Native cap uses badge table 5393: category 8, timeline 313, clocks 2..7.
  for i=0,count-1 do
    local category=categories+i*16
    if readInteger(category)==8 then
      local node=readQword(category+8)
      for depth=1,64 do
        if not node or node==0 then return 5 end
        node=node &amp; 0xFFFFFFFFFFFF
        local offset=readSmallInteger(node+14)
        if not offset then return nil end
        if offset&gt;=0x8000 then offset=offset-0x10000 end
        local value=node+offset
        local key=readInteger(value+16)
        if not key then return nil end
        if key==313 then
          local clocks=readQword(value+0x20)
          local n=readInteger(value+0x2C)
          if not clocks or clocks==0 or not n or n&lt;0 or n&gt;4096 then return nil end
          local cap=5
          for j=0,n-1 do
            local clock=readInteger(clocks+j*24+16)
            if clock and clock&gt;=2 and clock&lt;=7 then
              local index=readInteger(clocks+j*24)
              if not index or index&lt;0 or index&gt;=n then return nil end
              local flags=bytes(clocks+index*24+4,1)
              if not flags then return nil end
              if (flags[1] &amp; 1)~=0 then cap=math.max(cap,math.min(50,(clock-1)*10)) end
            end
          end
          return cap
        end
        node=readQword(node+(key&gt;313 and 0 or 8))
      end
      return nil
    end
  end
  return 5
end
function S.stopSujimonGrowth()
  if S.sujimonGrowthTimer then S.sujimonGrowthTimer.destroy();S.sujimonGrowthTimer=nil end
  S.sujimonGrowthJobs=nil
end
local function maxSujimonGrowth(kind)
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  local c=S.context
  local manager=readQword(c.base+0x38C8750)
  local roster=manager+0x11808
  local data=readQword(roster+8)
  local capacity=readInteger(roster+0x10)
  local count=readInteger(roster+0x14)
  if readQword(roster)~=c.base+0x2B559F8 or not data or data==0
    or not capacity or not count or count&lt;1 or count&gt;capacity or capacity&gt;4096 then
    return tell('Open your Sujimon roster after loading your save, then try again.')
  end
  local function sameRoster()
    return getOpenedProcessID()==c.pid and module(c.pid)
      and readQword(c.base+0x38C8750)==manager
      and readQword(manager)==c.base+0x2B03680
      and readQword(roster)==c.base+0x2B559F8
      and readQword(roster+8)==data and readInteger(roster+0x10)==capacity
      and readInteger(roster+0x14)==count
  end
  S.sujimonGrowthJobs=S.sujimonGrowthJobs or {}
  if S.sujimonGrowthJobs[kind] then return true end
  local job={index=0}
  S.sujimonGrowthJobs[kind]=job
  job.tick=function()
    if not sameRoster() then S.stopSujimonGrowth();return end
    local cap=kind=='level' and sujimonLevelCap(c) or 100
    assert(cap,'Sujimon level cap unavailable')
    local selected={}
    local scanned=0
    local start=job.index
    local limit=math.min(64,count-start)
    local block=bytes(data+start*0x40,limit*0x40)
    assert(block and #block==limit*0x40,'Sujimon data unreadable')
    -- Skip empty/already-completed slots without suspending the game.
    while job.index&lt;count and scanned&lt;64 and #selected&lt;4 do
      local index=job.index
      local raw={}
      for j=1,64 do raw[j]=block[(index-start)*64+j] end
      local id=raw[5]|(raw[6]&lt;&lt;8)|(raw[7]&lt;&lt;16)|(raw[8]&lt;&lt;24)
      local owned=false
      for j=25,32 do if raw[j]~=0 then owned=true end end
      local value=kind=='level' and raw[48] or (raw[37]|(raw[38]&lt;&lt;8))
      if owned and sujimonLevelExp[id] and
        (kind=='level' and value&gt;=1 and value&lt;cap or kind~='level' and value&lt;100) then
        local identity={}
        for j=25,32 do identity[#identity+1]=raw[j] end
        selected[#selected+1]={index=index,identity=identity,id=id}
      end
      job.index=job.index+1;scanned=scanned+1
    end
    if #selected==0 then
      if job.index&gt;=count then S.sujimonGrowthJobs[kind]=nil end
      return
    end
    local ok,reason=paused(function()
      assert(sameRoster(),'Sujimon roster changed')
      if kind=='level' then cap=sujimonLevelCap(c);assert(cap,'Sujimon level cap unavailable') end
      local changes={}
      local function change(address,value,size)
        local before=bytes(address,size)
        assert(before and #before==size,'Sujimon data unreadable')
        local after=integerBytes(value,size)
        if not equal(before,after) then
          changes[#changes+1]={address=address,before=before,after=after}
        end
      end
      for _,entry in ipairs(selected) do
        local p=data+entry.index*0x40
        assert(readInteger(p+4)==entry.id and equal(bytes(p+0x18,8),entry.identity),'Sujimon changed')
        local id=readInteger(p+4)
        local getID=readQword(p+0x18)
        local curve=sujimonLevelExp[id]
        local target=curve and curve[cap]
        if curve and getID and getID&gt;0 then
          if kind=='level' then
            local level=bytes(p+0x2F,1)
            local exp=readInteger(p+0x20)
            assert(level and exp,'Sujimon level unreadable')
            if level[1]&gt;=1 and level[1]&lt;cap then
              change(p+0x20,target,4)
              change(p+0x2F,cap,1)
            end
          else
            local friendship=readSmallInteger(p+0x24)
            assert(friendship,'Sujimon friendship unreadable')
            if friendship&gt;=0 and friendship&lt;100 then change(p+0x24,100,2) end
          end
        end
      end
      local written=0
      local changed,why=pcall(function()
        for i,v in ipairs(changes) do written=i;put(v.address,v.after) end
      end)
      if not changed then
        for i=written,1,-1 do put(changes[i].address,changes[i].before) end
        error(why)
      end
    end)
    if not ok then
      S.detail=reason
      S.stopSujimonGrowth()
      return tell('The Sujimon upgrade stopped because the roster changed or could not be updated. Earlier completed upgrades were kept. Open the roster and retry.')
    end
    if job.index&gt;=count then S.sujimonGrowthJobs[kind]=nil end
  end
  if not S.sujimonGrowthTimer then
    local timer=createTimer(nil,false)
    S.sujimonGrowthTimer=timer
    timer.Interval=100
    timer.OnTimer=function()
      if S.closing or S.dead or not main.Active then S.stopSujimonGrowth();return end
      local jobs=S.sujimonGrowthJobs
      local pending=jobs and (jobs.level or jobs.friendship)
      if not pending then S.stopSujimonGrowth();return end
      local ok,why=pcall(pending.tick)
      if not ok then S.detail=why;S.stopSujimonGrowth() end
      if S.sujimonGrowthJobs and not next(S.sujimonGrowthJobs) then S.stopSujimonGrowth() end
    end
    timer.Enabled=true
  end
  return true
end

local function oneShot(id,action)
  list.getMemoryRecordByID(id).OnActivate=function(_,before)
    if before then action();return false end
    return true
  end
end
oneShot(2,function() shellExecute('https://ko-fi.com/katzy') end)
oneShot(3,function() showMessage([==[How to use - Katzy

Table identification: Katzy.

Like a Dragon: Infinite Wealth | Game version 1.20 | Table v1.94



Open the table in Cheat Engine 7.7 or later and allow its table Lua script. Start the supported Steam game and load your save. Tick MAIN, then choose each option separately. Entries marked (One-shot) run once and immediately untick; most other cheat options stay enabled until turned off. Win Mahjong Match waits for a suitable turn and unticks after completing its request.



Auto-Attach and Version Check: automatically finds the game and checks the supported executable (Steam build 17233673).

☕ Fuel the Cheats — Tip Katzy (Toggle to open my Ko-fi page): opens Katzy's Ko-fi page only when deliberately checked, then stays unticked.

How to use: shows these instructions and stays unticked.

Clear All: disables all options and MAIN.

[MAIN] Like a Dragon: Infinite Wealth: checks the game and reveals the options. Turning it off disables all options.



MiniGames: expand this folder for Anaconda Escape, darts, karaoke (Always Perfect Notes), Sicko Snap, Crazy Eats, Shogi, Miss Match, Lemonade Stand Timer, Overworld Fishing, Overworld Chase QTEs and Aloha-Link Friendship. Folder headers organize options; collapsing a folder does not disable its cheats. Use the individual options or Clear All.

Sicko Snap: expand this folder for Always Perfect Sicko Snap and Infinite Sicko Snap Points. Each option works independently.

Shogi: expand this folder for Win Shogi Match (One-shot) and Infinite Shogi Points. Each option works independently.

Anaconda Escape: enable the group, then choose the options below. Turning the group off disables both options.

Auto Answer Quizzes: enable before opening either Anaconda Escape laptop quiz. Automatically submits its correct answer through the normal answer handler. Approach laptops and advance dialogue normally. Does not open chests or finish the escape for you.

Infinite Timer (Anaconda Escape): keeps the active escape countdown at six minutes. Battle penalties are replenished on the next countdown update. Enable before time runs out; expired attempts are not restarted. Off resumes the countdown from its current value. Other activities are unaffected.

Always Perfect Darts: guarantees Perfect timing for your dart throws, with the game’s normal success feedback. Aim and throw normally; Perfect timing removes timing-related deviation but does not choose a target or guarantee a bullseye. Works with every dart type. Computer throws are unchanged. Turning it off restores normal timing.

Always Perfect Guard: automatically passes the input-timing check for eligible incoming attacks against party members. No timed button press is needed. The game's attack, target, and status eligibility checks remain in effect; attacks that cannot be Perfect Guarded remain excluded. Turning it off restores manual timing.

Always Perfect Notes: automatically awards the best judgement to karaoke notes without button presses. Tap notes complete at their start; held and repeated-press notes complete at their end, using native hit feedback, combo and scoring. Enable before the song. Turning it off restores manual play; completed notes remain scored.

Always Perfect Sicko Snap: gives each newly captured eligible Sicko the best photo quality and timing bonus, using normal scoring and feedback. Aim at a Sicko and take the photo normally. Points retain the target-type value: white 700, blue 800, red 900 and gold 1,000. Empty shots and already-captured targets remain subject to normal rules. Turning it off restores normal judging; scored photos remain.

Always Skill Bonus: covers the current party's timed-press and repeated-press skill checks, including cinematic battle button and repeated-press QTEs during their active window. It skips these input checks and immediately takes the normal success path when the prompt is processed. Leave the game's Action Prompts setting on. Uses the game's own bonus and success popup, including the +DMG feedback for damage bonuses. Does not create a separate popup or alter base damage, enemy prompts or chance-based status effects. Turning it off restores manual input for subsequent checks.

Overworld Chase QTEs: automatically supplies the correct response to active running/chase prompts, including Kasuga's Chapter 3 chase, for both button and directional prompts. Uses the normal success animation and chase action. Keep controlling the chase normally. Turning it off restores manual QTE input; completed actions remain. Other QTE categories are unchanged.

Overworld Fishing: automatically supplies the requested button at the center of the regular fishing prompt, for all four button choices and both gauge directions. Start fishing and cast normally. The normal success animation and catch reward continue; fishing costs, bait and loot selection are unchanged. Does not automate casting, repeat sessions, or control Sega Bass Fishing or spearfishing. Turning it off restores manual input.
Crazy Eats: enable this group to reveal its options. Options apply during delivery runs, including subsequent runs.

Always Extreme: keeps Extreme active and includes continuous Bonus Time. Uses the normal Extreme and Bonus Time entry paths. Turning it off lets the remaining combo and bonus timers expire naturally.

Infinite Delivery Points: adds a renewable allowance of 90,000 to your earned Delivery Points. Rewards increase the total; purchases spend earned surplus first, stopping at the allowance. Turning it off keeps remaining earned points. Reopen the Delivery Points Exchange to refresh its display.

Infinite Food Items: continuously refills burgers, sushi, and noodles to their normal limit of 100 during a run. Deliveries continue normally. Turning it off keeps the remaining food.

Infinite Timer (Crazy Eats): stops the delivery countdown. Turning it off sets the remaining time to 10 seconds so the run can finish shortly afterward. Does not restart an expired run.

Max Stage Rank: keeps the current run score at or above that course's S-rank requirement. Applies to subsequent runs while enabled and preserves higher earned scores. Turn off Infinite Timer to finish normally. Turning this option off stops further fills and keeps score already added; normal stage rewards and progress are awarded when the run finishes.

Gambles: enable this group for Oicho-Kabu, Koi-Koi, Wooden Tags, poker chips, Win Poker Hand and Win Mahjong Match. Turning it off disables its active options and cancels an unprocessed mahjong request; completed winnings remain.

Always Win Oicho-Kabu: enable before a showdown. Settled losses become wins for you as dealer or challenger, reversing the points transferred for that wager. Play and place bets normally; cards stay unchanged, so the winning result can differ from the visible hand. Existing wins remain unchanged. Retiring without a showdown is excluded. Turning it off restores normal results for subsequent showdowns and keeps completed winnings.

Auto Play Koi-Koi: automatically chooses your hand and field cards using the game's strongest built-in card-selection strategy, confirms the dealer draw and round results, and selects Don't Call Koi to bank completed hands. Set the match rules, difficulty and wager normally, then start playing. Enable before your turn. Match setup, optional help and replay choices remain manual. This is a heuristic strategy, not a guarantee of the best possible move or a win. Enable Max Round Points (Koi-Koi) alongside this option to award the rules-based maximum when you win. Turning it off restores manual control for subsequent choices.

Max Round Points (Koi-Koi): raises your normal winning round to the rules-based scoring ceiling for a legal 36-card capture set. Respects viewing, season and sake-cup scoring, then lets the game apply its normal 7-or-more doubling rule. Enable before the round is scored. It does not force a win, alter cards, or change the opponent's award; the displayed hand list still reflects the cards you actually captured. Special opening-hand wins retain their normal six points. Turning it off keeps awarded points and restores subsequent scoring.

Infinite Wooden Tags: adds a renewable allowance of 90,000 to your earned Gambling Hall tags. Earnings increase the total; spending consumes earned surplus first, stopping at the allowance. Turning it off keeps remaining earned tags. Reopen the exchange or minigame to refresh its display.

Infinite Health: refills the current party's living members to their maximum HP when enabled, including their active combat HP, then prevents HP loss through the normal party and combat setters. Does not revive defeated characters or change maximum HP, MP, enemy HP, or scripted defeat conditions. Turning it off restores normal damage and keeps the refilled HP.

Infinite Items: fills owned, carried stackable items to their individual stack limit minus one and holds them there, leaving room for drops. Automatically checks inventory twice per second and includes newly acquired eligible items. Settled inventory checks do not pause the game; refills use small batches. Items whose maximum stack is one, equipment, storage and unowned items are excluded. An ordinary stackable item with only one copy owned is included. Refilling a large inventory may take a few seconds; reopen the inventory if its display has not refreshed. Turning it off stops the lock and automatic checks, and keeps quantities already filled. Items already at their maximum are reduced by one to make pickup room.

Infinite Mana: refills the current party's MP to its maximum when enabled, including active combat MP, then prevents MP spending through the normal party and combat setters. Does not change maximum MP, HP, or enemy MP. Turning it off restores normal MP spending and keeps the refilled MP. Each option refills only its own meter; the display may refresh on the next HUD/menu update.

Infinite Money: adds a renewable allowance of 90,000,000 internal cash units to your natural cash balance. Earnings increase the displayed total. Normal purchases spend your natural balance first, stopping at the allowance. Turning it off removes the allowance and keeps your remaining natural balance. Applies to regular cash, not minigame tokens. Native limits on natural earnings remain in effect. Close and reopen a menu if its displayed total has not refreshed.

Infinite Poker Chips: adds a renewable allowance of 90,000 to both regular casino chips and m HOLD’EM chips. Gains increase the total and spending consumes earned surplus before stopping at the allowance. Turning it off removes the allowance and preserves remaining earnings. Also updates your active poker stack; spending stops at the allowance. Prize exchanges use the same balances.


Infinite Shogi Points: adds a renewable allowance of 90,000 shogi points to your earned balance. Match rewards still increase the displayed total. Prize purchases spend your earned surplus first, stopping at the allowance. Turning it off removes the allowance and keeps your remaining earned points. Reopen the prize exchange if the display has not refreshed. Works independently of Infinite Money and Win Shogi Match.

Infinite Sicko Snap Points: adds a renewable allowance of 900,000 points at the Snap Points Exchange. Earned points increase the displayed total; purchases spend earned surplus first, stopping at the allowance. Turning it off removes the allowance and keeps remaining earned points. Reopen the exchange to refresh its display. Works independently of Always Perfect Sicko Snap.

Infinite Tag Gauge: keeps the Tag Team gauge reading full for party members, including after using a Tag Team skill. Skills must already be unlocked and normal battle eligibility still applies. Turning it off restores the naturally stored gauge value. Does not change companion bond levels.

Lemonade Stand Timer: freezes the remaining time during all three lemonade delivery rounds. Enable before time runs out. Turn it off to resume the countdown from the remaining time. Does not restart an expired round or affect other activities.

Max Bond: enable before gaining bond points with a companion, including Kiryu. Their next positive bond award supplies enough points to reach bond level 100 through the current game’s normal award and level-up path, including battle gains. Applies separately to each companion who receives points; merely enabling it does not change everyone. Story requirements and Drink Links remain separate. Turning it off keeps earned bond points, which are retained when you save.

Aloha-Link Friendship: brings met friends to 999/1,000 points. Complete their next normal friendship interaction to reach Best Buddy through the game's event/reward processing. Some friends still require their usual item or other interaction condition. Checks for newly met friends every two seconds, up to three per batch. Unmet friends and existing Best Buddies are unchanged. Does not manufacture notifications or Best Buddy counts. Turning it off keeps added points. Re-enable after loading another save. Friends already set to 1,000 by older table versions may need individual repair; this option does not reset completed friendships.

Max Job Rank: enable before earning job EXP. Current party members' jobs reach rank 99 when they next receive a positive job EXP award. Uses the normal rank-up and stat-recalculation path. Only jobs receiving EXP are affected; change jobs and earn EXP again to raise another job. Turning it off keeps earned ranks, which are retained when you save. Works independently of Max Level.

Max Level: enable before earning character EXP. Current party members reach level 99 when they next receive a positive EXP award, through the game's normal level-up and stat-recalculation path. Does not take effect just by ticking the box. Job ranks progress normally. Turn it off after the reward sequence; earned levels and stats remain and are retained when you save.


Miss Match: reveals the three conversation options below. Enable each separately. Turning the parent off disables all its options.

Always Best Emoji Result: gives Miss Match's emoji roulette its best result wherever you stop it: Excellent with the highest timing bonus, worth 25 points. Stop the roulette normally; a timed-out spin also receives the best result. Uses the game's normal result message and reward. Turning it off restores normal results for subsequent spins; awarded points remain. Works independently of Always Excellent Replies and Auto Miss Match Inputs.

Always Excellent Replies: rates each completed player reply in Miss Match as Excellent, with the game's normal rating feedback and point award. Raises the reply score to at least 20 and removes its penalty; higher earned scores are kept. The affection gauge fills through normal awards. Choose and submit replies normally, or combine with Auto Miss Match Inputs. Turning it off restores normal judging; awarded points remain.

Auto Miss Match Inputs: automatically completes the requested button sequences during Miss Match conversations, including consecutive sequences. Choose your profile and reply choices normally. Works independently of Always Excellent Replies. Turning it off restores manual input for subsequent checks.

No Random Encounters: keeps the street-enemy detection gauge empty and bypasses close-range spotting while enabled. Enable before enemies fully spot you. Does not end an existing battle or cancel an already-alerted group. Turning it off restores normal detection. Scripted encounters are not directly patched.

Personality: reveals six separate options: Max Charisma, Max Confidence, Max Intellect, Max Kindness, Max Passion and Max Style. Check a child to set only that trait to level 10 (2,070 points); the child then stays unticked. Reopen the Personality menu to refresh its display. Turning the parent or MAIN off hides the children and keeps the increased points. Changes are retained when you save the game.

Arcade: expand this folder to find Sega Bass Fishing, SpikeOut, UFO Catcher, and Virtua Fighter. Enable each game and its options individually. Collapsing this folder does not turn off active cheats.

Sega Bass Fishing: open the fishing arcade game, then enable this group.

Always Green Tension: holds line tension at 160 (40% of the gauge) after a fish bites, using the value read by both the gauge and the native line-break checks. Reel in normally. Turning it off restores normal tension calculation. Does not change fish weight or reel speed.

Infinite Timer (Sega Bass Fishing): stops the round clock while fish and animations continue normally. Time bonuses still apply. Turning it off resumes the countdown; an already expired stage is not restarted.

Max Points (Sega Bass Fishing): keep enabled to automatically fill each stage to 100 g below its clear requirement. Checks twice per second while the stage clock is running. Catches add their normal weight and can clear the stage; higher totals are never reduced. The HUD may update only with the next catch. Turning it off stops further fills and keeps points already added. Re-enable after leaving and reopening the arcade game.



Win Mahjong Match: stays checked while waiting for your next discard turn with the board ready and score animations finished. You may enable it before entering a match. Stays pending while the game is paused, with no real-time timeout. Applies once, then unticks after settlement. Leaving the match cancels a submitted request. Transfers the table's remaining points to you, leaves each opponent at -100, and uses the game's normal bankruptcy settlement to end the match in first place. Dismiss results normally. Untick to cancel a waiting request. MAIN/Gambling House Off, Clear All, table close or process change cancels waiting; completed results remain.

Win Poker Hand: makes you the sole pot winner when a hand reaches its normal payout. Play the betting rounds normally and stay in the hand; folding is excluded. Uses the normal pot distribution and chip reward path. Does not end the entire poker session. Turning it off restores normal results for subsequent hands; awarded winnings remain.

Win Shogi Match (One-shot): use once during your turn in a regular shogi match, with the board open. Triggers the game's normal victory and reward sequence, then stays unticked. Dismiss the result screens normally. Does not solve puzzle challenges. Clear All or closing the table cancels a request only if the game has not processed it; an awarded win is kept.



SpikeOut: start SpikeOut Final Edition, then enable this group. These options apply to the player and enemy slots in the current arcade instance.

Infinite Health (SpikeOut): prevents attack damage to living player characters. It does not revive defeated players. Turning it off restores normal damage.

Infinite Super Gauge (SpikeOut): replenishes the lightning-bolt Super Attack stock to five, checking four times per second. It does not change the charge-attack meter. Turning it off restores the captured stock for a still-active player if the counter still contains the last refill; spent or changed stock is left alone.

Max Charge (SpikeOut): keeps the charge-attack meter at the character's full-charge threshold while you hold Charge. Release Charge to attack normally. Checks every tenth of a second. Turning it off resumes normal charging and restores the previous charge value when that same held charge still contains the last value written.

Set Enemy Health to 1 (SpikeOut): checks all sixteen enemy slots twice per second, including newly spawned enemies and bosses. Living enemies are reduced to 1 HP in batches of up to eight; dead enemies stay dead. Turning it off stops further reductions and keeps damage already applied.


Sujimon: enable this group, then its individual options. Turning the group off disables all its options.

Infinite Sujimon Points: adds a renewable 90,000-point allowance to your earned Sujimon Points. Earnings increase the total; purchases spend earned surplus first, stopping at the allowance. Off keeps your remaining earned points. Reopen the shop to refresh its display.

Infinite SP (Sujimon): refills your team’s SP to its normal maximum when the battle updates or spends SP. Enemy SP and the separate special-attack resource are unchanged. Off resumes normal SP use and keeps the last refill.

Infinite MP (Sujimon): refills your MP to its normal maximum on each trainer update. Enemy MP is unchanged. Off resumes normal MP use and keeps the last refill.

Always Best Roulette Result (Sujimon): stop the Encouragement Roulette normally. It lands on the highest tier (35 points, 1.25x damage multiplier), using the normal result animation and reward. Off restores normal outcomes on subsequent spins.

Best Recruitment Effort (Sujimon): gives the gift-timing attempt its highest rating, including a timed-out attempt. Select a gift normally. Off restores normal timing for later attempts.

Auto Encouragement Presses (Sujimon): automatically repeats the encouragement button during the follow-up recruitment phase once the game accepts input. The encouragement meter should visibly increase without manual presses; enabling the checkbox alone does not confirm an active attempt. It stops when the phase ends; Off stops automatic presses immediately. This option works independently of Best Recruitment Effort. Gift quality and normal recruitment chances still apply.

Max Friendship (One-shot) (Sujimon): raises friendship to 100 for all currently owned Sujimon. Use from the Sujimon menu outside a battle, then reopen the roster to refresh its display. The option unticks immediately and applies upgrades in small background batches over a few seconds. Upgrades remain and can be saved normally. Turning off Sujimon or MAIN, or using Clear All, cancels unfinished upgrades. Run again for new recruits.

Max Level (One-shot) (Sujimon): raises owned Sujimon to the level cap currently unlocked by your story badges, with matching EXP. It rechecks the cap for every batch and never raises a Sujimon above it. Existing levels already above that cap are left unchanged. Use from the Sujimon menu outside a battle, then reopen the roster. The option unticks immediately and applies upgrades in small background batches over a few seconds. Upgrades remain and can be saved normally. Turning off Sujimon or MAIN, or using Clear All, cancels unfinished upgrades. Run again for new recruits. Trainer rank, badges, awakening and evolution are unchanged.

Virtua Fighter: open Virtua Fighter 3tb, then enable this group to reveal its three options, including between rounds or after a knockout. Player 1 is your fighter; Player 2 is the opponent.

Infinite Health (Virtua Fighter): refills your living fighter and prevents attack damage. Ring-outs still defeat you normally. Turning it off restores damage and keeps the refilled health.

Infinite Timer (Virtua Fighter): stops the remaining round time from decreasing. Knockouts and ring-outs still end rounds normally. Turning it off resumes the countdown from its current value.

Set Enemy Health to 1: keep enabled to automatically reduce the current opponent to 1 HP, including new rounds and subsequent matches in the same arcade session. Checks twice per second. Health can still reach zero, so the next damaging hit can defeat them; defeated opponents are never revived. Turning it off stops further changes and keeps health already reduced. Re-enable after leaving and reopening the arcade game.



Disable all options before switching Cheat Engine to another process. Use Clear All before replacing the table. Close Cheat Engine normally to restore its hooks.


UFO Catcher: enable this group, then Sticky Claw. Turning the group off disables Sticky Claw.

Sticky Claw: enable before an attempt. Prizes detected touching the claw follow it during lifting and returning, then release when it opens at the chute. Off resumes normal physics at the current position. Up to eight prizes per attempt.

Dondoko Islands: separate options for the island minigame.

Infinite Dokobucks: adds a temporary 9,000,000 allowance to your current balance. Earnings increase the total; purchases spend your natural balance down to zero. Turning it off removes the allowance and keeps your remaining natural balance.

Infinite Materials: refills the seven basic crafting materials and all 28 stored special ingredients used in DIY and souvenir recipes to 9,999 when read or checked for crafting. Open a crafting or storage screen to refresh. Refilled materials remain after disabling. Includes ores, gems, fossils, pearls, shells, mushrooms, produce, meat, eggs and recipe-required fish and insects. Unused collectibles and furniture are unchanged.

Max Building Talent: treats building talent as level 50 while enabled. Your earned building EXP is preserved. Recipe/story requirements other than talent still apply.

Max Satisfaction: supplies the normal 999,999-point cap for the island satisfaction total while enabled. Does not change your house score or directly complete resort objectives.

Max Popularity: supplies the normal 99,999-point cap while enabled. Disable and let the island status refresh to see natural points again.

Freeze Time of Day: stops normal clock progression at the current time, preserving daylight, dusk or night. While enabled, the calendar also allows sleeping during the day, dusk or night. Busy/transition and story requirements still apply. Sleeping and scripted time changes still work. Disable to resume the clock and normal sleep hours.

Infinite HP (Dondoko Islands): restores Dondoko hearts to your current house-based maximum when checked by the game. Independent of main-game HP; does not change maximum hearts or house rank.


Vocational School / Auto Correct Answers: visibly selects the correct answer, waits one second, then submits it. Handles shuffled and reversed choices. Start the exam yourself; result screens, fees, rewards and unlock rules remain normal. Disable to answer manually.
Vocational School / Infinite Timer: stops the current question countdown. Disable to resume from the remaining time; an already expired question is not revived.

]==]) end)
oneShot(4,clear)
oneShot(81,function() maxSujimonGrowth('level') end)
oneShot(82,function() maxSujimonGrowth('friendship') end)
oneShot(12,winShogi)
local mahjongRow=list.getMemoryRecordByID(14)
mahjongCanStart=function(c)
  local b=c.base
  local task,parent=readQword(b+0x38DEDA0),readQword(b+0x38DE6C0)
  if not mahjongOwner(c,task,parent) then return false end
  if readQword(task-0x38)~=b+0x2693CD0 or readInteger(task+4)~=7
    or readInteger(b+0x38DEB28)~=3 or readInteger(b+0x38DEB2C)~=6
    or readQword(b+0x38DEDB0)~=0 or bytes(b+0x38DED07,1)[1]~=0
    or bytes(b+0x38DED0C,1)[1]~=0 then return false end
  local human,total=nil,0
  for i=0,3 do
    local p=readQword(b+0x38DECC8+i*8)
    if not p or p==0 or readInteger(p+8)~=i then return false end
    local kind,points=readInteger(p),readInteger(p+12)
    if kind~=0 and kind~=1 then return false end
    if kind==0 then if human then return false end;human=i end
    if not points or points&lt;0 or points&gt;100000 or readInteger(p+16)~=points then return false end
    total=total+points
  end
  return human~=nil and bytes(b+0x38DED0D,1)[1]==human and total&gt;0 and total&lt;=100000
end
mahjongRow.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  if S.mahjongPending or S.mahjongWait then return true end
  local c={pid=S.context.pid,base=S.context.base}
  S.mahjongWait=c
  S.mahjongWaitTimer=createTimer(nil,false)
  S.mahjongWaitTimer.Interval=250
  S.mahjongWaitTimer.OnTimer=function()
    if not S.mahjongWait then return end
    local m=module(c.pid)
    if S.dead or S.closing or not main.Active or getOpenedProcessID()~=c.pid or not m or m.Address~=c.base then
      cancelMahjong();mahjongRow.Active=false;return
    end
    local ok,available=pcall(mahjongCanStart,c)
    if not ok or not available then return end
    -- Final eligibility is checked again with the game paused by winMahjong.
    S.mahjongWait=nil
    S.mahjongWaitTimer.destroy();S.mahjongWaitTimer=nil
    local applied=winMahjong()
    if applied==nil then mahjongRow.OnActivate(mahjongRow,true)
    elseif not applied then mahjongRow.Active=false end
  end
  S.mahjongWaitTimer.Enabled=true
  return true
end
mahjongRow.OnDeactivate=function(_,before)
  if S.mahjongUnchecking then return true end
  if before then return cancelMahjong() end
  return true
end

gamblingGroup.OnActivate=function(_,before)
  if before then if not main.Active then return tell('Enable MAIN first.') end;return ready() end
  return true
end
gamblingGroup.OnDeactivate=function(_,before)
  if before then
    local a,b,c,d=restore('oichowin'),restore('woodentags'),restore('koiauto'),restore('koipoints')
    local e,f,g=restore('pokerchips'),restore('pokerwin'),cancelMahjong()
    if not a or not b or not c or not d or not e or not f or not g then return S.closing or tell('A Gambles option could not be restored. Remove conflicting cheats and retry.') end
    records.koipoints.Active=false
    records.koiauto.Active=false
    records.oichowin.Active=false;records.woodentags.Active=false
    records.pokerchips.Active=false;records.pokerwin.Active=false
  end
  return true
end
crazyGroup.OnActivate=function(_,before)
  if before then if not main.Active then return tell('Enable MAIN first.') end;return ready() end
  return true
end
crazyGroup.OnDeactivate=function(_,before)
  if before then
    local a,b,c,d,e=restore('crazyextreme'),restore('crazyfood'),restore('crazytimer'),restore('crazyrank'),restore('deliverypoints')
    if not a or not b or not c or not d or not e then return S.closing or tell('A Crazy Eats option could not be restored. Remove conflicting cheats and retry.') end
    records.crazyextreme.Active=false;records.crazyfood.Active=false;records.crazytimer.Active=false;records.crazyrank.Active=false;records.deliverypoints.Active=false
  end
  return true
end
missMatchGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  return ready()
end
missMatchGroup.OnDeactivate=function(_,before)
  if before then
    local a,b,c=restore('emoji'),restore('match'),restore('matchauto')
    if not a or not b or not c then return S.closing or tell('A Miss Match option could not be restored. Remove conflicting cheats and retry.') end
    records.emoji.Active=false;records.match.Active=false;records.matchauto.Active=false
  end
  return true
end
local bassGroup=list.getMemoryRecordByID(31)
bassGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  local ok,why=pcall(bassResolve)
  S.detail=why
  return ok or tell('Start Sega Bass Fishing before enabling this group.')
end
bassGroup.OnDeactivate=function(_,before)
  if before then
    local a,b=bassRestore('basstimer'),bassRestore('basstension')
    bassRestore('basspoints')
    if not a or not b then return S.closing or tell('A fishing hook could not be restored. Remove conflicting cheats and retry.') end
    records.basstimer.Active=false;records.basstension.Active=false;records.basspoints.Active=false
  end
  return true
end
spikeGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  local ok,why=pcall(spikeResolve)
  if not ok then S.detail=why;return tell('Start SpikeOut Final Edition before enabling this group.') end
  return true
end
spikeGroup.OnDeactivate=function(_,before)
  if before then
    local hp,enemy,gauge,stock=spikeRestore('spikehealth'),spikeRestore('spikeenemy'),spikeRestore('spikecharge'),spikeRestore('spikesuper')
    if not hp or not enemy or not gauge or not stock then return S.closing or tell('A SpikeOut option could not be restored. Remove conflicting cheats and retry.') end
    records.spikehealth.Active=false;records.spikeenemy.Active=false;records.spikecharge.Active=false;records.spikesuper.Active=false
  end
  return true
end
ufoGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  return ready()
end
ufoGroup.OnDeactivate=function(_,before)
  if before then
    local us=restore('ufosticky')
    if not us then return S.closing or tell('The claw option could not be restored. Remove conflicting cheats and retry.') end
    records.ufosticky.Active=false
  end
  return true
end
schoolGroup.OnActivate=function(_,before)
  if before then if not main.Active then return tell('Enable MAIN first.') end;return ready() end
  return true
end
schoolGroup.OnDeactivate=function(_,before)
  if before then
    local ok=restoreKinds(restore,{'schoolanswer','schooltimer'})
    if ok then records.schoolanswer.Active=false;records.schooltimer.Active=false end
    return ok or S.closing
  end
  return true
end
dondokoGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  return ready()
end
dondokoGroup.OnDeactivate=function(_,before)
  if before then
    local ok=true
    for _,kind in ipairs({'dokomoney','dokomaterials','dokotalent','dokosatisfaction','dokopopularity','dokotime','dokohp'}) do
      local stopped=restore(kind)
      ok=stopped and ok
      if stopped then records[kind].Active=false end
    end
    if not ok then return S.closing or tell('A Dondoko option could not be restored. Remove conflicting cheats and retry.') end
  end
  return true
end
sujimonGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  return ready()
end
sujimonGroup.OnDeactivate=function(_,before)
  if before then
    S.stopSujimonGrowth()
    local re=restore('recruiteffort');local ra=restore('recruitauto')
    local sjp=restore('sujimonpoints')
    local sm=restore('sujimonmp');local sr=restore('sujimonroulette');local sp=restore('sujimonsp')
    if not (sjp and re and ra and sm and sr and sp) then return S.closing or tell('The Sujimon option could not be restored. Remove conflicting cheats and retry.') end
    records.sujimonpoints.Active=false;records.recruiteffort.Active=false;records.recruitauto.Active=false;records.sujimonsp.Active=false;records.sujimonmp.Active=false;records.sujimonroulette.Active=false
  end
  return true
end
anacondaGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  return ready()
end
anacondaGroup.OnDeactivate=function(_,before)
  if before then
    local a,b=restore('anacondatimer'),restore('anacondaquiz')
    if not (a and b) then return S.closing or tell('The Anaconda Escape options could not be restored. Remove conflicting cheats and retry.') end
    records.anacondatimer.Active=false;records.anacondaquiz.Active=false
  end
  return true
end
local vfGroup=list.getMemoryRecordByID(27)
vfGroup.OnActivate=function(_,before)
  if not before then return true end
  if not main.Active then return tell('Enable MAIN first.') end
  if not ready() then return false end
  local ok,why=pcall(vfResolve)
  if not ok then return vfFailure(why,'Open Virtua Fighter 3tb before enabling this group.') end
  return true
end
vfGroup.OnDeactivate=function(_,before)
  if before then
    local hp,clock=vfRestore('vfhealth'),vfRestore('vftimer')
    vfRestore('vfenemy');records.vfenemy.Active=false
    if not hp or not clock then return S.closing or tell('An arcade hook could not be restored. Remove conflicting cheats and retry.') end
    records.vfhealth.Active=false;records.vftimer.Active=false
  end
  return true
end
for recordID,pointID in pairs({[16]=334,[17]=332,[18]=336,[19]=333,[20]=331,[21]=338}) do
  oneShot(recordID,function() maxPersonality(pointID) end)
end
personality.OnActivate=function(_,before)
  if before then
    if not main.Active then return tell('Enable MAIN first.') end
    return ready()
  end
  return true
end
main.OnActivate=function(_,before) if before then return ready() end return true end
main.OnDeactivate=function(_,before)
  if before then
    if not restoreAll() then return S.closing or tell('A hook could not be restored. Remove conflicting cheats and retry.') end
    for _,record in pairs(records) do record.Active=false end
    personality.Active=false
    missMatchGroup.Active=false
    gamblingGroup.Active=false
    crazyGroup.Active=false
    spikeGroup.Active=false;records.ufosticky.Active=false;ufoGroup.Active=false
    vfGroup.Active=false
    bassGroup.Active=false
    schoolGroup.Active=false;dondokoGroup.Active=false;sujimonGroup.Active=false;anacondaGroup.Active=false
  end
  return true
end
for kind,record in pairs(records) do
  record.OnActivate=function(_,before) if before then return enable(kind) end return true end
  record.OnDeactivate=function(_,before)
    if before and not restore(kind) then return S.closing or tell('The hook could not be restored. Remove conflicting cheats and retry.') end
    return true
  end
  record.OnActivationFailure=function() restore(kind);return false end
end
local form=getMainForm()
local priorClose=form.OnClose
local closeHandler
function S.unload()
  if S.dead then return true end
  local ok,result=pcall(restoreAll)
  if not ok or not result then return false end
  S.dead=true
  if S.timer then S.timer.destroy();S.timer=nil end
  if form.OnClose==closeHandler then form.OnClose=priorClose end
  return true
end
closeHandler=function(sender,action)
  S.closing=true
  pcall(S.unload)
  if priorClose then
    local ok,result=pcall(priorClose,sender,action)
    if ok and result~=nil then return result end
  end
  return action
end
form.OnClose=closeHandler
for _,r in pairs(records) do r.OnDestroy=function() pcall(S.unload) end end
S.timer=createTimer(nil,false)
S.timer.Interval=2000
S.timer.OnTimer=function()
  if S.dead or S.closing then return end
  for _,kind in ipairs({'basstimer','basstension'}) do
    if S.active[kind] and not bassSame(S.bassPages[kind]) then
      if bassRestore(kind) then records[kind].Active=false end
    end
  end
  if S.active.spikehealth and not spikeSame(S.spikePage) then
    if spikeRestore('spikehealth') then records.spikehealth.Active=false end
  end
  for _,kind in ipairs({'vfhealth','vftimer'}) do
    if S.active[kind] and not vfSame(S.vfPages[kind]) then
      if vfRestore(kind) then records[kind].Active=false end
    end
  end
  if anyActive() and not module(S.context.pid) then
    cancelMahjong()
    S.stopSujimonGrowth()
    friendshipRestore()
    spikeRestore('spikeenemy');spikeRestore('spikecharge');spikeRestore('spikesuper')
    spikeGroup.Active=false;records.ufosticky.Active=false;ufoGroup.Active=false
    vfRestore('vfenemy')
    bassRestore('basspoints')
    if S.fillTimer then S.fillTimer.destroy();S.fillTimer=nil;S.itemFill=nil end
    S.active={}
    S.shogiPending=nil
    for _,record in pairs(records) do record.Active=false end
    main.Active=false
    personality.Active=false
    missMatchGroup.Active=false
    gamblingGroup.Active=false
    crazyGroup.Active=false
    schoolGroup.Active=false;dondokoGroup.Active=false;sujimonGroup.Active=false
    S.context=nil
  end
  if anyActive() and getOpenedProcessID()~=S.context.pid then
    if restoreAll() then
      for _,record in pairs(records) do record.Active=false end
      main.Active=false
      schoolGroup.Active=false;dondokoGroup.Active=false;sujimonGroup.Active=false
      personality.Active=false
    missMatchGroup.Active=false
    gamblingGroup.Active=false
    crazyGroup.Active=false
    end
    return
  end
  local pending=S.shogiPending
  if pending and (shogiState(pending.context,pending.handle)~=pending.state or not equal(bytes(pending.state+8,8),pending.after)) then
    S.shogiPending=nil
  end
  local ok,reason=pcall(attach)
  if not ok then S.detail=reason;S.attachError='The game could not be checked. Restart the game and try again.' end
end
S.timer.Enabled=true
pcall(attach)
</LuaScript>
</CheatTable>