Skip to content

Commit f4cdd09

Browse files
committed
fix monothreadinfo bug and sj + relax typeload
Fixes #20 Fixes #15
1 parent 3acd616 commit f4cdd09

File tree

9 files changed

+63
-16
lines changed

9 files changed

+63
-16
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
bin
22
obj
33
/statics
4-
/nuget
54
/emsdk
65

76
/FNA

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
STATICS_RELEASE=87d20f43-0820-47e0-8cf1-b4e0cd1a50aa
1+
STATICS_RELEASE=cfcd2c33-e3c3-4d49-a05f-c6d6ec247eb4
22
DOTNETFLAGS=--nodereuse:false -v n
33

44
statics:
@@ -36,7 +36,7 @@ emsdk:
3636
rm -rvf emsdk/upstream/emscripten/cache/*
3737

3838
dotnetclean:
39-
rm -rvf {loader,patcher,corefier,Steamworks}/{bin,obj} frontend/public/_framework nuget || true
39+
rm -rvf {loader,patcher,corefier,Steamworks}/{bin,obj} frontend/public/_framework || true
4040
clean: dotnetclean
4141
rm -rvf statics MonoMod NLua FNA SteamKit2.WASM emsdk || true
4242

frontend/src/game/dotnet.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,20 @@ export const gameState: Stateful<{
1111
initting: boolean;
1212
playing: boolean;
1313
hasEverest: boolean;
14+
memory: number;
1415
}> = $state({
1516
ready: false,
1617
initting: false,
1718
playing: false,
1819
hasEverest: false,
20+
memory: -1,
1921
});
22+
(globalThis as any).gameState = gameState;
2023
export const loglisteners: ((log: Log) => void)[] = [];
2124

25+
let logs: string[] = [];
26+
(globalThis as any).logs = logs;
27+
2228
function proxyConsole(name: string, color: string) {
2329
// @ts-expect-error ts sucks
2430
const old = console[name].bind(console);
@@ -34,6 +40,7 @@ function proxyConsole(name: string, color: string) {
3440
for (const logger of loglisteners) {
3541
logger({ color, log: str });
3642
}
43+
logs.push(str);
3744
};
3845
return old;
3946
}
@@ -42,6 +49,7 @@ export const bypassWarn = proxyConsole("warn", "var(--warning)");
4249
export const bypassLog = proxyConsole("log", "var(--fg)");
4350
export const bypassInfo = proxyConsole("info", "var(--info)");
4451
export const bypassDebug = proxyConsole("debug", "var(--fg4)");
52+
(globalThis as any).bypassLog = bypassLog;
4553

4654
function hookfmod() {
4755
let contexts: AudioContext[] = [];
@@ -200,6 +208,7 @@ export async function preInit() {
200208
console.debug("initializing dotnet");
201209
const runtime = await dotnet
202210
.withConfig({
211+
pthreadPoolInitialSize: 16
203212
})
204213
.withRuntimeOptions([
205214
// jit functions quickly and jit more functions
@@ -391,14 +400,25 @@ export async function UploadSteamCloud() {
391400

392401
const SEAMLESSCOUNT = 5;
393402

403+
function monitorMem(): () => void {
404+
let stop = false;
405+
exports.CelesteLoader.WatchMemoryUsage((mem: number) => {
406+
gameState.memory = mem;
407+
return stop;
408+
})
409+
return () => stop = true;
410+
}
411+
394412
export async function play() {
395413
gameState.playing = true;
396414
gameState.initting = true;
397415

416+
let stopMonitoring = monitorMem();
417+
398418
console.debug("Init...");
399419
const before = performance.now();
400420

401-
await exports.CelesteLoader.Init();
421+
await exports.CelesteLoader.Init(false);
402422

403423
// run some frames for seamless transition
404424
for (let i = 0; i < SEAMLESSCOUNT; i++) {
@@ -413,8 +433,9 @@ export async function play() {
413433

414434
await exports.CelesteLoader.MainLoop();
415435

416-
console.debug("Cleanup...");
436+
stopMonitoring();
417437

438+
console.debug("Cleanup...");
418439
await exports.CelesteLoader.Cleanup();
419440
gameState.ready = false;
420441
gameState.playing = false;

frontend/src/splash.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ const Copy: Component<
388388
try {
389389
let orig = await directory.getDirectoryHandle("orig", { create: false });
390390
celesteExe = await orig.getFileHandle("Celeste.exe", { create: false });
391+
console.debug("found everest install");
391392
} catch {
392393
celesteExe = await directory.getFileHandle("Celeste.exe", {
393394
create: false,
@@ -447,6 +448,7 @@ const Copy: Component<
447448
(e) => e.name === "Celeste.exe"
448449
) as FileSystemFileEntry;
449450
});
451+
console.debug("found everest install");
450452
} catch {
451453
celesteExe = entries.find(
452454
(e) => e.name === "Celeste.exe"

loader/Celeste.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ internal static Task PreInit()
5252
static FieldInfo RunApplication;
5353

5454
[JSExport]
55-
internal static Task Init()
55+
internal static Task Init(bool tailcalls)
5656
{
5757
try
5858
{
@@ -69,7 +69,7 @@ internal static Task Init()
6969

7070
celeste = Assembly.LoadFrom("/libsdl/CustomCeleste.dll");
7171

72-
MonoMod.Core.Platforms.WasmDetourFactory.EnableTailCallDetours = true;
72+
MonoMod.Core.Platforms.WasmDetourFactory.EnableTailCallDetours = tailcalls;
7373

7474
AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, name) =>
7575
{
@@ -115,7 +115,7 @@ internal static Task Init()
115115
ParseArgs.Invoke(null, [new string[] { }]);
116116
}
117117

118-
Console.WriteLine($"CelesteWasm on {RuntimeInformation.FrameworkDescription}");
118+
Console.WriteLine($"CelesteWasm on {RuntimeInformation.FrameworkDescription}");
119119
game = (Game)GameConstructor.Invoke([]);
120120
RunApplication = Celeste.GetField("RunApplication", BindingFlags.NonPublic | BindingFlags.Instance);
121121
}
@@ -175,6 +175,20 @@ internal static Task MainLoop()
175175
Console.Error.WriteLine(e);
176176
return Task.FromException(e);
177177
}
178-
return Task.Delay(0);
178+
return Task.Delay(0);
179+
}
180+
181+
[JSExport]
182+
internal static Task WatchMemoryUsage([JSMarshalAs<JSType.Function<JSType.Number, JSType.Boolean>>] Func<double, bool> callback)
183+
{
184+
return Task.Run(async () =>
185+
{
186+
while (true)
187+
{
188+
bool stop = callback((double)GC.GetTotalMemory(false) / (1024 * 1024));
189+
if (stop) break;
190+
await Task.Delay(1000 * 30);
191+
}
192+
});
179193
}
180194
}

loader/CelesteLoader.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
</Target>
5959

6060
<ItemGroup>
61-
<WasmOptConfigurationFlags Include="-O4 -O4 -O4"></WasmOptConfigurationFlags>
61+
<WasmOptConfigurationFlags Include="-O4 -O4 -O4 -g"></WasmOptConfigurationFlags>
6262
</ItemGroup>
6363

6464
<ItemGroup>

loader/Emscripten.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ uint32_t SDL__GetWindowFlags(void *window) {
3737
}
3838

3939
void wasm_func_viil(int x, int y, uint64_t l) {}
40+
41+
void mono_threads_request_thread_dump (void);
42+
EMSCRIPTEN_KEEPALIVE void perform_thread_dump() {
43+
mono_threads_request_thread_dump();
44+
}

patcher/FMOD.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,7 @@ static partial class MonoModRules
181181
public static void PatchFMODVersion(ILContext context, CustomAttribute attrib)
182182
{
183183
ILCursor cursor = new(context);
184-
cursor.GotoNext(i => i.MatchLdcI4(out var num) && num == 69652);
185-
186-
if (!context.Instrs[cursor.Index].MatchLdcI4(out var _))
184+
if (!cursor.TryGotoNext(i => i.MatchLdcI4(out var num) && num == 69652))
187185
throw new Exception("[FMODPatcher] Unable to find FMOD version in FMOD.Studio.System.create");
188186

189187
context.Instrs[cursor.Index].Operand = (int)0x00020307;

patcher/MonoModRules.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ static MonoModRules()
2525
Console.WriteLine($"[Celeste.Wasm] Loaded into module {MonoModRule.Modder.Module}");
2626
MonoModRule.Modder.Log($"[Celeste.Wasm] Loaded into module {MonoModRule.Modder.Module}");
2727
MonoModRule.Modder.PostProcessors += FMODPostProcessor;
28+
MonoModRule.Modder.PostProcessors += GCPostProcessor;
2829

2930
HackRelinkType("System.Net.Sockets.Socket", typeof(Celeste.Wasm.WasmSocket));
3031
HackRelinkType("System.Net.Sockets.NetworkStream", typeof(Celeste.Wasm.WasmNetworkStream));
3132
}
3233

3334
// hacky relink without copying the type
34-
public static void HackRelinkType(string source, Type dest)
35+
internal static void HackRelinkType(string source, Type dest)
3536
{
3637
MonoModRule.RelinkType(source, dest.FullName);
3738
foreach (var member in dest.GetMembers())
@@ -40,13 +41,13 @@ public static void HackRelinkType(string source, Type dest)
4041
}
4142
}
4243

43-
public static void FMODPostProcessor(MonoModder modder)
44+
internal static void FMODPostProcessor(MonoModder modder)
4445
{
4546
foreach (TypeDefinition type in modder.Module.Types)
4647
foreach (MethodDefinition method in type.Methods)
4748
FMODPostProcessMethod(modder, method);
4849
}
49-
public static void FMODPostProcessMethod(MonoModder modder, MethodDefinition method)
50+
internal static void FMODPostProcessMethod(MonoModder modder, MethodDefinition method)
5051
{
5152
if (!method.HasBody && method.HasPInvokeInfo && method.PInvokeInfo.Module.Name.StartsWith("fmod"))
5253
{
@@ -57,5 +58,12 @@ public static void FMODPostProcessMethod(MonoModder modder, MethodDefinition met
5758
}
5859
}
5960
}
61+
62+
internal static void GCPostProcessor(MonoModder modder)
63+
{
64+
GC.Collect();
65+
Console.WriteLine("[Celeste.Wasm] Forced GC after patch");
66+
MonoModRule.Modder.Log($"[Celeste.Wasm] Forced GC after patch");
67+
}
6068
}
6169
}

0 commit comments

Comments
 (0)