Skip to content

v0.3.0

Latest
Compare
Choose a tag to compare
@MolotovCherry MolotovCherry released this 14 Jan 17:54
cfbe4b3

Highlights

Added autostart version that behaves like NML in that it automatically patches without requiring manual starting/stopping. This requires installation. (see INSTRUCTIONS.txt for how to use).

Notes

This comes with a new file loader.dll. No special setup is required. Just keep loader.dll in the same folder as the 2 exe's and everything will work.

Changes

Did a massive refactoring of most of the codebase. Plugin loading logic was separated out into a separate loader dll for flexibility.

  • Faster plugin loading. Once the loader is injected, it does the work of the actual plugin loading at full speed from within the actual process.
  • Also multi-threaded plugin loading to load plugins in parallel. Before this, they loaded sequentially.
  • The loader now calls any exported Init fn so that any plugin developers can properly program their plugin.1 (P.S. as a plugin dev, your init function can take as long as you want. But you should spawn your own thread so Init can finish in a timely manner)
  • Additionally to the above, developer plugins can also detect when yabg3ml is running vs other mod loaders. This allows you to do things like not run Init code in DllMain, and instead let my mod loader call Init. Otherwise, if it's not mine, you can Init from DllMain to keep compatibility with other mod loaders. See the plugin template for how to do this.
  • Note to plugin devs / mod loader makers: If you were using an old commit of native plugin lib, please update asap. There has been dev work on it and the previous metadata macro is incompatible with this version.
  • native plugin template for plugin devs has been updated and improved. Check it out if you used a previous version.
  • More robust dirty module check, which is accurate cause it checks windows file identifier.
  • Improved process watching code.
  • Use default config values if config is malformed. This will allow it to load if entries are missing, though note if you're doing default values it may load the wrong one since you haven't configured it. Also added popup if loading config failed so it's clearer what happened.
  • Grant SE_DEBUG_NAME if running as admin just to ensure we get extra permissions. This will ensure the program succeeds if it didn't work in non-admin mode
  • General stability improvements due to the refactor and testing.
  • Various ux improvements to not crash but rather display a popup with better information
  • Updated visual style of popups to look more modern.
  • Added log level to config file to allow easily adjusting the level.
  • Added warn popup to loader.dll if it was not loaded from support application.
  • If api call in patch check failed, sleep a little bit to let process catch up before retrying again. If it's still failing after a set timeout period, it's considered an error. (Error in the sense that process injection is aborted)
  • Greatly improved all the warning messages to clearly state what's happening, and that you can press OK and the app continues normally.
  • Refactored multithreaded communication and process shutdown system
  • Added tray icon to injector as well
  • Added tooltips to tray icon to see which tool is running
  • Made our own custom win32 event loop and removed winit dependency
  • Slightly decreased binary size by using a lighter cli arg parsing library (also removed the help and version flags since I doubt they're needed anyways; --cli will still spawn a cli window as usual)
  • Fixed long-time bug with the injector where after starting it, the mouse showed a busy loading icon for a long time even though the process worked normally. This was because we didn't run the event loop on this tool - now we do
  • Lots of general misc fixes and improvements

Default config file

Your config file may be missing some optional entries. Missing entries are filled with default values. For reference, here's what a full default config file looks like

[core]
enabled = true # whether plugin loading is enabled or not
install_root = 'C:\Program Files (x86)\Steam\steamapps\common\Baldurs Gate 3'
disabled_plugins = [] # list of plugins to disable
cli = false # show console window

[log]
level = "info" # increase verbosity of logs. useful when debugging. please set to "trace" if you have a bug to report
target = false

Full Changelog: v0.2.6...v0.3.0


  1. Why? Because actually doing anything non-basic inside DllMain is a very bad idea. Deadlocks, UB (even silent UB), and a whole host of other nasty things can happen if you use DllMain for anything except simple tasks. An Init function is the proper way to do it, so now we support it! This is also reflected in some updates to the plugin template. Also, if you're a dev, the Rust signature is extern "C" fn Init(); if you use C, it is void __cdecl Init(void). See articles below.
    https://devblogs.microsoft.com/oldnewthing/20070904-00/?p=25283
    https://devblogs.microsoft.com/oldnewthing/20040128-00/?p=40853
    https://devblogs.microsoft.com/oldnewthing/20040127-00/?p=40873
    https://devblogs.microsoft.com/oldnewthing/20100115-00/?p=15253
    https://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/
    https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain?redirectedfrom=MSDN (see warning section)
    https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices