Advertisement
Guest User

PrintLetterDelay in speedrunning

a guest
Aug 22nd, 2016
447
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.89 KB | None | 0 0
  1. So PrintLetterDelay is the function that makes the game wait frames between each letter based on your text speed. It's also the source of the latest "fuckery" that gifvex found involving RNG manip. I'll explain the rough code flow that happens [on Fast text speed, anyway], then the implications it has on speedrunning.
  2.  
  3. Code:
  4. 1) START
  5. 2) call [process]joypad
  6. 3) Is A button held?
  7. 4) If it is, delay 1 frame and exit.
  8. 5) Is B button held?
  9. 6) If it is, delay 1 frame and exit.
  10. 7) Has a frame passed since the start of this loop?
  11. 8) If it has, exit.
  12. 9) If it hasn't, go to START.
  13.  
  14. First off, the [process]joypad call doesn't imply subframe input polling or anything disastrous like that. The actual polling of the physical hardware is done by a function called ReadJoypad which is only called in VBlank. ProcessJoypad just takes the cached joypad inputs from the last poll and processes them into variables like Held, Pressed and Released. Held is equivalent to the buttons that were held on the previous frame, so we're fine.
  15.  
  16. So why did gifvex's variance happen? Well, take a look at the above loop. You can see that if A or B is held, there's a manual delay of 1 frame and then the wait is over. But if there is no button hold, the program just goes through the loop until vblank interrupts it and sets the variable it checks to see if a "frame passed". The problem with this in regards to RNG is that the CPU cycle that vblank starts on can be different with this waiting method. This is because the game's delay frame method uses "halt", which will resume the CPU into an interrupt as soon as one becomes available. But interrupts that come outside of a halt instruction will only start once the current instruction has been completed, so that the CPU doesn't horribly screw anything up. Add to that the fact that different instructions take different lengths in cycles to finish, and you can quickly see where the variance comes from.
  17.  
  18. For RNG manipulation purposes, this means that the time that you release A after buffering the pickup of an item needs to be consistent for the RNG to stay predictable. You have two options - either let go of A before the text starts rendering at all, or hold it all the way until the jingle starts playing, by which time the game no longer cares about your inputs. I'd recommend the latter because it's a much bigger window, but feel free to go for the former as well.
  19.  
  20. I did mention "implications", not just a single implication. So what is the second? Well, people have probably noticed in the past that it is possible for text to lag slightly when you mash. And by looking over PrintLetterDelay in a little more detail we can analyse why this is the case.
  21.  
  22. It is possible for a letter to take 2 frames to print under the following scenario:
  23. * Player is not pressing A or B as the letter is printed
  24. * Player starts holding/pressing A or B in time for the next VBlank
  25. * VBlank interrupts the above waitloop anywhere between line 8 and halfway through line 2 on the next pass (before the "buttons held" are computed in [process]joypad). VBlank happening in this particular window is "random" based on a bunch of other factors, probably including our old friend IGTimer0, but it CAN happen. So 1 frame has been waited for this letter.
  26. * The game registers that A/B has been pressed in the joypad polling
  27. * The game then completes through processjoypad, registering that A or B is held and putting it into hJoyHeld
  28. * Waitloop step 3/5 then register the button hold BEFORE the game can register that the frame has already passed (which would require reaching step 7 again). So ANOTHER frame is waited, then the routine is done.
  29.  
  30. If you didn't get all that, that's totally fine. Just know that you can avoid inducing 2 frame delays for letters by holding one of A or B while mashing the other. This forces all text letter delays to be exactly 1 frame long and doesn't bother with the potentially frame-wasting waitloop.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement