mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-09-12 22:52:17 -06:00
Compare commits
4 Commits
Canary-1.3
...
Canary-1.3
Author | SHA1 | Date | |
---|---|---|---|
56e6339553 | |||
042362ee2b | |||
7347ee2212 | |||
01a9b636af |
@ -24338,7 +24338,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "打开 LDN 游戏列表",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24363,7 +24363,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "LDN 游戏浏览器 - {0} 个游戏",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24388,7 +24388,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "搜索到 {0} 个 LDN 游戏...",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24413,7 +24413,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "什么是 LDN",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24438,7 +24438,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "在 {0} 时从服务器刷新可用游戏",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24463,7 +24463,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "玩家计数 - 关闭",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24488,7 +24488,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "玩家计数 - 递增",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24513,12 +24513,37 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "玩家计数 - 递减",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "LdnGameListOnlyShowPublicGames",
|
||||
"ID": "LdnGameListFiltersHeading",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Filters",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "筛选",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "LdnGameListFiltersOnlyShowPublicGames",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
@ -24538,12 +24563,12 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "仅显示公开游戏",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "LdnGameListOnlyShowJoinableGames",
|
||||
"ID": "LdnGameListFiltersOnlyShowJoinableGames",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
@ -24563,7 +24588,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "仅显示可加入的游戏",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24588,7 +24613,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "主服务器代理",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24613,7 +24638,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": null,
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24638,7 +24663,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "通过 RyuLDN 服务器进行连接 (较慢)。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24663,7 +24688,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "通过 UPnP 进行点对点连接 (较快)。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24688,7 +24713,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "已创建: {0} ",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24713,7 +24738,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "玩家 ({0} 之 {1}):",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24738,7 +24763,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "可加入",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24763,7 +24788,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "如果游戏是公开的或您知道口令则它是可加入的。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24788,7 +24813,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "不可加入",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24813,7 +24838,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "游戏当前正在进行中。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24838,7 +24863,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "公开",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24863,7 +24888,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "任何人都可以加入此游戏。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24888,7 +24913,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "私密",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
@ -24913,7 +24938,7 @@
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_CN": "如果您在设置中有某些 LDN 口令则可加入此游戏。",
|
||||
"zh_TW": ""
|
||||
}
|
||||
}
|
||||
|
@ -81,16 +81,8 @@ namespace Ryujinx.Graphics.Device
|
||||
if (index < Size)
|
||||
{
|
||||
uint alignedOffset = index * RegisterSize;
|
||||
|
||||
Func<int> readCallback = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_readCallbacks), (nint)index);
|
||||
if (readCallback != null)
|
||||
{
|
||||
return readCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetRefUnchecked<int>(alignedOffset);
|
||||
}
|
||||
|
||||
return _readCallbacks[index]?.Invoke() ?? GetRefUnchecked<int>(alignedOffset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -107,7 +99,7 @@ namespace Ryujinx.Graphics.Device
|
||||
|
||||
GetRefIntAlignedUncheck(index) = data;
|
||||
|
||||
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (nint)index)?.Invoke(data);
|
||||
_writeCallbacks[index]?.Invoke(data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +116,7 @@ namespace Ryujinx.Graphics.Device
|
||||
changed = storage != data;
|
||||
storage = data;
|
||||
|
||||
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (nint)index)?.Invoke(data);
|
||||
_writeCallbacks[index]?.Invoke(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
if (index < BlockSize)
|
||||
{
|
||||
int groupIndex = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_registerToGroupMapping), (nint)index);
|
||||
int groupIndex = _registerToGroupMapping[index];
|
||||
if (groupIndex != 0)
|
||||
{
|
||||
groupIndex--;
|
||||
|
@ -120,11 +120,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
public void ExcludeModifiedRegions(ulong address, ulong size, Action<ulong, ulong> action)
|
||||
{
|
||||
// Slices a given region using the modified regions in the list. Calls the action for the new slices.
|
||||
bool lockOwner = Lock.IsReadLockHeld;
|
||||
if (!lockOwner)
|
||||
{
|
||||
Lock.EnterReadLock();
|
||||
}
|
||||
Lock.EnterReadLock();
|
||||
|
||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
|
||||
|
||||
@ -145,10 +141,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
if (!lockOwner)
|
||||
{
|
||||
Lock.ExitReadLock();
|
||||
}
|
||||
Lock.ExitReadLock();
|
||||
|
||||
if ((long)size > 0)
|
||||
{
|
||||
@ -179,9 +172,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
return;
|
||||
}
|
||||
|
||||
BufferModifiedRange buffPost = null;
|
||||
bool extendsPost = false;
|
||||
bool extendsPre = false;
|
||||
|
||||
|
||||
if (first == last)
|
||||
{
|
||||
@ -196,14 +187,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
if (first.Address < address)
|
||||
{
|
||||
first.Value.Size = address - first.Address;
|
||||
|
||||
extendsPre = true;
|
||||
Update(first);
|
||||
|
||||
if (first.EndAddress > endAddress)
|
||||
{
|
||||
buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||
first.Value.SyncNumber, first.Value.Parent);
|
||||
extendsPost = true;
|
||||
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||
first.Value.SyncNumber, first.Value.Parent));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -212,6 +201,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
first.Value.Size = first.EndAddress - endAddress;
|
||||
first.Value.Address = endAddress;
|
||||
Update(first);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,11 +209,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
}
|
||||
}
|
||||
|
||||
if (extendsPre && extendsPost)
|
||||
{
|
||||
Add(buffPost);
|
||||
}
|
||||
|
||||
Add(new BufferModifiedRange(address, size, syncNumber, this));
|
||||
Lock.ExitWriteLock();
|
||||
|
||||
@ -231,6 +216,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
}
|
||||
|
||||
BufferModifiedRange buffPre = null;
|
||||
BufferModifiedRange buffPost = null;
|
||||
bool extendsPost = false;
|
||||
bool extendsPre = false;
|
||||
|
||||
if (first.Address < address)
|
||||
{
|
||||
@ -329,7 +317,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
public bool HasRange(ulong address, ulong size)
|
||||
{
|
||||
Lock.EnterReadLock();
|
||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> _) = FindOverlaps(address, size);
|
||||
RangeItem<BufferModifiedRange> first = FindOverlapFast(address, size);
|
||||
bool result = first is not null;
|
||||
Lock.ExitReadLock();
|
||||
return result;
|
||||
@ -386,9 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
ulong clampAddress = Math.Max(address, overlap.Address);
|
||||
ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
|
||||
|
||||
Lock.EnterWriteLock();
|
||||
ClearPart(overlap, clampAddress, clampEnd);
|
||||
Lock.ExitWriteLock();
|
||||
|
||||
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
|
||||
}
|
||||
@ -418,40 +404,33 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
ulong endAddress = address + size;
|
||||
ulong currentSync = _context.SyncNumber;
|
||||
|
||||
int rangeCount = 0;
|
||||
|
||||
List<RangeItem<BufferModifiedRange>> overlaps = [];
|
||||
|
||||
// Range list must be consistent for this operation
|
||||
Lock.EnterReadLock();
|
||||
if (_migrationTarget != null)
|
||||
{
|
||||
rangeCount = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
|
||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
|
||||
|
||||
RangeItem<BufferModifiedRange> current = first;
|
||||
while (last != null && current != last.Next)
|
||||
{
|
||||
rangeCount++;
|
||||
overlaps.Add(current);
|
||||
current = current.Next;
|
||||
}
|
||||
}
|
||||
Lock.ExitReadLock();
|
||||
|
||||
if (rangeCount == -1)
|
||||
{
|
||||
_migrationTarget!.WaitForAndFlushRanges(address, size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Lock.EnterWriteLock();
|
||||
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
|
||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
|
||||
|
||||
RangeItem<BufferModifiedRange> current = first;
|
||||
while (last != null && current != last.Next)
|
||||
{
|
||||
overlaps.Add(current);
|
||||
current = current.Next;
|
||||
}
|
||||
|
||||
int rangeCount = overlaps.Count;
|
||||
|
||||
if (rangeCount == 0)
|
||||
{
|
||||
Lock.ExitWriteLock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -474,6 +453,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
|
||||
if (highestDiff == long.MinValue)
|
||||
{
|
||||
Lock.ExitWriteLock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -481,6 +462,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
_context.Renderer.WaitSync(currentSync + (ulong)highestDiff);
|
||||
|
||||
RemoveRangesAndFlush(overlaps.ToArray(), rangeCount, highestDiff, currentSync, address, endAddress);
|
||||
|
||||
Lock.ExitWriteLock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -607,22 +590,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
return;
|
||||
}
|
||||
|
||||
BufferModifiedRange buffPost = null;
|
||||
bool extendsPost = false;
|
||||
bool extendsPre = false;
|
||||
|
||||
if (first == last)
|
||||
{
|
||||
if (first.Address < address)
|
||||
{
|
||||
first.Value.Size = address - first.Address;
|
||||
extendsPre = true;
|
||||
Update(first);
|
||||
|
||||
if (first.EndAddress > endAddress)
|
||||
{
|
||||
buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||
first.Value.SyncNumber, first.Value.Parent);
|
||||
extendsPost = true;
|
||||
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||
first.Value.SyncNumber, first.Value.Parent));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -631,6 +609,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
first.Value.Size = first.EndAddress - endAddress;
|
||||
first.Value.Address = endAddress;
|
||||
Update(first);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -638,16 +617,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
}
|
||||
}
|
||||
|
||||
if (extendsPre && extendsPost)
|
||||
{
|
||||
Add(buffPost);
|
||||
}
|
||||
|
||||
Lock.ExitWriteLock();
|
||||
return;
|
||||
}
|
||||
|
||||
BufferModifiedRange buffPre = null;
|
||||
BufferModifiedRange buffPost = null;
|
||||
bool extendsPost = false;
|
||||
bool extendsPre = false;
|
||||
|
||||
if (first.Address < address)
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Tamper
|
||||
Logger.Error?.Print(LogClass.TamperMachine, ex.ToString());
|
||||
}
|
||||
|
||||
Logger.Error?.Print(LogClass.TamperMachine, "There was a problem while compiling the Atmosphere cheat");
|
||||
Logger.Error?.Print(LogClass.TamperMachine, $"There was a problem while compiling the Atmosphere cheat '{name}'");
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Tamper
|
||||
DebugLog.Emit(instruction, context);
|
||||
break;
|
||||
default:
|
||||
throw new TamperCompilationException($"Code type {codeType} not implemented in Atmosphere cheat");
|
||||
throw new TamperCompilationException($"Code type {codeType} not implemented in Atmosphere cheat compiler");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,8 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
||||
}
|
||||
|
||||
// Use the conditional begin instruction stored in the stack.
|
||||
byte[] upperInstruction = context.CurrentBlock.BaseInstruction;
|
||||
byte[] upperInstruction = context.CurrentBlock.BaseInstruction
|
||||
?? throw new TamperCompilationException($"Base instruction in current block was null; termination type '{terminationType}'");
|
||||
CodeType codeType = InstructionHelper.GetCodeType(upperInstruction);
|
||||
|
||||
// Pop the current block of operations from the stack so control instructions
|
||||
|
@ -87,6 +87,43 @@ namespace Ryujinx.Memory.Range
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an item's end address on the list. Address must be the same.
|
||||
/// </summary>
|
||||
/// <param name="item">The RangeItem to be updated</param>
|
||||
/// <returns>True if the item was located and updated, false otherwise</returns>
|
||||
protected override bool Update(RangeItem<T> item)
|
||||
{
|
||||
int index = BinarySearch(item.Address);
|
||||
|
||||
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
Items[index - 1].Next = rangeItem;
|
||||
}
|
||||
|
||||
if (index < Count - 1)
|
||||
{
|
||||
Items[index + 1].Previous = rangeItem;
|
||||
}
|
||||
|
||||
foreach (ulong addr in item.QuickAccessAddresses)
|
||||
{
|
||||
_quickAccess.Remove(addr);
|
||||
_fastQuickAccess.Remove(addr);
|
||||
}
|
||||
|
||||
Items[index] = rangeItem;
|
||||
|
||||
if (item.Address != rangeItem.Address)
|
||||
_quickAccess.Remove(item.Address);
|
||||
|
||||
_quickAccess[rangeItem.Address] = rangeItem;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Insert(int index, RangeItem<T> item)
|
||||
{
|
||||
@ -193,10 +230,9 @@ namespace Ryujinx.Memory.Range
|
||||
return;
|
||||
}
|
||||
|
||||
int startIndex = BinarySearch(startItem.Address);
|
||||
int endIndex = BinarySearch(endItem.Address);
|
||||
(int startIndex, int endIndex) = BinarySearchEdges(startItem.Address, endItem.EndAddress);
|
||||
|
||||
for (int i = startIndex; i <= endIndex; i++)
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
_quickAccess.Remove(Items[i].Address);
|
||||
foreach (ulong addr in Items[i].QuickAccessAddresses)
|
||||
@ -206,23 +242,23 @@ namespace Ryujinx.Memory.Range
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex < Count - 1)
|
||||
if (endIndex < Count)
|
||||
{
|
||||
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
|
||||
Items[endIndex].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
|
||||
}
|
||||
|
||||
if (startIndex > 0)
|
||||
{
|
||||
Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
|
||||
Items[startIndex - 1].Next = endIndex < Count ? Items[endIndex] : null;
|
||||
}
|
||||
|
||||
|
||||
if (endIndex < Count - 1)
|
||||
if (endIndex < Count)
|
||||
{
|
||||
Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
|
||||
Array.Copy(Items, endIndex, Items, startIndex, Count - endIndex);
|
||||
}
|
||||
|
||||
Count -= endIndex - startIndex + 1;
|
||||
Count -= endIndex - startIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -81,12 +81,73 @@ namespace Ryujinx.Memory.Range
|
||||
{
|
||||
if (Items[index].Value.Equals(item))
|
||||
{
|
||||
RangeItem<T> rangeItem = new(item) { Previous = Items[index].Previous, Next = Items[index].Next };
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
Items[index - 1].Next = rangeItem;
|
||||
}
|
||||
|
||||
if (index < Count - 1)
|
||||
{
|
||||
Items[index + 1].Previous = rangeItem;
|
||||
}
|
||||
|
||||
foreach (ulong address in Items[index].QuickAccessAddresses)
|
||||
{
|
||||
_quickAccess.Remove(address);
|
||||
}
|
||||
|
||||
Items[index] = new RangeItem<T>(item);
|
||||
Items[index] = rangeItem;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Items[index].Address > item.Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an item's end address on the list. Address must be the same.
|
||||
/// </summary>
|
||||
/// <param name="item">The RangeItem to be updated</param>
|
||||
/// <returns>True if the item was located and updated, false otherwise</returns>
|
||||
protected override bool Update(RangeItem<T> item)
|
||||
{
|
||||
int index = BinarySearch(item.Address);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index < Count)
|
||||
{
|
||||
if (Items[index].Equals(item))
|
||||
{
|
||||
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
Items[index - 1].Next = rangeItem;
|
||||
}
|
||||
|
||||
if (index < Count - 1)
|
||||
{
|
||||
Items[index + 1].Previous = rangeItem;
|
||||
}
|
||||
|
||||
foreach (ulong address in item.QuickAccessAddresses)
|
||||
{
|
||||
_quickAccess.Remove(address);
|
||||
}
|
||||
|
||||
Items[index] = rangeItem;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace Ryujinx.Memory.Range
|
||||
return u1 == u2;
|
||||
}
|
||||
|
||||
public int GetHashCode(ulong value) => (int)(value >> 5);
|
||||
public int GetHashCode(ulong value) => (int)(value << 5);
|
||||
|
||||
public static readonly AddressEqualityComparer Comparer = new();
|
||||
}
|
||||
@ -63,6 +63,13 @@ namespace Ryujinx.Memory.Range
|
||||
/// <returns>True if the item was located and updated, false otherwise</returns>
|
||||
protected abstract bool Update(T item);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an item's end address on the list. Address must be the same.
|
||||
/// </summary>
|
||||
/// <param name="item">The RangeItem to be updated</param>
|
||||
/// <returns>True if the item was located and updated, false otherwise</returns>
|
||||
protected abstract bool Update(RangeItem<T> item);
|
||||
|
||||
public abstract bool Remove(T item);
|
||||
|
||||
public abstract void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem);
|
||||
|
@ -182,11 +182,15 @@ namespace Ryujinx.Memory.Tracking
|
||||
{
|
||||
if (region.Guest)
|
||||
{
|
||||
_guestVirtualRegions.Lock.EnterWriteLock();
|
||||
_guestVirtualRegions.Remove(region);
|
||||
_guestVirtualRegions.Lock.ExitWriteLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
_virtualRegions.Lock.EnterWriteLock();
|
||||
_virtualRegions.Remove(region);
|
||||
_virtualRegions.Lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@
|
||||
Margin="10, 0, 148, 0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Content="Filters"
|
||||
Content="{ext:Locale LdnGameListFiltersHeading}"
|
||||
DockPanel.Dock="Right">
|
||||
<DropDownButton.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
@ -124,10 +124,10 @@
|
||||
<TextBlock Text="{ext:Locale CompatibilityListOnlyShowOwnedGames}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding OnlyShowPublicGames}">
|
||||
<TextBlock Text="{ext:Locale LdnGameListOnlyShowPublicGames}" />
|
||||
<TextBlock Text="{ext:Locale LdnGameListFiltersOnlyShowPublicGames}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding OnlyShowJoinableGames}">
|
||||
<TextBlock Text="{ext:Locale LdnGameListOnlyShowJoinableGames}" />
|
||||
<TextBlock Text="{ext:Locale LdnGameListFiltersOnlyShowJoinableGames}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
@ -213,7 +213,7 @@
|
||||
Margin="10, 5, 20, 5"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Content="Filters"
|
||||
Content="{ext:Locale LdnGameListFiltersHeading}"
|
||||
DockPanel.Dock="Right">
|
||||
<DropDownButton.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
@ -222,10 +222,10 @@
|
||||
<TextBlock Text="{ext:Locale CompatibilityListOnlyShowOwnedGames}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding OnlyShowPublicGames}">
|
||||
<TextBlock Text="{ext:Locale LdnGameListOnlyShowPublicGames}" />
|
||||
<TextBlock Text="{ext:Locale LdnGameListFiltersOnlyShowPublicGames}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding OnlyShowJoinableGames}">
|
||||
<TextBlock Text="{ext:Locale LdnGameListOnlyShowJoinableGames}" />
|
||||
<TextBlock Text="{ext:Locale LdnGameListFiltersOnlyShowJoinableGames}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
|
Reference in New Issue
Block a user