christofsteel / pyautosplit

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

More documentation on the config setup #5

Closed ShadiestGoat closed 3 years ago

ShadiestGoat commented 3 years ago

Heya, I'm trying to figure out how to set this module up, and well, I'm having trouble. First off, how do you get the different states for events, or variables?

I'm doing this for Hollow Knight. There is an auto splitter for Hollow Knight in ShootMe/LiveSplit.HollowKnight, and there are some values there, but I honestly cannot get the hang of how to set this up. Can you please add more documentation on the setup of these files? Thank you!

christofsteel commented 3 years ago

Hi, to use pyAutosplit, you have to create two files. One for the game and one for the route you are Autosplitting. In the "Game"-file you just define the variables, that are updated regularly (as defined by the frequency parameter). Like the amount of trinkets, or what level you are on, or if you are in a loading zone. Based on the variables you can define events, like if some variable has some specific value. The variables are available via state.variablename. E.g. state.trinkets, state.level or whatever you named the variables. There is a second state called oldstate, that you can use to compare the current values, with the values in the last update. That way you can monitor changes in the variables. In the "route"-File you can then use this specific events to trigger where you are on your route. Existing autosplitter for LiveSplit are most probably of little use, because they are written for the windows version of the game and use a completely different memory layout. Unfortunately you need to figure out the memory locations by yourself :( . There are cheat engines on linux, that may help. Maybe you are lucky, and the game executable is compiled with debug flags, and tools like gdb can help you.

ShadiestGoat commented 3 years ago

Thank you, I'll see what i can do!

ShadiestGoat commented 3 years ago

Hey, so I'm using game conqueror to find the memory things, but all that I get is an address like 7f7544265cb8, what do I do with that? Do I somehow have to transfer it to 0xSomething? I'm kinda lost haha

christofsteel commented 3 years ago

Hi, I'm leaving this open. If it's unclear, what needs to be done, the documentation needs updating. For your specific case, you can use software like game conqueror to find out at which memory locations your desired variables are stored. The locations are usually represented as a hexadecimal number, like 7f7544265cb8. 0x... is (usually) used to specify, that a number is in hexadecimal. Otherwise, you cannot know if like the number 878 is a decimal, or a hexadecimal number. Therefore one interprets 878 without a prefix as a decimal number and 0x878 as a hexadecimal number. Granted, if a number has f, c, or b in it (like 7f7544265cb8), it is safe to assume, that this is a hexadecimal number. But in order to stay consistent one prefixes it with 0x anyway. So the memory address for pyAutosplit should be 0x7f7544265cb8.

christofsteel commented 3 years ago

Mind you, 0x7f7544265cb8 does look like a stack address, which means things can become complicated..

ShadiestGoat commented 3 years ago

Thank you for your explanation! It's kind of weird, but every time I go onto a different save file, the address changes. Also I found out that there is a Mod API for unix, could that also help?

christofsteel commented 3 years ago

Yeah the address change is most likely related to the address being a stack address... In theory this can be fixed. The game VVVVVV (version 2.2 and prior) has the same problem. The solution there is the following: All data is saved in a game object. Once we know the memory location of the game object, we can calculate all variables, that we need for the splits, because the variables are always at a fixed offset to that game object. Problem is, that the game object can be located at (semi-)random spots on the stack. So you cannot know the memory location before running the program. But you can intercept the program at just the right time (by creating a breakpoint) and then just read the memory location from memory. In theory the same approach should work for Hollow Knight. Unfortunately the situation is slightly different for the two games: For VVVVVV have access to the source code, so finding the right spot was easy... I fear for Hollow Knight, this would involve quite a bit of reverse engineering...

ShadiestGoat commented 3 years ago

Dam.. Thank you for all your help ^^ I don't think I myself can do the reverse engeneering required, given that I'm not really knowlegeable on the low level languages haha

ShadiestGoat commented 3 years ago

Wait a sec, if there is a community made, open source, mod api for the game, shoudln't there be a break point somewhere in there that I can use? If so, what would it look like?

christofsteel commented 3 years ago

That might be a start, but as far as I can tell, Hollow Knight is written in unity, therefore in C#... and I am not certain how that translates into lower level machinecode... Regarding the breakpoint issue: A breakpoint can be any point in a program. You just say (externally) After you executed this command, hold on for a bit, and give control to a debugger (PyAutosplit acts here as a debugger)

ShadiestGoat commented 3 years ago

Wait why can't it just be launched at the same time? Does it have to be a precise point?

christofsteel commented 3 years ago

The control flow is as follows:

pyAutosplit starts -> pyAutosplit executes the game binary, sets a breakpoint in the code of the binary, right after the game object is created and waits -> The game starts -> the game creates the game object -> BREAK -> pyAutosplit is resumed, reads the current stack pointer (that corresponds roughly to the address of the game object), and resumes the game -> gameplay

But you have to know, where to set the breakpoint in the executable... It is possible, that the mod api can help you with that, but... I don't know that

ShadiestGoat commented 3 years ago

How could one find when the game creates a game object?

Lucki commented 3 years ago

Hey, so I'm using game conqueror to find the memory things, but all that I get is an address like 7f7544265cb8, what do I do with that? Do I somehow have to transfer it to 0xSomething? I'm kinda lost haha

I'd like to give some advise here that I've found out the last couple of days:

Edit: There's now the pre-defined variable process_start which represents the program name displayed in Cheat Engine. [program.exe + 0xABC] will be "address": "process_start + 0xABC" in the config.