Advertisement
Tuerkenheimer

Keaton Grass 01 write

Feb 19th, 2022 (edited)
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.24 KB | None | 0 0
  1. 01 byte write
  2.  
  3. Spawned Keaton grass actors (id 0171) have a pointer to the parent actor at +1C0. The pointer is used for the mechanic that lets other Keaton bushes dance once any other bush is cut or picked up.
  4.  
  5. Every frame any bush individually checks if a byte in parent +1BE is none-zero. If none-zero, it will start dancing.
  6. Likewise a bush will write the byte 01 to parent +1BE when picked up or cut.
  7.  
  8. We can change the parent pointer with Deku Bubble SRM to write the byte 01 somewhere else.
  9.  
  10. To write to the pointer with xy-angle we need offset +190:
  11. Angle set 1 in Deku Bubble at +30, load the bubble 190 after where grass will spawn -> xy-angle will write to +1C0 in the grass actor.
  12.  
  13. Heap manipulations found so far:
  14. English https://www.youtube.com/watch?v=ZU5Y868SrJE
  15. Japanese https://www.youtube.com/watch?v=j_L5BpkdYnI
  16.  
  17. update 2023-09-05:
  18. Japanese with Sakon https://www.youtube.com/watch?v=9wDc_KJJJqA
  19. with Bomber https://www.youtube.com/watch?v=-Kge-z_TV6c
  20.  
  21. One important condition to note: Normally actors have their update function pointer at +138. A common mechanic is to check the pointer just to see if the actor is still alive. This kind of alive check is fortunately not checking if a valid pointer is present, but simply if the word is non-zero.
  22. The child Keaton grass actors check every frame if the parent actor is still alive. If it is not, then the pointer to parent will null. In practice for us this means that our new glitched pointer needs to also fulfill this alive check.
  23.  
  24. It can happen that the change of pointer will lead to the glitched bush actor to start dancing. This happens if the byte at pointer+1BE is non-zero. A glitched write can still happen when cutting the bush, though you need to hurry to make it in time to the grass.
  25.  
  26.  
  27. Unfortunately the angles of Deku Bubbles are handled with low precision. This means we can only get about one in 16 values for x and y angle respectively.
  28. A list of possible angles y-angles: https://pastebin.com/7trQENkV
  29.  
  30. The possible x-angles are the same, but only in the range C000 to 4000. The other half is not possible.
  31. We need to start the pointer with a valid prefix. To write to uncached RAM we need to start with C0- or E0-.
  32.  
  33. The possible ones:
  34. C000, C00A, C01F, C029, C03D, C047, C05C, C070, C07A
  35. E00A, E01A, E029, E038, E04D, E05C, E06C, E07C
  36.  
  37. This is mostly the limiting factor since this already determines the regions of memory we can reach.
  38.  
  39. Well, the angles listed above are not quite the full story. In The bubble actor at +144 there is a float responsible for the distortion of Deku Link's head when the bubble is charged. This distortion has influence on the x-angle and can also make new x-angles possible. The list above is for the case of distortion float being zero.
  40.  
  41. Even after the Deku bubble expired, as long as Link is in a frozen state, the distortion will still apply. The game will just keep looking at the same address. The two heap manips listed above will have another Keaton grass actor loaded after the one we manipulate. They will also overwrite the distortion float with zero. So in practice, with the heap manips given, the listed possible angles apply.
  42.  
  43. However, there are vague ideas to prevent another keaton grass actor from loading after the one we manipulate. Specific heap would still need to be figured out.
  44. ---
  45. Update 2022-04-01
  46. I found a setup that keeps the distortion of the bubble in it's final state (float 417E28AC). This gives us the new angles C066, E048 and E057. (TODO look up potential new ROM pointers)
  47. https://www.youtube.com/watch?v=iDh34SiKmyI
  48. ---
  49.  
  50.  
  51. Uncached reads and how they can lead to KEK-Bro behaviour:
  52. For the write to work it is necessary to load the related function shortly before cutting the manipulated bush. You can easily do so by cutting any of the other bushes. If you don't do so and cut the manipulated bush first, then no write will happen.
  53.  
  54. I don't have the expertise to explain how exactly it works, but ~something~something~ the function needs to be loaded to uncached memory I think? ~something~something~
  55.  
  56. Slashing another bush seemed to make it work consistently, as far as I can tell from my testing. (If testing on KZ with savestates, the states don't change the status of the function loaded. To unload it you would need to reload the area.)
  57.  
  58. A popular example for failure is the OoT Any% KEK-Bro warp. The two Light Node pointers used are one to cached and one to uncached memory. When the credits warp doesn't work, it is because of spontaneous unloading of uncached data ~or something~something~I don't know~. But unlike OoT Any%, we have good control over it here.
  59.  
  60.  
  61. Writing to "ROM" data:
  62. On booting the game the Wii console makes a copy of the actual ROM that is then used to run the game. It starts at address 8F3867A0. We can change it with this glitch, just like we can change usual RAM.
  63. Possible x-angles to write to uncached "ROM" data (with distortion float = 0):
  64. CFD3, CFDC, CFED, CFFF, D010
  65.  
  66. Pointers starting with EF or F0 crash. They might be valid for writes but maybe invalid for reads.
  67.  
  68. As far as I have seen, most data is compressed in the Yaz0 format. It is a "run length encoding method". For us that means that in most cases it is not hard to track down the responsible ROM data for something loading into RAM.
  69.  
  70.  
  71. Writing to uncached data:
  72. We have witnessed some quirks with word-misaligned writes to uncached memory with Light Node SRM. Something of equal nature is happening with this method, but because we only write a single byte and not a full word there are some differences. We have a few different cases.
  73. First of all the write should not be seen as a 1 byte write because the game fails the masking. A better way to put it is a double-word write of 0000 0100 0000 0100, written with offset 1B8. But it becomes more complicated in a few cases depending on the pointer's alignment. Here some examples:
  74.  
  75. Pointer ends in 0, 4, 8 or C
  76. pointer = 8007000 -> writes 0000 0100 0000 0100 to 80071B8
  77. pointer = 8007004 -> writes 0000 0100 0000 0100 to 80071C0
  78. pointer = 8007008 -> writes 0000 0100 0000 0100 to 80071C0
  79. pointer = 800700C -> writes 0000 0100 0000 0100 to 80071C8
  80.  
  81. Pointer ends in 1, 5 , 9 or D
  82. pointer = 8007001 -> writes 0000 0001 0000 0001 to 80071B8
  83. pointer = 8007005 -> writes 0000 0001 0000 0001 to 80071C0
  84. pointer = 8007009 -> writes 0000 0001 0000 0001 to 80071C0
  85. pointer = 800700D -> writes 0000 0001 0000 0001 to 80071C8
  86.  
  87. Pointer ends in 6 or E
  88. pointer = 8007006 -> writes 0100 0000 0100 0000 to 80071C0
  89. pointer = 800700E -> writes 0100 0000 0100 0000 to 80071C8
  90.  
  91. Pointer ends in 7 or F
  92. pointer = 8007007 -> writes 0001 0000 0001 0000 to 80071C0
  93. pointer = 800700F -> writes 0001 0000 0001 0000 to 80071C8
  94.  
  95. but here things get interesting
  96.  
  97. Pointer ends in 2 or A
  98. Example for pointer = 8007002 https://cdn.discordapp.com/attachments/888558556335444009/931341099233067028/Wii_bullshot_part_2_edit.png
  99.  
  100. Pointer ends in 3 or B
  101. Example for pointer = 8007003 https://cdn.discordapp.com/attachments/888558556335444009/931348460668600330/the_thing_with_03.png
  102.  
  103. The examples should explain it better than I could explain with words, so I will leave it at that. As far as I know this behaviour is currently (2022-02-19) not implemented in the Dolphin emulator yet.
  104.  
  105.  
  106.  
  107. Idea of a dynamic bubble distortion float - The super heap:
  108. The basic idea is to trigger bubble SRM with a dynamic float aligning with the distortion float, then unload the sign, reload keaton grass, and that will then load to a lignup for 01-thing SRM.
  109. I technically found such a setup for the English version. There are several issues with this setup, but it is such a cool concept that I wanted to share it.
  110.  
  111. issues:
  112.  
  113. - The setup currently uses 25 bubbles but we only have 24 units of magic. I already brought it down from 28 by combining a few things, so maybe the last bubble could be saved somewhere.
  114. - The float we use for the distortion here is pretty damn high... like in the millions. The resulting distortion leads to a far out of bounds camera. It does not seem to be possible to uncull the grass with that camera.
  115. - I didn't even check if this theoretically gives us new x-angles. Probably it doesn't. But I wanted to try finding a heap setup for this anyway, just to see if I can manage to do it. And I did :)
  116. https://pastebin.com/5RxrAQNu
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement