christofsteel / pyautosplit

Autosplitter for Linux (for the LiveSplit Server)
Apache License 2.0
45 stars 5 forks source link

Memory address is not read correctly #13

Open jpoep opened 3 years ago

jpoep commented 3 years ago

Hey @christofsteel,

thanks for the cool project! I am trying to get Super Mario 64 on Mupen64Plus running with this autosplitter but couldn't get it to work so far.

As a disclaimer, I am pretty clueless about all of this low level stuff, so everything I tried I've picked up from the issues and PRs in this repo, by playing around with PINCE and CheatEngine, and reading some tutorials.

From what I've gathered, all I need is a static memory address that points to a value I wanna track to use in events, right? In my case, I want to track the amount of stars I've collected, and I could successfully find out an address that stores this value (7ffff6c70678, in my case). Using my dangerous superficial knowledge, I googled how to make programs use the same addresses every time, and by starting my emulator with a flag that turns off memory randomization, this address is persistent across restarts, so there should be no need to mess around with pointers, right?

For reference, here is my variable definition:

  "variables": {
    "stars": {
      "type": "memory",
      "address": "0x7ffff6c70678",
      "length": "2",
      "signed": false,
      "byteorder": "little"
    }
  },

The autosplitter launches the game and doesn't spit out any errors, but no event is ever triggered. In fact, it doesn't seem like my stars variable is correctly initialized, because when I print all variables on every tick, stars shows up as having a None value. Am I using the correct memory address here? Is the one that PINCE shows me even the correct one? Is the memory address in PINCE's output local to the program or do I need to strip away some kind of namespace address to let the autosplitter read it correctly? What got me confused is that CheatEngine running through wine gave me a slightly different memory address for my stars, namely libmupen64plus.so.2.0.0+CC5678, so I thought that maybe only CC5678 is the relevant part of the address. However, using this and some other variations (including process_start + CC5678) all resulted in the same behavior. For reference, I couldn't get the pointer scan to give me any meaningful result, but because my value address is static, I figured it shouldn't be needed anyway.

As you can see, I'm pretty clueless about how memory addresses work, so any help would be huge :heart:

Lucki commented 2 years ago

From the CE-Wiki about multilevel pointers:

I did find a static base on the first scan of the base address but I remember this being a false base. So here what we want is a base address in the form of 'process.exe+offset', you can try one of the others that look like 'module.dll+offset' but I want to say that here they will prove to be false pointers. And yes most newer games will have many false values and pointers.

I gave it a quick shot and found stars at libmupen64plus.so.2.0.0+CC69E8 and lives at libmupen64plus.so.2.0.0+CC69EE. The difference can come from compilation or versions.

So my current guess is that process_start is not libmupen64plus.so.2.0.0. You basically want to go down the multilevel pointer chain until you find an offset from the entry binary which gets called by pyautosplit instead of an included library.

Here's a previous how to with links to the wiki tutorials how to achieve this.