• 0 Posts
  • 49 Comments
Joined 2 years ago
cake
Cake day: March 21st, 2024

help-circle

  • I do this quite a lot myself.

    Beside the games that do officially support it via modding APIs, or older games that are just naturally extensible like Unreal Engine games that ship with an editor; it is usually done by the way of code injection.

    Think of code injection like a manually placed interrupt - you modify the flow of execution at some point to execute your own code.

    For this, you need something known as an entrypoint - place where mod code begins executing. Usually, at the entrypoint, the mod code bootstraps itself further.

    To obtain an entrypoint, you have 2 options:

    1. On supported OSs, you can abuse dynamic library loading and make a library wrapper which masquerades as the original library. When its execution begins (on Windows this is usually very early in the importing stage, on Unix/Linux you need to swap functions), you can bootstrap your mod(s) further.
    2. On other systems (game consoles, embedded, etc), you have to modify the game executable directly. Either via the way of memory injection of another tool or direct binary modifications. Depending on the platform, if it supports loading of libraries, you would either load your mod as a library or, if not, inject the mod elsewhere into memory (slack/unused space).

    How do you figure all of this mumbo-jumbo out? Well, you use tools designed to disassemble the game binary into machine language. Most popular examples are IDA, Ghidra and Binary Ninja.

    You usually won’t have any information on what’s what, but if you know a bit about code design of games, you come to realize that a lot of them follow similar principles/patterns (depending on the era and platform), so you can probably figure it out once you’ve seen a few games. Especially if the game is using the same game engines as others, then you can cross reference stuff.

    However, if you’re lucky, you can obtain something known as debugging symbols which have all of the information about the generated binary. Ideally, it’d be for your executable that you’re working with directly, but if it’s not, you can usually just cross reference it by either binary pattern matching or simple deduction (same execution flows, same data, etc). This will give you a nice map of where’s what in your disassembler tool.

    Thanks to standardization of binaries, ABIs (Application Binary Interfaces) usually allows you to match the types as they’re defined originally and have them work directly in your bespoke code. This means, for example, that if a function takes 3 arguments, those 3 arguments will be passed in the same way (depending on its calling convention), so you can expect to receive them in your own code the same way. (This is what we call code reflection - you can reflect the game’s types in your own code. If you’re using the same compiler as the original, even better!)

    And, ideally, you would be working with code directly and not with machine language, but some lower level stuff will need it inevitably.

    Usually, in your mod source code, you would work with a library that is specifically designed for code injection. This is effectively a JIT compiler which emits machine code instructions which are needed to redirect the flow of execution to your own modded functions. (Usually is capable of memory editing and making branch instructions)

    There are 2 ways to perform a code modification:

    1. Inlined code - this means you write your own code in the middle of another game function. Usually, this is done via lower level assembly and a branch instruction to put it in. Requires decent knowledge of the target CPU to use it (to not corrupt any stack or registers)
    2. High-level function hooks - this usually means that you interrupt a function call/branch with your own equivalent. Your equivalent function will have to do the job of the original usually, but depending on the case, you may replace it outright or simply pass the call onto the original function. Thanks to ABIs, this is possible.

    With all of this being said, you need to have the knowledge being able to read machine language of CPUs. This isn’t too difficult once you realize RISC CPUs are mostly very similar at a glance which helps out a lot.

    But, in order to be able to read it, you have to first obtain it and, as we all know, DRMs, executable packers and anti-cheats/tampers protect this, so you may need to get your hands dirty a bit to bypass that (e.g. memory dumps). A lot of the same tricks that security researchers use in their rulebook apply to modding as well.

    I hope I’ve explained enough. I’m aware I used a bunch of terms that may be foreign, so I hope you will get the gist at the very least.




  • You do not need a dev account.

    The process to sideloading on iOS requires you to use something like AltStore and self-sign the app package (IPA) with your own Apple ID.

    The signature is valid for 7 days and you can do it with up to 10 apps.

    Normally you need a computer in the network with a server that communicates with the sideloading client on the device to perform the signatures, however there are workarounds to do this all on device too (just needs internet access).

    Does this suck? Yes. But the reality is, I hadn’t have had the need to use it. There are (mostly) niche reasons you’d do this (JIT emulation, modded apps, unapproved apps).

    But to be real here, to most people this just isn’t worth it. There are emulators on the App Store now too, so what’s left there aren’t things most people need.

    Is there a bigger argument to be made here on how the need is also silenced by NOT having it easily accessible? Yes. But, do keep in mind, most people don’t bother on Android today already anyway.




  • Precisely. MS didn’t do a very good job maintaining it for Ryzen CPUs recently, though. I remember the whole fiasco with Zen 4, when it just came out, it ran better on Windows 10 than 11.

    Then, more recently, 9950X3D needs manual thread pinning to run some games better.

    Like, come on… this isn’t something any user should even be worried about.

    But also keep in mind that “just talking to the hardware” is one hell of a reduction and oversimplification, too.

    Keep in mind, these issues with Ryzen scheduling are fairly new. People yap about NT being an issue when it wasn’t for many years and it still isn’t even the primary issue (and it usually gets fixed by the vendors themselves in one way or another).


  • In fairness to Windows, the kernel and the drivers are the few of the objectively good things about it.

    Neither NT nor its age are the problem. It should be a testament to how well it works for the things we’re using it for today.

    The problem is the userspace. The things that you interact with and see. That is what you’re referring to when you mention “the format dialog”. Not NT. Win32 isn’t a kernel, it’s an API that is used to sometimes talk to NT indirectly and give userspace functionality.

    Where NT is truly starting to show its age is with things like scheduling on AMD Ryzen chips with 2 different CCDs. That is a Microsoft skill issue. Had this issue cropped up not even 10 years ago, they would’ve figured it out. This is what is gonna age NT. New hardware, not new software.


  • Not having CFW isn’t the end of the world. It’s a slight inconvenience having to press the button at boot and maybe sometimes randomly a game not launching.

    Also, later super slims are using more modern chips and therefore are much quieter and nicer to use.

    Lastly, currently there is a modchip being developed for a qCFW (quasi-CFW) which will allow for basically 99% CFW capabilities on later models anyway, so there is that going for it too.

    Super slims are a hidden gem imo


  • From a glance, this is just a value parser that exports them by symbols and allows you to edit the static values from a file neatly.

    I don’t know how practical this is yet since I haven’t seen the video, but in order for it to be more practical it needs to be easier to implement and use than other methods to accomplish tweakable values for debugging.

    There are many already:

    • parsing a config/text file in runtime
    • parsing commandline args
    • parsing environment variables
    • using a debugger and a memory watch
    • using external tools that can edit memory

    Now, not all methods are available on all platforms, but, it needs to be better than any of these methods in some way for it to have any point in using it.

    Game devs often have their own frameworks that can communicate with the game via network to tweak exposed values anyway for realtime debugging. Adjust.h from what I can see requires the program to be reset on each iteration.









  • It’s very good.

    Basically, there is one maintainer in the AUR (the name escapes me, jonathon I think it was?) who applies the necessary patches to the old NVIDIA drivers to make them run with a modern Linux kernel.

    Of course, there won’t be any Wayland support, but the experience is acceptable as long as you temper your expectations in terms of graphics API support. (No vulkan sadly)

    I hadn’t used it myself but I know a person who does and loves it. iGPU handles Wayland stuff while the NVIDIA is there for the heavy lifting in Xorg.