-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
461 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<mxfile host="app.diagrams.net" modified="2022-10-22T07:33:29.789Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" etag="n-qEOJJ9jjRaBc-dsnah" version="20.5.0" type="device"><diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">5Vpbd9o4EP41nE0e4PiCjXkMJE3Tpt12YXPpS4+wZVsbYVFZ5pJfvyNbBgsMIWFD9qR5INZoNJJG33wzFjTs/nh+ydEk/sICTBuWEcwb9nnDsjrdDnxKwaIQ2I5ZCCJOgkJUEQzII1ZCQ0kzEuBUUxSMUUEmutBnSYJ9ockQ52ymq4WM6rNOUIQ3BAMf0U3pLQlEXEg9q7OSf8QkisuZTbdb9IxRqax2ksYoYLOKyL5o2H3OmCiexvM+ptJ3pV9urxa39PrBvfz0Pf2F/u59Hn69aRbGPjxnyHILHCfixaa7IzL/7HQFukGzH/eDx/PR159Ny1V7E4vSYTgA/6km4yJmEUsQvVhJe5xlSYClWQNaK51rxiYgNEH4DxZiocCAMsFAFIsxVb14TsSdHN5yVOu+0nM+V5bzxqJsJIIvKoNk877atxqWt8pxqeDsAfcZZRwkAQ5RRsGJvQClcb4HOe2eDlYHkbKM+8pbZ3fz7s2w/dP98+OnH9mUGndz2rQUzhGPsNihpzAoPV4Bqzq+S8zGGHYCChxTJMhURzRSgREt9ZZDvzEC+7AMFcNux2gZlT+1vEUZqLLX9tqu6eSfuvlis8piFV5rk3TKMCl5wjV0Q4U3NgydcY4WFbWJVEirGvBQ8cZKlOP7GVh3lLuniGbKlX2OkQB2soyzfPzJB8JTcVobE9doBMyo4RhREiXw7ANsMMCrN8VcEOCeM9UxJkFQhAxOySMa5fYkKtUuwbjTazjnIAlZIlTAdGsRuTN+5cR4XkeoalKNszRwqVFGy7TNjnaECicHoq+pw61p6wZYGKZYHHjetdHlbhz3xrlGQGWTZ3pwX57Y6mnb1CPFLCNltspPS1lczU22u935mvee6yqjxlUuGgOb93Ky1Fs+RWm6FEWaQtnKFUccnnRJKfjGWcTReLsm7GO0LpMxoh2g+ytjZUczzaPnDBS6k3kxSnWXdv7ClCHIXH/IiM/ThDxNCdfWzoUU85biNQzp2XAWE4EHE5TnhxlUVDpjhITSMhc1LDtwsBe0N7IU9HjWyHbd5Xw16KyicDv+N1H4FMqc1wKZdXSQDWcYPYzY/LgoG8Z4HV4NSR2FdVKqFbnn5LSyFLJaChS6sFhjrx28K3gqUvTc/TjRMV4JrfZ7L4xra899z22PItjYswi2Dqx5DzrlzZJwFyepcsFgoawOJEHhQynqqs+SkEQZh82y5CQ9PS5X9VAqyYrI+jWUrFASD8p95+eLy7NlK4IcaVAWLcVvlTMR9kK/jpRc38OjcF9SekHl1l17xWnXFG7dY5KU9+bwHZAkoliwZID5lPj46AhW86atFUg3Uu2XLCW+UtyZboGpBGxIuidLBRvLayA5VvIYR/4DuKtfm8tz7UuM+AtniWAo/AuQQL9fWFldR48rp71fXHmvFVfd9578a26/dlYCR7kO8w6sBJ64T6q/nrC3kPq2e64n9OGhWMF/epVhmhtEv3F1NcCQloP/z93VCy9UtsfjVv5oGi3T8HQOKUF34OXV2lWppY9/vburcqa3LUwhE1CK+dFzeoHo5T4MESNpLyAc0EPlyY9ZQEL5EKGxLFpHOEZTAkRUKQOuooRxPMz4KKM48fFqQwUUZUNaJ9JpE4oWRQdK8m5KSYDzHAQpCJawNPP75WfHfGHd+2r52Xz3b+dagq7l17fP1+abvrqb7adz4jAm/J2mxCIEdnydY3hr2as8/0O/z/FqrR6SE6G5+hq9UF/9FsG++Bc=</diagram></mxfile> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Heap | ||
|
||
!!! info | ||
|
||
Explains how Sonic Riders' vanilla memory allocation system works. | ||
|
||
|
||
|
||
## Changes in Tweakbox | ||
|
||
!!! todo | ||
|
||
To be added. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Book of the Tweakbox | ||
|
||
Welcome to the Book of the Tweakbox (BOTT) for Riders Tweakbox. This page contains a collection of articles about the internals of both Riders Tweakbox itself, as well as Sonic Riders. The intended audience of this book is people wishing to work on Tweakbox, or wishing to understand Tweakbox and/or the base game. | ||
|
||
| Page | Description | | ||
| ------------------------------------------- | ---------------------------------------------------------------- | | ||
| [Introduction](./introduction.md) | Describes the general structure/layout of Tweakbox' source code. | | ||
| [Overlay Helper APIs](./overlay-helpers.md) | Useful APIs for creating menus in Tweakbox. | | ||
| [Heap](./heap.md) | Describes how Sonic Riders' memory allocator works. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,303 @@ | ||
# Introduction | ||
|
||
!!! info | ||
|
||
Provides an introduction to Tweakbox' internal code structure, including how things are laid out. | ||
|
||
|
||
## Initialization | ||
|
||
!!! info | ||
|
||
Provides a simplified top level view of how initialization happens in Tweakbox. | ||
|
||
![](./images/basic-layout.png) | ||
|
||
### Entry Point (Program) | ||
|
||
The life of Tweakbox begins in `Program.StartEx()`, this method is responsible for the following: | ||
- Setting up 3rd party libraries (e.g. one time method calls). | ||
- Fetching Reloaded dependencies [e.g. [File Redirector](https://github.com/Reloaded-Project/reloaded.universal.redirector) to use with music]. | ||
- Adjusting anything runtime related. | ||
|
||
Program then delegates to `Tweakbox`, which sets up Tweakbox' code. | ||
|
||
### Tweakbox Entry Point (Tweakbox) | ||
|
||
The `Tweakbox` component is responsible for the following [in order]: | ||
- Sanity checks (e.g. ensure files don't use vanilla compression). | ||
- Setting up UI Menus. | ||
- Initialising all `IConfiguration`(s), `ISingletonService`(s) & `IController`(s) in this specific order. | ||
|
||
## Components | ||
|
||
!!! info | ||
|
||
Defines the common kinds/types of items you'll find in Tweakbox' source code. | ||
|
||
!!! note | ||
|
||
Unless stated otherwise, assume components are singletons, i.e. there is only ONE instance of each configuration in memory and it's reused everywhere. | ||
|
||
### Configs (IConfiguration) | ||
|
||
!!! info | ||
|
||
Stores an individual configuration for a component or a set of Tweakbox components. | ||
|
||
Within Tweakbox' source, you will find two types of configurations, `Binary` and `JSON`. | ||
|
||
`JSON` configurations are used when all of the data is known, and inherit from `JsonConfigBase` which provides all of the backbone code for the configuration(s). | ||
|
||
Example: | ||
```csharp | ||
// JsonConfigBase inherits from IConfiguration and provides all needed boilerplate code. | ||
public class TextureInjectionConfig : JsonConfigBase<TextureInjectionConfig, TextureInjectionConfig.Internal> | ||
{ | ||
public class Internal | ||
{ | ||
public bool DumpTextures = false; | ||
public DumpingMode DumpingMode = DumpingMode.All; | ||
public int DeduplicationMaxFiles = 2; | ||
} | ||
|
||
public enum DumpingMode | ||
{ | ||
All = 0, | ||
OnlyNew = 1, | ||
Deduplicate = 2, | ||
} | ||
} | ||
``` | ||
|
||
`Binary` configurations are typically used when the data: | ||
- Needs to be small. | ||
- Contains unknown values (e.g. Not fully reversed Sonic Riders' game structs). | ||
|
||
Example `Binary` configuration: | ||
```csharp | ||
public unsafe class GearEditorConfig : IConfiguration | ||
{ | ||
private static GearEditorConfig _default = new GearEditorConfig(); | ||
|
||
/// <summary> | ||
/// Extreme gears assigned to this config. | ||
/// </summary> | ||
public ExtremeGear[] Gears; | ||
|
||
/// <summary> | ||
/// Creates the default editor config. | ||
/// </summary> | ||
public GearEditorConfig() | ||
{ | ||
Gears = new ExtremeGear[Player.OriginalNumberOfGears]; | ||
Player.Gears.CopyTo(Gears, Gears.Length); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="GearEditorConfig"/> from the values present in game memory. | ||
/// </summary> | ||
public static GearEditorConfig FromGame() => new GearEditorConfig(); | ||
|
||
/// <summary> | ||
/// Updates the game information with the gear data stored in the class. | ||
/// </summary> | ||
public unsafe void Apply() => Player.Gears.CopyFrom(Gears, Player.OriginalNumberOfGears); | ||
|
||
/// <inheritdoc /> | ||
public Action ConfigUpdated { get; set; } | ||
public byte[] ToBytes() => LZ4.CompressLZ4Stream(StructArray.GetBytes(Gears), LZ4Level.L12_MAX); | ||
|
||
public void FromBytes(Span<byte> bytes) | ||
{ | ||
var outputArray = new byte[StructArray.GetSize<ExtremeGear>(Player.OriginalNumberOfGears)]; | ||
var decompressed = LZ4.DecompressLZ4Stream(outputArray, bytes, out int bytesRead); | ||
|
||
StructArray.FromArray(decompressed, out Gears, true, Player.OriginalNumberOfGears); | ||
ConfigUpdated?.Invoke(); | ||
} | ||
|
||
public IConfiguration GetCurrent() => FromGame(); | ||
public IConfiguration GetDefault() => _default; | ||
} | ||
``` | ||
|
||
[Stores the whole array of all extreme gear data in Riders] | ||
|
||
### Services (ISingletonService) | ||
|
||
!!! info | ||
|
||
Provides various utility functions to be used throughout Tweakbox. | ||
Also a singleton. | ||
|
||
Example API(s): | ||
|
||
```csharp | ||
/// <summary> | ||
/// Keeps track of all music tracks provided by other mods (as well as the vanilla game) | ||
/// </summary> | ||
public class MusicService | ||
{ | ||
/// <summary> | ||
/// Gets the name of a random alternative track for a given file name. | ||
/// </summary> | ||
/// <param name="fileName">The file name for which to get a replacement track.</param> | ||
/// <param name="includeVanilla">Whether to include vanilla tracks or not.</param> | ||
/// <param name="includePerStageTracks">Whether to include stage-specific tracks.</param> | ||
/// <returns>Path to the replacement track.</returns> | ||
public unsafe string GetRandomTrack(string fileName, bool includeVanilla, bool includePerStageTracks); | ||
|
||
/// <summary> | ||
/// Obtains all potential candidate tracks for a given stage. | ||
/// </summary> | ||
/// <param name="stageId">The stage index.</param> | ||
/// <param name="files">List of files to add the candidates to.</param> | ||
public void GetTracksForStage(int stageId, List<string> files); | ||
} | ||
``` | ||
|
||
```csharp | ||
/// <summary> | ||
/// Converts Sonic Riders' PVRT texture format to DDS using the game's built-in converter. | ||
/// </summary> | ||
public class PvrtConverterService : ISingletonService | ||
{ | ||
/// <summary> | ||
/// Converts a texture to DDS. | ||
/// </summary> | ||
/// <param name="pvrtData">The PVRT texture to convert.</param> | ||
/// <returns>DDS data generated from PVRT.</returns> | ||
public unsafe byte[] Convert(Span<byte> pvrtData); | ||
} | ||
``` | ||
|
||
### Controllers (IController) | ||
|
||
!!! info | ||
|
||
Controllers contain all the functionality that modifies directly how the game itself functions. | ||
These controllers usually 'hook' into the game code, by either replacing the method or injecting some assembly code. | ||
|
||
Random Example(s): | ||
|
||
| Controller | Description | | ||
| ---------------------------- | ----------------------------------------------------------------------------- | | ||
| MusicInjectionController | Replaces the music track(s) that will be loaded by the game. | | ||
| IgnoreTurbulenceController | The 'C toggle' for ignoring turbulence if desired. | | ||
| BorderlessWindowedController | Toggles the game's Borderless Windowed state during startup and in real time. | | ||
| RailController | Controls the speed of the Rails. | | ||
| AutoSectionController | Automates Left+Right inputs during automated sections. | | ||
|
||
Within controllers there exists one special case, `EventController`. This controller is implemented mainly in x86 assembly, split over multiple files and provides callbacks which you can subscribe to that modify various game behaviours. | ||
|
||
For example: | ||
```csharp | ||
EventController.SetRingsOnHit += SetRingsOnHit; | ||
private void SetRingsOnHit(Player* player) => player->Rings = 42; | ||
``` | ||
|
||
### Menus (IComponent) | ||
|
||
!!! info | ||
|
||
Menus use the `IComponent` interface and are created + registered during Tweakbox startup. | ||
|
||
Random Example(s): | ||
|
||
| Controller | Description | | ||
| ---------------- | ------------------------------------------- | | ||
| AboutMenu | Renders the about page. | | ||
| TweakboxSettings | Renders the Tweakbox general settings menu. | | ||
| SlipstreamDebug | Shows slipstream data in real time. | | ||
|
||
#### Creating Menus | ||
|
||
In practice, all menus inherit from `ComponentBase` or `ComponentBase<TConfig>`, which provide a default implementation of `IComponent`. | ||
|
||
Sample dummy menu (via `ComponentBase`): | ||
```csharp | ||
// Renders | ||
public class DummyMenu : ComponentBase | ||
{ | ||
public override string Name { get; set; } = "Dummy Menu"; | ||
public override void Render() | ||
{ | ||
if (ImGui.Begin(Name, ref IsEnabled(), 0)) | ||
{ | ||
// Code to render menu here | ||
} | ||
|
||
ImGui.End(); | ||
} | ||
} | ||
``` | ||
|
||
If you need to have a config for this menu, use `ComponentBase<TConfig>`. | ||
|
||
```csharp | ||
// InfoEditorConfig is an IConfiguration | ||
public class InfoEditor : ComponentBase<InfoEditorConfig>, IComponent | ||
{ | ||
public override string Name { get; set; } = "Info Editor"; | ||
|
||
// Note the constructor, it passes some stuff to base class. | ||
public InfoEditor(IO io) : base(io, io.InfoConfigFolder, io.GetInfoConfigFiles, ".json") { } | ||
|
||
public override void Render() | ||
{ | ||
if (ImGui.Begin(Name, ref IsEnabled(), 0)) | ||
{ | ||
// Provides the New/Delete/Load/Save part of the menu. | ||
ProfileSelector.Render(); | ||
|
||
// Code to render menu here | ||
} | ||
|
||
ImGui.End(); | ||
} | ||
} | ||
``` | ||
|
||
#### Registering Menus | ||
|
||
!!! info | ||
|
||
Custom Menus must be registered in `Tweakbox.cs` to show in the overlay. | ||
|
||
Example: | ||
```csharp | ||
new MenuBarItem("Main", new List<IComponent>() | ||
{ | ||
// Your custom menu here. | ||
Benchmark(() => IoC.GetSingleton<DummyMenu>(), nameof(DummyMenu)), | ||
|
||
// Previously existing menus. | ||
Benchmark(() => IoC.GetSingleton<NetplayMenu>(), nameof(NetplayMenu)), | ||
Benchmark(() => IoC.GetSingleton<UserGuideWindow>(), nameof(UserGuideWindow)), | ||
Benchmark(() => IoC.GetSingleton<AboutMenu>(), nameof(AboutMenu)), | ||
Benchmark(() => IoC.GetSingleton<OpenSourceLibraries>(), nameof(OpenSourceLibraries)), | ||
}) | ||
``` | ||
|
||
## Projects | ||
|
||
!!! info | ||
|
||
Provides a listing of projects within the Tweakbox source code. | ||
|
||
| Project | Description | | ||
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| Riders.Netplay.Messages | Contains all code responsible for writing/reading individual messages over the network. | | ||
| Riders.Netplay.Messages.Tests | Test code for messages library; can be barebones at times. | | ||
| Riders.Tweakbox.API.SDK | Code for communicating with the [Web Server providing server browser, ranking](https://github.com/Sewer56/Riders.Tweakbox.API). | | ||
| Riders.Tweakbox | Main mod code. | | ||
| Riders.Tweakbox.CharacterPack.DX | Test/example mod for adding custom character behaviours. [Ports SRDX 1.0.1 char stats to Tweakbox] | | ||
| Riders.Tweakbox.Gearpack | Test/example mod for adding custom gear behaviours. [Ports all gears from all mods released before late 2021] | | ||
| Riders.Tweakbox.Interfaces | API for other mods to use. [Recommend Reading: Dependency Injection in Reloaded-II](https://reloaded-project.github.io/Reloaded-II/DependencyInjection_HowItWork/) | | ||
| Sewer56.Hooks.Utilities | Helper code for manipulating game functions with x86 assembly. | | ||
| Sewer56.Imgui | Helpers for creating menus. (Extensions for our *Dear ImGui* wrapper.) | | ||
| Sewer56.SonicRiders | API and definitions for hacking Sonic Riders | | ||
|
||
[Some projects have been omitted to keep the list simpler.] |
Oops, something went wrong.