Mono x86-32 JIT machine code hooks

Started by RawCode, December 24, 2015, 05:38:45 AM

Previous topic - Next topic

ppumkin

Hi Guys
I have just started to do mods first time ever since I saw you can do it with C# pretty easily, for most things. Obviously I ran into a problem where I want to change one little static method in Rimworld just to do something slightly different. I had no knowledge of CCL or this thread before.

I started searching for answers on StackOverflow obviously, and found this one http://stackoverflow.com/a/22014532/706363 talking about CLR injection, basically injection IL code. It was a bit over my head and I tried it but nothing happened. I think I was not doing it correctly but I eventually landed up on this page to see it looks very similar to what that post mentioned, both from rawcode and gentlemen.

Thanks for good work guys.

This is gonna be very noobish though. I admit I don't fully grasp Unity and the full spectrum of the Rimworld dll but I understand C# well. I am just wondering, where do I put this code, either version of it? I understand it should be loaded before the game fires up, I think?

Not had time to try any of these solution here, I am a bit tired after searching and searching but can I use this jumping/swapping/detouring code like when I first create a think, on like PostMake() or do I need to create some class for earlier binding somewhere. Sorry if that sounds a bit stupid, I am a bit confused how to use this.


'Sharing is caring'
- Unknown

ppumkin

Ahhh. It was a stupid question. Never mind. I was so tired I wasn't reading my code properly any more. It was a typo in the methodName I wanted. [Copy and Paste + Tiredness syndrome]

It works now. I did it using
[StaticConstructorOnStartup]

And inject my method there. Tested in game and works. Bloody amazing rawcode.

Thanks allot for this, seriously rawcode,
Thank you for sharing!

(sharing is caring)
'Sharing is caring'
- Unknown

Rock5

Quote from: Fluffy (l2032) on February 21, 2016, 10:47:48 AM
Not really in the current way of doing things. The problem is the first few bytes of the 'old' method are overwritten with a jump to the new method, pretty much destroying what was there.

In theory I'm sure it's possible to copy the old method to a new one, see for example here;
http://stackoverflow.com/questions/24350769/copy-method-from-another-appdomains-assembly-and-execute-it-from-currentdomain
But thats going squarely into the domain of self-altering code, which is horrible to debug in the best of circumstances, and virtually impossible with the limited options we have in RimWorld.

So I'm afraid it's still the good old copy/paste from core. The good news is that you only have to copy paste the one method - not everything that calls it as well.

That said, a truly dynamic way to basically turn any method whatsoever into an event that can be hooked into would be awesome, so if anyone feels like spending a couple of months figuring this out, please know I'd send you cookies.
So do I understand correctly that the beginning of the original function gets overwritten with an instruction to jump to the new function thereby making the original function unusable?

Does that mean that if 2 mods try to jump the same method then the second to run will overwrite the changes of the first?

Couldn't you copy the bit at the beginning before overwriting it then use that to jump back and run the original function?

If this is nonsense please forgive my ignorance.

Hm... I feel like I might have read something like that somewhere. My memory is not the best.
Rock5 [B18] Mods
- Butchers Can Count Meat
- Sun Lamp Planner
- JTZoneButtons
- RimSearch
- JTExport


Rock5

Thanks. So I take it the copied data can't be used to somehow call the original function? That's what I understood from the topic.

I could nearly envision it working. Say you had Afunction(args) and you copy the beginning bit to another provided function, lets call it _CallOriginalAfunction(args). Then follow it with a jump back into the original Afunction() to continue after the beginning bit. Then you do what you do now and overwrite the beginning bit with a jump to the new function called say _Afunction(args). Then in _Afunction(args) you could call the original function if needed. If this could work then multiple modders could modify the same function as long as they call the original function.

Oh well. I suspect it doesn't work because you can't expect code that is split arbitrarily, and joined with a jump instruction, to work.
Rock5 [B18] Mods
- Butchers Can Count Meat
- Sun Lamp Planner
- JTZoneButtons
- RimSearch
- JTExport

RawCode

you can copy original function and call it if needed...

please read book about C and ASM for more info, trying to explain how x86 works is waste of time.