RNG in Quest64

Hacking Any Other Offline Single-Player Game

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

RNG in Quest64

Postby CGoCPftF » Sun Aug 12, 2007 6:38 am

First I would like to say that MHS is the best I have seen both because it has a lot of nice features that are easy to understand and because it looks professional.

I am trying to figure of how Quest 64's RNG works for the purpose of exploiting it in a TAS (Tool Assissted Speedrun), but am 1. not the best programmer in the world 2. mostly unsure of how RNG works in video games. That being said, I was still able to make a little program that can figure out linear congruence RNGs(?) (multiply by a number then add by a number), but it does not seem to work for what I think is the RNG address in the game (if I lock the value, damage will not vary). Any help or suggestions if much appreciated!
CGoCPftF
I Have A Few Questions
 
Posts: 3
Joined: Sun Aug 12, 2007 6:13 am

Postby L. Spiro » Sun Aug 12, 2007 10:47 am

Then you certainly know about TAS Videos, and you probably even found my software from that very site.

They have been doing random-number manipulation for a long time on many emulated systems, and someone might have even done the very game you want to hack, so for that particular question it would be better to ask there.

Manipulating random numbers in Windows® is simply a matter of forcing the return value of rand(), and I susect it is similar on emulated systems.
And of course doing this in MHS is a very simply matter of just changing some bytes (though you have to find them on your own and know to what value to change them on your own).

As for your other problem, the thing about manipulating the random-number generator is that it effects the entire game.
You might be able to find a better answer on TAS Videos, but my own way to tackle this problem would be to set a flag on the event that you want to de-randomize and then only return your fake random numbers when that flag is set.

In other words, find the code that uses the random numbers to do something.
Inject code (in N64 assembly obviously, which you probably should know at least a little to be doing this kind of work) to set a global flag, then allow it to call the normal rand() function it always calls, then inject code after that to unset the flag.
You modify the rand() function in the game to check the flag and only give non-random numbers when it is set. So all the other places in the game that call rand() still get random numbers, but the place you modified gets solid numbers.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby CGoCPftF » Sun Aug 12, 2007 12:04 pm

Yes that is exactly where I found your program and this forum. Unfortunately, there is a shortage of people that are interested in TASing N64 games in general, and the one guy I know of who is really good with RNG manipulation told me he wasn't too interested. Are you talking about actually modifiying the values of the RNG? If so, that is against the rules at TASvidoes. All that I want to do is figure out how the RNG calculates the values. With this data I could simulate battles starting with RNG values XXX, and go through all of the options that I have for each turn, taking into account how the RNG would change. This way I could get a battle where I never miss and my enemies always miss without modifiying the values (or something like that). Hopefully my words make a little sense. In most games that I have seen the RNG changes after a certain amount of frames, but in this game that is not the case in the majority of battles, so manipulation has to be calculated way in advance. That is why I need to figure out how the RNG works. I have found atleast one of the RNG addresses. I would like to 'attach the debugger to see what accesses/modifies the address', but it is grayed out and I am unsure of how to change that. I read through the help but couldn't find anything, but it is 1 AM here so...
CGoCPftF
I Have A Few Questions
 
Posts: 3
Joined: Sun Aug 12, 2007 6:13 am

Postby L. Spiro » Sun Aug 12, 2007 1:19 pm

Are you talking about actually modifiying the values of the RNG? If so, that is against the rules at TASvidoes.

I was but I forgot about their rules (and don’t know them entirely).

To cover the major point first.
I would like to 'attach the debugger to see what accesses/modifies the address', but it is grayed out and I am unsure of how to change that. I read through the help but couldn't find anything, but it is 1 AM here so...

You have to have the special version released only in the General section of these forums.
But even with that it is not going to help you.
Your game is emulated. Debuggers don’t work (effectively) on emulated games. You will get a hit on what reads that address, but that code is used to read/modify nearly every address in the game since it is part of the Project 64 (or otherwise) emulator.
Don’t bother with any debuggers.



Unfortunately what you need to do is a matter of studying and it is game-specific, so you wouldn’t get help fom anyone who didn’t already study the same game.
If the random numbers are generated each time the rand() function is called andy ou aren’t allowed to modify it, you just have to deal with the fact that you might miss (of course I wouldn’t be 100% on this as there might be some other ultra-creative but game-specific way) and instead plan the best ways to miss.

In normal Windows®, you call rand() and it pumps out a number and changes a global, then sits and waits for the next time you call the function.
So the sequence of the numbers is always the same no matter how long you wait before calling it again.
If your game is doing that during battles, then you would just have to accept that the next number generated would fail the test and cause a miss.
If that is the case, it is time to get creative and figure out how to divert the misses to the enemy or to whatever else, or to use them to attack yourself for comical value (just throwing out examples here).

There isn’t much direct help I can give you since it really is up to your knowledge of that specific game.
MHS comes with tons of ways to allow you to do that research, however, and I think you already know how to use most of them, so I wouldn’t need to explain much else.
But if you do have a question about MHS itself, of course then I could answer anything.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby CGoCPftF » Mon Aug 13, 2007 1:51 am

When you say not to bother with debuggers, would viewing the disassembly not do too much help either for the same reason? I attempted to find the memory address in question, but I am a little confused and cannot find it.

you just have to deal with the fact that you might miss


Even though I am unable to change the seed rand value in battle, I have ways to change it outside of battle, waaay in advance. So, I can manually go through all the possibilities of a battle per starting RNG address (which takes 4-5 minutes) or my dream is the completely understand the RNG so that I can simulate 100 possible starting RNG values in a couple of minutes to find the best one. I know you probably don't care about the game specifics but I keep talking about them anyways :P sorry... Anyways this post is semi legit because I am asking if the disassembler would be useful in my situation.

One more thing, if a address turns purple in the hex editor for one value and then back to blue does that mean it is a non-static pointer or something else?
CGoCPftF
I Have A Few Questions
 
Posts: 3
Joined: Sun Aug 12, 2007 6:13 am

Postby L. Spiro » Mon Aug 13, 2007 10:19 am

Studying the mechanics is right.
Lack of disassembly help is right (though I often consider ways to add Nintendo® 64 and Super Nintendo Entertainment System® disassembly to MHS for emulator hacking).

Purple addresses in the Hex Editor indicate pointers.
But if they change blue it means the data there changed and is no longer a pointer.
Sometimes purple values are not pointers at all; it is not 100% fail-proof but nothing is. But it often gives very good clues.

However to decode Nintendo® 64 pointers you mask off the top 8 bits (ADDRESS & 0x00FFFFFF) and add the result to the main-memory base pointer inside Project 64 (which is probably [Project64.exe+0xD6A3C] if your version is correct).
So if your pointer was 0x804E6D70 (pointers in Nintendo® 64 always start with 80, 81, A0, or A1 [from memory] which is a bank-select code) you would find where it points by doing:
(0x804E6D70&0xFFFFFF)+[Project64.exe+0xD6A3C]
This would be a valid exression you could enter into the real-time Expression Evaluator so you can play with this until you get everything you need.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan


Return to Others (Offline)

Who is online

Users browsing this forum: No registered users and 0 guests