AxelDV Posted September 20, 2017 Share Posted September 20, 2017 I need the pattern or function to get rpm please Link to comment Share on other sites More sharing options...
alloc8or Posted September 20, 2017 Share Posted September 20, 2017 (edited) Just read the float at CVehicle + 0x844 and multiply it by 10000.0f. Edited September 20, 2017 by Unknown_Modder Link to comment Share on other sites More sharing options...
uNiverselEgacy Posted September 21, 2017 Share Posted September 21, 2017 I don't think there's a function for that. You just need to read the float value in the CVehicle struct. The offset can be found using this pattern: F3 44 0F 10 93 ? ? ? ? F3 0F 10 0D. For 1180 it's at 0x844. You get a value from 0.0 to 1.0. You need to adjust it depending on which vehicle it is if you want the real rpm number. Link to comment Share on other sites More sharing options...
kagikn Posted September 21, 2017 Share Posted September 21, 2017 (edited) It's surprising that uNiverselEgacy told us the pattern for RPM faster than Unknown Modder. I believe Unknown Modder also knows the pattern, though. Anyway, now we don't need to track the offset of RPM when a GTA update changed the vehicle class unless the pattern is wrong. Edited September 21, 2017 by kagikn Link to comment Share on other sites More sharing options...
ikt Posted September 22, 2017 Share Posted September 22, 2017 How do you find these patterns and what are they used in? Or do you just search for code that uses that offset and use that as pattern? Link to comment Share on other sites More sharing options...
uNiverselEgacy Posted September 23, 2017 Share Posted September 23, 2017 How do you find these patterns and what are they used in? Or do you just search for code that uses that offset and use that as pattern? Yea just use a debugger to find the code that accesses that address. ikt 1 Link to comment Share on other sites More sharing options...
kagikn Posted September 23, 2017 Share Posted September 23, 2017 (edited) So, could you show us usage? We can use it by finding the pattern and reading value as a int pointer? Edited September 23, 2017 by kagikn Link to comment Share on other sites More sharing options...
Cuky Posted September 23, 2017 Share Posted September 23, 2017 Hi all, uNiverselEgacy could you please do a short tutorial how to get these offsets? Link to comment Share on other sites More sharing options...
ikt Posted September 23, 2017 Share Posted September 23, 2017 So, could you show us usage? We can use it by finding the pattern and reading value as a int pointer? I just implemented something similar once I realized this is a much better way than a bunch of offsets uint64_t getHandlingOffset() { int gameVersion = getGameVersion(); auto offset = gameVersion >= 24 ? 0x830 : 0; offset = gameVersion >= 26 ? 0x850 : offset; offset = gameVersion >= 28 ? 0x878 : offset; offset = gameVersion >= 34 ? 0x888 : offset; offset = gameVersion >= 36 ? 0x8A8 : offset; return offset;}becomes uint64_t getHandlingOffset() { auto addr = MemoryAccess::FindPattern("\x48\x8b\x87\x00\x00\x00\x00\xf3\x0f\x10\xc8", "xxx????xxxx"); uint64_t offset = *(int*)(addr + 3); return offset;}For the pattern I just chose some instruction that accessed 0x8A8. I hope it's not an exact science, and any sufficiently distinct pattern of any function accessing this address should work. kagikn 1 Link to comment Share on other sites More sharing options...
K^2 Posted September 23, 2017 Share Posted September 23, 2017 uint64_t getHandlingOffset() { int gameVersion = getGameVersion(); auto offset = gameVersion >= 24 ? 0x830 : 0; offset = gameVersion >= 26 ? 0x850 : offset; offset = gameVersion >= 28 ? 0x878 : offset; offset = gameVersion >= 34 ? 0x888 : offset; offset = gameVersion >= 36 ? 0x8A8 : offset; return offset;} I know it hardly matters in this particular case, but ternary operator chains are about the worst thing you can do for performance, readability, and debugging in general. I know this particular snippet is defunct anyhow, but in the future, if you encounter a similar need, consider doing something like the following. uint64_t getHandlingOffset() { static const std::map<int, uint64_t, std::greater<int>> kVersionOffsets { {0, 0}, {24, 0x830}, {26, 0x850}, {28, 0x878}, {34, 0x888}, {36, 0x8A8} }; const int gameVersion = getGameVersion(); return kVersionOffsets.lower_bound(gameVersion)->second;}Believe it or not, map will actually perform slightly better even in this simple case. It will perform way better if you get to 10-20 versions. But more importantly, it's easier to edit, can be loaded dynamically from a data file, and won't make hopeless C++ nerds like myself choke on a drink while casually reading a forum. Oh, and const qualifiers. Use them. They help compiler do its job, and make code easier to read. ikt and kagikn 2 Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...
ikt Posted September 23, 2017 Share Posted September 23, 2017 (edited) I know it hardly matters in this particular case, but ternary operator chains are about the worst thing you can do for performance, readability, and debugging in general. I know this particular snippet is defunct anyhow, but in the future, if you encounter a similar need, consider doing something like the following. [...] Believe it or not, map will actually perform slightly better even in this simple case. It will perform way better if you get to 10-20 versions. But more importantly, it's easier to edit, can be loaded dynamically from a data file, and won't make hopeless C++ nerds like myself choke on a drink while casually reading a forum. Oh, and const qualifiers. Use them. They help compiler do its job, and make code easier to read. Thanks, I never thought about using maps like this. Can you give some background information on why/how this is faster? I did find something about ternary operator chains being slightly slower than if-else chains, but not much about using maps for this. Edited September 23, 2017 by ikt Link to comment Share on other sites More sharing options...
K^2 Posted September 23, 2017 Share Posted September 23, 2017 Ordered maps, such as std::map, are O(ln N) order of complexity, because they are organized as a tree. If you wanted to achieve the same effect with if-else statements, you'd write something like this. uint64_t getHandlingOffset() { const int gameVersion = getGameVersion(); if (gameVersion >= 28) { if (gameVersion >= 34) { if (gameVersion >= 36) return 0x8A8; else return 0x888; } else return 0x878; } else { if (gameVersion >= 24) { if (gameVersion >= 26) return 0x850; else return 0x830; } else return 0; }}This is probably the most efficient method that doesn't involve writing a redundant lookup table, but it's absolutely horrible for readability or editing. Maps effectively build a tree like that for you, including doing all of the heavy lifting on balancing it. There is an added cost of function calls there, but that's still not as bad as having a bunch of extra branches. Your biggest potential loss with maps is cache misses, but you minimize that exposure by setting the map up all at once, which will mean that all of it is nearly guaranteed to be allocated in continuous chunk of memory. Now, the reason if-else blocks are more efficient to begin with than ternary operators is because of how much work went into optimization. Both CPU and compiler optimizers are geared towards them, and they expect certain layout. When you throw ternary operators at such a compiler, they don't do so well. And the reason for that is that, in general, you might not want to evaluate both branches of the ternary operator, which means that decision on which branch to evaluate has to be made upfront. And that greatly limits how much rearranging the optimizer can do and how much look-ahead work the CPU can do. Which leads us to another trick. Sometimes, it's cheaper to do extra math. These two are equivalent in most cases. int z = (a > b) ? x : y; const bool choose = a > b;int z = choose * x + (1 - choose) * y;And despite the later being a lot more instructions, if you have to do a lot of such decisions, it's going to run a hell of a lot faster. Because math is something CPU does well, and branching is a touch harder. As an added bonus, while branching has to involve a CPU core checking each condition one at a time, if you are running this code via SIMD or shaders, you can usually do them in bulk. So instead of hitting a prediction miss that interrupts your entire pipeline for a hundred cycles, you end up doing eight of these in 3 cycles on the same core without slowing down for a beat. Not that you'd ever want to use something like this to choose an offset in a file. The realistic scenario where you pull out heavy guns like that is running animation on tends of thousands of characters in a complex scene, where you have to apply different joint constraints depending on what's happening with the animation. So at the end of the day, the main reason to use maps still comes back to how easy it is for somebody to follow the code. If I have a forest of ternary operators, a person seeing that code for the first time has to figure out how everything works to be able to make the change. If you have a map initialized from a list of pairs, somebody can come in and edit that list without having any idea how the rest of the code works. And even if you are working on a piece of code alone, a month later, you might as well be a completely different person. It's worth it to be kind to your future self. Sorry that it turned into a rant. This just happens to touch on so many subjects. Wesser and ikt 2 Prior to filing a bug against any of my code, please consider this response to common concerns. Link to comment Share on other sites More sharing options...