Wow, what a coincidence to hear from the original author!
I never looked at (or even located) the actual password generation code, but only worked on the password verification code,
as it's way easier to do it in that direction. What I initially did was to use the PCSX emulator's cheat finder feature
to locate the memory address of the variable that holds the length of the entered password, then placed a memory breakpoint on that
address in the NO$PSX emulator, which then lead to the discovery of the virtual machine.
After some reverse engineering of the VM's instruction set and programming the VM tracer, as I knew
the address of the VM instruction that incremented the password length counter, I could mash
one button for 24 times, and then look at the differences in the instruction traces when the final password character was entered.
The function `check()` in https://github.com/dezgeg/crash-bandicoot-password-cracking/... is a bit cleaned-up version of
the verification function written in JavaScript, mentally translated from this trace dump: https://github.com/dezgeg/crash-bandicoot-password-cracking/...
. All the cryptic variable names in the JS come directly from the virtual machine's "registers".
The function make() in the JS is my implementation of the password generator, i.e. inverse of check(), which
wasn't too hard to figure out. I never did bother to find a closed-form expression for the inverse of `mixAndPermute()` function,
so maybe that's where the modular exponentiation hides, but I personally don't have enough number theory-fu to crack that.