Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 5 additions & 42 deletions Ryo.Reloaded/CRI/CriAtomEx/CriAtomEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Ryo.Definitions.Classes;
using static Ryo.Definitions.Functions.CriAtomExFunctions;
using Ryo.Definitions.Enums;
using Ryo.Reloaded.Common;
using SharedScans.Interfaces;

namespace Ryo.Reloaded.CRI.CriAtomEx;
Expand Down Expand Up @@ -46,9 +47,7 @@ internal unsafe class CriAtomEx : ICriAtomEx
private readonly WrapperContainer<criAtomExCategory_GetVolume> getCategoryVolume;
private readonly WrapperContainer<criAtomExCategory_GetVolumeById> getVolumeById;
private readonly WrapperContainer<criAtomExCategory_SetVolume> setVolumeByIndex;
private criAtomExPlayer_SetFormat? setFormat;
private readonly object setFormatLock = new();
private int setFormatSignaturesScanned;
private readonly MultiSignature<criAtomExPlayer_SetFormat> setFormat;
private readonly WrapperContainer<criAtomExPlayer_SetSamplingRate> setSamplingRate;
private readonly WrapperContainer<criAtomExPlayer_SetNumChannels> setNumChannels;
private readonly WrapperContainer<criAtomExPlayer_SetVolume> setVolume;
Expand Down Expand Up @@ -138,44 +137,8 @@ public CriAtomEx(string game, ISharedScans scans, IReloadedHooks reloadedHooks)

scans.AddScan<criAtomExPlayer_GetNumPlayedSamples>(this.patterns.criAtomExPlayer_GetNumPlayedSamples);
this.getNumPlayedSamples = scans.CreateWrapper<criAtomExPlayer_GetNumPlayedSamples>(Mod.NAME);

foreach (var (Index, Candidate) in this.patterns.criAtomExPlayer_SetFormat.Select((x, i) => (i, x)))
{
Project.Scans.AddScanHook($"criAtomExPlayer_SetFormat[{Index}]", Candidate, (result, hooks) =>
{
lock (setFormatLock)
{
setFormatSignaturesScanned++;
if (this.setFormat == null)
{
scans.Broadcast<criAtomExPlayer_SetFormat>(result);
}
this.setFormat ??= hooks.CreateWrapper<criAtomExPlayer_SetFormat>(result, out _);
}
}, () =>
{
lock (setFormatLock)
{
setFormatSignaturesScanned++;
if (setFormatSignaturesScanned == this.patterns.criAtomExPlayer_SetFormat.Length)
{
Log.Error($"Failed to find a pattern for criAtomExPlayer_SetFormat.");
}
else
{
Log.Debug($"No matching pattern for criAtomExPlayer_SetFormat[{Index}].");
}
}
});
/*
var ListenerId = $"criAtomExPlayer_SetFormat_{Index}";
scans.AddScan(ListenerId, Candidate);
scans.CreateListener(ListenerId, x =>
{
this.setFormat[Index] = this.reloadedHooks.CreateWrapper<criAtomExPlayer_SetFormat>(x, out _);
});
*/
}

this.setFormat = new(scans, this.patterns.criAtomExPlayer_SetFormat);

scans.AddScan<criAtomExPlayer_SetSamplingRate>(this.patterns.criAtomExPlayer_SetSamplingRate);
this.setSamplingRate = scans.CreateWrapper<criAtomExPlayer_SetSamplingRate>(Mod.NAME);
Expand Down Expand Up @@ -267,7 +230,7 @@ public nint Acb_LoadAcbData(nint acbData, int acbDataSize, nint awbBinder, nint

public void Player_SetFile(nint playerHn, nint criBinderHn, byte* path) => this.setFile.Wrapper(playerHn, criBinderHn, path);

public void Player_SetFormat(nint playerHn, CriAtomFormat format) => this.setFormat!(playerHn, format);
public void Player_SetFormat(nint playerHn, CriAtomFormat format) => this.setFormat.Function.Wrapper(playerHn, format);

public void Player_SetNumChannels(nint playerHn, int numChannels) => this.setNumChannels.Wrapper(playerHn, numChannels);

Expand Down
56 changes: 56 additions & 0 deletions Ryo.Reloaded/Common/MultiSignature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using SharedScans.Interfaces;

namespace Ryo.Reloaded.Common;

public class MultiSignature<TFunction>
{
public readonly WrapperContainer<TFunction> Function;
// public TFunction? Wrapper;
private readonly object Lock = new();
private string[] Signatures;
private int ScansCompleted;

// Add support for multiple signature candidates to allow support for multiple game versions instead of *just* the
// latest version. The selected function will be the first candidate to successfully match their signature to
// some offset in the executable.
// Note that if you are using both hardcoded signatures and Scan INI, the mod may complain that it can't find a
// signature from the hardcoded list but does from Scan INI.
public MultiSignature(ISharedScans scans, string[] Signatures)
{
this.Signatures = Signatures;
// Check for a single pattern defined inside a Scan INI
scans.AddScan(typeof(TFunction).Name, null);
Function = scans.CreateWrapper<TFunction>(Mod.NAME);

// Check for multiple signature candidates defined in code
foreach (var (Index, Candidate) in this.Signatures.Select((x, i) => (i, x)))
{
Project.Scans.AddScanHook($"{typeof(TFunction).Name}[{Index}]", Candidate, (result, hooks) =>
{
lock (Lock)
{
ScansCompleted++;
if (Function.Wrapper == null)
{
scans.Broadcast<TFunction>(result);
}
Function.Wrapper ??= hooks.CreateWrapper<TFunction>(result, out _);
}
}, () =>
{
lock (Lock)
{
ScansCompleted++;
if (Function.Wrapper == null && ScansCompleted == this.Signatures.Length)
{
Log.Error($"Failed to find a pattern for {typeof(TFunction).Name}.");
}
else
{
Log.Debug($"No matching pattern for {typeof(TFunction).Name}[{Index}].");
}
}
});
}
}
}
2 changes: 1 addition & 1 deletion Ryo.Reloaded/ModConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"ModId": "Ryo.Reloaded",
"ModName": "Ryo Framework",
"ModAuthor": "RyoTune",
"ModVersion": "2.11.4",
"ModVersion": "2.11.5",
"ModDescription": "Ryo Framework adds the ability to add or replace game audio and movies with zero file editing.",
"ModDll": "Ryo.Reloaded.dll",
"ModIcon": "Preview.png",
Expand Down
Loading