Skip to content

Commit

Permalink
Update to support Wii 1.0, improve accuracy of heap visualizations
Browse files Browse the repository at this point in the history
  • Loading branch information
Zachary Canann committed Nov 12, 2022
1 parent 78e3d30 commit a4dd03a
Show file tree
Hide file tree
Showing 11 changed files with 431 additions and 226 deletions.
30 changes: 23 additions & 7 deletions Twilight.Engine.Memory/Windows/WindowsMemoryQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,6 @@ public IEnumerable<NormalizedRegion> GetEmulatorVirtualPages(Process process, Em
{
case EmulatorType.Dolphin:
IEnumerable<NormalizedRegion> mappedRegions = this.GetVirtualPages(process, 0, 0, MemoryTypeEnum.Mapped, 0, this.GetMaximumAddress(process));
IEnumerable<NormalizedRegion> privateRegions = this.GetVirtualPages(process, 0, 0, MemoryTypeEnum.Private, 0, this.GetMaximumAddress(process));

foreach (NormalizedRegion region in mappedRegions)
{
Expand All @@ -626,7 +625,7 @@ public IEnumerable<NormalizedRegion> GetEmulatorVirtualPages(Process process, Em
{
String gameIdStr = Encoding.ASCII.GetString(gameId);

if (gameIdStr.StartsWith('G') && gameIdStr.All(character => Char.IsLetterOrDigit(character)))
if ((gameIdStr.StartsWith('G') || gameIdStr.StartsWith('R')) && gameIdStr.All(character => Char.IsLetterOrDigit(character)))
{
// Oddly Dolphin seems to map multiple main memory regions into RAM. These are identical.
// Changing values in one will change the other. This means that we can just take the first one we find.
Expand All @@ -637,25 +636,42 @@ public IEnumerable<NormalizedRegion> GetEmulatorVirtualPages(Process process, Em
}
}

// Disabled for now: Fetching Wii extended memory. We should find a consistent signature for this.
/*
foreach (NormalizedRegion region in privateRegions)
bool mem2Found = false;
foreach (NormalizedRegion region in mappedRegions)
{
// Dolphin stores wii memory in a memory mapped region of this exact size.
if (region.RegionSize == 0x4000000 && IsRegionBackedByPhysicalMemory(processHandle, region))
{
regions.Add(region);
mem2Found = true;
break;
}
}*/
}

// Try private regions if mapped didn't contain mem2
if (!mem2Found)
{
IEnumerable<NormalizedRegion> privateRegions = this.GetVirtualPages(process, 0, 0, MemoryTypeEnum.Private, 0, this.GetMaximumAddress(process));

foreach (NormalizedRegion region in privateRegions)
{
// Dolphin stores wii memory in a memory mapped region of this exact size.
if (region.RegionSize == 0x4000000 && IsRegionBackedByPhysicalMemory(processHandle, region))
{
regions.Add(region);
mem2Found = true;
break;
}
}
}
break;
default:
break;
}

if (regions.Count > 0)
{
this.DolphinRegionCache.Add(regions);
this.DolphinRegionCache.Add(regions);
}

return regions;
Expand Down
12 changes: 12 additions & 0 deletions Twilight/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Twilight/Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@
<Setting Name="ShowHeap7" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="IsWii" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Twilight.Source.Main;

namespace Twilight.Source.ActorReferenceCountVisualizer
{
public class ActorReferenceCountTableConstants
{
public static readonly UInt32 ActorReferenceTableBase = 0x804224B8;
public static readonly UInt32 ActorReferenceTableBaseGc = 0x804224B8;
public static readonly UInt32 ActorReferenceTableBaseWii_1_0 = 0x804AEC34;
public static readonly UInt32 ActorReferenceTableBaseWii_1_2 = 0x8049623C;
public static readonly Int32 ActorReferenceCountTableMaxEntries = 128;
public static readonly Int32 ActorSlotStructSize = typeof(ActorReferenceCountTableSlot).StructLayoutAttribute.Size;

public static UInt32 GetActorReferenceTableSize()
{
return MainViewModel.GetInstance().IsWii ? ActorReferenceTableBaseWii_1_0 : ActorReferenceTableBaseGc;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public String Name
this.RaisePropertyChanged(nameof(this.Name));
MemoryWriter.Instance.WriteBytes(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
data
);
}
Expand All @@ -65,7 +65,7 @@ public UInt16 ReferenceCount
this.RaisePropertyChanged(nameof(this.ReferenceCount));
MemoryWriter.Instance.Write<UInt16>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0xC + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0xC + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand Down Expand Up @@ -104,7 +104,7 @@ public UInt32 MDMCommandPtr
this.RaisePropertyChanged(nameof(this.MDMCommandPtr));
MemoryWriter.Instance.Write<UInt32>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0x10 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0x10 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand All @@ -126,7 +126,7 @@ public UInt32 MArchivePtr
this.RaisePropertyChanged(nameof(this.MArchivePtr));
MemoryWriter.Instance.Write<UInt32>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0x14 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0x14 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand All @@ -148,7 +148,7 @@ public UInt32 HeapPtr
this.RaisePropertyChanged(nameof(this.HeapPtr));
MemoryWriter.Instance.Write<UInt32>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0x18 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0x18 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand All @@ -170,7 +170,7 @@ public UInt32 MDataHeapPtr
this.RaisePropertyChanged(nameof(this.MDataHeapPtr));
MemoryWriter.Instance.Write<UInt32>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0x1C + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0x1C + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand All @@ -192,7 +192,7 @@ public UInt32 MResPtrPtr
this.RaisePropertyChanged(nameof(this.MResPtrPtr));
MemoryWriter.Instance.Write<UInt32>(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase + 0x20 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize() + 0x20 + (UInt64)this.Slot.ActorSlotIndex * 0x24, EmulatorType.Dolphin),
BinaryPrimitives.ReverseEndianness(value)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private void UpdateActorSlots()
bool success = false;
byte[] actorReferenceCountTable = MemoryReader.Instance.ReadBytes(
SessionManager.Session.OpenedProcess,
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.ActorReferenceTableBase, EmulatorType.Dolphin),
MemoryQueryer.Instance.EmulatorAddressToRealAddress(SessionManager.Session.OpenedProcess, ActorReferenceCountTableConstants.GetActorReferenceTableSize(), EmulatorType.Dolphin),
ActorReferenceCountTableConstants.ActorSlotStructSize * ActorReferenceCountTableConstants.ActorReferenceCountTableMaxEntries,
out success);

Expand All @@ -149,6 +149,8 @@ private void UpdateActorSlots()
// Copy data over field by field to avoid triggering the FullyObservableCollection changes.
if (result != null)
{
this.ActorReferenceCountSlots[actorSlotIndex].Slot.ActorSlotIndex = actorSlotIndex;

// Avoid calling setters to bypass the write-back to Dolphin memory
this.ActorReferenceCountSlots[actorSlotIndex].Slot.name = Encoding.ASCII.GetBytes(result.Name);
this.ActorReferenceCountSlots[actorSlotIndex].Slot.referenceCount = result.ReferenceCount;
Expand Down
13 changes: 11 additions & 2 deletions Twilight/Source/HeapVisualizer/HeapCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ namespace Twilight.Source.HeapVisualizer
using System.Buffers.Binary;
using System.Runtime.InteropServices;


[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x28)]
public class HeapCheck
{
Expand Down Expand Up @@ -41,14 +40,24 @@ public class HeapCheck

public static HeapCheck FromByteArray(byte[] bytes)
{
// Convert Wii structure to GC. jNamePointer field is missing, so we shift all the bytes down and leave that as nullptr.
if (bytes.Length == 0x24)
{
byte[] newBytes = new byte[0x28];

Array.Copy(bytes, newBytes, 0x4);
Array.Copy(bytes, 0x4, newBytes, 0x8, 0x20);

bytes = newBytes;
}

GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
HeapCheck result = Marshal.PtrToStructure<HeapCheck>(handle.AddrOfPinnedObject());

// Fix GC endianness
result.mNamePointer = BinaryPrimitives.ReverseEndianness(result.mNamePointer);
result.jNamePointer = BinaryPrimitives.ReverseEndianness(result.jNamePointer);
result.heapPointer = BinaryPrimitives.ReverseEndianness(result.heapPointer);
result.maxTotalUsedSize = BinaryPrimitives.ReverseEndianness(result.maxTotalUsedSize);
result.maxTotalFreeSize = BinaryPrimitives.ReverseEndianness(result.maxTotalFreeSize);
Expand Down
Loading

0 comments on commit a4dd03a

Please sign in to comment.