News:

11 March 2016 - Forum Rules

Main Menu

Finding RAM address in ROM using LemAsm

Started by starfishmaster, January 26, 2016, 08:34:53 PM

Previous topic - Next topic

starfishmaster

Using the command tool in Nemu64, I have found an address I want to modify in the ROM. It is located at 802D386C. How do I find this address in the ROM using LemAsm? I have read that you have to take away the offset (802D386Ch - 8000400h) plus the header (+1000h), however modifying the line of code in LemAsm (NOP it out) does nothing. Is this the correct address? I'm not sure if I'm actually at the correct line in LemAsm.

Zoinkity

That only works if the address happens to fall within the initial block of code loaded at the beginning of the game.  That's definitely not true in your case.

So, you have to track down the code that you want to modify.  There's a couple ways to go about this.  If the code isn't compressed you can just do a simple search for it.  Basically just copy out maybe 16-32 bytes of the binary from that address and search the ROM for hits.  If you don't get any then you're dealing with a compressed title.  Since uncompressed data is usually DMA'd directly to its final location you can't use breakpoints to find it, but a search is probably faster anyway.

Hopefully that's all you'll need to do.  Otherwise...

For compressed files you need to work out what file was loaded at this address range plus what type of compression was used.  For a general idea of which file it came from you can set a write breakpoint on 802D386C, then either open the registers window and look at the PI tab for the source ROM address or read it directly from A4600004.  In most cases you'd have to look at addresses backwards from there in whatever increments the compression algo works in (which is the read size +1).  Chances are this breakpoint was triggered by fastcopy, so there's a slim chance you can find the decompressor this way.

As for the decompression algo one of the simpler ways to find it is to set a breakpoint on A460000C at boot (or better yet at the run address).  The first few DMAs can be ignored (cart bootstrap, then cart data for checksum, then usually the audio libraries), but eventually you'll get to a compressed file.  When the breakpoint hits you can advance one step to load the data to the address given at A4600000.  Set a read breakpoint on that data and it will trigger as soon as the decompressor starts to use it.
Once you find it you can look at the code to work out the algorithm needed to decompress the file.  Compressing it again is a bit of a hassle if you have to write your own algo for that based on the decompressor, but a fair number of N64 titles used codecs that are publicly available now.

-or you can tell me which title it is and I probably have one already written ;*) 

starfishmaster

#2
Hi Zoinkity,

Thanks for the details. Actually, the game I'm trying to modify is your modified Blitz 2000! I have been posting over at the nflblitzfans.com forums talking with Jaker3 about gameplay modifications.

Basically I'm trying to modify the player speeds, with my first attempt at changing QB speed. I have found the correct address that writes to the lateral QB speed, and just need to find that in the actual ROM now.

If you have any other suggestions about modifying this specific ROM it would be greatly appreciated. And thanks for the hack with the Texans! Now I can replay that nightmare of a game against the Chiefs...

p.s. I previously found out how to modify the gravity (it is modified using a gameshark code). I have a video here showing it (really starts @ 00:30): https://www.youtube.com/watch?v=ZH0_J60gDNI

January 28, 2016, 11:47:38 AM - (Auto Merged - Double Posts are not allowed before 7 days.)

Zoinkity,

So I tried what I think you suggested. I think I may have found the correct addresses to modify in LemAsm. I will walk you through what I did. I was actually looking for address 802f7fd4, which does that actual writing to the player speed.

On bootup, 802F7FD4 has the values 3C 04 80 34-24 84 8E 38.

I did a search for these values in the ROM using a hex editor, and found address 000E64F0. I opened this address in LemAsm, and the MIPS instructions look much more like what the commands window shows in Nemu64.

Does this process sound correct? Thanks again for the help.

January 28, 2016, 01:34:38 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Okay I definitely found the right address in LemAsm. Now I have a question that hopefully you could help with as well. I am modifying the player speed.

The address that writes to the player speed has the command SWC1 F0, $0014 (S0).

directly above it is MUL.S F0, F20, F0. I assume this is multiplying whatever is in F0 * F20 = F0.
above this is NOP. If I change it to MUL.S F0, F20, F0, the player speed increases drastically (I assume because this extra MUL.S takes what ever F0 was, and multiplies it again by F20). However, this speed is too fast, so I want to multiply it not by some arbitrary value, but a specific one I want to set.

I'm wondering:

1. How to determine the value of F0 and F20 at a given point;

2. if there is a way to set one of the floating point registers (f0-F31 I think) to be a specific value (i.e. store the number 1.23 into F30 or something).

and

3. How would I change the rom to include this code? Are there "extra" unused addresses where I could stick in these extra functions/variables and call them when I need to? I figure I shouldn't just overwrite other addresses.

Zoinkity

Sorry about not getting back to you sooner!  Had meant to, been busy finishing off a file inserter for Harvest Moon 64.

The values in F20 and F22 were set earlier, near the beginning of that function.  There were some common design rules that were used with N64 regarding registers and how they are used, so I can tell you with 95% certainty that F20 and F22 won't be changed by any of those JALs.  F0, however, can be.

The function started at 802F7D18.  F20 and F22 are set a little later, starting at 802F7DA4.  What they do is they load the initial value into a general register then use a MTC1 (move to co-processor 1) to push that into an FPU register.  What makes this function "fun" is that it can alter those values conditionally.  The first entries listed below are the original values, and the ones following them are conditional cases you can figure out on your own ;*)

Things that set F20:
802F7DB0 + 802F7DB4 (0x9BE00 + 0x9BE04) = 3FCCCCCD  (~1.6)
802F7E14 + 802F7E18 (0x9BE64 + 0x9BE68) = 3FB9999A  (~1.45)
802F7E40 + 802F7E44 (0x9BE90 + 0x9BE94) = 3FB9999A  (~1.45)
802F7E6C + 802F7E70 (0x9BEBC + 0x9BEC0) = 3FB9999A  (~1.45)

Things that set F22:
802F7DA4 + 802F7DA8 (0x9BDF4 + 0x9BDF8) = 3FA66666  (~1.3)
802F7E5C + 802F7E60 (0x9BEAC + 0x9BEB0) = 3FA66666  (~1.3)

There's an extra condition in there that can multiply both values by 0.6- at 802F7F54.  Can't remember if that's tied to tournament mode or not.  It should be good enough altering the base values though.

Not sure if you realized it or not, but at 802F7F98 it will either do F0*=F22 or F0*=F20.  Likely branches only execute the operation in their delay slot (the instruction following the delay) if the condition is true.

My personal preference is to try to utilize or make room within the existing code for more code.  With N64 it's rather simple to do; optimization wasn't quite as aggressive back.  Otherwise that's a very per-game situation, what you can put where.  I'd have to check the old notes on the patch to know what swaths of code were cleared out and available for use now (or, I suppose, you could search for long chains of 00s).

starfishmaster

Wow, thanks for the details! I have a few questions about what you mentioned:

1. You said the function starts at 802F7D18. How did you know this??

2. To be sure I'm looking at the correct line, the command I see at 802F7D18 is CVT.S.W F0,F0; is this correct (this is when I just boot up the rom)? I noticed if I'm in an actual game, the command changes to ADDIU SP, SP, 0xFFC8.

2. So neither F20 nor F22 actually change? Are they acting essentially as constants?

3. I see 802F7DA4 is LUI AT, 0xF3A6. How is this setting F20 and/or F22? I see a few lines down MTC1 AT, F22 - is this what actually does the loading into the register?

4. How did you know that the specific addresses you mention in your table set to F20/F22?? The only thing I see for 0x9BE00 and 0x9BE04 are LUI AT 0x3FCC and ORI AT, AT, 0xCCCD. How did you know this? I would have never guessed.

5. Why are the two address added together? And how do you get ~1.6 out of 3FCCCCCD? I know 3FCCCCD is hex, but I don't see how you got that it is ~1.6 as a floating point.

6. Last thing - if I am able to find some "room" where there are some addresses w/ just 00s, can I just stick in some code there and it work? Or does it have to be referenced by the function somehow?

Sorry for all these questions, especially if they're naive -  I'm still pretty novice at this. Thanks again for all the help.

Zoinkity

1) Functions are usually in-line, and most will start by saving the return address (RA) and modifying the stack pointer (SP).  So, a really quick way to find one is to look for a JR RA before the code you're looking at.

2) Things will be loaded into and out of rdram as the game progresses.   Since you're aiming for the movement modification code I waited until that was loaded (which it is during a match) and based the addresses off that.

3) F20 and F22 are acting as constants.  There are a couple of things that can modify them, but they're basically constants that are used as multipliers to your movement.

4) There are only two ways to set a floating point register on COP1.  You can use a COP1 load command to load a value from an address or move the value from the general registers into a floating-point register.  In this case they move them from the general registers.
AT is set equal to 3FCCCCCD using two opcodes.  LUI sets the upper half of a 32bit value, and ORI sets the lower half.  The MTC1 copies the value in AT to the FPU register.  AT sets F20/F22.  By setting AT to a different value you set F20/F22 to a different value.

5) 3FCCCCCD is the binary representation of an IEEE 32bit precision floating point value roughly equal to 1.6.  Honestly you're sort of better off with a calculator for these, but the idea is that the upper-most bit is the sign, next 8 bits an exponent of 2, and the remaining bits a fractional part.  There's a lot of documentation on these online, some more confusing than others.

6) In order for code to function it has to be run.  In order to affect anything in this function it either has to be within this function or you need to link it in here using jumps.  If you just want to increase everybody's speed that's as easy as modifying these multipliers--no additional code required.  If you're thinking about a per-player effect though that could get very messy very quickly and will undoubtedly require tables.  The normal method is to just use a JAL, make sure your function doesn't overwrite any important registers the calling function was using, then jump back using JR RA.  (Jump Register: Return Address)

One rule you do need to follow if you want this to work on a real N64 is you can't mix code and data.  (or at least a whole lot of it)  There's a data and instruction cache, and reading data from the midst of instructions can cause a cache miss.  Likewise, trying to execute code from someplace that isn't in the instruction cache causes a miss.  Best case it just runs slow temporarily and the cache sorts itself out, worst case bad things will happen.
Currently the only emulator to bother emulating the cache is Cen64, but it isn't feature-complete yet.
Avoiding cache collisions is why I usually rewrite code instead of finding someplace unused to shove it.

starfishmaster

Thanks for the explanation on all of these!

However, based on some troubleshooting playing with these values I don't think that modifying them (at least within this function) affects all player speeds - in fact, I'm fairly certain it only affects the speed of who ever has the ball in the back field. I changed 3FCCCCCD at  0x9BE00 + 0x9BE04 to 40066666 (~2.1) - this resulted in the QB or who ever has the ball in the back field to move much quicker laterally. I also changed the other values you mentioned at the other addresses, but it hasn't appeared to change anything.

I think this is in line with what I have seen before - the address 802F7FB0, which is outside of the function you described, controls the speed of the QB moving forward and backward. Additionally, I have also found that the RB is controlled by yet another address, 802F70AC (I think, I'm looking at old notes). Point is, I'm fairly certain that each player has a separate function writing to them, with a different one depending on if they're in the backfield or passed the line of scrimmage.

Feel free to correct me if I'm wrong, this is just what I have observed. I am going to try and apply your same strategy to other players and see what happens.

Thanks again for all the helpful responses.

Zoinkity

Each position is treated differently by the game, so yes, they should have independent functions for all of them.  I'd expect all the linemen will use the same one, but anybody who can handle the ball will their own functions.

The other addresses are for some kind of conditional effects.  They're testing if some value falls within a particular range and if so changing the multiplier.  One is definitely testing for turbo, one could be for when you're on fire, but you'd have to track them down to know for certain.  Anything in the function that can change the multipliers will affect speed at least some of the time.

starfishmaster

You're right - the x1.6 multiplier is only with turbo. Not sure about the others, but modifying the turbo speed alone should work for what I'm looking for.

The other hack I'm looking into is going to be much more difficult, but not impossible I think. I am wanting to be able to only perform specific tackle animations. Typically if the player you are tackling is on the ground, there are only a few animations that could occur, but if the player is standing, there are quite a few - the suplex, "levitator", dump truck (all names my friends and I refer to them as), etc. Anyway, I would like  to be able to do specific tackle animations at will - preferably by doing maybe a button combination prior to tackling, but I assume this will be extremely difficult to do.

Regardless, as a "case study" I would like to be able to at least force the game to only do 1 tackle animation. I have been able to narrow down some addresses related to the animation - the value at an address I monitor corresponds to different tackles. However, I haven't figured out how the animation is chosen. It could be like other aspects of the game where dice rolling is involved (as tackle animations seem totally random), but I'm not sure. If you could let me know if you think this will even be possible (to isolate how the animation is set and then forcing it a certain way) that would be awesome.

Zoinkity

Undoubtedly they're going to be selecting the animations.  Depending on the number of them they may use a table or just write it in ASM.  I'd suspect a table, and more like index numbers.

Anyway, the function to return a random number is 80026B10.  They'll JAL to that when they need a random value, so you can search for the binary equiv. (0C009AC4).  80026B44 sets the seed value for the randomizer.  Incidentally, the code used is from the standard C library and the best example of how virtually all games on the system really do use 64bit math.

Not certain exactly where animation selection occurs.  Did see some animation-like things at points while sorting out some of the die-rolling and left some notes.  Probably be pretty fast ruling them out.
@ 0x99580   802F5530   should be false positive; animation
@ 0xB3C9C   8030FC4C   should be false positive; animation
@ 0xB7570   80313520   should be false positive; animation
@ 0xB92DC   8031528C   should be false positive; animation
@ 0xC1CDC   8031DC8C   should be false positive; related to field goal
@ 0xE7440   802F8F60   preceeded by randomizer; probably an animation controller

starfishmaster

#10
I have been playing around with cheat engine to try and isolate addresses that change during tackle animations. I have been able to narrow it down, but haven't had any luck beyond that.

802D89D9 may be related somehow. If I freeze address 802D89D9, the player that I tackle will infinitely continue doing tackle animation although it often ends up freezing the game. It is constantly being written to by (at least) two addresses:

when idle:
8027EC8C      SW V0, 0x000C (S0)
8027CD90      SW V0, 0x000C (S0) --> I think this writes to all the players.. perhaps setting the animations?

in a tackle animation (didn't check multiple animations):
8027CD90      SW V0, 0x000C (S0)
8027F27C      SW V0, 0x000C (S0)



The thing is, I'm not sure if even finding the tackle animation will lead me to how the animation was determined. Also, I'm not sure just how "random" they are. I can stop the game after a play without it progressing (just freeze address 800AE8CC at 7A 00 00 00; it's the late hits timer basically) and then saving the state. I can then tackle the player, load the state, tackle again, load, etc. Every time I do this, the tackle animation (assuming I tackle from roughly the same orientation) is the same. so it must have that animation "on deck" ready to use, as opposed to randomly choosing an animation.



I'm not familiar with tables or index numbers - is there a way to try and find them?



February 01, 2016, 10:20:28 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

So after some troubleshooting, I'm pretty sure all animations, or something related to them, are set by 8027CB38 or 8027CD90. I have found a few different addresses that 8027CB38 writes to when I tackle:

802D89D4
802D5B75
802D89D5

The thing is though, the command at these addresses changes depending on if I'm tackling, sitting idle, etc. I see that the LB command happens often - not sure if this is loading a bit from somewhere. For instance, when idle, the commands are:

802D89D4 LB A2, 0xCFE7 (AT)
802D89D8 LB A2, 0xCFFB (AT)

but if I tackle a player, they change to:

802D89D4 LB A2, 0xFC8E (AT)
802D89D8 LB A2, 0xFCD5 (AT)

Actually, it looks like If I freeze 802D89D8 at a value during an animation (such as 28 FD 26 80 B1 00 00 00) the player will infinitely do that animation. This is written to from:
8027CD90 SW V0, 0x000C (S0)

Above this line are several JALs and BNEZ commands. I'm wondering if these may be what sets the animation?

Also, you mentioned it maybe using a table - how would one find these? I assume a hex editor and not nemu. If I can find the code where it pulls the animation in from, I think I could figure it out.

Tomcraft

Dear Zoinkity,

I read in your post #3 above that you made some "HM64tools" in 2016.

Unfortunately, the link no longer works. Is there any chance to have a look at these tools somewhere else or would it be possible you send them to me via mail? Not sure what to expect, but I have to admit I am very curious. I am trying to get myself more and more into the code behind Harvest Moon 64 (though it seems impossible...) and im curious if your tools will help.

Thank you so much in advance! And sorry for replying to such an old thread. I wanted to contact you via PM, but your inbox is full :)

Kind Regards

Tom

Pennywise

If their inbox is full, you might want to try another forum where they post at. Not sure Zoinkitty will see this.