Skip to content

Commit b28c0b2

Browse files
authored
Merge pull request #133 from MilchRatchet/dev-memory-leaks
Memory leak fixes
2 parents 4a2e5eb + 95e7ac4 commit b28c0b2

20 files changed

Lines changed: 207 additions & 19 deletions

LibReplanetizer/Level Objects/Gameplay/Moby.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ public IngameMobyMemory()
741741

742742
public bool IsDead()
743743
{
744-
return (state & 0x80) > 0;
744+
return (state & 0x80) > 0 || oClass == 0xFFFF || UID == 0xFFFF;
745745
}
746746

747747
public void SetDead()

LibReplanetizer/Level.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
namespace LibReplanetizer
1919
{
20-
public class Level
20+
public class Level : IDisposable
2121
{
2222
private static readonly NLog.Logger LOGGER = NLog.LogManager.GetCurrentClassLogger();
2323

@@ -461,6 +461,15 @@ public void EmplaceCommonData()
461461
});
462462
}
463463

464+
public void Dispose()
465+
{
466+
if (textures != null) foreach (var tex in textures) tex?.Dispose();
467+
if (armorTextures != null) foreach (var list in armorTextures) { if (list != null) foreach (var tex in list) tex?.Dispose(); }
468+
if (gadgetTextures != null) foreach (var tex in gadgetTextures) tex?.Dispose();
469+
if (mobyloadTextures != null) foreach (var list in mobyloadTextures) { if (list != null) foreach (var tex in list) tex?.Dispose(); }
470+
if (missions != null) foreach (var mission in missions) { if (mission?.textures != null) foreach (var tex in mission.textures) tex?.Dispose(); }
471+
}
472+
464473
public void Save(string outputFile)
465474
{
466475
string? directory;

LibReplanetizer/Models/Texture.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
namespace LibReplanetizer
1717
{
18-
public class Texture
18+
public class Texture : IDisposable
1919
{
2020
public enum CompressionFormat : byte
2121
{
@@ -379,6 +379,12 @@ private static void ConvertRgb565ToRgb888(ushort color, out byte r, out byte g,
379379
temp = (color & 0x001F) * 255 + 16;
380380
b = (byte) ((temp / 32 + temp) / 32);
381381
}
382+
383+
public void Dispose()
384+
{
385+
renderedImage?.Dispose();
386+
img?.Dispose();
387+
}
382388
}
383389
}
384390

Replanetizer/Frames/Frame.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
// either version 3 of the License, or (at your option) any later version.
66
// Please see the LICENSE.md file for more details.
77

8+
using System;
89
using ImGuiNET;
910

1011
namespace Replanetizer.Frames
1112
{
12-
public abstract class Frame
13+
public abstract class Frame : IDisposable
1314
{
1415
protected Window wnd;
1516
protected abstract string frameName { get; set; }
@@ -44,5 +45,9 @@ public virtual void RenderAsWindow(float deltaTime)
4445
ImGui.End();
4546
}
4647
}
48+
49+
public virtual void Dispose()
50+
{
51+
}
4752
}
4853
}

Replanetizer/Frames/LevelFrame.cs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ public class LevelFrame : Frame
8585

8686
private List<Frame> subFrames;
8787

88+
private void ToolboxOnToolChanged(object? sender, EventArgs e) => InvalidateView();
89+
8890
public LevelFrame(Window wnd, string res) : base(wnd)
8991
{
9092
level = new Level(res);
@@ -102,7 +104,7 @@ public LevelFrame(Window wnd, string res) : base(wnd)
102104
selectedObjects = new Selection();
103105
selectedObjects.CollectionChanged += SelectedObjectsOnCollectionChanged;
104106

105-
toolbox.ToolChanged += (_, _) => InvalidateView();
107+
toolbox.ToolChanged += ToolboxOnToolChanged;
106108

107109
rendererPayload = new RendererPayload(camera, selectedObjects, toolbox, showBangles);
108110

@@ -524,7 +526,15 @@ public override void Render(float deltaTime)
524526

525527
private void RenderSubFrames(float deltaTime)
526528
{
529+
foreach (Frame levelSubFrame in subFrames)
530+
{
531+
if (FrameMustClose(levelSubFrame))
532+
{
533+
levelSubFrame.Dispose();
534+
}
535+
}
527536
subFrames.RemoveAll(FrameMustClose);
537+
528538
foreach (Frame levelSubFrame in subFrames)
529539
{
530540
levelSubFrame.RenderAsWindow(deltaTime);
@@ -1055,14 +1065,12 @@ public void InvalidateView()
10551065

10561066
public bool StartMemoryHook(ref string message)
10571067
{
1068+
hook?.Dispose();
10581069
hook = new MemoryHook.MemoryHookHandle(level);
10591070

10601071
message = hook.GetLastErrorMessage();
10611072

1062-
if (hook.hookWorking)
1063-
{
1064-
interactiveSession = true;
1065-
}
1073+
interactiveSession = hook.hookWorking;
10661074

10671075
return hook.hookWorking;
10681076
}
@@ -1105,6 +1113,41 @@ public void AddSubFrame(Frame frame)
11051113
{
11061114
if (!subFrames.Contains(frame)) subFrames.Add(frame);
11071115
}
1116+
1117+
public override void Dispose()
1118+
{
1119+
hook?.Dispose();
1120+
1121+
selectedObjects.CollectionChanged -= SelectedObjectsOnCollectionChanged;
1122+
toolbox.ToolChanged -= ToolboxOnToolChanged;
1123+
toolbox?.Dispose();
1124+
1125+
base.Dispose();
1126+
1127+
if (subFrames != null)
1128+
{
1129+
foreach (var subFrame in subFrames)
1130+
{
1131+
subFrame.Dispose();
1132+
}
1133+
subFrames.Clear();
1134+
}
1135+
1136+
renderer?.Dispose();
1137+
levelRenderer?.Dispose();
1138+
shaderTable?.Dispose();
1139+
1140+
if (textureIds != null)
1141+
{
1142+
foreach (var texture in textureIds.Values)
1143+
{
1144+
texture.Dispose();
1145+
}
1146+
textureIds.Clear();
1147+
}
1148+
1149+
level?.Dispose();
1150+
}
11081151
}
11091152

11101153
}

Replanetizer/Frames/ModelFrame.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,5 +916,12 @@ private void ExportSelectedModelTextures()
916916
TextureIO.ExportTexture(texture, Path.Combine(folder, $"{textureId}.png"), includeTransparency);
917917
}
918918
}
919+
920+
public override void Dispose()
921+
{
922+
base.Dispose();
923+
renderer?.Dispose();
924+
meshRenderer?.Dispose();
925+
}
919926
}
920927
}

Replanetizer/MemoryHook/MemoryHookHandle.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
namespace Replanetizer.MemoryHook
2121
{
22-
public class MemoryHookHandle
22+
public class MemoryHookHandle : IDisposable
2323
{
2424
// Read and write acceess
2525
const int PROCESS_WM_READ = 0x38;
@@ -33,6 +33,10 @@ public class MemoryHookHandle
3333

3434
[DllImport("kernel32.dll")]
3535
private static extern bool WriteProcessMemory(IntPtr hProcess, Int64 lpBaseAddress, byte[] lpBuffer, int nSize, ref int lpNumberOfBytesWritten);
36+
37+
[DllImport("kernel32.dll", SetLastError = true)]
38+
[return: MarshalAs(UnmanagedType.Bool)]
39+
private static extern bool CloseHandle(IntPtr hObject);
3640
#endif
3741

3842
private readonly Process? PROCESS;
@@ -211,5 +215,16 @@ public void HandleSplineTranslation(Level level, Spline spline, int currentSplin
211215
WriteProcessMemory(processHandle, splinePtr + currentSplineVertex * 0x10, buff, buff.Length, ref bytesRead);
212216
*/
213217
}
218+
219+
public void Dispose()
220+
{
221+
#if _WINDOWS
222+
if (PROCESS_HANDLE != IntPtr.Zero)
223+
{
224+
CloseHandle(PROCESS_HANDLE);
225+
}
226+
#endif
227+
PROCESS?.Dispose();
228+
}
214229
}
215230
}

Replanetizer/Renderer/BillboardRenderer.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static BillboardRenderer()
6363

6464
// Only a single placeholder texture currently.
6565

66-
Image<Rgba32> image = Image.Load<Rgba32>(Path.Join(iconsFolder, "Placeholder.png"));
66+
using Image<Rgba32> image = Image.Load<Rgba32>(Path.Join(iconsFolder, "Placeholder.png"));
6767
GLTexture placeholderTex = new GLTexture("BillboardTexture", image, true, true);
6868

6969
billboardTextures = new Dictionary<RenderedObjectType, GLTexture>();
@@ -146,6 +146,16 @@ public override void Render(RendererPayload payload)
146146

147147
public override void Dispose()
148148
{
149+
}
150+
151+
public static void CleanupStaticResources()
152+
{
153+
foreach (var texture in billboardTextures.Values)
154+
{
155+
texture.Dispose();
156+
}
157+
billboardTextures.Clear();
158+
149159
GL.DeleteBuffer(ibo);
150160
GL.DeleteBuffer(vbo);
151161
GL.DeleteVertexArray(vao);

Replanetizer/Renderer/DirectionalLightsBuffer.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public void Bind()
7676
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, buffer);
7777
}
7878

79-
public void Dispose() => throw new NotImplementedException();
79+
public void Dispose()
80+
{
81+
GL.DeleteBuffer(buffer);
82+
}
8083
}
8184
}

Replanetizer/Renderer/GLTexture.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static GLTexture()
4242

4343
string? applicationFolder = System.AppContext.BaseDirectory;
4444
string resourcesFolder = Path.Join(applicationFolder, "Resources");
45-
Image<L8> image = Image.Load<L8>(Path.Join(resourcesFolder, "blue_noise.png"));
45+
using Image<L8> image = Image.Load<L8>(Path.Join(resourcesFolder, "blue_noise.png"));
4646
blueNoiseTexture = new GLTexture("BlueNoiseTextrue", image);
4747
}
4848

@@ -277,5 +277,10 @@ public void Dispose()
277277
{
278278
GL.DeleteTexture(textureID);
279279
}
280+
281+
public static void CleanupStaticResources()
282+
{
283+
blueNoiseTexture?.Dispose();
284+
}
280285
}
281286
}

0 commit comments

Comments
 (0)