fix opcodes conflict
This commit is contained in:
commit
cc022057ec
344 changed files with 13132 additions and 13369 deletions
|
@ -28,11 +28,11 @@ namespace ChocolArm64.Decoders
|
|||
return block;
|
||||
}
|
||||
|
||||
public static (Block[] Graph, Block Root) DecodeSubroutine(
|
||||
TranslatorCache cache,
|
||||
CpuThreadState state,
|
||||
MemoryManager memory,
|
||||
long start)
|
||||
public static Block DecodeSubroutine(
|
||||
TranslatorCache cache,
|
||||
CpuThreadState state,
|
||||
MemoryManager memory,
|
||||
long start)
|
||||
{
|
||||
Dictionary<long, Block> visited = new Dictionary<long, Block>();
|
||||
Dictionary<long, Block> visitedEnd = new Dictionary<long, Block>();
|
||||
|
@ -53,7 +53,7 @@ namespace ChocolArm64.Decoders
|
|||
return output;
|
||||
}
|
||||
|
||||
Block root = Enqueue(start);
|
||||
Block entry = Enqueue(start);
|
||||
|
||||
while (blocks.Count > 0)
|
||||
{
|
||||
|
@ -118,33 +118,7 @@ namespace ChocolArm64.Decoders
|
|||
visitedEnd.Add(current.EndPosition, current);
|
||||
}
|
||||
|
||||
//Make and sort Graph blocks array by position.
|
||||
Block[] graph = new Block[visited.Count];
|
||||
|
||||
while (visited.Count > 0)
|
||||
{
|
||||
ulong firstPos = ulong.MaxValue;
|
||||
|
||||
foreach (Block block in visited.Values)
|
||||
{
|
||||
if (firstPos > (ulong)block.Position)
|
||||
firstPos = (ulong)block.Position;
|
||||
}
|
||||
|
||||
Block current = visited[(long)firstPos];
|
||||
|
||||
do
|
||||
{
|
||||
graph[graph.Length - visited.Count] = current;
|
||||
|
||||
visited.Remove(current.Position);
|
||||
|
||||
current = current.Next;
|
||||
}
|
||||
while (current != null);
|
||||
}
|
||||
|
||||
return (graph, root);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private static void FillBlock(CpuThreadState state, MemoryManager memory, Block block)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
@ -12,8 +11,8 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
public OpCodeAlu64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||
{
|
||||
Rd = (opCode >> 0) & 0x1f;
|
||||
Rn = (opCode >> 5) & 0x1f;
|
||||
Rd = (opCode >> 0) & 0x1f;
|
||||
Rn = (opCode >> 5) & 0x1f;
|
||||
DataOp = (DataOp)((opCode >> 24) & 0x3);
|
||||
|
||||
RegisterSize = (opCode >> 31) != 0
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
Shift = shift;
|
||||
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
ShiftType = (ShiftType)((opCode >> 22) & 0x3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
public OpCodeAluRx64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||
{
|
||||
Shift = (opCode >> 10) & 0x7;
|
||||
Shift = (opCode >> 10) & 0x7;
|
||||
IntType = (IntType)((opCode >> 13) & 0x7);
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
|
|
@ -21,9 +21,9 @@ namespace ChocolArm64.Decoders
|
|||
return;
|
||||
}
|
||||
|
||||
Nzcv = (opCode >> 0) & 0xf;
|
||||
Nzcv = (opCode >> 0) & 0xf;
|
||||
Cond = (Cond)((opCode >> 12) & 0xf);
|
||||
RmImm = (opCode >> 16) & 0x1f;
|
||||
RmImm = (opCode >> 16) & 0x1f;
|
||||
|
||||
Rd = CpuThreadState.ZrIndex;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
public OpCodeCsel64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||
{
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Cond = (Cond)((opCode >> 12) & 0xf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace ChocolArm64.Decoders
|
|||
if (WBack || Unscaled)
|
||||
{
|
||||
//9-bits Signed Immediate.
|
||||
Imm = (opCode << 43) >> 55;
|
||||
Imm = (opCode << 11) >> 23;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -11,10 +11,10 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
public OpCodeMemReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||
{
|
||||
Shift = ((opCode >> 12) & 0x1) != 0;
|
||||
Shift = ((opCode >> 12) & 0x1) != 0;
|
||||
IntType = (IntType)((opCode >> 13) & 0x7);
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Extend64 = ((opCode >> 22) & 0x3) == 2;
|
||||
Rm = (opCode >> 16) & 0x1f;
|
||||
Extend64 = ((opCode >> 22) & 0x3) == 2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
@ -61,12 +60,12 @@ namespace ChocolArm64.Decoders
|
|||
else if ((modeHigh & 0b110) == 0b100)
|
||||
{
|
||||
//16-bits shifted Immediate.
|
||||
Size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
Size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b100) == 0b000)
|
||||
{
|
||||
//32-bits shifted Immediate.
|
||||
Size = 2; imm <<= modeHigh << 3;
|
||||
Size = 2; imm <<= modeHigh << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b111) == 0b110)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ChocolArm64.Instructions;
|
||||
using ChocolArm64.State;
|
||||
|
||||
namespace ChocolArm64.Decoders
|
||||
{
|
||||
|
|
|
@ -2,9 +2,9 @@ namespace ChocolArm64.Decoders
|
|||
{
|
||||
enum ShiftType
|
||||
{
|
||||
Lsl,
|
||||
Lsr,
|
||||
Asr,
|
||||
Ror
|
||||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
}
|
||||
}
|
|
@ -2,11 +2,11 @@ using System;
|
|||
|
||||
namespace ChocolArm64.Events
|
||||
{
|
||||
public class InvalidAccessEventArgs : EventArgs
|
||||
public class MemoryAccessEventArgs : EventArgs
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
|
||||
public InvalidAccessEventArgs(long position)
|
||||
public MemoryAccessEventArgs(long position)
|
||||
{
|
||||
Position = position;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace ChocolArm64.Instructions
|
|||
|
||||
if (context.CurrBlock.Next != null)
|
||||
{
|
||||
context.EmitLoadState(context.CurrBlock.Next);
|
||||
context.EmitLoadState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ namespace ChocolArm64.Instructions
|
|||
|
||||
if (context.CurrBlock.Next != null)
|
||||
{
|
||||
context.EmitLoadState(context.CurrBlock.Next);
|
||||
context.EmitLoadState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace ChocolArm64.Instructions
|
|||
|
||||
context.Emit(OpCodes.Pop);
|
||||
|
||||
context.EmitLoadState(context.CurrBlock.Next);
|
||||
context.EmitLoadState();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,13 +73,10 @@ namespace ChocolArm64.Instructions
|
|||
OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;
|
||||
|
||||
context.EmitLdintzr(op.Rn);
|
||||
context.EmitSttmp();
|
||||
|
||||
context.EmitLdc_I(op.Position + 4);
|
||||
context.EmitStint(CpuThreadState.LrIndex);
|
||||
context.EmitStoreState();
|
||||
|
||||
context.EmitLdtmp();
|
||||
context.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace ChocolArm64.Instructions
|
|||
EmitWBackIfNeeded(context);
|
||||
}
|
||||
|
||||
public static void LdrLit(ILEmitterCtx context)
|
||||
public static void Ldr_Literal(ILEmitterCtx context)
|
||||
{
|
||||
IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp;
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace ChocolArm64.Instructions
|
|||
EmitFcvt_s_Gp(context, () => { });
|
||||
}
|
||||
|
||||
public static void Fcvtzs_Gp_Fix(ILEmitterCtx context)
|
||||
public static void Fcvtzs_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtzs_Gp_Fix(context);
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ namespace ChocolArm64.Instructions
|
|||
EmitFcvt_u_Gp(context, () => { });
|
||||
}
|
||||
|
||||
public static void Fcvtzu_Gp_Fix(ILEmitterCtx context)
|
||||
public static void Fcvtzu_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtzu_Gp_Fix(context);
|
||||
}
|
||||
|
|
|
@ -17,18 +17,18 @@ namespace ChocolArm64.Memory
|
|||
{
|
||||
private const int PtLvl0Bits = 13;
|
||||
private const int PtLvl1Bits = 14;
|
||||
private const int PtPageBits = 12;
|
||||
public const int PageBits = 12;
|
||||
|
||||
private const int PtLvl0Size = 1 << PtLvl0Bits;
|
||||
private const int PtLvl1Size = 1 << PtLvl1Bits;
|
||||
public const int PageSize = 1 << PtPageBits;
|
||||
public const int PageSize = 1 << PageBits;
|
||||
|
||||
private const int PtLvl0Mask = PtLvl0Size - 1;
|
||||
private const int PtLvl1Mask = PtLvl1Size - 1;
|
||||
public const int PageMask = PageSize - 1;
|
||||
|
||||
private const int PtLvl0Bit = PtPageBits + PtLvl1Bits;
|
||||
private const int PtLvl1Bit = PtPageBits;
|
||||
private const int PtLvl0Bit = PageBits + PtLvl1Bits;
|
||||
private const int PtLvl1Bit = PageBits;
|
||||
|
||||
private const long ErgMask = (4 << CpuThreadState.ErgSizeLog2) - 1;
|
||||
|
||||
|
@ -53,7 +53,9 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private byte*** _pageTable;
|
||||
|
||||
public event EventHandler<InvalidAccessEventArgs> InvalidAccess;
|
||||
public event EventHandler<MemoryAccessEventArgs> InvalidAccess;
|
||||
|
||||
public event EventHandler<MemoryAccessEventArgs> ObservedAccess;
|
||||
|
||||
public MemoryManager(IntPtr ram)
|
||||
{
|
||||
|
@ -119,6 +121,8 @@ namespace ChocolArm64.Memory
|
|||
|
||||
if (!_monitors.TryGetValue(core, out ArmMonitor threadMon))
|
||||
{
|
||||
Monitor.Exit(_monitors);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -630,7 +634,7 @@ namespace ChocolArm64.Memory
|
|||
return false;
|
||||
}
|
||||
|
||||
return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PtPageBits);
|
||||
return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PageBits);
|
||||
}
|
||||
|
||||
public long GetPhysicalAddress(long virtualAddress)
|
||||
|
@ -676,14 +680,14 @@ Unmapped:
|
|||
|
||||
private byte* HandleNullPte(long position)
|
||||
{
|
||||
long key = position >> PtPageBits;
|
||||
long key = position >> PageBits;
|
||||
|
||||
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
||||
{
|
||||
return (byte*)ptr + (position & PageMask);
|
||||
}
|
||||
|
||||
InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
|
||||
InvalidAccess?.Invoke(this, new MemoryAccessEventArgs(position));
|
||||
|
||||
throw new VmmPageFaultException(position);
|
||||
}
|
||||
|
@ -724,16 +728,20 @@ Unmapped:
|
|||
|
||||
private byte* HandleNullPteWrite(long position)
|
||||
{
|
||||
long key = position >> PtPageBits;
|
||||
long key = position >> PageBits;
|
||||
|
||||
MemoryAccessEventArgs e = new MemoryAccessEventArgs(position);
|
||||
|
||||
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
||||
{
|
||||
SetPtEntry(position, (byte*)ptr);
|
||||
|
||||
ObservedAccess?.Invoke(this, e);
|
||||
|
||||
return (byte*)ptr + (position & PageMask);
|
||||
}
|
||||
|
||||
InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
|
||||
InvalidAccess?.Invoke(this, e);
|
||||
|
||||
throw new VmmPageFaultException(position);
|
||||
}
|
||||
|
@ -782,53 +790,20 @@ Unmapped:
|
|||
_pageTable[l0][l1] = ptr;
|
||||
}
|
||||
|
||||
public (bool[], int) IsRegionModified(long position, long size)
|
||||
public void StartObservingRegion(long position, long size)
|
||||
{
|
||||
long endPosition = (position + size + PageMask) & ~PageMask;
|
||||
|
||||
position &= ~PageMask;
|
||||
|
||||
size = endPosition - position;
|
||||
|
||||
bool[] modified = new bool[size >> PtPageBits];
|
||||
|
||||
int count = 0;
|
||||
|
||||
lock (_observedPages)
|
||||
while ((ulong)position < (ulong)endPosition)
|
||||
{
|
||||
for (int page = 0; page < modified.Length; page++)
|
||||
{
|
||||
byte* ptr = Translate(position);
|
||||
_observedPages[position >> PageBits] = (IntPtr)Translate(position);
|
||||
|
||||
if (_observedPages.TryAdd(position >> PtPageBits, (IntPtr)ptr))
|
||||
{
|
||||
modified[page] = true;
|
||||
SetPtEntry(position, null);
|
||||
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
|
||||
long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
|
||||
|
||||
byte** lvl1 = _pageTable[l0];
|
||||
|
||||
if (lvl1 != null)
|
||||
{
|
||||
if (modified[page] = lvl1[l1] != null)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetPtEntry(position, null);
|
||||
|
||||
position += PageSize;
|
||||
}
|
||||
position += PageSize;
|
||||
}
|
||||
|
||||
return (modified, count);
|
||||
}
|
||||
|
||||
public void StopObservingRegion(long position, long size)
|
||||
|
@ -839,7 +814,7 @@ Unmapped:
|
|||
{
|
||||
lock (_observedPages)
|
||||
{
|
||||
if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr))
|
||||
if (_observedPages.TryRemove(position >> PageBits, out IntPtr ptr))
|
||||
{
|
||||
SetPtEntry(position, (byte*)ptr);
|
||||
}
|
||||
|
@ -889,7 +864,7 @@ Unmapped:
|
|||
|
||||
public bool IsValidPosition(long position)
|
||||
{
|
||||
return position >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) == 0;
|
||||
return position >> (PtLvl0Bits + PtLvl1Bits + PageBits) == 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@ namespace ChocolArm64
|
|||
|
||||
public DynamicMethod Method { get; private set; }
|
||||
|
||||
public ReadOnlyCollection<Register> Params { get; private set; }
|
||||
public ReadOnlyCollection<Register> SubArgs { get; private set; }
|
||||
|
||||
private HashSet<long> _callers;
|
||||
|
||||
|
@ -34,20 +34,10 @@ namespace ChocolArm64
|
|||
|
||||
private bool _needsReJit;
|
||||
|
||||
public TranslatedSub(DynamicMethod method, List<Register> Params)
|
||||
public TranslatedSub(DynamicMethod method, List<Register> subArgs)
|
||||
{
|
||||
if (method == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(method));
|
||||
}
|
||||
|
||||
if (Params == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Params));
|
||||
}
|
||||
|
||||
Method = method;
|
||||
this.Params = Params.AsReadOnly();
|
||||
Method = method ?? throw new ArgumentNullException(nameof(method));;
|
||||
SubArgs = subArgs?.AsReadOnly() ?? throw new ArgumentNullException(nameof(subArgs));
|
||||
|
||||
_callers = new HashSet<long>();
|
||||
|
||||
|
@ -89,7 +79,7 @@ namespace ChocolArm64
|
|||
|
||||
generator.EmitLdargSeq(FixedArgTypes.Length);
|
||||
|
||||
foreach (Register reg in Params)
|
||||
foreach (Register reg in SubArgs)
|
||||
{
|
||||
generator.EmitLdarg(StateArgIdx);
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@ namespace ChocolArm64.Translation
|
|||
{
|
||||
interface IILEmit
|
||||
{
|
||||
void Emit(ILEmitter context);
|
||||
void Emit(ILMethodBuilder context);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,6 @@ namespace ChocolArm64.Translation
|
|||
{
|
||||
struct ILBarrier : IILEmit
|
||||
{
|
||||
public void Emit(ILEmitter context) { }
|
||||
public void Emit(ILMethodBuilder context) { }
|
||||
}
|
||||
}
|
|
@ -14,19 +14,21 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public bool HasStateStore { get; private set; }
|
||||
|
||||
public List<IILEmit> IlEmitters { get; private set; }
|
||||
private List<IILEmit> _emitters;
|
||||
|
||||
public int Count => _emitters.Count;
|
||||
|
||||
public ILBlock Next { get; set; }
|
||||
public ILBlock Branch { get; set; }
|
||||
|
||||
public ILBlock()
|
||||
{
|
||||
IlEmitters = new List<IILEmit>();
|
||||
_emitters = new List<IILEmit>();
|
||||
}
|
||||
|
||||
public void Add(IILEmit ilEmitter)
|
||||
public void Add(IILEmit emitter)
|
||||
{
|
||||
if (ilEmitter is ILBarrier)
|
||||
if (emitter is ILBarrier)
|
||||
{
|
||||
//Those barriers are used to separate the groups of CIL
|
||||
//opcodes emitted by each ARM instruction.
|
||||
|
@ -35,7 +37,7 @@ namespace ChocolArm64.Translation
|
|||
IntAwOutputs = IntOutputs;
|
||||
VecAwOutputs = VecOutputs;
|
||||
}
|
||||
else if (ilEmitter is IlOpCodeLoad ld && ILEmitter.IsRegIndex(ld.Index))
|
||||
else if (emitter is ILOpCodeLoad ld && ILMethodBuilder.IsRegIndex(ld.Index))
|
||||
{
|
||||
switch (ld.IoType)
|
||||
{
|
||||
|
@ -44,30 +46,26 @@ namespace ChocolArm64.Translation
|
|||
case IoType.Vector: VecInputs |= (1L << ld.Index) & ~VecAwOutputs; break;
|
||||
}
|
||||
}
|
||||
else if (ilEmitter is IlOpCodeStore st)
|
||||
else if (emitter is ILOpCodeStore st && ILMethodBuilder.IsRegIndex(st.Index))
|
||||
{
|
||||
if (ILEmitter.IsRegIndex(st.Index))
|
||||
switch (st.IoType)
|
||||
{
|
||||
switch (st.IoType)
|
||||
{
|
||||
case IoType.Flag: IntOutputs |= (1L << st.Index) << 32; break;
|
||||
case IoType.Int: IntOutputs |= 1L << st.Index; break;
|
||||
case IoType.Vector: VecOutputs |= 1L << st.Index; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (st.IoType == IoType.Fields)
|
||||
{
|
||||
HasStateStore = true;
|
||||
case IoType.Flag: IntOutputs |= (1L << st.Index) << 32; break;
|
||||
case IoType.Int: IntOutputs |= 1L << st.Index; break;
|
||||
case IoType.Vector: VecOutputs |= 1L << st.Index; break;
|
||||
}
|
||||
}
|
||||
else if (emitter is ILOpCodeStoreState)
|
||||
{
|
||||
HasStateStore = true;
|
||||
}
|
||||
|
||||
IlEmitters.Add(ilEmitter);
|
||||
_emitters.Add(emitter);
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
foreach (IILEmit ilEmitter in IlEmitters)
|
||||
foreach (IILEmit ilEmitter in _emitters)
|
||||
{
|
||||
ilEmitter.Emit(context);
|
||||
}
|
||||
|
|
|
@ -14,15 +14,20 @@ namespace ChocolArm64.Translation
|
|||
|
||||
private Dictionary<long, ILLabel> _labels;
|
||||
|
||||
private int _blkIndex;
|
||||
private long _subPosition;
|
||||
|
||||
private int _opcIndex;
|
||||
|
||||
private Block[] _graph;
|
||||
private Block _root;
|
||||
public Block CurrBlock => _graph[_blkIndex];
|
||||
public OpCode64 CurrOp => _graph[_blkIndex].OpCodes[_opcIndex];
|
||||
private Block _currBlock;
|
||||
|
||||
private ILEmitter _emitter;
|
||||
public Block CurrBlock => _currBlock;
|
||||
public OpCode64 CurrOp => _currBlock?.OpCodes[_opcIndex];
|
||||
|
||||
private Dictionary<Block, ILBlock> _visitedBlocks;
|
||||
|
||||
private Queue<Block> _branchTargets;
|
||||
|
||||
private List<ILBlock> _ilBlocks;
|
||||
|
||||
private ILBlock _ilBlock;
|
||||
|
||||
|
@ -33,69 +38,61 @@ namespace ChocolArm64.Translation
|
|||
//values needed by some functions, since IL doesn't have a swap instruction.
|
||||
//You can use any value here as long it doesn't conflict with the indices
|
||||
//for the other registers. Any value >= 64 or < 0 will do.
|
||||
private const int Tmp1Index = -1;
|
||||
private const int Tmp2Index = -2;
|
||||
private const int Tmp3Index = -3;
|
||||
private const int Tmp4Index = -4;
|
||||
private const int Tmp5Index = -5;
|
||||
private const int Tmp6Index = -6;
|
||||
private const int IntTmpIndex = -1;
|
||||
private const int RorTmpIndex = -2;
|
||||
private const int CmpOptTmp1Index = -3;
|
||||
private const int CmpOptTmp2Index = -4;
|
||||
private const int VecTmp1Index = -5;
|
||||
private const int VecTmp2Index = -6;
|
||||
|
||||
public ILEmitterCtx(
|
||||
TranslatorCache cache,
|
||||
Block[] graph,
|
||||
Block root,
|
||||
string subName)
|
||||
public ILEmitterCtx(TranslatorCache cache, Block graph)
|
||||
{
|
||||
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
|
||||
_graph = graph ?? throw new ArgumentNullException(nameof(graph));
|
||||
_root = root ?? throw new ArgumentNullException(nameof(root));
|
||||
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
|
||||
_currBlock = graph ?? throw new ArgumentNullException(nameof(graph));
|
||||
|
||||
_labels = new Dictionary<long, ILLabel>();
|
||||
|
||||
_emitter = new ILEmitter(graph, root, subName);
|
||||
_visitedBlocks = new Dictionary<Block, ILBlock>();
|
||||
|
||||
_ilBlock = _emitter.GetIlBlock(0);
|
||||
_visitedBlocks.Add(graph, new ILBlock());
|
||||
|
||||
_opcIndex = -1;
|
||||
_branchTargets = new Queue<Block>();
|
||||
|
||||
if (graph.Length == 0 || !AdvanceOpCode())
|
||||
{
|
||||
throw new ArgumentException(nameof(graph));
|
||||
}
|
||||
_ilBlocks = new List<ILBlock>();
|
||||
|
||||
_subPosition = graph.Position;
|
||||
|
||||
ResetBlockState();
|
||||
|
||||
AdvanceOpCode();
|
||||
}
|
||||
|
||||
public TranslatedSub GetSubroutine()
|
||||
public ILBlock[] GetILBlocks()
|
||||
{
|
||||
return _emitter.GetSubroutine();
|
||||
EmitAllOpCodes();
|
||||
|
||||
return _ilBlocks.ToArray();
|
||||
}
|
||||
|
||||
public bool AdvanceOpCode()
|
||||
private void EmitAllOpCodes()
|
||||
{
|
||||
if (_opcIndex + 1 == CurrBlock.OpCodes.Count &&
|
||||
_blkIndex + 1 == _graph.Length)
|
||||
do
|
||||
{
|
||||
return false;
|
||||
EmitOpCode();
|
||||
}
|
||||
|
||||
while (++_opcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
|
||||
{
|
||||
_blkIndex++;
|
||||
_opcIndex = -1;
|
||||
|
||||
_optOpLastFlagSet = null;
|
||||
_optOpLastCompare = null;
|
||||
|
||||
_ilBlock = _emitter.GetIlBlock(_blkIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
while (AdvanceOpCode());
|
||||
}
|
||||
|
||||
public void EmitOpCode()
|
||||
private void EmitOpCode()
|
||||
{
|
||||
if (_currBlock == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_opcIndex == 0)
|
||||
{
|
||||
MarkLabel(GetLabel(CurrBlock.Position));
|
||||
MarkLabel(GetLabel(_currBlock.Position));
|
||||
|
||||
EmitSynchronization();
|
||||
}
|
||||
|
@ -109,7 +106,7 @@ namespace ChocolArm64.Translation
|
|||
{
|
||||
EmitLdarg(TranslatedSub.StateArgIdx);
|
||||
|
||||
EmitLdc_I4(CurrBlock.OpCodes.Count);
|
||||
EmitLdc_I4(_currBlock.OpCodes.Count);
|
||||
|
||||
EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize));
|
||||
|
||||
|
@ -126,9 +123,86 @@ namespace ChocolArm64.Translation
|
|||
MarkLabel(lblContinue);
|
||||
}
|
||||
|
||||
private bool AdvanceOpCode()
|
||||
{
|
||||
if (_currBlock == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (++_opcIndex >= _currBlock.OpCodes.Count)
|
||||
{
|
||||
if (!AdvanceBlock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ResetBlockState();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AdvanceBlock()
|
||||
{
|
||||
if (_currBlock.Branch != null)
|
||||
{
|
||||
if (_visitedBlocks.TryAdd(_currBlock.Branch, _ilBlock.Branch))
|
||||
{
|
||||
_branchTargets.Enqueue(_currBlock.Branch);
|
||||
}
|
||||
}
|
||||
|
||||
if (_currBlock.Next != null)
|
||||
{
|
||||
if (_visitedBlocks.TryAdd(_currBlock.Next, _ilBlock.Next))
|
||||
{
|
||||
_currBlock = _currBlock.Next;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Emit(OpCodes.Br, GetLabel(_currBlock.Next.Position));
|
||||
}
|
||||
}
|
||||
|
||||
return _branchTargets.TryDequeue(out _currBlock);
|
||||
}
|
||||
|
||||
private void ResetBlockState()
|
||||
{
|
||||
_ilBlock = _visitedBlocks[_currBlock];
|
||||
|
||||
_ilBlocks.Add(_ilBlock);
|
||||
|
||||
_ilBlock.Next = GetOrCreateILBlock(_currBlock.Next);
|
||||
_ilBlock.Branch = GetOrCreateILBlock(_currBlock.Branch);
|
||||
|
||||
_opcIndex = -1;
|
||||
|
||||
_optOpLastFlagSet = null;
|
||||
_optOpLastCompare = null;
|
||||
}
|
||||
|
||||
private ILBlock GetOrCreateILBlock(Block block)
|
||||
{
|
||||
if (block == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_visitedBlocks.TryGetValue(block, out ILBlock ilBlock))
|
||||
{
|
||||
return ilBlock;
|
||||
}
|
||||
|
||||
return new ILBlock();
|
||||
}
|
||||
|
||||
public bool TryOptEmitSubroutineCall()
|
||||
{
|
||||
if (CurrBlock.Next == null)
|
||||
if (_currBlock.Next == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -148,7 +222,7 @@ namespace ChocolArm64.Translation
|
|||
EmitLdarg(index);
|
||||
}
|
||||
|
||||
foreach (Register reg in subroutine.Params)
|
||||
foreach (Register reg in subroutine.SubArgs)
|
||||
{
|
||||
switch (reg.Type)
|
||||
{
|
||||
|
@ -160,7 +234,7 @@ namespace ChocolArm64.Translation
|
|||
|
||||
EmitCall(subroutine.Method);
|
||||
|
||||
subroutine.AddCaller(_root.Position);
|
||||
subroutine.AddCaller(_subPosition);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -171,11 +245,11 @@ namespace ChocolArm64.Translation
|
|||
|
||||
InstEmitAluHelper.EmitDataLoadOpers(this);
|
||||
|
||||
Stloc(Tmp4Index, IoType.Int);
|
||||
Stloc(Tmp3Index, IoType.Int);
|
||||
Stloc(CmpOptTmp2Index, IoType.Int);
|
||||
Stloc(CmpOptTmp1Index, IoType.Int);
|
||||
}
|
||||
|
||||
private Dictionary<Cond, System.Reflection.Emit.OpCode> _branchOps = new Dictionary<Cond, System.Reflection.Emit.OpCode>()
|
||||
private Dictionary<Cond, OpCode> _branchOps = new Dictionary<Cond, OpCode>()
|
||||
{
|
||||
{ Cond.Eq, OpCodes.Beq },
|
||||
{ Cond.Ne, OpCodes.Bne_Un },
|
||||
|
@ -191,15 +265,15 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public void EmitCondBranch(ILLabel target, Cond cond)
|
||||
{
|
||||
System.Reflection.Emit.OpCode ilOp;
|
||||
OpCode ilOp;
|
||||
|
||||
int intCond = (int)cond;
|
||||
|
||||
if (_optOpLastCompare != null &&
|
||||
_optOpLastCompare == _optOpLastFlagSet && _branchOps.ContainsKey(cond))
|
||||
{
|
||||
Ldloc(Tmp3Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
||||
Ldloc(Tmp4Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
||||
Ldloc(CmpOptTmp1Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
||||
Ldloc(CmpOptTmp2Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
||||
|
||||
ilOp = _branchOps[cond];
|
||||
}
|
||||
|
@ -285,11 +359,11 @@ namespace ChocolArm64.Translation
|
|||
}
|
||||
}
|
||||
|
||||
public void EmitLsl(int amount) => EmitIlShift(amount, OpCodes.Shl);
|
||||
public void EmitLsr(int amount) => EmitIlShift(amount, OpCodes.Shr_Un);
|
||||
public void EmitAsr(int amount) => EmitIlShift(amount, OpCodes.Shr);
|
||||
public void EmitLsl(int amount) => EmitILShift(amount, OpCodes.Shl);
|
||||
public void EmitLsr(int amount) => EmitILShift(amount, OpCodes.Shr_Un);
|
||||
public void EmitAsr(int amount) => EmitILShift(amount, OpCodes.Shr);
|
||||
|
||||
private void EmitIlShift(int amount, System.Reflection.Emit.OpCode ilOp)
|
||||
private void EmitILShift(int amount, OpCode ilOp)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
|
@ -303,14 +377,14 @@ namespace ChocolArm64.Translation
|
|||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
Stloc(Tmp2Index, IoType.Int);
|
||||
Ldloc(Tmp2Index, IoType.Int);
|
||||
Stloc(RorTmpIndex, IoType.Int);
|
||||
Ldloc(RorTmpIndex, IoType.Int);
|
||||
|
||||
EmitLdc_I4(amount);
|
||||
|
||||
Emit(OpCodes.Shr_Un);
|
||||
|
||||
Ldloc(Tmp2Index, IoType.Int);
|
||||
Ldloc(RorTmpIndex, IoType.Int);
|
||||
|
||||
EmitLdc_I4(CurrOp.GetBitsCount() - amount);
|
||||
|
||||
|
@ -336,12 +410,12 @@ namespace ChocolArm64.Translation
|
|||
_ilBlock.Add(label);
|
||||
}
|
||||
|
||||
public void Emit(System.Reflection.Emit.OpCode ilOp)
|
||||
public void Emit(OpCode ilOp)
|
||||
{
|
||||
_ilBlock.Add(new ILOpCode(ilOp));
|
||||
}
|
||||
|
||||
public void Emit(System.Reflection.Emit.OpCode ilOp, ILLabel label)
|
||||
public void Emit(OpCode ilOp, ILLabel label)
|
||||
{
|
||||
_ilBlock.Add(new ILOpCodeBranch(ilOp, label));
|
||||
}
|
||||
|
@ -353,7 +427,7 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public void EmitLdarg(int index)
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeLoad(index, IoType.Arg));
|
||||
_ilBlock.Add(new ILOpCodeLoad(index, IoType.Arg));
|
||||
}
|
||||
|
||||
public void EmitLdintzr(int index)
|
||||
|
@ -380,24 +454,29 @@ namespace ChocolArm64.Translation
|
|||
}
|
||||
}
|
||||
|
||||
public void EmitLoadState(Block retBlk)
|
||||
public void EmitLoadState()
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeLoad(Array.IndexOf(_graph, retBlk), IoType.Fields));
|
||||
if (_ilBlock.Next == null)
|
||||
{
|
||||
throw new InvalidOperationException("Can't load state for next block, because there's no next block.");
|
||||
}
|
||||
|
||||
_ilBlock.Add(new ILOpCodeLoadState(_ilBlock.Next));
|
||||
}
|
||||
|
||||
public void EmitStoreState()
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeStore(Array.IndexOf(_graph, CurrBlock), IoType.Fields));
|
||||
_ilBlock.Add(new ILOpCodeStoreState(_ilBlock));
|
||||
}
|
||||
|
||||
public void EmitLdtmp() => EmitLdint(Tmp1Index);
|
||||
public void EmitSttmp() => EmitStint(Tmp1Index);
|
||||
public void EmitLdtmp() => EmitLdint(IntTmpIndex);
|
||||
public void EmitSttmp() => EmitStint(IntTmpIndex);
|
||||
|
||||
public void EmitLdvectmp() => EmitLdvec(Tmp5Index);
|
||||
public void EmitStvectmp() => EmitStvec(Tmp5Index);
|
||||
public void EmitLdvectmp() => EmitLdvec(VecTmp1Index);
|
||||
public void EmitStvectmp() => EmitStvec(VecTmp1Index);
|
||||
|
||||
public void EmitLdvectmp2() => EmitLdvec(Tmp6Index);
|
||||
public void EmitStvectmp2() => EmitStvec(Tmp6Index);
|
||||
public void EmitLdvectmp2() => EmitLdvec(VecTmp2Index);
|
||||
public void EmitStvectmp2() => EmitStvec(VecTmp2Index);
|
||||
|
||||
public void EmitLdint(int index) => Ldloc(index, IoType.Int);
|
||||
public void EmitStint(int index) => Stloc(index, IoType.Int);
|
||||
|
@ -415,17 +494,17 @@ namespace ChocolArm64.Translation
|
|||
|
||||
private void Ldloc(int index, IoType ioType)
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeLoad(index, ioType, CurrOp.RegisterSize));
|
||||
_ilBlock.Add(new ILOpCodeLoad(index, ioType, CurrOp.RegisterSize));
|
||||
}
|
||||
|
||||
private void Ldloc(int index, IoType ioType, RegisterSize registerSize)
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeLoad(index, ioType, registerSize));
|
||||
_ilBlock.Add(new ILOpCodeLoad(index, ioType, registerSize));
|
||||
}
|
||||
|
||||
private void Stloc(int index, IoType ioType)
|
||||
{
|
||||
_ilBlock.Add(new IlOpCodeStore(index, ioType, CurrOp.RegisterSize));
|
||||
_ilBlock.Add(new ILOpCodeStore(index, ioType, CurrOp.RegisterSize));
|
||||
}
|
||||
|
||||
public void EmitCallPropGet(Type objType, string propName)
|
||||
|
@ -536,7 +615,7 @@ namespace ChocolArm64.Translation
|
|||
EmitZnCheck(OpCodes.Clt, (int)PState.NBit);
|
||||
}
|
||||
|
||||
private void EmitZnCheck(System.Reflection.Emit.OpCode ilCmpOp, int flag)
|
||||
private void EmitZnCheck(OpCode ilCmpOp, int flag)
|
||||
{
|
||||
Emit(OpCodes.Dup);
|
||||
Emit(OpCodes.Ldc_I4_0);
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace ChocolArm64.Translation
|
|||
|
||||
private Label _lbl;
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
context.Generator.MarkLabel(GetLabel(context));
|
||||
}
|
||||
|
||||
public Label GetLabel(ILEmitter context)
|
||||
public Label GetLabel(ILMethodBuilder context)
|
||||
{
|
||||
if (!_hasLabel)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using ChocolArm64.Decoders;
|
||||
using ChocolArm64.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -7,7 +6,7 @@ using System.Runtime.Intrinsics;
|
|||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
class ILEmitter
|
||||
class ILMethodBuilder
|
||||
{
|
||||
public LocalAlloc LocalAlloc { get; private set; }
|
||||
|
||||
|
@ -17,70 +16,23 @@ namespace ChocolArm64.Translation
|
|||
|
||||
private ILBlock[] _ilBlocks;
|
||||
|
||||
private ILBlock _root;
|
||||
|
||||
private TranslatedSub _subroutine;
|
||||
|
||||
private string _subName;
|
||||
|
||||
private int _localsCount;
|
||||
|
||||
public ILEmitter(Block[] graph, Block root, string subName)
|
||||
public ILMethodBuilder(ILBlock[] ilBlocks, string subName)
|
||||
{
|
||||
_subName = subName;
|
||||
|
||||
_locals = new Dictionary<Register, int>();
|
||||
|
||||
_ilBlocks = new ILBlock[graph.Length];
|
||||
|
||||
ILBlock GetBlock(int index)
|
||||
{
|
||||
if (index < 0 || index >= _ilBlocks.Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_ilBlocks[index] == null)
|
||||
{
|
||||
_ilBlocks[index] = new ILBlock();
|
||||
}
|
||||
|
||||
return _ilBlocks[index];
|
||||
}
|
||||
|
||||
for (int index = 0; index < _ilBlocks.Length; index++)
|
||||
{
|
||||
ILBlock block = GetBlock(index);
|
||||
|
||||
block.Next = GetBlock(Array.IndexOf(graph, graph[index].Next));
|
||||
block.Branch = GetBlock(Array.IndexOf(graph, graph[index].Branch));
|
||||
}
|
||||
|
||||
_root = _ilBlocks[Array.IndexOf(graph, root)];
|
||||
_ilBlocks = ilBlocks;
|
||||
_subName = subName;
|
||||
}
|
||||
|
||||
public ILBlock GetIlBlock(int index) => _ilBlocks[index];
|
||||
|
||||
public TranslatedSub GetSubroutine()
|
||||
{
|
||||
LocalAlloc = new LocalAlloc(_ilBlocks, _root);
|
||||
LocalAlloc = new LocalAlloc(_ilBlocks, _ilBlocks[0]);
|
||||
|
||||
InitSubroutine();
|
||||
InitLocals();
|
||||
List<Register> subArgs = new List<Register>();
|
||||
|
||||
foreach (ILBlock ilBlock in _ilBlocks)
|
||||
{
|
||||
ilBlock.Emit(this);
|
||||
}
|
||||
|
||||
return _subroutine;
|
||||
}
|
||||
|
||||
private void InitSubroutine()
|
||||
{
|
||||
List<Register> Params = new List<Register>();
|
||||
|
||||
void SetParams(long inputs, RegisterType baseType)
|
||||
void SetArgs(long inputs, RegisterType baseType)
|
||||
{
|
||||
for (int bit = 0; bit < 64; bit++)
|
||||
{
|
||||
|
@ -88,37 +40,43 @@ namespace ChocolArm64.Translation
|
|||
|
||||
if ((inputs & mask) != 0)
|
||||
{
|
||||
Params.Add(GetRegFromBit(bit, baseType));
|
||||
subArgs.Add(GetRegFromBit(bit, baseType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetParams(LocalAlloc.GetIntInputs(_root), RegisterType.Int);
|
||||
SetParams(LocalAlloc.GetVecInputs(_root), RegisterType.Vector);
|
||||
SetArgs(LocalAlloc.GetIntInputs(_ilBlocks[0]), RegisterType.Int);
|
||||
SetArgs(LocalAlloc.GetVecInputs(_ilBlocks[0]), RegisterType.Vector);
|
||||
|
||||
DynamicMethod mthd = new DynamicMethod(_subName, typeof(long), GetParamTypes(Params));
|
||||
DynamicMethod method = new DynamicMethod(_subName, typeof(long), GetArgumentTypes(subArgs));
|
||||
|
||||
Generator = mthd.GetILGenerator();
|
||||
Generator = method.GetILGenerator();
|
||||
|
||||
_subroutine = new TranslatedSub(mthd, Params);
|
||||
}
|
||||
TranslatedSub subroutine = new TranslatedSub(method, subArgs);
|
||||
|
||||
private void InitLocals()
|
||||
{
|
||||
int paramsStart = TranslatedSub.FixedArgTypes.Length;
|
||||
int argsStart = TranslatedSub.FixedArgTypes.Length;
|
||||
|
||||
_locals = new Dictionary<Register, int>();
|
||||
|
||||
for (int index = 0; index < _subroutine.Params.Count; index++)
|
||||
{
|
||||
Register reg = _subroutine.Params[index];
|
||||
_localsCount = 0;
|
||||
|
||||
Generator.EmitLdarg(index + paramsStart);
|
||||
for (int index = 0; index < subroutine.SubArgs.Count; index++)
|
||||
{
|
||||
Register reg = subroutine.SubArgs[index];
|
||||
|
||||
Generator.EmitLdarg(index + argsStart);
|
||||
Generator.EmitStloc(GetLocalIndex(reg));
|
||||
}
|
||||
|
||||
foreach (ILBlock ilBlock in _ilBlocks)
|
||||
{
|
||||
ilBlock.Emit(this);
|
||||
}
|
||||
|
||||
return subroutine;
|
||||
}
|
||||
|
||||
private Type[] GetParamTypes(IList<Register> Params)
|
||||
private Type[] GetArgumentTypes(IList<Register> Params)
|
||||
{
|
||||
Type[] fixedArgs = TranslatedSub.FixedArgTypes;
|
||||
|
||||
|
@ -140,7 +98,7 @@ namespace ChocolArm64.Translation
|
|||
{
|
||||
if (!_locals.TryGetValue(reg, out int index))
|
||||
{
|
||||
Generator.DeclareLocal(GetLocalType(reg));
|
||||
Generator.DeclareLocal(GetFieldType(reg.Type));
|
||||
|
||||
index = _localsCount++;
|
||||
|
||||
|
@ -150,9 +108,7 @@ namespace ChocolArm64.Translation
|
|||
return index;
|
||||
}
|
||||
|
||||
public Type GetLocalType(Register reg) => GetFieldType(reg.Type);
|
||||
|
||||
public Type GetFieldType(RegisterType regType)
|
||||
private static Type GetFieldType(RegisterType regType)
|
||||
{
|
||||
switch (regType)
|
||||
{
|
||||
|
@ -182,7 +138,7 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public static bool IsRegIndex(int index)
|
||||
{
|
||||
return index >= 0 && index < 32;
|
||||
return (uint)index < 32;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace ChocolArm64.Translation
|
|||
_ilOp = ilOp;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
context.Generator.Emit(_ilOp);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ChocolArm64.Translation
|
|||
_label = label;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
context.Generator.Emit(_ilOp, _label.GetLabel(context));
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ChocolArm64.Translation
|
|||
_mthdInfo = mthdInfo;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
context.Generator.Emit(OpCodes.Call, _mthdInfo);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace ChocolArm64.Translation
|
|||
_value = new ImmVal { R8 = value };
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
switch (_type)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Reflection.Emit;
|
|||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
struct IlOpCodeLoad : IILEmit
|
||||
struct ILOpCodeLoad : IILEmit
|
||||
{
|
||||
public int Index { get; private set; }
|
||||
|
||||
|
@ -11,55 +11,26 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public RegisterSize RegisterSize { get; private set; }
|
||||
|
||||
public IlOpCodeLoad(int index, IoType ioType, RegisterSize registerSize = 0)
|
||||
public ILOpCodeLoad(int index, IoType ioType, RegisterSize registerSize = 0)
|
||||
{
|
||||
Index = index;
|
||||
IoType = ioType;
|
||||
RegisterSize = registerSize;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
switch (IoType)
|
||||
{
|
||||
case IoType.Arg: context.Generator.EmitLdarg(Index); break;
|
||||
|
||||
case IoType.Fields:
|
||||
{
|
||||
long intInputs = context.LocalAlloc.GetIntInputs(context.GetIlBlock(Index));
|
||||
long vecInputs = context.LocalAlloc.GetVecInputs(context.GetIlBlock(Index));
|
||||
|
||||
LoadLocals(context, intInputs, RegisterType.Int);
|
||||
LoadLocals(context, vecInputs, RegisterType.Vector);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IoType.Flag: EmitLdloc(context, Index, RegisterType.Flag); break;
|
||||
case IoType.Int: EmitLdloc(context, Index, RegisterType.Int); break;
|
||||
case IoType.Vector: EmitLdloc(context, Index, RegisterType.Vector); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadLocals(ILEmitter context, long inputs, RegisterType baseType)
|
||||
{
|
||||
for (int bit = 0; bit < 64; bit++)
|
||||
{
|
||||
long mask = 1L << bit;
|
||||
|
||||
if ((inputs & mask) != 0)
|
||||
{
|
||||
Register reg = ILEmitter.GetRegFromBit(bit, baseType);
|
||||
|
||||
context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
|
||||
context.Generator.Emit(OpCodes.Ldfld, reg.GetField());
|
||||
|
||||
context.Generator.EmitStloc(context.GetLocalIndex(reg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitLdloc(ILEmitter context, int index, RegisterType registerType)
|
||||
private void EmitLdloc(ILMethodBuilder context, int index, RegisterType registerType)
|
||||
{
|
||||
Register reg = new Register(index, registerType);
|
||||
|
||||
|
|
42
ChocolArm64/Translation/ILOpCodeLoadState.cs
Normal file
42
ChocolArm64/Translation/ILOpCodeLoadState.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using ChocolArm64.State;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
struct ILOpCodeLoadState : IILEmit
|
||||
{
|
||||
private ILBlock _block;
|
||||
|
||||
public ILOpCodeLoadState(ILBlock block)
|
||||
{
|
||||
_block = block;
|
||||
}
|
||||
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
long intInputs = context.LocalAlloc.GetIntInputs(_block);
|
||||
long vecInputs = context.LocalAlloc.GetVecInputs(_block);
|
||||
|
||||
LoadLocals(context, intInputs, RegisterType.Int);
|
||||
LoadLocals(context, vecInputs, RegisterType.Vector);
|
||||
}
|
||||
|
||||
private void LoadLocals(ILMethodBuilder context, long inputs, RegisterType baseType)
|
||||
{
|
||||
for (int bit = 0; bit < 64; bit++)
|
||||
{
|
||||
long mask = 1L << bit;
|
||||
|
||||
if ((inputs & mask) != 0)
|
||||
{
|
||||
Register reg = ILMethodBuilder.GetRegFromBit(bit, baseType);
|
||||
|
||||
context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
|
||||
context.Generator.Emit(OpCodes.Ldfld, reg.GetField());
|
||||
|
||||
context.Generator.EmitStloc(context.GetLocalIndex(reg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace ChocolArm64.Translation
|
|||
_text = text;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
context.Generator.EmitWriteLine(_text);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Reflection.Emit;
|
|||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
struct IlOpCodeStore : IILEmit
|
||||
struct ILOpCodeStore : IILEmit
|
||||
{
|
||||
public int Index { get; private set; }
|
||||
|
||||
|
@ -11,55 +11,26 @@ namespace ChocolArm64.Translation
|
|||
|
||||
public RegisterSize RegisterSize { get; private set; }
|
||||
|
||||
public IlOpCodeStore(int index, IoType ioType, RegisterSize registerSize = 0)
|
||||
public ILOpCodeStore(int index, IoType ioType, RegisterSize registerSize = 0)
|
||||
{
|
||||
Index = index;
|
||||
IoType = ioType;
|
||||
RegisterSize = registerSize;
|
||||
}
|
||||
|
||||
public void Emit(ILEmitter context)
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
switch (IoType)
|
||||
{
|
||||
case IoType.Arg: context.Generator.EmitStarg(Index); break;
|
||||
|
||||
case IoType.Fields:
|
||||
{
|
||||
long intOutputs = context.LocalAlloc.GetIntOutputs(context.GetIlBlock(Index));
|
||||
long vecOutputs = context.LocalAlloc.GetVecOutputs(context.GetIlBlock(Index));
|
||||
|
||||
StoreLocals(context, intOutputs, RegisterType.Int);
|
||||
StoreLocals(context, vecOutputs, RegisterType.Vector);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IoType.Flag: EmitStloc(context, Index, RegisterType.Flag); break;
|
||||
case IoType.Int: EmitStloc(context, Index, RegisterType.Int); break;
|
||||
case IoType.Vector: EmitStloc(context, Index, RegisterType.Vector); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreLocals(ILEmitter context, long outputs, RegisterType baseType)
|
||||
{
|
||||
for (int bit = 0; bit < 64; bit++)
|
||||
{
|
||||
long mask = 1L << bit;
|
||||
|
||||
if ((outputs & mask) != 0)
|
||||
{
|
||||
Register reg = ILEmitter.GetRegFromBit(bit, baseType);
|
||||
|
||||
context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
|
||||
context.Generator.EmitLdloc(context.GetLocalIndex(reg));
|
||||
|
||||
context.Generator.Emit(OpCodes.Stfld, reg.GetField());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitStloc(ILEmitter context, int index, RegisterType registerType)
|
||||
private void EmitStloc(ILMethodBuilder context, int index, RegisterType registerType)
|
||||
{
|
||||
Register reg = new Register(index, registerType);
|
||||
|
||||
|
|
42
ChocolArm64/Translation/ILOpCodeStoreState.cs
Normal file
42
ChocolArm64/Translation/ILOpCodeStoreState.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using ChocolArm64.State;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
struct ILOpCodeStoreState : IILEmit
|
||||
{
|
||||
private ILBlock _block;
|
||||
|
||||
public ILOpCodeStoreState(ILBlock block)
|
||||
{
|
||||
_block = block;
|
||||
}
|
||||
|
||||
public void Emit(ILMethodBuilder context)
|
||||
{
|
||||
long intOutputs = context.LocalAlloc.GetIntOutputs(_block);
|
||||
long vecOutputs = context.LocalAlloc.GetVecOutputs(_block);
|
||||
|
||||
StoreLocals(context, intOutputs, RegisterType.Int);
|
||||
StoreLocals(context, vecOutputs, RegisterType.Vector);
|
||||
}
|
||||
|
||||
private void StoreLocals(ILMethodBuilder context, long outputs, RegisterType baseType)
|
||||
{
|
||||
for (int bit = 0; bit < 64; bit++)
|
||||
{
|
||||
long mask = 1L << bit;
|
||||
|
||||
if ((outputs & mask) != 0)
|
||||
{
|
||||
Register reg = ILMethodBuilder.GetRegFromBit(bit, baseType);
|
||||
|
||||
context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
|
||||
context.Generator.EmitLdloc(context.GetLocalIndex(reg));
|
||||
|
||||
context.Generator.Emit(OpCodes.Stfld, reg.GetField());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.Translation
|
||||
{
|
||||
[Flags]
|
||||
enum IoType
|
||||
{
|
||||
Arg,
|
||||
Fields,
|
||||
Flag,
|
||||
Int,
|
||||
Float,
|
||||
Vector
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ChocolArm64.Translation
|
||||
|
@ -65,11 +66,41 @@ namespace ChocolArm64.Translation
|
|||
public long VecInputs;
|
||||
public long IntOutputs;
|
||||
public long VecOutputs;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is BlockIo other))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return other.Block == Block &&
|
||||
other.Entry == Entry &&
|
||||
other.IntInputs == IntInputs &&
|
||||
other.VecInputs == VecInputs &&
|
||||
other.IntOutputs == IntOutputs &&
|
||||
other.VecOutputs == VecOutputs;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Block, Entry, IntInputs, VecInputs, IntOutputs, VecOutputs);
|
||||
}
|
||||
|
||||
public static bool operator ==(BlockIo lhs, BlockIo rhs)
|
||||
{
|
||||
return lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool operator !=(BlockIo lhs, BlockIo rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
|
||||
private const int MaxOptGraphLength = 40;
|
||||
|
||||
public LocalAlloc(ILBlock[] graph, ILBlock root)
|
||||
public LocalAlloc(ILBlock[] graph, ILBlock entry)
|
||||
{
|
||||
_intPaths = new Dictionary<ILBlock, PathIo>();
|
||||
_vecPaths = new Dictionary<ILBlock, PathIo>();
|
||||
|
@ -77,7 +108,7 @@ namespace ChocolArm64.Translation
|
|||
if (graph.Length > 1 &&
|
||||
graph.Length < MaxOptGraphLength)
|
||||
{
|
||||
InitializeOptimal(graph, root);
|
||||
InitializeOptimal(graph, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -85,7 +116,7 @@ namespace ChocolArm64.Translation
|
|||
}
|
||||
}
|
||||
|
||||
private void InitializeOptimal(ILBlock[] graph, ILBlock root)
|
||||
private void InitializeOptimal(ILBlock[] graph, ILBlock entry)
|
||||
{
|
||||
//This will go through all possible paths on the graph,
|
||||
//and store all inputs/outputs for each block. A register
|
||||
|
@ -93,7 +124,7 @@ namespace ChocolArm64.Translation
|
|||
//When a block can be reached by more than one path, then the
|
||||
//output from all paths needs to be set for this block, and
|
||||
//only outputs present in all of the parent blocks can be considered
|
||||
//when doing input elimination. Each block chain have a root, that's where
|
||||
//when doing input elimination. Each block chain have a entry, that's where
|
||||
//the code starts executing. They are present on the subroutine start point,
|
||||
//and on call return points too (address written to X30 by BL).
|
||||
HashSet<BlockIo> visited = new HashSet<BlockIo>();
|
||||
|
@ -112,8 +143,8 @@ namespace ChocolArm64.Translation
|
|||
|
||||
Enqueue(new BlockIo()
|
||||
{
|
||||
Block = root,
|
||||
Entry = root
|
||||
Block = entry,
|
||||
Entry = entry
|
||||
});
|
||||
|
||||
while (unvisited.Count > 0)
|
||||
|
@ -146,22 +177,22 @@ namespace ChocolArm64.Translation
|
|||
|
||||
void EnqueueFromCurrent(ILBlock block, bool retTarget)
|
||||
{
|
||||
BlockIo blkIO = new BlockIo() { Block = block };
|
||||
BlockIo blockIo = new BlockIo() { Block = block };
|
||||
|
||||
if (retTarget)
|
||||
{
|
||||
blkIO.Entry = block;
|
||||
blockIo.Entry = block;
|
||||
}
|
||||
else
|
||||
{
|
||||
blkIO.Entry = current.Entry;
|
||||
blkIO.IntInputs = current.IntInputs;
|
||||
blkIO.VecInputs = current.VecInputs;
|
||||
blkIO.IntOutputs = current.IntOutputs;
|
||||
blkIO.VecOutputs = current.VecOutputs;
|
||||
blockIo.Entry = current.Entry;
|
||||
blockIo.IntInputs = current.IntInputs;
|
||||
blockIo.VecInputs = current.VecInputs;
|
||||
blockIo.IntOutputs = current.IntOutputs;
|
||||
blockIo.VecOutputs = current.VecOutputs;
|
||||
}
|
||||
|
||||
Enqueue(blkIO);
|
||||
Enqueue(blockIo);
|
||||
}
|
||||
|
||||
if (current.Block.Next != null)
|
||||
|
@ -179,7 +210,7 @@ namespace ChocolArm64.Translation
|
|||
private void InitializeFast(ILBlock[] graph)
|
||||
{
|
||||
//This is WAY faster than InitializeOptimal, but results in
|
||||
//uneeded loads and stores, so the resulting code will be slower.
|
||||
//unneeded loads and stores, so the resulting code will be slower.
|
||||
long intInputs = 0, intOutputs = 0;
|
||||
long vecInputs = 0, vecOutputs = 0;
|
||||
|
||||
|
|
|
@ -83,47 +83,45 @@ namespace ChocolArm64
|
|||
{
|
||||
Block block = Decoder.DecodeBasicBlock(state, memory, position);
|
||||
|
||||
Block[] graph = new Block[] { block };
|
||||
ILEmitterCtx context = new ILEmitterCtx(_cache, block);
|
||||
|
||||
string subName = GetSubroutineName(position);
|
||||
|
||||
ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName);
|
||||
ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName);
|
||||
|
||||
do
|
||||
{
|
||||
context.EmitOpCode();
|
||||
}
|
||||
while (context.AdvanceOpCode());
|
||||
|
||||
TranslatedSub subroutine = context.GetSubroutine();
|
||||
TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();
|
||||
|
||||
subroutine.SetType(TranslatedSubType.SubTier0);
|
||||
|
||||
_cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);
|
||||
|
||||
OpCode64 lastOp = block.GetLastOp();
|
||||
|
||||
return subroutine;
|
||||
}
|
||||
|
||||
private void TranslateTier1(CpuThreadState state, MemoryManager memory, long position)
|
||||
{
|
||||
(Block[] graph, Block root) = Decoder.DecodeSubroutine(_cache, state, memory, position);
|
||||
Block graph = Decoder.DecodeSubroutine(_cache, state, memory, position);
|
||||
|
||||
ILEmitterCtx context = new ILEmitterCtx(_cache, graph);
|
||||
|
||||
ILBlock[] ilBlocks = context.GetILBlocks();
|
||||
|
||||
string subName = GetSubroutineName(position);
|
||||
|
||||
ILEmitterCtx context = new ILEmitterCtx(_cache, graph, root, subName);
|
||||
ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName);
|
||||
|
||||
if (context.CurrBlock.Position != position)
|
||||
TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();
|
||||
|
||||
subroutine.SetType(TranslatedSubType.SubTier1);
|
||||
|
||||
int ilOpCount = 0;
|
||||
|
||||
foreach (ILBlock ilBlock in ilBlocks)
|
||||
{
|
||||
context.Emit(OpCodes.Br, context.GetLabel(position));
|
||||
ilOpCount += ilBlock.Count;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
context.EmitOpCode();
|
||||
}
|
||||
while (context.AdvanceOpCode());
|
||||
_cache.AddOrUpdate(position, subroutine, ilOpCount);
|
||||
|
||||
//Mark all methods that calls this method for ReJiting,
|
||||
//since we can now call it directly which is faster.
|
||||
|
@ -137,29 +135,11 @@ namespace ChocolArm64
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TranslatedSub subroutine = context.GetSubroutine();
|
||||
|
||||
subroutine.SetType(TranslatedSubType.SubTier1);
|
||||
|
||||
_cache.AddOrUpdate(position, subroutine, GetGraphInstCount(graph));
|
||||
}
|
||||
|
||||
private string GetSubroutineName(long position)
|
||||
{
|
||||
return $"Sub{position:x16}";
|
||||
}
|
||||
|
||||
private int GetGraphInstCount(Block[] graph)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
foreach (Block block in graph)
|
||||
{
|
||||
size += block.OpCodes.Count;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ namespace ChocolArm64
|
|||
{
|
||||
class TranslatorCache
|
||||
{
|
||||
//Maximum size of the cache, in bytes, measured in ARM code size.
|
||||
private const int MaxTotalSize = 4 * 1024 * 256;
|
||||
//Maximum size of the cache, the unit used is completely arbitrary.
|
||||
private const int MaxTotalSize = 0x800000;
|
||||
|
||||
//Minimum time required in milliseconds for a method to be eligible for deletion.
|
||||
private const int MinTimeDelta = 2 * 60000;
|
||||
|
@ -63,10 +63,10 @@ namespace ChocolArm64
|
|||
{
|
||||
ClearCacheIfNeeded();
|
||||
|
||||
_totalSize += size;
|
||||
|
||||
lock (_sortedCache)
|
||||
{
|
||||
_totalSize += size;
|
||||
|
||||
LinkedListNode<long> node = _sortedCache.AddLast(position);
|
||||
|
||||
CacheBucket newBucket = new CacheBucket(subroutine, node, size);
|
||||
|
@ -98,11 +98,18 @@ namespace ChocolArm64
|
|||
{
|
||||
try
|
||||
{
|
||||
bucket.CallCount = 0;
|
||||
//The bucket value on the dictionary may have changed between the
|
||||
//time we get the value from the dictionary, and we acquire the
|
||||
//lock. So we need to ensure we are working with the latest value,
|
||||
//we can do that by getting the value again, inside the lock.
|
||||
if (_cache.TryGetValue(position, out CacheBucket latestBucket))
|
||||
{
|
||||
latestBucket.CallCount = 0;
|
||||
|
||||
_sortedCache.Remove(bucket.Node);
|
||||
_sortedCache.Remove(latestBucket.Node);
|
||||
|
||||
bucket.UpdateNode(_sortedCache.AddLast(position));
|
||||
latestBucket.UpdateNode(_sortedCache.AddLast(position));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Memory
|
|||
{
|
||||
this.Memory = Memory;
|
||||
|
||||
Cache = new NvGpuVmmCache();
|
||||
Cache = new NvGpuVmmCache(Memory);
|
||||
|
||||
PageTable = new long[PTLvl0Size][];
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ namespace Ryujinx.Graphics.Memory
|
|||
|
||||
public bool IsRegionModified(long PA, long Size, NvGpuBufferType BufferType)
|
||||
{
|
||||
return Cache.IsRegionModified(Memory, BufferType, PA, Size);
|
||||
return Cache.IsRegionModified(PA, Size, BufferType);
|
||||
}
|
||||
|
||||
public bool TryGetHostAddress(long Position, long Size, out IntPtr Ptr)
|
||||
|
|
|
@ -1,130 +1,83 @@
|
|||
using ChocolArm64.Events;
|
||||
using ChocolArm64.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Ryujinx.Graphics.Memory
|
||||
{
|
||||
class NvGpuVmmCache
|
||||
{
|
||||
private struct CachedResource
|
||||
private const int PageBits = MemoryManager.PageBits;
|
||||
|
||||
private const long PageSize = MemoryManager.PageSize;
|
||||
private const long PageMask = MemoryManager.PageMask;
|
||||
|
||||
private ConcurrentDictionary<long, int>[] CachedPages;
|
||||
|
||||
private MemoryManager _memory;
|
||||
|
||||
public NvGpuVmmCache(MemoryManager memory)
|
||||
{
|
||||
public long Key;
|
||||
public int Mask;
|
||||
_memory = memory;
|
||||
|
||||
public CachedResource(long Key, int Mask)
|
||||
{
|
||||
this.Key = Key;
|
||||
this.Mask = Mask;
|
||||
}
|
||||
_memory.ObservedAccess += MemoryAccessHandler;
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)(Key * 23 + Mask);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is CachedResource Cached && Equals(Cached);
|
||||
}
|
||||
|
||||
public bool Equals(CachedResource other)
|
||||
{
|
||||
return Key == other.Key && Mask == other.Mask;
|
||||
}
|
||||
CachedPages = new ConcurrentDictionary<long, int>[1 << 20];
|
||||
}
|
||||
|
||||
private ValueRangeSet<CachedResource> CachedRanges;
|
||||
|
||||
public NvGpuVmmCache()
|
||||
private void MemoryAccessHandler(object sender, MemoryAccessEventArgs e)
|
||||
{
|
||||
CachedRanges = new ValueRangeSet<CachedResource>();
|
||||
long pa = _memory.GetPhysicalAddress(e.Position);
|
||||
|
||||
CachedPages[pa >> PageBits]?.Clear();
|
||||
}
|
||||
|
||||
public bool IsRegionModified(MemoryManager Memory, NvGpuBufferType BufferType, long Start, long Size)
|
||||
public bool IsRegionModified(long position, long size, NvGpuBufferType bufferType)
|
||||
{
|
||||
(bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(Start, Size);
|
||||
long pa = _memory.GetPhysicalAddress(position);
|
||||
|
||||
//Remove all modified ranges.
|
||||
int Index = 0;
|
||||
long addr = pa;
|
||||
|
||||
long Position = Start & ~NvGpuVmm.PageMask;
|
||||
long endAddr = (addr + size + PageMask) & ~PageMask;
|
||||
|
||||
while (ModifiedCount > 0)
|
||||
int newBuffMask = 1 << (int)bufferType;
|
||||
|
||||
_memory.StartObservingRegion(position, size);
|
||||
|
||||
long cachedPagesCount = 0;
|
||||
|
||||
while (addr < endAddr)
|
||||
{
|
||||
if (Modified[Index++])
|
||||
{
|
||||
CachedRanges.Remove(new ValueRange<CachedResource>(Position, Position + NvGpuVmm.PageSize));
|
||||
long page = addr >> PageBits;
|
||||
|
||||
ModifiedCount--;
|
||||
ConcurrentDictionary<long, int> dictionary = CachedPages[page];
|
||||
|
||||
if (dictionary == null)
|
||||
{
|
||||
dictionary = new ConcurrentDictionary<long, int>();
|
||||
|
||||
CachedPages[page] = dictionary;
|
||||
}
|
||||
|
||||
Position += NvGpuVmm.PageSize;
|
||||
if (dictionary.TryGetValue(pa, out int currBuffMask))
|
||||
{
|
||||
if ((currBuffMask & newBuffMask) != 0)
|
||||
{
|
||||
cachedPagesCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary[pa] |= newBuffMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary[pa] = newBuffMask;
|
||||
}
|
||||
|
||||
addr += PageSize;
|
||||
}
|
||||
|
||||
//Mask has the bit set for the current resource type.
|
||||
//If the region is not yet present on the list, then a new ValueRange
|
||||
//is directly added with the current resource type as the only bit set.
|
||||
//Otherwise, it just sets the bit for this new resource type on the current mask.
|
||||
//The physical address of the resource is used as key, those keys are used to keep
|
||||
//track of resources that are already on the cache. A resource may be inside another
|
||||
//resource, and in this case we should return true if the "sub-resource" was not
|
||||
//yet cached.
|
||||
int Mask = 1 << (int)BufferType;
|
||||
|
||||
CachedResource NewCachedValue = new CachedResource(Start, Mask);
|
||||
|
||||
ValueRange<CachedResource> NewCached = new ValueRange<CachedResource>(Start, Start + Size);
|
||||
|
||||
ValueRange<CachedResource>[] Ranges = CachedRanges.GetAllIntersections(NewCached);
|
||||
|
||||
bool IsKeyCached = Ranges.Length > 0 && Ranges[0].Value.Key == Start;
|
||||
|
||||
long LastEnd = NewCached.Start;
|
||||
|
||||
long Coverage = 0;
|
||||
|
||||
for (Index = 0; Index < Ranges.Length; Index++)
|
||||
{
|
||||
ValueRange<CachedResource> Current = Ranges[Index];
|
||||
|
||||
CachedResource Cached = Current.Value;
|
||||
|
||||
long RgStart = Math.Max(Current.Start, NewCached.Start);
|
||||
long RgEnd = Math.Min(Current.End, NewCached.End);
|
||||
|
||||
if ((Cached.Mask & Mask) != 0)
|
||||
{
|
||||
Coverage += RgEnd - RgStart;
|
||||
}
|
||||
|
||||
//Highest key value has priority, this prevents larger resources
|
||||
//for completely invalidating smaller ones on the cache. For example,
|
||||
//consider that a resource in the range [100, 200) was added, and then
|
||||
//another one in the range [50, 200). We prevent the new resource from
|
||||
//completely replacing the old one by spliting it like this:
|
||||
//New resource key is added at [50, 100), old key is still present at [100, 200).
|
||||
if (Cached.Key < Start)
|
||||
{
|
||||
Cached.Key = Start;
|
||||
}
|
||||
|
||||
Cached.Mask |= Mask;
|
||||
|
||||
CachedRanges.Add(new ValueRange<CachedResource>(RgStart, RgEnd, Cached));
|
||||
|
||||
if (RgStart > LastEnd)
|
||||
{
|
||||
CachedRanges.Add(new ValueRange<CachedResource>(LastEnd, RgStart, NewCachedValue));
|
||||
}
|
||||
|
||||
LastEnd = RgEnd;
|
||||
}
|
||||
|
||||
if (LastEnd < NewCached.End)
|
||||
{
|
||||
CachedRanges.Add(new ValueRange<CachedResource>(LastEnd, NewCached.End, NewCachedValue));
|
||||
}
|
||||
|
||||
return !IsKeyCached || Coverage != Size;
|
||||
return cachedPagesCount != (endAddr - pa + PageMask) >> PageBits;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
namespace Ryujinx.Graphics
|
||||
{
|
||||
struct ValueRange<T>
|
||||
{
|
||||
public long Start { get; private set; }
|
||||
public long End { get; private set; }
|
||||
|
||||
public T Value { get; set; }
|
||||
|
||||
public ValueRange(long Start, long End, T Value = default(T))
|
||||
{
|
||||
this.Start = Start;
|
||||
this.End = End;
|
||||
this.Value = Value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics
|
||||
{
|
||||
class ValueRangeSet<T>
|
||||
{
|
||||
private List<ValueRange<T>> Ranges;
|
||||
|
||||
public ValueRangeSet()
|
||||
{
|
||||
Ranges = new List<ValueRange<T>>();
|
||||
}
|
||||
|
||||
public void Add(ValueRange<T> Range)
|
||||
{
|
||||
if (Range.End <= Range.Start)
|
||||
{
|
||||
//Empty or invalid range, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
int First = BinarySearchFirstIntersection(Range);
|
||||
|
||||
if (First == -1)
|
||||
{
|
||||
//No intersections case.
|
||||
//Find first greater than range (after the current one).
|
||||
//If found, add before, otherwise add to the end of the list.
|
||||
int GtIndex = BinarySearchGt(Range);
|
||||
|
||||
if (GtIndex != -1)
|
||||
{
|
||||
Ranges.Insert(GtIndex, Range);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ranges.Add(Range);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
(int Start, int End) = GetAllIntersectionRanges(Range, First);
|
||||
|
||||
ValueRange<T> Prev = Ranges[Start];
|
||||
ValueRange<T> Next = Ranges[End];
|
||||
|
||||
Ranges.RemoveRange(Start, (End - Start) + 1);
|
||||
|
||||
InsertNextNeighbour(Start, Range, Next);
|
||||
|
||||
int NewIndex = Start;
|
||||
|
||||
Ranges.Insert(Start, Range);
|
||||
|
||||
InsertPrevNeighbour(Start, Range, Prev);
|
||||
|
||||
//Try merging neighbours if the value is equal.
|
||||
if (NewIndex > 0)
|
||||
{
|
||||
Prev = Ranges[NewIndex - 1];
|
||||
|
||||
if (Prev.End == Range.Start && CompareValues(Prev, Range))
|
||||
{
|
||||
Ranges.RemoveAt(--NewIndex);
|
||||
|
||||
Ranges[NewIndex] = new ValueRange<T>(Prev.Start, Range.End, Range.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (NewIndex < Ranges.Count - 1)
|
||||
{
|
||||
Next = Ranges[NewIndex + 1];
|
||||
|
||||
if (Next.Start == Range.End && CompareValues(Next, Range))
|
||||
{
|
||||
Ranges.RemoveAt(NewIndex + 1);
|
||||
|
||||
Ranges[NewIndex] = new ValueRange<T>(Ranges[NewIndex].Start, Next.End, Range.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CompareValues(ValueRange<T> LHS, ValueRange<T> RHS)
|
||||
{
|
||||
return LHS.Value?.Equals(RHS.Value) ?? RHS.Value == null;
|
||||
}
|
||||
|
||||
public void Remove(ValueRange<T> Range)
|
||||
{
|
||||
int First = BinarySearchFirstIntersection(Range);
|
||||
|
||||
if (First == -1)
|
||||
{
|
||||
//Nothing to remove.
|
||||
return;
|
||||
}
|
||||
|
||||
(int Start, int End) = GetAllIntersectionRanges(Range, First);
|
||||
|
||||
ValueRange<T> Prev = Ranges[Start];
|
||||
ValueRange<T> Next = Ranges[End];
|
||||
|
||||
Ranges.RemoveRange(Start, (End - Start) + 1);
|
||||
|
||||
InsertNextNeighbour(Start, Range, Next);
|
||||
InsertPrevNeighbour(Start, Range, Prev);
|
||||
}
|
||||
|
||||
private void InsertNextNeighbour(int Index, ValueRange<T> Range, ValueRange<T> Next)
|
||||
{
|
||||
//Split last intersection (ordered by Start) if necessary.
|
||||
if (Range.End < Next.End)
|
||||
{
|
||||
InsertNewRange(Index, Range.End, Next.End, Next.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertPrevNeighbour(int Index, ValueRange<T> Range, ValueRange<T> Prev)
|
||||
{
|
||||
//Split first intersection (ordered by Start) if necessary.
|
||||
if (Range.Start > Prev.Start)
|
||||
{
|
||||
InsertNewRange(Index, Prev.Start, Range.Start, Prev.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertNewRange(int Index, long Start, long End, T Value)
|
||||
{
|
||||
Ranges.Insert(Index, new ValueRange<T>(Start, End, Value));
|
||||
}
|
||||
|
||||
public ValueRange<T>[] GetAllIntersections(ValueRange<T> Range)
|
||||
{
|
||||
int First = BinarySearchFirstIntersection(Range);
|
||||
|
||||
if (First == -1)
|
||||
{
|
||||
return new ValueRange<T>[0];
|
||||
}
|
||||
|
||||
(int Start, int End) = GetAllIntersectionRanges(Range, First);
|
||||
|
||||
return Ranges.GetRange(Start, (End - Start) + 1).ToArray();
|
||||
}
|
||||
|
||||
private (int Start, int End) GetAllIntersectionRanges(ValueRange<T> Range, int BaseIndex)
|
||||
{
|
||||
int Start = BaseIndex;
|
||||
int End = BaseIndex;
|
||||
|
||||
while (Start > 0 && Intersects(Range, Ranges[Start - 1]))
|
||||
{
|
||||
Start--;
|
||||
}
|
||||
|
||||
while (End < Ranges.Count - 1 && Intersects(Range, Ranges[End + 1]))
|
||||
{
|
||||
End++;
|
||||
}
|
||||
|
||||
return (Start, End);
|
||||
}
|
||||
|
||||
private int BinarySearchFirstIntersection(ValueRange<T> Range)
|
||||
{
|
||||
int Left = 0;
|
||||
int Right = Ranges.Count - 1;
|
||||
|
||||
while (Left <= Right)
|
||||
{
|
||||
int Size = Right - Left;
|
||||
|
||||
int Middle = Left + (Size >> 1);
|
||||
|
||||
ValueRange<T> Current = Ranges[Middle];
|
||||
|
||||
if (Intersects(Range, Current))
|
||||
{
|
||||
return Middle;
|
||||
}
|
||||
|
||||
if (Range.Start < Current.Start)
|
||||
{
|
||||
Right = Middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Left = Middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int BinarySearchGt(ValueRange<T> Range)
|
||||
{
|
||||
int GtIndex = -1;
|
||||
|
||||
int Left = 0;
|
||||
int Right = Ranges.Count - 1;
|
||||
|
||||
while (Left <= Right)
|
||||
{
|
||||
int Size = Right - Left;
|
||||
|
||||
int Middle = Left + (Size >> 1);
|
||||
|
||||
ValueRange<T> Current = Ranges[Middle];
|
||||
|
||||
if (Range.Start < Current.Start)
|
||||
{
|
||||
Right = Middle - 1;
|
||||
|
||||
if (GtIndex == -1 || Current.Start < Ranges[GtIndex].Start)
|
||||
{
|
||||
GtIndex = Middle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Left = Middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return GtIndex;
|
||||
}
|
||||
|
||||
private bool Intersects(ValueRange<T> LHS, ValueRange<T> RHS)
|
||||
{
|
||||
return LHS.Start < RHS.End && RHS.Start < LHS.End;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,107 +9,107 @@ namespace Ryujinx.HLE
|
|||
|
||||
public IntPtr RamPointer { get; private set; }
|
||||
|
||||
private unsafe byte* RamPtr;
|
||||
private unsafe byte* _ramPtr;
|
||||
|
||||
public unsafe DeviceMemory()
|
||||
{
|
||||
RamPointer = Marshal.AllocHGlobal(new IntPtr(RamSize));
|
||||
|
||||
RamPtr = (byte*)RamPointer;
|
||||
_ramPtr = (byte*)RamPointer;
|
||||
}
|
||||
|
||||
public sbyte ReadSByte(long Position)
|
||||
public sbyte ReadSByte(long position)
|
||||
{
|
||||
return (sbyte)ReadByte(Position);
|
||||
return (sbyte)ReadByte(position);
|
||||
}
|
||||
|
||||
public short ReadInt16(long Position)
|
||||
public short ReadInt16(long position)
|
||||
{
|
||||
return (short)ReadUInt16(Position);
|
||||
return (short)ReadUInt16(position);
|
||||
}
|
||||
|
||||
public int ReadInt32(long Position)
|
||||
public int ReadInt32(long position)
|
||||
{
|
||||
return (int)ReadUInt32(Position);
|
||||
return (int)ReadUInt32(position);
|
||||
}
|
||||
|
||||
public long ReadInt64(long Position)
|
||||
public long ReadInt64(long position)
|
||||
{
|
||||
return (long)ReadUInt64(Position);
|
||||
return (long)ReadUInt64(position);
|
||||
}
|
||||
|
||||
public unsafe byte ReadByte(long Position)
|
||||
public unsafe byte ReadByte(long position)
|
||||
{
|
||||
return *((byte*)(RamPtr + Position));
|
||||
return *(_ramPtr + position);
|
||||
}
|
||||
|
||||
public unsafe ushort ReadUInt16(long Position)
|
||||
public unsafe ushort ReadUInt16(long position)
|
||||
{
|
||||
return *((ushort*)(RamPtr + Position));
|
||||
return *((ushort*)(_ramPtr + position));
|
||||
}
|
||||
|
||||
public unsafe uint ReadUInt32(long Position)
|
||||
public unsafe uint ReadUInt32(long position)
|
||||
{
|
||||
return *((uint*)(RamPtr + Position));
|
||||
return *((uint*)(_ramPtr + position));
|
||||
}
|
||||
|
||||
public unsafe ulong ReadUInt64(long Position)
|
||||
public unsafe ulong ReadUInt64(long position)
|
||||
{
|
||||
return *((ulong*)(RamPtr + Position));
|
||||
return *((ulong*)(_ramPtr + position));
|
||||
}
|
||||
|
||||
public void WriteSByte(long Position, sbyte Value)
|
||||
public void WriteSByte(long position, sbyte value)
|
||||
{
|
||||
WriteByte(Position, (byte)Value);
|
||||
WriteByte(position, (byte)value);
|
||||
}
|
||||
|
||||
public void WriteInt16(long Position, short Value)
|
||||
public void WriteInt16(long position, short value)
|
||||
{
|
||||
WriteUInt16(Position, (ushort)Value);
|
||||
WriteUInt16(position, (ushort)value);
|
||||
}
|
||||
|
||||
public void WriteInt32(long Position, int Value)
|
||||
public void WriteInt32(long position, int value)
|
||||
{
|
||||
WriteUInt32(Position, (uint)Value);
|
||||
WriteUInt32(position, (uint)value);
|
||||
}
|
||||
|
||||
public void WriteInt64(long Position, long Value)
|
||||
public void WriteInt64(long position, long value)
|
||||
{
|
||||
WriteUInt64(Position, (ulong)Value);
|
||||
WriteUInt64(position, (ulong)value);
|
||||
}
|
||||
|
||||
public unsafe void WriteByte(long Position, byte Value)
|
||||
public unsafe void WriteByte(long position, byte value)
|
||||
{
|
||||
*((byte*)(RamPtr + Position)) = Value;
|
||||
*(_ramPtr + position) = value;
|
||||
}
|
||||
|
||||
public unsafe void WriteUInt16(long Position, ushort Value)
|
||||
public unsafe void WriteUInt16(long position, ushort value)
|
||||
{
|
||||
*((ushort*)(RamPtr + Position)) = Value;
|
||||
*((ushort*)(_ramPtr + position)) = value;
|
||||
}
|
||||
|
||||
public unsafe void WriteUInt32(long Position, uint Value)
|
||||
public unsafe void WriteUInt32(long position, uint value)
|
||||
{
|
||||
*((uint*)(RamPtr + Position)) = Value;
|
||||
*((uint*)(_ramPtr + position)) = value;
|
||||
}
|
||||
|
||||
public unsafe void WriteUInt64(long Position, ulong Value)
|
||||
public unsafe void WriteUInt64(long position, ulong value)
|
||||
{
|
||||
*((ulong*)(RamPtr + Position)) = Value;
|
||||
*((ulong*)(_ramPtr + position)) = value;
|
||||
}
|
||||
|
||||
public void FillWithZeros(long Position, int Size)
|
||||
public void FillWithZeros(long position, int size)
|
||||
{
|
||||
int Size8 = Size & ~(8 - 1);
|
||||
int size8 = size & ~(8 - 1);
|
||||
|
||||
for (int Offs = 0; Offs < Size8; Offs += 8)
|
||||
for (int offs = 0; offs < size8; offs += 8)
|
||||
{
|
||||
WriteInt64(Position + Offs, 0);
|
||||
WriteInt64(position + offs, 0);
|
||||
}
|
||||
|
||||
for (int Offs = Size8; Offs < (Size - Size8); Offs++)
|
||||
for (int offs = size8; offs < (size - size8); offs++)
|
||||
{
|
||||
WriteByte(Position + Offs, 0);
|
||||
WriteByte(position + offs, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ namespace Ryujinx.HLE
|
|||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool Disposing)
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
Marshal.FreeHGlobal(RamPointer);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ namespace Ryujinx.HLE.Exceptions
|
|||
{
|
||||
public class InvalidNpdmException : Exception
|
||||
{
|
||||
public InvalidNpdmException(string ExMsg) : base(ExMsg) { }
|
||||
public InvalidNpdmException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ namespace Ryujinx.HLE.Exceptions
|
|||
|
||||
public UndefinedInstructionException() : base() { }
|
||||
|
||||
public UndefinedInstructionException(long Position, int OpCode) : base(string.Format(ExMsg, Position, OpCode)) { }
|
||||
public UndefinedInstructionException(long position, int opCode) : base(string.Format(ExMsg, position, opCode)) { }
|
||||
}
|
||||
}
|
|
@ -9,297 +9,297 @@ namespace Ryujinx.HLE.FileSystem.Content
|
|||
{
|
||||
internal class ContentManager
|
||||
{
|
||||
private Dictionary<StorageId, LinkedList<LocationEntry>> LocationEntries;
|
||||
private Dictionary<StorageId, LinkedList<LocationEntry>> _locationEntries;
|
||||
|
||||
private Dictionary<string, long> SharedFontTitleDictionary;
|
||||
private Dictionary<string, long> _sharedFontTitleDictionary;
|
||||
|
||||
private SortedDictionary<(ulong, ContentType), string> ContentDictionary;
|
||||
private SortedDictionary<(ulong, ContentType), string> _contentDictionary;
|
||||
|
||||
private Switch Device;
|
||||
private Switch _device;
|
||||
|
||||
public ContentManager(Switch Device)
|
||||
public ContentManager(Switch device)
|
||||
{
|
||||
ContentDictionary = new SortedDictionary<(ulong, ContentType), string>();
|
||||
LocationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
|
||||
_contentDictionary = new SortedDictionary<(ulong, ContentType), string>();
|
||||
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
|
||||
|
||||
SharedFontTitleDictionary = new Dictionary<string, long>()
|
||||
_sharedFontTitleDictionary = new Dictionary<string, long>
|
||||
{
|
||||
{ "FontStandard", 0x0100000000000811 },
|
||||
{ "FontChineseSimplified", 0x0100000000000814 },
|
||||
{ "FontExtendedChineseSimplified", 0x0100000000000814 },
|
||||
{ "FontKorean", 0x0100000000000812 },
|
||||
{ "FontChineseTraditional", 0x0100000000000813 },
|
||||
{ "FontNintendoExtended" , 0x0100000000000810 },
|
||||
{ "FontNintendoExtended", 0x0100000000000810 }
|
||||
};
|
||||
|
||||
this.Device = Device;
|
||||
_device = device;
|
||||
}
|
||||
|
||||
public void LoadEntries()
|
||||
{
|
||||
ContentDictionary = new SortedDictionary<(ulong, ContentType), string>();
|
||||
_contentDictionary = new SortedDictionary<(ulong, ContentType), string>();
|
||||
|
||||
foreach (StorageId StorageId in Enum.GetValues(typeof(StorageId)))
|
||||
foreach (StorageId storageId in Enum.GetValues(typeof(StorageId)))
|
||||
{
|
||||
string ContentDirectory = null;
|
||||
string ContentPathString = null;
|
||||
string RegisteredDirectory = null;
|
||||
string contentDirectory = null;
|
||||
string contentPathString = null;
|
||||
string registeredDirectory = null;
|
||||
|
||||
try
|
||||
{
|
||||
ContentPathString = LocationHelper.GetContentRoot(StorageId);
|
||||
ContentDirectory = LocationHelper.GetRealPath(Device.FileSystem, ContentPathString);
|
||||
RegisteredDirectory = Path.Combine(ContentDirectory, "registered");
|
||||
contentPathString = LocationHelper.GetContentRoot(storageId);
|
||||
contentDirectory = LocationHelper.GetRealPath(_device.FileSystem, contentPathString);
|
||||
registeredDirectory = Path.Combine(contentDirectory, "registered");
|
||||
}
|
||||
catch (NotSupportedException NEx)
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(RegisteredDirectory);
|
||||
Directory.CreateDirectory(registeredDirectory);
|
||||
|
||||
LinkedList<LocationEntry> LocationList = new LinkedList<LocationEntry>();
|
||||
LinkedList<LocationEntry> locationList = new LinkedList<LocationEntry>();
|
||||
|
||||
void AddEntry(LocationEntry Entry)
|
||||
void AddEntry(LocationEntry entry)
|
||||
{
|
||||
LocationList.AddLast(Entry);
|
||||
locationList.AddLast(entry);
|
||||
}
|
||||
|
||||
foreach (string DirectoryPath in Directory.EnumerateDirectories(RegisteredDirectory))
|
||||
foreach (string directoryPath in Directory.EnumerateDirectories(registeredDirectory))
|
||||
{
|
||||
if (Directory.GetFiles(DirectoryPath).Length > 0)
|
||||
if (Directory.GetFiles(directoryPath).Length > 0)
|
||||
{
|
||||
string NcaName = new DirectoryInfo(DirectoryPath).Name.Replace(".nca", string.Empty);
|
||||
string ncaName = new DirectoryInfo(directoryPath).Name.Replace(".nca", string.Empty);
|
||||
|
||||
using (FileStream NcaFile = new FileStream(Directory.GetFiles(DirectoryPath)[0], FileMode.Open, FileAccess.Read))
|
||||
using (FileStream ncaFile = new FileStream(Directory.GetFiles(directoryPath)[0], FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
Nca Nca = new Nca(Device.System.KeySet, NcaFile, false);
|
||||
Nca nca = new Nca(_device.System.KeySet, ncaFile, false);
|
||||
|
||||
string SwitchPath = Path.Combine(ContentPathString + ":",
|
||||
NcaFile.Name.Replace(ContentDirectory, string.Empty).TrimStart('\\'));
|
||||
string switchPath = Path.Combine(contentPathString + ":",
|
||||
ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart('\\'));
|
||||
|
||||
// Change path format to switch's
|
||||
SwitchPath = SwitchPath.Replace('\\', '/');
|
||||
switchPath = switchPath.Replace('\\', '/');
|
||||
|
||||
LocationEntry Entry = new LocationEntry(SwitchPath,
|
||||
LocationEntry entry = new LocationEntry(switchPath,
|
||||
0,
|
||||
(long)Nca.Header.TitleId,
|
||||
Nca.Header.ContentType);
|
||||
(long)nca.Header.TitleId,
|
||||
nca.Header.ContentType);
|
||||
|
||||
AddEntry(Entry);
|
||||
AddEntry(entry);
|
||||
|
||||
ContentDictionary.Add((Nca.Header.TitleId, Nca.Header.ContentType), NcaName);
|
||||
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
|
||||
|
||||
NcaFile.Close();
|
||||
Nca.Dispose();
|
||||
NcaFile.Dispose();
|
||||
ncaFile.Close();
|
||||
nca.Dispose();
|
||||
ncaFile.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string FilePath in Directory.EnumerateFiles(ContentDirectory))
|
||||
foreach (string filePath in Directory.EnumerateFiles(contentDirectory))
|
||||
{
|
||||
if (Path.GetExtension(FilePath) == ".nca")
|
||||
if (Path.GetExtension(filePath) == ".nca")
|
||||
{
|
||||
string NcaName = Path.GetFileNameWithoutExtension(FilePath);
|
||||
string ncaName = Path.GetFileNameWithoutExtension(filePath);
|
||||
|
||||
using (FileStream NcaFile = new FileStream(FilePath, FileMode.Open, FileAccess.Read))
|
||||
using (FileStream ncaFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
Nca Nca = new Nca(Device.System.KeySet, NcaFile, false);
|
||||
Nca nca = new Nca(_device.System.KeySet, ncaFile, false);
|
||||
|
||||
string SwitchPath = Path.Combine(ContentPathString + ":",
|
||||
FilePath.Replace(ContentDirectory, string.Empty).TrimStart('\\'));
|
||||
string switchPath = Path.Combine(contentPathString + ":",
|
||||
filePath.Replace(contentDirectory, string.Empty).TrimStart('\\'));
|
||||
|
||||
// Change path format to switch's
|
||||
SwitchPath = SwitchPath.Replace('\\', '/');
|
||||
switchPath = switchPath.Replace('\\', '/');
|
||||
|
||||
LocationEntry Entry = new LocationEntry(SwitchPath,
|
||||
LocationEntry entry = new LocationEntry(switchPath,
|
||||
0,
|
||||
(long)Nca.Header.TitleId,
|
||||
Nca.Header.ContentType);
|
||||
(long)nca.Header.TitleId,
|
||||
nca.Header.ContentType);
|
||||
|
||||
AddEntry(Entry);
|
||||
AddEntry(entry);
|
||||
|
||||
ContentDictionary.Add((Nca.Header.TitleId, Nca.Header.ContentType), NcaName);
|
||||
_contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName);
|
||||
|
||||
NcaFile.Close();
|
||||
Nca.Dispose();
|
||||
NcaFile.Dispose();
|
||||
ncaFile.Close();
|
||||
nca.Dispose();
|
||||
ncaFile.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(LocationEntries.ContainsKey(StorageId) && LocationEntries[StorageId]?.Count == 0)
|
||||
if(_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0)
|
||||
{
|
||||
LocationEntries.Remove(StorageId);
|
||||
_locationEntries.Remove(storageId);
|
||||
}
|
||||
|
||||
if (!LocationEntries.ContainsKey(StorageId))
|
||||
if (!_locationEntries.ContainsKey(storageId))
|
||||
{
|
||||
LocationEntries.Add(StorageId, LocationList);
|
||||
_locationEntries.Add(storageId, locationList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearEntry(long TitleId, ContentType ContentType,StorageId StorageId)
|
||||
public void ClearEntry(long titleId, ContentType contentType,StorageId storageId)
|
||||
{
|
||||
RemoveLocationEntry(TitleId, ContentType, StorageId);
|
||||
RemoveLocationEntry(titleId, contentType, storageId);
|
||||
}
|
||||
|
||||
public void RefreshEntries(StorageId StorageId, int Flag)
|
||||
public void RefreshEntries(StorageId storageId, int flag)
|
||||
{
|
||||
LinkedList<LocationEntry> LocationList = LocationEntries[StorageId];
|
||||
LinkedListNode<LocationEntry> LocationEntry = LocationList.First;
|
||||
LinkedList<LocationEntry> locationList = _locationEntries[storageId];
|
||||
LinkedListNode<LocationEntry> locationEntry = locationList.First;
|
||||
|
||||
while (LocationEntry != null)
|
||||
while (locationEntry != null)
|
||||
{
|
||||
LinkedListNode<LocationEntry> NextLocationEntry = LocationEntry.Next;
|
||||
LinkedListNode<LocationEntry> nextLocationEntry = locationEntry.Next;
|
||||
|
||||
if (LocationEntry.Value.Flag == Flag)
|
||||
if (locationEntry.Value.Flag == flag)
|
||||
{
|
||||
LocationList.Remove(LocationEntry.Value);
|
||||
locationList.Remove(locationEntry.Value);
|
||||
}
|
||||
|
||||
LocationEntry = NextLocationEntry;
|
||||
locationEntry = nextLocationEntry;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasNca(string NcaId, StorageId StorageId)
|
||||
public bool HasNca(string ncaId, StorageId storageId)
|
||||
{
|
||||
if (ContentDictionary.ContainsValue(NcaId))
|
||||
if (_contentDictionary.ContainsValue(ncaId))
|
||||
{
|
||||
var Content = ContentDictionary.FirstOrDefault(x => x.Value == NcaId);
|
||||
long TitleId = (long)Content.Key.Item1;
|
||||
ContentType ContentType = Content.Key.Item2;
|
||||
StorageId Storage = GetInstalledStorage(TitleId, ContentType, StorageId);
|
||||
var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId);
|
||||
long titleId = (long)content.Key.Item1;
|
||||
ContentType contentType = content.Key.Item2;
|
||||
StorageId storage = GetInstalledStorage(titleId, contentType, storageId);
|
||||
|
||||
return Storage == StorageId;
|
||||
return storage == storageId;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public UInt128 GetInstalledNcaId(long TitleId, ContentType ContentType)
|
||||
public UInt128 GetInstalledNcaId(long titleId, ContentType contentType)
|
||||
{
|
||||
if (ContentDictionary.ContainsKey(((ulong)TitleId,ContentType)))
|
||||
if (_contentDictionary.ContainsKey(((ulong)titleId,contentType)))
|
||||
{
|
||||
return new UInt128(ContentDictionary[((ulong)TitleId,ContentType)]);
|
||||
return new UInt128(_contentDictionary[((ulong)titleId,contentType)]);
|
||||
}
|
||||
|
||||
return new UInt128();
|
||||
}
|
||||
|
||||
public StorageId GetInstalledStorage(long TitleId, ContentType ContentType, StorageId StorageId)
|
||||
public StorageId GetInstalledStorage(long titleId, ContentType contentType, StorageId storageId)
|
||||
{
|
||||
LocationEntry LocationEntry = GetLocation(TitleId, ContentType, StorageId);
|
||||
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
|
||||
|
||||
return LocationEntry.ContentPath != null ?
|
||||
LocationHelper.GetStorageId(LocationEntry.ContentPath) : StorageId.None;
|
||||
return locationEntry.ContentPath != null ?
|
||||
LocationHelper.GetStorageId(locationEntry.ContentPath) : StorageId.None;
|
||||
}
|
||||
|
||||
public string GetInstalledContentPath(long TitleId, StorageId StorageId, ContentType ContentType)
|
||||
public string GetInstalledContentPath(long titleId, StorageId storageId, ContentType contentType)
|
||||
{
|
||||
LocationEntry LocationEntry = GetLocation(TitleId, ContentType, StorageId);
|
||||
LocationEntry locationEntry = GetLocation(titleId, contentType, storageId);
|
||||
|
||||
if (VerifyContentType(LocationEntry, ContentType))
|
||||
if (VerifyContentType(locationEntry, contentType))
|
||||
{
|
||||
return LocationEntry.ContentPath;
|
||||
return locationEntry.ContentPath;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void RedirectLocation(LocationEntry NewEntry, StorageId StorageId)
|
||||
public void RedirectLocation(LocationEntry newEntry, StorageId storageId)
|
||||
{
|
||||
LocationEntry LocationEntry = GetLocation(NewEntry.TitleId, NewEntry.ContentType, StorageId);
|
||||
LocationEntry locationEntry = GetLocation(newEntry.TitleId, newEntry.ContentType, storageId);
|
||||
|
||||
if (LocationEntry.ContentPath != null)
|
||||
if (locationEntry.ContentPath != null)
|
||||
{
|
||||
RemoveLocationEntry(NewEntry.TitleId, NewEntry.ContentType, StorageId);
|
||||
RemoveLocationEntry(newEntry.TitleId, newEntry.ContentType, storageId);
|
||||
}
|
||||
|
||||
AddLocationEntry(NewEntry, StorageId);
|
||||
AddLocationEntry(newEntry, storageId);
|
||||
}
|
||||
|
||||
private bool VerifyContentType(LocationEntry LocationEntry, ContentType ContentType)
|
||||
private bool VerifyContentType(LocationEntry locationEntry, ContentType contentType)
|
||||
{
|
||||
if (LocationEntry.ContentPath == null)
|
||||
if (locationEntry.ContentPath == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
StorageId StorageId = LocationHelper.GetStorageId(LocationEntry.ContentPath);
|
||||
string InstalledPath = Device.FileSystem.SwitchPathToSystemPath(LocationEntry.ContentPath);
|
||||
StorageId storageId = LocationHelper.GetStorageId(locationEntry.ContentPath);
|
||||
string installedPath = _device.FileSystem.SwitchPathToSystemPath(locationEntry.ContentPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(InstalledPath))
|
||||
if (!string.IsNullOrWhiteSpace(installedPath))
|
||||
{
|
||||
if (File.Exists(InstalledPath))
|
||||
if (File.Exists(installedPath))
|
||||
{
|
||||
FileStream File = new FileStream(InstalledPath, FileMode.Open, FileAccess.Read);
|
||||
Nca Nca = new Nca(Device.System.KeySet, File, false);
|
||||
bool ContentCheck = Nca.Header.ContentType == ContentType;
|
||||
FileStream file = new FileStream(installedPath, FileMode.Open, FileAccess.Read);
|
||||
Nca nca = new Nca(_device.System.KeySet, file, false);
|
||||
bool contentCheck = nca.Header.ContentType == contentType;
|
||||
|
||||
Nca.Dispose();
|
||||
File.Dispose();
|
||||
nca.Dispose();
|
||||
file.Dispose();
|
||||
|
||||
return ContentCheck;
|
||||
return contentCheck;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddLocationEntry(LocationEntry Entry, StorageId StorageId)
|
||||
private void AddLocationEntry(LocationEntry entry, StorageId storageId)
|
||||
{
|
||||
LinkedList<LocationEntry> LocationList = null;
|
||||
LinkedList<LocationEntry> locationList = null;
|
||||
|
||||
if (LocationEntries.ContainsKey(StorageId))
|
||||
if (_locationEntries.ContainsKey(storageId))
|
||||
{
|
||||
LocationList = LocationEntries[StorageId];
|
||||
locationList = _locationEntries[storageId];
|
||||
}
|
||||
|
||||
if (LocationList != null)
|
||||
if (locationList != null)
|
||||
{
|
||||
if (LocationList.Contains(Entry))
|
||||
if (locationList.Contains(entry))
|
||||
{
|
||||
LocationList.Remove(Entry);
|
||||
locationList.Remove(entry);
|
||||
}
|
||||
|
||||
LocationList.AddLast(Entry);
|
||||
locationList.AddLast(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveLocationEntry(long TitleId, ContentType ContentType, StorageId StorageId)
|
||||
private void RemoveLocationEntry(long titleId, ContentType contentType, StorageId storageId)
|
||||
{
|
||||
LinkedList<LocationEntry> LocationList = null;
|
||||
LinkedList<LocationEntry> locationList = null;
|
||||
|
||||
if (LocationEntries.ContainsKey(StorageId))
|
||||
if (_locationEntries.ContainsKey(storageId))
|
||||
{
|
||||
LocationList = LocationEntries[StorageId];
|
||||
locationList = _locationEntries[storageId];
|
||||
}
|
||||
|
||||
if (LocationList != null)
|
||||
if (locationList != null)
|
||||
{
|
||||
LocationEntry Entry =
|
||||
LocationList.ToList().Find(x => x.TitleId == TitleId && x.ContentType == ContentType);
|
||||
LocationEntry entry =
|
||||
locationList.ToList().Find(x => x.TitleId == titleId && x.ContentType == contentType);
|
||||
|
||||
if (Entry.ContentPath != null)
|
||||
if (entry.ContentPath != null)
|
||||
{
|
||||
LocationList.Remove(Entry);
|
||||
locationList.Remove(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetFontTitle(string FontName, out long TitleId)
|
||||
public bool TryGetFontTitle(string fontName, out long titleId)
|
||||
{
|
||||
return SharedFontTitleDictionary.TryGetValue(FontName, out TitleId);
|
||||
return _sharedFontTitleDictionary.TryGetValue(fontName, out titleId);
|
||||
}
|
||||
|
||||
private LocationEntry GetLocation(long TitleId, ContentType ContentType,StorageId StorageId)
|
||||
private LocationEntry GetLocation(long titleId, ContentType contentType,StorageId storageId)
|
||||
{
|
||||
LinkedList<LocationEntry> LocationList = LocationEntries[StorageId];
|
||||
LinkedList<LocationEntry> locationList = _locationEntries[storageId];
|
||||
|
||||
return LocationList.ToList().Find(x => x.TitleId == TitleId && x.ContentType == ContentType);
|
||||
return locationList.ToList().Find(x => x.TitleId == titleId && x.ContentType == contentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using LibHac;
|
||||
using LibHac;
|
||||
|
||||
namespace Ryujinx.HLE.FileSystem.Content
|
||||
{
|
||||
|
@ -12,17 +9,17 @@ namespace Ryujinx.HLE.FileSystem.Content
|
|||
public long TitleId { get; private set; }
|
||||
public ContentType ContentType { get; private set; }
|
||||
|
||||
public LocationEntry(string ContentPath, int Flag, long TitleId, ContentType ContentType)
|
||||
public LocationEntry(string contentPath, int flag, long titleId, ContentType contentType)
|
||||
{
|
||||
this.ContentPath = ContentPath;
|
||||
this.Flag = Flag;
|
||||
this.TitleId = TitleId;
|
||||
this.ContentType = ContentType;
|
||||
ContentPath = contentPath;
|
||||
Flag = flag;
|
||||
TitleId = titleId;
|
||||
ContentType = contentType;
|
||||
}
|
||||
|
||||
public void SetFlag(int Flag)
|
||||
public void SetFlag(int flag)
|
||||
{
|
||||
this.Flag = Flag;
|
||||
Flag = flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,30 +7,30 @@ namespace Ryujinx.HLE.FileSystem.Content
|
|||
{
|
||||
internal static class LocationHelper
|
||||
{
|
||||
public static string GetRealPath(VirtualFileSystem FileSystem, string SwitchContentPath)
|
||||
public static string GetRealPath(VirtualFileSystem fileSystem, string switchContentPath)
|
||||
{
|
||||
string BasePath = FileSystem.GetBasePath();
|
||||
string basePath = fileSystem.GetBasePath();
|
||||
|
||||
switch (SwitchContentPath)
|
||||
switch (switchContentPath)
|
||||
{
|
||||
case ContentPath.SystemContent:
|
||||
return Path.Combine(FileSystem.GetBasePath(), SystemNandPath, "Contents");
|
||||
return Path.Combine(fileSystem.GetBasePath(), SystemNandPath, "Contents");
|
||||
case ContentPath.UserContent:
|
||||
return Path.Combine(FileSystem.GetBasePath(), UserNandPath, "Contents");
|
||||
return Path.Combine(fileSystem.GetBasePath(), UserNandPath, "Contents");
|
||||
case ContentPath.SdCardContent:
|
||||
return Path.Combine(FileSystem.GetSdCardPath(), "Nintendo", "Contents");
|
||||
return Path.Combine(fileSystem.GetSdCardPath(), "Nintendo", "Contents");
|
||||
case ContentPath.System:
|
||||
return Path.Combine(BasePath, SystemNandPath);
|
||||
return Path.Combine(basePath, SystemNandPath);
|
||||
case ContentPath.User:
|
||||
return Path.Combine(BasePath, UserNandPath);
|
||||
return Path.Combine(basePath, UserNandPath);
|
||||
default:
|
||||
throw new NotSupportedException($"Content Path `{SwitchContentPath}` is not supported.");
|
||||
throw new NotSupportedException($"Content Path `{switchContentPath}` is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetContentPath(ContentStorageId ContentStorageId)
|
||||
public static string GetContentPath(ContentStorageId contentStorageId)
|
||||
{
|
||||
switch (ContentStorageId)
|
||||
switch (contentStorageId)
|
||||
{
|
||||
case ContentStorageId.NandSystem:
|
||||
return ContentPath.SystemContent;
|
||||
|
@ -39,13 +39,13 @@ namespace Ryujinx.HLE.FileSystem.Content
|
|||
case ContentStorageId.SdCard:
|
||||
return ContentPath.SdCardContent;
|
||||
default:
|
||||
throw new NotSupportedException($"Content Storage `{ContentStorageId}` is not supported.");
|
||||
throw new NotSupportedException($"Content Storage `{contentStorageId}` is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetContentRoot(StorageId StorageId)
|
||||
public static string GetContentRoot(StorageId storageId)
|
||||
{
|
||||
switch (StorageId)
|
||||
switch (storageId)
|
||||
{
|
||||
case StorageId.NandSystem:
|
||||
return ContentPath.SystemContent;
|
||||
|
@ -54,15 +54,15 @@ namespace Ryujinx.HLE.FileSystem.Content
|
|||
case StorageId.SdCard:
|
||||
return ContentPath.SdCardContent;
|
||||
default:
|
||||
throw new NotSupportedException($"Storage Id `{StorageId}` is not supported.");
|
||||
throw new NotSupportedException($"Storage Id `{storageId}` is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public static StorageId GetStorageId(string ContentPathString)
|
||||
public static StorageId GetStorageId(string contentPathString)
|
||||
{
|
||||
string CleanedPath = ContentPathString.Split(':')[0];
|
||||
string cleanedPath = contentPathString.Split(':')[0];
|
||||
|
||||
switch (CleanedPath)
|
||||
switch (cleanedPath)
|
||||
{
|
||||
case ContentPath.SystemContent:
|
||||
case ContentPath.System:
|
||||
|
|
|
@ -10,228 +10,228 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
class FileSystemProvider : IFileSystemProvider
|
||||
{
|
||||
private readonly string BasePath;
|
||||
private readonly string RootPath;
|
||||
private readonly string _basePath;
|
||||
private readonly string _rootPath;
|
||||
|
||||
public FileSystemProvider(string BasePath, string RootPath)
|
||||
public FileSystemProvider(string basePath, string rootPath)
|
||||
{
|
||||
this.BasePath = BasePath;
|
||||
this.RootPath = RootPath;
|
||||
_basePath = basePath;
|
||||
_rootPath = rootPath;
|
||||
|
||||
CheckIfDescendentOfRootPath(BasePath);
|
||||
CheckIfDescendentOfRootPath(basePath);
|
||||
}
|
||||
|
||||
public long CreateDirectory(string Name)
|
||||
public long CreateDirectory(string name)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
if (Directory.Exists(Name))
|
||||
if (Directory.Exists(name))
|
||||
{
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Name);
|
||||
Directory.CreateDirectory(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long CreateFile(string Name, long Size)
|
||||
public long CreateFile(string name, long size)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
if (File.Exists(Name))
|
||||
if (File.Exists(name))
|
||||
{
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
|
||||
}
|
||||
|
||||
using (FileStream NewFile = File.Create(Name))
|
||||
using (FileStream newFile = File.Create(name))
|
||||
{
|
||||
NewFile.SetLength(Size);
|
||||
newFile.SetLength(size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long DeleteDirectory(string Name, bool Recursive)
|
||||
public long DeleteDirectory(string name, bool recursive)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
string DirName = Name;
|
||||
string dirName = name;
|
||||
|
||||
if (!Directory.Exists(DirName))
|
||||
if (!Directory.Exists(dirName))
|
||||
{
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
Directory.Delete(DirName, Recursive);
|
||||
Directory.Delete(dirName, recursive);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long DeleteFile(string Name)
|
||||
public long DeleteFile(string name)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
if (!File.Exists(Name))
|
||||
if (!File.Exists(name))
|
||||
{
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Delete(Name);
|
||||
File.Delete(name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetDirectories(string Path)
|
||||
public DirectoryEntry[] GetDirectories(string path)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Path);
|
||||
CheckIfDescendentOfRootPath(path);
|
||||
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach(string Directory in Directory.EnumerateDirectories(Path))
|
||||
foreach(string directory in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory, DirectoryEntryType.Directory);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(directory, DirectoryEntryType.Directory);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Entries.ToArray();
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetEntries(string Path)
|
||||
public DirectoryEntry[] GetEntries(string path)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Path);
|
||||
CheckIfDescendentOfRootPath(path);
|
||||
|
||||
if (Directory.Exists(Path))
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach (string Directory in Directory.EnumerateDirectories(Path))
|
||||
foreach (string directory in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory, DirectoryEntryType.Directory);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(directory, DirectoryEntryType.Directory);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
foreach (string File in Directory.EnumerateFiles(Path))
|
||||
foreach (string file in Directory.EnumerateFiles(path))
|
||||
{
|
||||
FileInfo FileInfo = new FileInfo(File);
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File, DirectoryEntryType.File, FileInfo.Length);
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file, DirectoryEntryType.File, fileInfo.Length);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetFiles(string Path)
|
||||
public DirectoryEntry[] GetFiles(string path)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Path);
|
||||
CheckIfDescendentOfRootPath(path);
|
||||
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach (string File in Directory.EnumerateFiles(Path))
|
||||
foreach (string file in Directory.EnumerateFiles(path))
|
||||
{
|
||||
FileInfo FileInfo = new FileInfo(File);
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File, DirectoryEntryType.File, FileInfo.Length);
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file, DirectoryEntryType.File, fileInfo.Length);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Entries.ToArray();
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
public long GetFreeSpace(ServiceCtx Context)
|
||||
public long GetFreeSpace(ServiceCtx context)
|
||||
{
|
||||
return Context.Device.FileSystem.GetDrive().AvailableFreeSpace;
|
||||
return context.Device.FileSystem.GetDrive().AvailableFreeSpace;
|
||||
}
|
||||
|
||||
public string GetFullPath(string Name)
|
||||
public string GetFullPath(string name)
|
||||
{
|
||||
if (Name.StartsWith("//"))
|
||||
if (name.StartsWith("//"))
|
||||
{
|
||||
Name = Name.Substring(2);
|
||||
name = name.Substring(2);
|
||||
}
|
||||
else if (Name.StartsWith('/'))
|
||||
else if (name.StartsWith('/'))
|
||||
{
|
||||
Name = Name.Substring(1);
|
||||
name = name.Substring(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string FullPath = Path.Combine(BasePath, Name);
|
||||
string fullPath = Path.Combine(_basePath, name);
|
||||
|
||||
CheckIfDescendentOfRootPath(FullPath);
|
||||
CheckIfDescendentOfRootPath(fullPath);
|
||||
|
||||
return FullPath;
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public long GetTotalSpace(ServiceCtx Context)
|
||||
public long GetTotalSpace(ServiceCtx context)
|
||||
{
|
||||
return Context.Device.FileSystem.GetDrive().TotalSize;
|
||||
return context.Device.FileSystem.GetDrive().TotalSize;
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string Name)
|
||||
public bool DirectoryExists(string name)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
return Directory.Exists(Name);
|
||||
return Directory.Exists(name);
|
||||
}
|
||||
|
||||
public bool FileExists(string Name)
|
||||
public bool FileExists(string name)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
return File.Exists(Name);
|
||||
return File.Exists(name);
|
||||
}
|
||||
|
||||
public long OpenDirectory(string Name, int FilterFlags, out IDirectory DirectoryInterface)
|
||||
public long OpenDirectory(string name, int filterFlags, out IDirectory directoryInterface)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
if (Directory.Exists(Name))
|
||||
if (Directory.Exists(name))
|
||||
{
|
||||
DirectoryInterface = new IDirectory(Name, FilterFlags, this);
|
||||
directoryInterface = new IDirectory(name, filterFlags, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DirectoryInterface = null;
|
||||
directoryInterface = null;
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
public long OpenFile(string Name, out IFile FileInterface)
|
||||
public long OpenFile(string name, out IFile fileInterface)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(Name);
|
||||
CheckIfDescendentOfRootPath(name);
|
||||
|
||||
if (File.Exists(Name))
|
||||
if (File.Exists(name))
|
||||
{
|
||||
FileStream Stream = new FileStream(Name, FileMode.Open);
|
||||
FileStream stream = new FileStream(name, FileMode.Open);
|
||||
|
||||
FileInterface = new IFile(Stream, Name);
|
||||
fileInterface = new IFile(stream, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileInterface = null;
|
||||
fileInterface = null;
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
public long RenameDirectory(string OldName, string NewName)
|
||||
public long RenameDirectory(string oldName, string newName)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(OldName);
|
||||
CheckIfDescendentOfRootPath(NewName);
|
||||
CheckIfDescendentOfRootPath(oldName);
|
||||
CheckIfDescendentOfRootPath(newName);
|
||||
|
||||
if (Directory.Exists(OldName))
|
||||
if (Directory.Exists(oldName))
|
||||
{
|
||||
Directory.Move(OldName, NewName);
|
||||
Directory.Move(oldName, newName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -241,14 +241,14 @@ namespace Ryujinx.HLE.FileSystem
|
|||
return 0;
|
||||
}
|
||||
|
||||
public long RenameFile(string OldName, string NewName)
|
||||
public long RenameFile(string oldName, string newName)
|
||||
{
|
||||
CheckIfDescendentOfRootPath(OldName);
|
||||
CheckIfDescendentOfRootPath(NewName);
|
||||
CheckIfDescendentOfRootPath(oldName);
|
||||
CheckIfDescendentOfRootPath(newName);
|
||||
|
||||
if (File.Exists(OldName))
|
||||
if (File.Exists(oldName))
|
||||
{
|
||||
File.Move(OldName, NewName);
|
||||
File.Move(oldName, newName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -258,24 +258,24 @@ namespace Ryujinx.HLE.FileSystem
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void CheckIfDescendentOfRootPath(string Path)
|
||||
public void CheckIfDescendentOfRootPath(string path)
|
||||
{
|
||||
DirectoryInfo PathInfo = new DirectoryInfo(Path);
|
||||
DirectoryInfo RootInfo = new DirectoryInfo(RootPath);
|
||||
DirectoryInfo pathInfo = new DirectoryInfo(path);
|
||||
DirectoryInfo rootInfo = new DirectoryInfo(_rootPath);
|
||||
|
||||
while (PathInfo.Parent != null)
|
||||
while (pathInfo.Parent != null)
|
||||
{
|
||||
if (PathInfo.Parent.FullName == RootInfo.FullName)
|
||||
if (pathInfo.Parent.FullName == rootInfo.FullName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathInfo = PathInfo.Parent;
|
||||
pathInfo = pathInfo.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Path {Path} is not a child directory of {RootPath}");
|
||||
throw new InvalidOperationException($"Path {path} is not a child directory of {_rootPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,40 @@
|
|||
using Ryujinx.HLE.HOS;
|
||||
using Ryujinx.HLE.HOS.Services.FspSrv;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
interface IFileSystemProvider
|
||||
{
|
||||
long CreateFile(string Name, long Size);
|
||||
long CreateFile(string name, long size);
|
||||
|
||||
long CreateDirectory(string Name);
|
||||
long CreateDirectory(string name);
|
||||
|
||||
long RenameFile(string OldName, string NewName);
|
||||
long RenameFile(string oldName, string newName);
|
||||
|
||||
long RenameDirectory(string OldName, string NewName);
|
||||
long RenameDirectory(string oldName, string newName);
|
||||
|
||||
DirectoryEntry[] GetEntries(string Path);
|
||||
DirectoryEntry[] GetEntries(string path);
|
||||
|
||||
DirectoryEntry[] GetDirectories(string Path);
|
||||
DirectoryEntry[] GetDirectories(string path);
|
||||
|
||||
DirectoryEntry[] GetFiles(string Path);
|
||||
DirectoryEntry[] GetFiles(string path);
|
||||
|
||||
long DeleteFile(string Name);
|
||||
long DeleteFile(string name);
|
||||
|
||||
long DeleteDirectory(string Name, bool Recursive);
|
||||
long DeleteDirectory(string name, bool recursive);
|
||||
|
||||
bool FileExists(string Name);
|
||||
bool FileExists(string name);
|
||||
|
||||
bool DirectoryExists(string Name);
|
||||
bool DirectoryExists(string name);
|
||||
|
||||
long OpenFile(string Name, out IFile FileInterface);
|
||||
long OpenFile(string name, out IFile fileInterface);
|
||||
|
||||
long OpenDirectory(string Name, int FilterFlags, out IDirectory DirectoryInterface);
|
||||
long OpenDirectory(string name, int filterFlags, out IDirectory directoryInterface);
|
||||
|
||||
string GetFullPath(string Name);
|
||||
string GetFullPath(string name);
|
||||
|
||||
long GetFreeSpace(ServiceCtx Context);
|
||||
long GetFreeSpace(ServiceCtx context);
|
||||
|
||||
long GetTotalSpace(ServiceCtx Context);
|
||||
long GetTotalSpace(ServiceCtx context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,98 +12,98 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
class PFsProvider : IFileSystemProvider
|
||||
{
|
||||
private Pfs Pfs;
|
||||
private Pfs _pfs;
|
||||
|
||||
public PFsProvider(Pfs Pfs)
|
||||
public PFsProvider(Pfs pfs)
|
||||
{
|
||||
this.Pfs = Pfs;
|
||||
_pfs = pfs;
|
||||
}
|
||||
|
||||
public long CreateDirectory(string Name)
|
||||
public long CreateDirectory(string name)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long CreateFile(string Name, long Size)
|
||||
public long CreateFile(string name, long size)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long DeleteDirectory(string Name, bool Recursive)
|
||||
public long DeleteDirectory(string name, bool recursive)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long DeleteFile(string Name)
|
||||
public long DeleteFile(string name)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetDirectories(string Path)
|
||||
public DirectoryEntry[] GetDirectories(string path)
|
||||
{
|
||||
return new DirectoryEntry[0];
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetEntries(string Path)
|
||||
public DirectoryEntry[] GetEntries(string path)
|
||||
{
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach (PfsFileEntry File in Pfs.Files)
|
||||
foreach (PfsFileEntry file in _pfs.Files)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File.Name, DirectoryEntryType.File, File.Size);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file.Name, DirectoryEntryType.File, file.Size);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Entries.ToArray();
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetFiles(string Path)
|
||||
public DirectoryEntry[] GetFiles(string path)
|
||||
{
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach (PfsFileEntry File in Pfs.Files)
|
||||
foreach (PfsFileEntry file in _pfs.Files)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File.Name, DirectoryEntryType.File, File.Size);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file.Name, DirectoryEntryType.File, file.Size);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Entries.ToArray();
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
public long GetFreeSpace(ServiceCtx Context)
|
||||
public long GetFreeSpace(ServiceCtx context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string GetFullPath(string Name)
|
||||
public string GetFullPath(string name)
|
||||
{
|
||||
return Name;
|
||||
return name;
|
||||
}
|
||||
|
||||
public long GetTotalSpace(ServiceCtx Context)
|
||||
public long GetTotalSpace(ServiceCtx context)
|
||||
{
|
||||
return Pfs.Files.Sum(x => x.Size);
|
||||
return _pfs.Files.Sum(x => x.Size);
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string Name)
|
||||
public bool DirectoryExists(string name)
|
||||
{
|
||||
return Name == "/" ? true : false;
|
||||
return name == "/";
|
||||
}
|
||||
|
||||
public bool FileExists(string Name)
|
||||
public bool FileExists(string name)
|
||||
{
|
||||
Name = Name.TrimStart('/');
|
||||
name = name.TrimStart('/');
|
||||
|
||||
return Pfs.FileExists(Name);
|
||||
return _pfs.FileExists(name);
|
||||
}
|
||||
|
||||
public long OpenDirectory(string Name, int FilterFlags, out IDirectory DirectoryInterface)
|
||||
public long OpenDirectory(string name, int filterFlags, out IDirectory directoryInterface)
|
||||
{
|
||||
if (Name == "/")
|
||||
if (name == "/")
|
||||
{
|
||||
DirectoryInterface = new IDirectory(Name, FilterFlags, this);
|
||||
directoryInterface = new IDirectory(name, filterFlags, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -111,34 +111,34 @@ namespace Ryujinx.HLE.FileSystem
|
|||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long OpenFile(string Name, out IFile FileInterface)
|
||||
public long OpenFile(string name, out IFile fileInterface)
|
||||
{
|
||||
Name = Name.TrimStart('/');
|
||||
name = name.TrimStart('/');
|
||||
|
||||
if (Pfs.FileExists(Name))
|
||||
if (_pfs.FileExists(name))
|
||||
{
|
||||
Stream Stream = Pfs.OpenFile(Name);
|
||||
FileInterface = new IFile(Stream, Name);
|
||||
Stream stream = _pfs.OpenFile(name);
|
||||
fileInterface = new IFile(stream, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileInterface = null;
|
||||
fileInterface = null;
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
public long RenameDirectory(string OldName, string NewName)
|
||||
public long RenameDirectory(string oldName, string newName)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long RenameFile(string OldName, string NewName)
|
||||
public long RenameFile(string oldName, string newName)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void CheckIfOutsideBasePath(string Path)
|
||||
public void CheckIfOutsideBasePath(string path)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
|
|
@ -12,150 +12,150 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
class RomFsProvider : IFileSystemProvider
|
||||
{
|
||||
private Romfs RomFs;
|
||||
private Romfs _romFs;
|
||||
|
||||
public RomFsProvider(Stream StorageStream)
|
||||
public RomFsProvider(Stream storageStream)
|
||||
{
|
||||
RomFs = new Romfs(StorageStream);
|
||||
_romFs = new Romfs(storageStream);
|
||||
}
|
||||
|
||||
public long CreateDirectory(string Name)
|
||||
public long CreateDirectory(string name)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long CreateFile(string Name, long Size)
|
||||
public long CreateFile(string name, long size)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long DeleteDirectory(string Name, bool Recursive)
|
||||
public long DeleteDirectory(string name, bool recursive)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long DeleteFile(string Name)
|
||||
public long DeleteFile(string name)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetDirectories(string Path)
|
||||
public DirectoryEntry[] GetDirectories(string path)
|
||||
{
|
||||
List<DirectoryEntry> Directories = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> directories = new List<DirectoryEntry>();
|
||||
|
||||
foreach(RomfsDir Directory in RomFs.Directories)
|
||||
foreach(RomfsDir directory in _romFs.Directories)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory.Name, DirectoryEntryType.Directory);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(directory.Name, DirectoryEntryType.Directory);
|
||||
|
||||
Directories.Add(DirectoryEntry);
|
||||
directories.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Directories.ToArray();
|
||||
return directories.ToArray();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetEntries(string Path)
|
||||
public DirectoryEntry[] GetEntries(string path)
|
||||
{
|
||||
List<DirectoryEntry> Entries = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> entries = new List<DirectoryEntry>();
|
||||
|
||||
foreach (RomfsDir Directory in RomFs.Directories)
|
||||
foreach (RomfsDir directory in _romFs.Directories)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory.Name, DirectoryEntryType.Directory);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(directory.Name, DirectoryEntryType.Directory);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
foreach (RomfsFile File in RomFs.Files)
|
||||
foreach (RomfsFile file in _romFs.Files)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File.Name, DirectoryEntryType.File, File.DataLength);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file.Name, DirectoryEntryType.File, file.DataLength);
|
||||
|
||||
Entries.Add(DirectoryEntry);
|
||||
entries.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Entries.ToArray();
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
public DirectoryEntry[] GetFiles(string Path)
|
||||
public DirectoryEntry[] GetFiles(string path)
|
||||
{
|
||||
List<DirectoryEntry> Files = new List<DirectoryEntry>();
|
||||
List<DirectoryEntry> files = new List<DirectoryEntry>();
|
||||
|
||||
foreach (RomfsFile File in RomFs.Files)
|
||||
foreach (RomfsFile file in _romFs.Files)
|
||||
{
|
||||
DirectoryEntry DirectoryEntry = new DirectoryEntry(File.Name, DirectoryEntryType.File, File.DataLength);
|
||||
DirectoryEntry directoryEntry = new DirectoryEntry(file.Name, DirectoryEntryType.File, file.DataLength);
|
||||
|
||||
Files.Add(DirectoryEntry);
|
||||
files.Add(directoryEntry);
|
||||
}
|
||||
|
||||
return Files.ToArray();
|
||||
return files.ToArray();
|
||||
}
|
||||
|
||||
public long GetFreeSpace(ServiceCtx Context)
|
||||
public long GetFreeSpace(ServiceCtx context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string GetFullPath(string Name)
|
||||
public string GetFullPath(string name)
|
||||
{
|
||||
return Name;
|
||||
return name;
|
||||
}
|
||||
|
||||
public long GetTotalSpace(ServiceCtx Context)
|
||||
public long GetTotalSpace(ServiceCtx context)
|
||||
{
|
||||
return RomFs.Files.Sum(x => x.DataLength);
|
||||
return _romFs.Files.Sum(x => x.DataLength);
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string Name)
|
||||
public bool DirectoryExists(string name)
|
||||
{
|
||||
return RomFs.Directories.Exists(x=>x.Name == Name);
|
||||
return _romFs.Directories.Exists(x=>x.Name == name);
|
||||
}
|
||||
|
||||
public bool FileExists(string Name)
|
||||
public bool FileExists(string name)
|
||||
{
|
||||
return RomFs.FileExists(Name);
|
||||
return _romFs.FileExists(name);
|
||||
}
|
||||
|
||||
public long OpenDirectory(string Name, int FilterFlags, out IDirectory DirectoryInterface)
|
||||
public long OpenDirectory(string name, int filterFlags, out IDirectory directoryInterface)
|
||||
{
|
||||
RomfsDir Directory = RomFs.Directories.Find(x => x.Name == Name);
|
||||
RomfsDir directory = _romFs.Directories.Find(x => x.Name == name);
|
||||
|
||||
if (Directory != null)
|
||||
if (directory != null)
|
||||
{
|
||||
DirectoryInterface = new IDirectory(Name, FilterFlags, this);
|
||||
directoryInterface = new IDirectory(name, filterFlags, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DirectoryInterface = null;
|
||||
directoryInterface = null;
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
public long OpenFile(string Name, out IFile FileInterface)
|
||||
public long OpenFile(string name, out IFile fileInterface)
|
||||
{
|
||||
if (RomFs.FileExists(Name))
|
||||
if (_romFs.FileExists(name))
|
||||
{
|
||||
Stream Stream = RomFs.OpenFile(Name);
|
||||
Stream stream = _romFs.OpenFile(name);
|
||||
|
||||
FileInterface = new IFile(Stream, Name);
|
||||
fileInterface = new IFile(stream, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileInterface = null;
|
||||
fileInterface = null;
|
||||
|
||||
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
|
||||
}
|
||||
|
||||
public long RenameDirectory(string OldName, string NewName)
|
||||
public long RenameDirectory(string oldName, string newName)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public long RenameFile(string OldName, string NewName)
|
||||
public long RenameFile(string oldName, string newName)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void CheckIfOutsideBasePath(string Path)
|
||||
public void CheckIfOutsideBasePath(string path)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
|
|
@ -7,39 +7,39 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
static class SaveHelper
|
||||
{
|
||||
public static string GetSavePath(SaveInfo SaveMetaData, ServiceCtx Context)
|
||||
public static string GetSavePath(SaveInfo saveMetaData, ServiceCtx context)
|
||||
{
|
||||
string BaseSavePath = NandPath;
|
||||
long CurrentTitleId = SaveMetaData.TitleId;
|
||||
string baseSavePath = NandPath;
|
||||
long currentTitleId = saveMetaData.TitleId;
|
||||
|
||||
switch (SaveMetaData.SaveSpaceId)
|
||||
switch (saveMetaData.SaveSpaceId)
|
||||
{
|
||||
case SaveSpaceId.NandUser:
|
||||
BaseSavePath = UserNandPath;
|
||||
baseSavePath = UserNandPath;
|
||||
break;
|
||||
case SaveSpaceId.NandSystem:
|
||||
BaseSavePath = SystemNandPath;
|
||||
baseSavePath = SystemNandPath;
|
||||
break;
|
||||
case SaveSpaceId.SdCard:
|
||||
BaseSavePath = Path.Combine(SdCardPath, "Nintendo");
|
||||
baseSavePath = Path.Combine(SdCardPath, "Nintendo");
|
||||
break;
|
||||
}
|
||||
|
||||
BaseSavePath = Path.Combine(BaseSavePath, "save");
|
||||
baseSavePath = Path.Combine(baseSavePath, "save");
|
||||
|
||||
if (SaveMetaData.TitleId == 0 && SaveMetaData.SaveDataType == SaveDataType.SaveData)
|
||||
if (saveMetaData.TitleId == 0 && saveMetaData.SaveDataType == SaveDataType.SaveData)
|
||||
{
|
||||
CurrentTitleId = Context.Process.TitleId;
|
||||
currentTitleId = context.Process.TitleId;
|
||||
}
|
||||
|
||||
string SaveAccount = SaveMetaData.UserId.IsZero() ? "savecommon" : SaveMetaData.UserId.ToString();
|
||||
string saveAccount = saveMetaData.UserId.IsZero() ? "savecommon" : saveMetaData.UserId.ToString();
|
||||
|
||||
string SavePath = Path.Combine(BaseSavePath,
|
||||
SaveMetaData.SaveId.ToString("x16"),
|
||||
SaveAccount,
|
||||
SaveMetaData.SaveDataType == SaveDataType.SaveData ? CurrentTitleId.ToString("x16") : string.Empty);
|
||||
string savePath = Path.Combine(baseSavePath,
|
||||
saveMetaData.SaveId.ToString("x16"),
|
||||
saveAccount,
|
||||
saveMetaData.SaveDataType == SaveDataType.SaveData ? currentTitleId.ToString("x16") : string.Empty);
|
||||
|
||||
return SavePath;
|
||||
return savePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,25 +4,25 @@ namespace Ryujinx.HLE.FileSystem
|
|||
{
|
||||
struct SaveInfo
|
||||
{
|
||||
public long TitleId { get; private set; }
|
||||
public long SaveId { get; private set; }
|
||||
public long TitleId { get; private set; }
|
||||
public long SaveId { get; private set; }
|
||||
public UInt128 UserId { get; private set; }
|
||||
|
||||
public SaveDataType SaveDataType { get; private set; }
|
||||
public SaveSpaceId SaveSpaceId { get; private set; }
|
||||
|
||||
public SaveInfo(
|
||||
long TitleId,
|
||||
long SaveId,
|
||||
SaveDataType SaveDataType,
|
||||
UInt128 UserId,
|
||||
SaveSpaceId SaveSpaceId)
|
||||
long titleId,
|
||||
long saveId,
|
||||
SaveDataType saveDataType,
|
||||
UInt128 userId,
|
||||
SaveSpaceId saveSpaceId)
|
||||
{
|
||||
this.TitleId = TitleId;
|
||||
this.UserId = UserId;
|
||||
this.SaveId = SaveId;
|
||||
this.SaveDataType = SaveDataType;
|
||||
this.SaveSpaceId = SaveSpaceId;
|
||||
TitleId = titleId;
|
||||
UserId = userId;
|
||||
SaveId = saveId;
|
||||
SaveDataType = saveDataType;
|
||||
SaveSpaceId = saveSpaceId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,40 +18,40 @@ namespace Ryujinx.HLE.FileSystem
|
|||
|
||||
public Stream RomFs { get; private set; }
|
||||
|
||||
public void LoadRomFs(string FileName)
|
||||
public void LoadRomFs(string fileName)
|
||||
{
|
||||
RomFs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
|
||||
RomFs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public void SetRomFs(Stream RomfsStream)
|
||||
public void SetRomFs(Stream romfsStream)
|
||||
{
|
||||
RomFs?.Close();
|
||||
RomFs = RomfsStream;
|
||||
RomFs = romfsStream;
|
||||
}
|
||||
|
||||
public string GetFullPath(string BasePath, string FileName)
|
||||
public string GetFullPath(string basePath, string fileName)
|
||||
{
|
||||
if (FileName.StartsWith("//"))
|
||||
if (fileName.StartsWith("//"))
|
||||
{
|
||||
FileName = FileName.Substring(2);
|
||||
fileName = fileName.Substring(2);
|
||||
}
|
||||
else if (FileName.StartsWith('/'))
|
||||
else if (fileName.StartsWith('/'))
|
||||
{
|
||||
FileName = FileName.Substring(1);
|
||||
fileName = fileName.Substring(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string FullPath = Path.GetFullPath(Path.Combine(BasePath, FileName));
|
||||
string fullPath = Path.GetFullPath(Path.Combine(basePath, fileName));
|
||||
|
||||
if (!FullPath.StartsWith(GetBasePath()))
|
||||
if (!fullPath.StartsWith(GetBasePath()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return FullPath;
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath);
|
||||
|
@ -60,84 +60,84 @@ namespace Ryujinx.HLE.FileSystem
|
|||
|
||||
public string GetSystemPath() => MakeDirAndGetFullPath(SystemPath);
|
||||
|
||||
public string GetGameSavePath(SaveInfo Save, ServiceCtx Context)
|
||||
public string GetGameSavePath(SaveInfo save, ServiceCtx context)
|
||||
{
|
||||
return MakeDirAndGetFullPath(SaveHelper.GetSavePath(Save, Context));
|
||||
return MakeDirAndGetFullPath(SaveHelper.GetSavePath(save, context));
|
||||
}
|
||||
|
||||
public string GetFullPartitionPath(string PartitionPath)
|
||||
public string GetFullPartitionPath(string partitionPath)
|
||||
{
|
||||
return MakeDirAndGetFullPath(PartitionPath);
|
||||
return MakeDirAndGetFullPath(partitionPath);
|
||||
}
|
||||
|
||||
public string SwitchPathToSystemPath(string SwitchPath)
|
||||
public string SwitchPathToSystemPath(string switchPath)
|
||||
{
|
||||
string[] Parts = SwitchPath.Split(":");
|
||||
string[] parts = switchPath.Split(":");
|
||||
|
||||
if (Parts.Length != 2)
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return GetFullPath(MakeDirAndGetFullPath(Parts[0]), Parts[1]);
|
||||
return GetFullPath(MakeDirAndGetFullPath(parts[0]), parts[1]);
|
||||
}
|
||||
|
||||
public string SystemPathToSwitchPath(string SystemPath)
|
||||
public string SystemPathToSwitchPath(string systemPath)
|
||||
{
|
||||
string BaseSystemPath = GetBasePath() + Path.DirectorySeparatorChar;
|
||||
string baseSystemPath = GetBasePath() + Path.DirectorySeparatorChar;
|
||||
|
||||
if (SystemPath.StartsWith(BaseSystemPath))
|
||||
if (systemPath.StartsWith(baseSystemPath))
|
||||
{
|
||||
string RawPath = SystemPath.Replace(BaseSystemPath, "");
|
||||
int FirstSeparatorOffset = RawPath.IndexOf(Path.DirectorySeparatorChar);
|
||||
string rawPath = systemPath.Replace(baseSystemPath, "");
|
||||
int firstSeparatorOffset = rawPath.IndexOf(Path.DirectorySeparatorChar);
|
||||
|
||||
if (FirstSeparatorOffset == -1)
|
||||
if (firstSeparatorOffset == -1)
|
||||
{
|
||||
return $"{RawPath}:/";
|
||||
return $"{rawPath}:/";
|
||||
}
|
||||
|
||||
string BasePath = RawPath.Substring(0, FirstSeparatorOffset);
|
||||
string FileName = RawPath.Substring(FirstSeparatorOffset + 1);
|
||||
string basePath = rawPath.Substring(0, firstSeparatorOffset);
|
||||
string fileName = rawPath.Substring(firstSeparatorOffset + 1);
|
||||
|
||||
return $"{BasePath}:/{FileName}";
|
||||
return $"{basePath}:/{fileName}";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private string MakeDirAndGetFullPath(string Dir)
|
||||
private string MakeDirAndGetFullPath(string dir)
|
||||
{
|
||||
// Handles Common Switch Content Paths
|
||||
switch (Dir)
|
||||
switch (dir)
|
||||
{
|
||||
case ContentPath.SdCard:
|
||||
case "@Sdcard":
|
||||
Dir = SdCardPath;
|
||||
dir = SdCardPath;
|
||||
break;
|
||||
case ContentPath.User:
|
||||
Dir = UserNandPath;
|
||||
dir = UserNandPath;
|
||||
break;
|
||||
case ContentPath.System:
|
||||
Dir = SystemNandPath;
|
||||
dir = SystemNandPath;
|
||||
break;
|
||||
case ContentPath.SdCardContent:
|
||||
Dir = Path.Combine(SdCardPath, "Nintendo", "Contents");
|
||||
dir = Path.Combine(SdCardPath, "Nintendo", "Contents");
|
||||
break;
|
||||
case ContentPath.UserContent:
|
||||
Dir = Path.Combine(UserNandPath, "Contents");
|
||||
dir = Path.Combine(UserNandPath, "Contents");
|
||||
break;
|
||||
case ContentPath.SystemContent:
|
||||
Dir = Path.Combine(SystemNandPath, "Contents");
|
||||
dir = Path.Combine(SystemNandPath, "Contents");
|
||||
break;
|
||||
}
|
||||
|
||||
string FullPath = Path.Combine(GetBasePath(), Dir);
|
||||
string fullPath = Path.Combine(GetBasePath(), dir);
|
||||
|
||||
if (!Directory.Exists(FullPath))
|
||||
if (!Directory.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(FullPath);
|
||||
Directory.CreateDirectory(fullPath);
|
||||
}
|
||||
|
||||
return FullPath;
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public DriveInfo GetDrive()
|
||||
|
@ -147,9 +147,9 @@ namespace Ryujinx.HLE.FileSystem
|
|||
|
||||
public string GetBasePath()
|
||||
{
|
||||
string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
return Path.Combine(AppDataPath, BasePath);
|
||||
return Path.Combine(appDataPath, BasePath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -4,22 +4,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ArraySubscriptingExpression : BaseNode
|
||||
{
|
||||
private BaseNode LeftNode;
|
||||
private BaseNode Subscript;
|
||||
private BaseNode _leftNode;
|
||||
private BaseNode _subscript;
|
||||
|
||||
public ArraySubscriptingExpression(BaseNode LeftNode, BaseNode Subscript) : base(NodeType.ArraySubscriptingExpression)
|
||||
public ArraySubscriptingExpression(BaseNode leftNode, BaseNode subscript) : base(NodeType.ArraySubscriptingExpression)
|
||||
{
|
||||
this.LeftNode = LeftNode;
|
||||
this.Subscript = Subscript;
|
||||
_leftNode = leftNode;
|
||||
_subscript = subscript;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
LeftNode.Print(Writer);
|
||||
Writer.Write(")[");
|
||||
Subscript.Print(Writer);
|
||||
Writer.Write("]");
|
||||
writer.Write("(");
|
||||
_leftNode.Print(writer);
|
||||
writer.Write(")[");
|
||||
_subscript.Print(writer);
|
||||
writer.Write("]");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,20 +4,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ArrayType : BaseNode
|
||||
{
|
||||
private BaseNode Base;
|
||||
private BaseNode DimensionExpression;
|
||||
private string DimensionString;
|
||||
private BaseNode _base;
|
||||
private BaseNode _dimensionExpression;
|
||||
private string _dimensionString;
|
||||
|
||||
public ArrayType(BaseNode Base, BaseNode DimensionExpression = null) : base(NodeType.ArrayType)
|
||||
public ArrayType(BaseNode Base, BaseNode dimensionExpression = null) : base(NodeType.ArrayType)
|
||||
{
|
||||
this.Base = Base;
|
||||
this.DimensionExpression = DimensionExpression;
|
||||
_base = Base;
|
||||
_dimensionExpression = dimensionExpression;
|
||||
}
|
||||
|
||||
public ArrayType(BaseNode Base, string DimensionString) : base(NodeType.ArrayType)
|
||||
public ArrayType(BaseNode Base, string dimensionString) : base(NodeType.ArrayType)
|
||||
{
|
||||
this.Base = Base;
|
||||
this.DimensionString = DimensionString;
|
||||
_base = Base;
|
||||
_dimensionString = dimensionString;
|
||||
}
|
||||
|
||||
public override bool HasRightPart()
|
||||
|
@ -30,30 +30,30 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Base.PrintLeft(Writer);
|
||||
_base.PrintLeft(writer);
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
// FIXME: detect if previous char was a ].
|
||||
Writer.Write(" ");
|
||||
writer.Write(" ");
|
||||
|
||||
Writer.Write("[");
|
||||
writer.Write("[");
|
||||
|
||||
if (DimensionString != null)
|
||||
if (_dimensionString != null)
|
||||
{
|
||||
Writer.Write(DimensionString);
|
||||
writer.Write(_dimensionString);
|
||||
}
|
||||
else if (DimensionExpression != null)
|
||||
else if (_dimensionExpression != null)
|
||||
{
|
||||
DimensionExpression.Print(Writer);
|
||||
_dimensionExpression.Print(writer);
|
||||
}
|
||||
|
||||
Writer.Write("]");
|
||||
writer.Write("]");
|
||||
|
||||
Base.PrintRight(Writer);
|
||||
_base.PrintRight(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public enum NodeType
|
||||
{
|
||||
CVQualifierType,
|
||||
CvQualifierType,
|
||||
SimpleReferenceType,
|
||||
NameType,
|
||||
EncodedFunction,
|
||||
|
@ -62,22 +62,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public NodeType Type { get; protected set; }
|
||||
|
||||
public BaseNode(NodeType Type)
|
||||
public BaseNode(NodeType type)
|
||||
{
|
||||
this.Type = Type;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public virtual void Print(TextWriter Writer)
|
||||
public virtual void Print(TextWriter writer)
|
||||
{
|
||||
PrintLeft(Writer);
|
||||
PrintLeft(writer);
|
||||
|
||||
if (HasRightPart())
|
||||
{
|
||||
PrintRight(Writer);
|
||||
PrintRight(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void PrintLeft(TextWriter Writer);
|
||||
public abstract void PrintLeft(TextWriter writer);
|
||||
|
||||
public virtual bool HasRightPart()
|
||||
{
|
||||
|
@ -99,15 +99,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
return null;
|
||||
}
|
||||
|
||||
public virtual void PrintRight(TextWriter Writer) {}
|
||||
public virtual void PrintRight(TextWriter writer) {}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringWriter Writer = new StringWriter();
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
Print(Writer);
|
||||
Print(writer);
|
||||
|
||||
return Writer.ToString();
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,37 +4,37 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class BinaryExpression : BaseNode
|
||||
{
|
||||
private BaseNode LeftPart;
|
||||
private string Name;
|
||||
private BaseNode RightPart;
|
||||
private BaseNode _leftPart;
|
||||
private string _name;
|
||||
private BaseNode _rightPart;
|
||||
|
||||
public BinaryExpression(BaseNode LeftPart, string Name, BaseNode RightPart) : base(NodeType.BinaryExpression)
|
||||
public BinaryExpression(BaseNode leftPart, string name, BaseNode rightPart) : base(NodeType.BinaryExpression)
|
||||
{
|
||||
this.LeftPart = LeftPart;
|
||||
this.Name = Name;
|
||||
this.RightPart = RightPart;
|
||||
_leftPart = leftPart;
|
||||
_name = name;
|
||||
_rightPart = rightPart;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (Name.Equals(">"))
|
||||
if (_name.Equals(">"))
|
||||
{
|
||||
Writer.Write("(");
|
||||
writer.Write("(");
|
||||
}
|
||||
|
||||
Writer.Write("(");
|
||||
LeftPart.Print(Writer);
|
||||
Writer.Write(") ");
|
||||
writer.Write("(");
|
||||
_leftPart.Print(writer);
|
||||
writer.Write(") ");
|
||||
|
||||
Writer.Write(Name);
|
||||
writer.Write(_name);
|
||||
|
||||
Writer.Write(" (");
|
||||
RightPart.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write(" (");
|
||||
_rightPart.Print(writer);
|
||||
writer.Write(")");
|
||||
|
||||
if (Name.Equals(">"))
|
||||
if (_name.Equals(">"))
|
||||
{
|
||||
Writer.Write(")");
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,37 +4,37 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class BracedExpression : BaseNode
|
||||
{
|
||||
private BaseNode Element;
|
||||
private BaseNode Expression;
|
||||
private bool IsArrayExpression;
|
||||
private BaseNode _element;
|
||||
private BaseNode _expression;
|
||||
private bool _isArrayExpression;
|
||||
|
||||
public BracedExpression(BaseNode Element, BaseNode Expression, bool IsArrayExpression) : base(NodeType.BracedExpression)
|
||||
public BracedExpression(BaseNode element, BaseNode expression, bool isArrayExpression) : base(NodeType.BracedExpression)
|
||||
{
|
||||
this.Element = Element;
|
||||
this.Expression = Expression;
|
||||
this.IsArrayExpression = IsArrayExpression;
|
||||
_element = element;
|
||||
_expression = expression;
|
||||
_isArrayExpression = isArrayExpression;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (IsArrayExpression)
|
||||
if (_isArrayExpression)
|
||||
{
|
||||
Writer.Write("[");
|
||||
Element.Print(Writer);
|
||||
Writer.Write("]");
|
||||
writer.Write("[");
|
||||
_element.Print(writer);
|
||||
writer.Write("]");
|
||||
}
|
||||
else
|
||||
{
|
||||
Writer.Write(".");
|
||||
Element.Print(Writer);
|
||||
writer.Write(".");
|
||||
_element.Print(writer);
|
||||
}
|
||||
|
||||
if (!Expression.GetType().Equals(NodeType.BracedExpression) || !Expression.GetType().Equals(NodeType.BracedRangeExpression))
|
||||
if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression))
|
||||
{
|
||||
Writer.Write(" = ");
|
||||
writer.Write(" = ");
|
||||
}
|
||||
|
||||
Expression.Print(Writer);
|
||||
_expression.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,31 +4,31 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class BracedRangeExpression : BaseNode
|
||||
{
|
||||
private BaseNode FirstNode;
|
||||
private BaseNode LastNode;
|
||||
private BaseNode Expression;
|
||||
private BaseNode _firstNode;
|
||||
private BaseNode _lastNode;
|
||||
private BaseNode _expression;
|
||||
|
||||
public BracedRangeExpression(BaseNode FirstNode, BaseNode LastNode, BaseNode Expression) : base(NodeType.BracedRangeExpression)
|
||||
public BracedRangeExpression(BaseNode firstNode, BaseNode lastNode, BaseNode expression) : base(NodeType.BracedRangeExpression)
|
||||
{
|
||||
this.FirstNode = FirstNode;
|
||||
this.LastNode = LastNode;
|
||||
this.Expression = Expression;
|
||||
_firstNode = firstNode;
|
||||
_lastNode = lastNode;
|
||||
_expression = expression;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("[");
|
||||
FirstNode.Print(Writer);
|
||||
Writer.Write(" ... ");
|
||||
LastNode.Print(Writer);
|
||||
Writer.Write("]");
|
||||
writer.Write("[");
|
||||
_firstNode.Print(writer);
|
||||
writer.Write(" ... ");
|
||||
_lastNode.Print(writer);
|
||||
writer.Write("]");
|
||||
|
||||
if (!Expression.GetType().Equals(NodeType.BracedExpression) || !Expression.GetType().Equals(NodeType.BracedRangeExpression))
|
||||
if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression))
|
||||
{
|
||||
Writer.Write(" = ");
|
||||
writer.Write(" = ");
|
||||
}
|
||||
|
||||
Expression.Print(Writer);
|
||||
_expression.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class CallExpression : NodeArray
|
||||
{
|
||||
private BaseNode Callee;
|
||||
private BaseNode _callee;
|
||||
|
||||
public CallExpression(BaseNode Callee, List<BaseNode> Nodes) : base(Nodes, NodeType.CallExpression)
|
||||
public CallExpression(BaseNode callee, List<BaseNode> nodes) : base(nodes, NodeType.CallExpression)
|
||||
{
|
||||
this.Callee = Callee;
|
||||
_callee = callee;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Callee.Print(Writer);
|
||||
_callee.Print(writer);
|
||||
|
||||
Writer.Write("(");
|
||||
Writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,25 +4,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class CastExpression : BaseNode
|
||||
{
|
||||
private string Kind;
|
||||
private BaseNode To;
|
||||
private BaseNode From;
|
||||
private string _kind;
|
||||
private BaseNode _to;
|
||||
private BaseNode _from;
|
||||
|
||||
public CastExpression(string Kind, BaseNode To, BaseNode From) : base(NodeType.CastExpression)
|
||||
public CastExpression(string kind, BaseNode to, BaseNode from) : base(NodeType.CastExpression)
|
||||
{
|
||||
this.Kind = Kind;
|
||||
this.To = To;
|
||||
this.From = From;
|
||||
_kind = kind;
|
||||
_to = to;
|
||||
_from = from;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write(Kind);
|
||||
Writer.Write("<");
|
||||
To.PrintLeft(Writer);
|
||||
Writer.Write(">(");
|
||||
From.PrintLeft(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write(_kind);
|
||||
writer.Write("<");
|
||||
_to.PrintLeft(writer);
|
||||
writer.Write(">(");
|
||||
_from.PrintLeft(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,26 +4,26 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ConditionalExpression : BaseNode
|
||||
{
|
||||
private BaseNode ThenNode;
|
||||
private BaseNode ElseNode;
|
||||
private BaseNode ConditionNode;
|
||||
private BaseNode _thenNode;
|
||||
private BaseNode _elseNode;
|
||||
private BaseNode _conditionNode;
|
||||
|
||||
public ConditionalExpression(BaseNode ConditionNode, BaseNode ThenNode, BaseNode ElseNode) : base(NodeType.ConditionalExpression)
|
||||
public ConditionalExpression(BaseNode conditionNode, BaseNode thenNode, BaseNode elseNode) : base(NodeType.ConditionalExpression)
|
||||
{
|
||||
this.ThenNode = ThenNode;
|
||||
this.ConditionNode = ConditionNode;
|
||||
this.ElseNode = ElseNode;
|
||||
_thenNode = thenNode;
|
||||
_conditionNode = conditionNode;
|
||||
_elseNode = elseNode;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
ConditionNode.Print(Writer);
|
||||
Writer.Write(") ? (");
|
||||
ThenNode.Print(Writer);
|
||||
Writer.Write(") : (");
|
||||
ElseNode.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
_conditionNode.Print(writer);
|
||||
writer.Write(") ? (");
|
||||
_thenNode.Print(writer);
|
||||
writer.Write(") : (");
|
||||
_elseNode.Print(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,21 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ConversionExpression : BaseNode
|
||||
{
|
||||
private BaseNode TypeNode;
|
||||
private BaseNode Expressions;
|
||||
private BaseNode _typeNode;
|
||||
private BaseNode _expressions;
|
||||
|
||||
public ConversionExpression(BaseNode TypeNode, BaseNode Expressions) : base(NodeType.ConversionExpression)
|
||||
public ConversionExpression(BaseNode typeNode, BaseNode expressions) : base(NodeType.ConversionExpression)
|
||||
{
|
||||
this.TypeNode = TypeNode;
|
||||
this.Expressions = Expressions;
|
||||
_typeNode = typeNode;
|
||||
_expressions = expressions;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
TypeNode.Print(Writer);
|
||||
Writer.Write(")(");
|
||||
Expressions.Print(Writer);
|
||||
writer.Write("(");
|
||||
_typeNode.Print(writer);
|
||||
writer.Write(")(");
|
||||
_expressions.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,12 +4,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ConversionOperatorType : ParentNode
|
||||
{
|
||||
public ConversionOperatorType(BaseNode Child) : base(NodeType.ConversionOperatorType, Child) { }
|
||||
public ConversionOperatorType(BaseNode child) : base(NodeType.ConversionOperatorType, child) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("operator ");
|
||||
Child.Print(Writer);
|
||||
writer.Write("operator ");
|
||||
Child.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,21 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class CtorDtorNameType : ParentNode
|
||||
{
|
||||
private bool IsDestructor;
|
||||
private bool _isDestructor;
|
||||
|
||||
public CtorDtorNameType(BaseNode Name, bool IsDestructor) : base(NodeType.CtorDtorNameType, Name)
|
||||
public CtorDtorNameType(BaseNode name, bool isDestructor) : base(NodeType.CtorDtorNameType, name)
|
||||
{
|
||||
this.IsDestructor = IsDestructor;
|
||||
_isDestructor = isDestructor;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (IsDestructor)
|
||||
if (_isDestructor)
|
||||
{
|
||||
Writer.Write("~");
|
||||
writer.Write("~");
|
||||
}
|
||||
|
||||
Writer.Write(Child.GetName());
|
||||
writer.Write(Child.GetName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,21 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class CtorVtableSpecialName : BaseNode
|
||||
{
|
||||
private BaseNode FirstType;
|
||||
private BaseNode SecondType;
|
||||
private BaseNode _firstType;
|
||||
private BaseNode _secondType;
|
||||
|
||||
public CtorVtableSpecialName(BaseNode FirstType, BaseNode SecondType) : base(NodeType.CtorVtableSpecialName)
|
||||
public CtorVtableSpecialName(BaseNode firstType, BaseNode secondType) : base(NodeType.CtorVtableSpecialName)
|
||||
{
|
||||
this.FirstType = FirstType;
|
||||
this.SecondType = SecondType;
|
||||
_firstType = firstType;
|
||||
_secondType = secondType;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("construction vtable for ");
|
||||
FirstType.Print(Writer);
|
||||
Writer.Write("-in-");
|
||||
SecondType.Print(Writer);
|
||||
writer.Write("construction vtable for ");
|
||||
_firstType.Print(writer);
|
||||
writer.Write("-in-");
|
||||
_secondType.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,30 +4,30 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class DeleteExpression : ParentNode
|
||||
{
|
||||
private bool IsGlobal;
|
||||
private bool IsArrayExpression;
|
||||
private bool _isGlobal;
|
||||
private bool _isArrayExpression;
|
||||
|
||||
public DeleteExpression(BaseNode Child, bool IsGlobal, bool IsArrayExpression) : base(NodeType.DeleteExpression, Child)
|
||||
public DeleteExpression(BaseNode child, bool isGlobal, bool isArrayExpression) : base(NodeType.DeleteExpression, child)
|
||||
{
|
||||
this.IsGlobal = IsGlobal;
|
||||
this.IsArrayExpression = IsArrayExpression;
|
||||
_isGlobal = isGlobal;
|
||||
_isArrayExpression = isArrayExpression;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (IsGlobal)
|
||||
if (_isGlobal)
|
||||
{
|
||||
Writer.Write("::");
|
||||
writer.Write("::");
|
||||
}
|
||||
|
||||
Writer.Write("delete");
|
||||
writer.Write("delete");
|
||||
|
||||
if (IsArrayExpression)
|
||||
if (_isArrayExpression)
|
||||
{
|
||||
Writer.Write("[] ");
|
||||
writer.Write("[] ");
|
||||
}
|
||||
|
||||
Child.Print(Writer);
|
||||
Child.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,12 +4,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class DtorName : ParentNode
|
||||
{
|
||||
public DtorName(BaseNode Name) : base(NodeType.DtOrName, Name) { }
|
||||
public DtorName(BaseNode name) : base(NodeType.DtOrName, name) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("~");
|
||||
Child.PrintLeft(Writer);
|
||||
writer.Write("~");
|
||||
Child.PrintLeft(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class DynamicExceptionSpec : ParentNode
|
||||
{
|
||||
public DynamicExceptionSpec(BaseNode Child) : base(NodeType.DynamicExceptionSpec, Child) { }
|
||||
public DynamicExceptionSpec(BaseNode child) : base(NodeType.DynamicExceptionSpec, child) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("throw(");
|
||||
Child.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("throw(");
|
||||
Child.Print(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,18 +4,18 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class ElaboratedType : ParentNode
|
||||
{
|
||||
private string Elaborated;
|
||||
private string _elaborated;
|
||||
|
||||
public ElaboratedType(string Elaborated, BaseNode Type) : base(NodeType.ElaboratedType, Type)
|
||||
public ElaboratedType(string elaborated, BaseNode type) : base(NodeType.ElaboratedType, type)
|
||||
{
|
||||
this.Elaborated = Elaborated;
|
||||
_elaborated = elaborated;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write(Elaborated);
|
||||
Writer.Write(" ");
|
||||
Child.Print(Writer);
|
||||
writer.Write(_elaborated);
|
||||
writer.Write(" ");
|
||||
Child.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,22 +4,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class EnclosedExpression : BaseNode
|
||||
{
|
||||
private string Prefix;
|
||||
private BaseNode Expression;
|
||||
private string Postfix;
|
||||
private string _prefix;
|
||||
private BaseNode _expression;
|
||||
private string _postfix;
|
||||
|
||||
public EnclosedExpression(string Prefix, BaseNode Expression, string Postfix) : base(NodeType.EnclosedExpression)
|
||||
public EnclosedExpression(string prefix, BaseNode expression, string postfix) : base(NodeType.EnclosedExpression)
|
||||
{
|
||||
this.Prefix = Prefix;
|
||||
this.Expression = Expression;
|
||||
this.Postfix = Postfix;
|
||||
_prefix = prefix;
|
||||
_expression = expression;
|
||||
_postfix = postfix;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write(Prefix);
|
||||
Expression.Print(Writer);
|
||||
Writer.Write(Postfix);
|
||||
writer.Write(_prefix);
|
||||
_expression.Print(writer);
|
||||
writer.Write(_postfix);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,36 +4,36 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class EncodedFunction : BaseNode
|
||||
{
|
||||
private BaseNode Name;
|
||||
private BaseNode Params;
|
||||
private BaseNode CV;
|
||||
private BaseNode Ref;
|
||||
private BaseNode Attrs;
|
||||
private BaseNode Ret;
|
||||
private BaseNode _name;
|
||||
private BaseNode _params;
|
||||
private BaseNode _cv;
|
||||
private BaseNode _ref;
|
||||
private BaseNode _attrs;
|
||||
private BaseNode _ret;
|
||||
|
||||
public EncodedFunction(BaseNode Name, BaseNode Params, BaseNode CV, BaseNode Ref, BaseNode Attrs, BaseNode Ret) : base(NodeType.NameType)
|
||||
public EncodedFunction(BaseNode name, BaseNode Params, BaseNode cv, BaseNode Ref, BaseNode attrs, BaseNode ret) : base(NodeType.NameType)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Params = Params;
|
||||
this.CV = CV;
|
||||
this.Ref = Ref;
|
||||
this.Attrs = Attrs;
|
||||
this.Ret = Ret;
|
||||
_name = name;
|
||||
_params = Params;
|
||||
_cv = cv;
|
||||
_ref = Ref;
|
||||
_attrs = attrs;
|
||||
_ret = ret;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (Ret != null)
|
||||
if (_ret != null)
|
||||
{
|
||||
Ret.PrintLeft(Writer);
|
||||
_ret.PrintLeft(writer);
|
||||
|
||||
if (!Ret.HasRightPart())
|
||||
if (!_ret.HasRightPart())
|
||||
{
|
||||
Writer.Write(" ");
|
||||
writer.Write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
Name.Print(Writer);
|
||||
_name.Print(writer);
|
||||
|
||||
}
|
||||
|
||||
|
@ -42,35 +42,35 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
writer.Write("(");
|
||||
|
||||
if (Params != null)
|
||||
if (_params != null)
|
||||
{
|
||||
Params.Print(Writer);
|
||||
_params.Print(writer);
|
||||
}
|
||||
|
||||
Writer.Write(")");
|
||||
writer.Write(")");
|
||||
|
||||
if (Ret != null)
|
||||
if (_ret != null)
|
||||
{
|
||||
Ret.PrintRight(Writer);
|
||||
_ret.PrintRight(writer);
|
||||
}
|
||||
|
||||
if (CV != null)
|
||||
if (_cv != null)
|
||||
{
|
||||
CV.Print(Writer);
|
||||
_cv.Print(writer);
|
||||
}
|
||||
|
||||
if (Ref != null)
|
||||
if (_ref != null)
|
||||
{
|
||||
Ref.Print(Writer);
|
||||
_ref.Print(writer);
|
||||
}
|
||||
|
||||
if (Attrs != null)
|
||||
if (_attrs != null)
|
||||
{
|
||||
Attrs.Print(Writer);
|
||||
_attrs.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,45 +4,45 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class FoldExpression : BaseNode
|
||||
{
|
||||
private bool IsLeftFold;
|
||||
private string OperatorName;
|
||||
private BaseNode Expression;
|
||||
private BaseNode Initializer;
|
||||
private bool _isLeftFold;
|
||||
private string _operatorName;
|
||||
private BaseNode _expression;
|
||||
private BaseNode _initializer;
|
||||
|
||||
public FoldExpression(bool IsLeftFold, string OperatorName, BaseNode Expression, BaseNode Initializer) : base(NodeType.FunctionParameter)
|
||||
public FoldExpression(bool isLeftFold, string operatorName, BaseNode expression, BaseNode initializer) : base(NodeType.FunctionParameter)
|
||||
{
|
||||
this.IsLeftFold = IsLeftFold;
|
||||
this.OperatorName = OperatorName;
|
||||
this.Expression = Expression;
|
||||
this.Initializer = Initializer;
|
||||
_isLeftFold = isLeftFold;
|
||||
_operatorName = operatorName;
|
||||
_expression = expression;
|
||||
_initializer = initializer;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
writer.Write("(");
|
||||
|
||||
if (IsLeftFold && Initializer != null)
|
||||
if (_isLeftFold && _initializer != null)
|
||||
{
|
||||
Initializer.Print(Writer);
|
||||
Writer.Write(" ");
|
||||
Writer.Write(OperatorName);
|
||||
Writer.Write(" ");
|
||||
_initializer.Print(writer);
|
||||
writer.Write(" ");
|
||||
writer.Write(_operatorName);
|
||||
writer.Write(" ");
|
||||
}
|
||||
|
||||
Writer.Write(IsLeftFold ? "... " : " ");
|
||||
Writer.Write(OperatorName);
|
||||
Writer.Write(!IsLeftFold ? " ..." : " ");
|
||||
Expression.Print(Writer);
|
||||
writer.Write(_isLeftFold ? "... " : " ");
|
||||
writer.Write(_operatorName);
|
||||
writer.Write(!_isLeftFold ? " ..." : " ");
|
||||
_expression.Print(writer);
|
||||
|
||||
if (!IsLeftFold && Initializer != null)
|
||||
if (!_isLeftFold && _initializer != null)
|
||||
{
|
||||
Initializer.Print(Writer);
|
||||
Writer.Write(" ");
|
||||
Writer.Write(OperatorName);
|
||||
Writer.Write(" ");
|
||||
_initializer.Print(writer);
|
||||
writer.Write(" ");
|
||||
writer.Write(_operatorName);
|
||||
writer.Write(" ");
|
||||
}
|
||||
|
||||
Writer.Write(")");
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,11 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
// TODO: Compute inside the Demangler
|
||||
public BaseNode Reference;
|
||||
private int Index;
|
||||
private int _index;
|
||||
|
||||
public ForwardTemplateReference(int Index) : base(NodeType.ForwardTemplateReference)
|
||||
public ForwardTemplateReference(int index) : base(NodeType.ForwardTemplateReference)
|
||||
{
|
||||
this.Index = Index;
|
||||
_index = index;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
|
@ -18,14 +18,14 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
return Reference.GetName();
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Reference.PrintLeft(Writer);
|
||||
Reference.PrintLeft(writer);
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
Reference.PrintRight(Writer);
|
||||
Reference.PrintRight(writer);
|
||||
}
|
||||
|
||||
public override bool HasRightPart()
|
||||
|
|
|
@ -4,20 +4,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class FunctionParameter : BaseNode
|
||||
{
|
||||
private string Number;
|
||||
private string _number;
|
||||
|
||||
public FunctionParameter(string Number) : base(NodeType.FunctionParameter)
|
||||
public FunctionParameter(string number) : base(NodeType.FunctionParameter)
|
||||
{
|
||||
this.Number = Number;
|
||||
_number = number;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("fp ");
|
||||
writer.Write("fp ");
|
||||
|
||||
if (Number != null)
|
||||
if (_number != null)
|
||||
{
|
||||
Writer.Write(Number);
|
||||
writer.Write(_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,47 +4,47 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class FunctionType : BaseNode
|
||||
{
|
||||
private BaseNode ReturnType;
|
||||
private BaseNode Params;
|
||||
private BaseNode CVQualifier;
|
||||
private SimpleReferenceType ReferenceQualifier;
|
||||
private BaseNode ExceptionSpec;
|
||||
private BaseNode _returnType;
|
||||
private BaseNode _params;
|
||||
private BaseNode _cvQualifier;
|
||||
private SimpleReferenceType _referenceQualifier;
|
||||
private BaseNode _exceptionSpec;
|
||||
|
||||
public FunctionType(BaseNode ReturnType, BaseNode Params, BaseNode CVQualifier, SimpleReferenceType ReferenceQualifier, BaseNode ExceptionSpec) : base(NodeType.FunctionType)
|
||||
public FunctionType(BaseNode returnType, BaseNode Params, BaseNode cvQualifier, SimpleReferenceType referenceQualifier, BaseNode exceptionSpec) : base(NodeType.FunctionType)
|
||||
{
|
||||
this.ReturnType = ReturnType;
|
||||
this.Params = Params;
|
||||
this.CVQualifier = CVQualifier;
|
||||
this.ReferenceQualifier = ReferenceQualifier;
|
||||
this.ExceptionSpec = ExceptionSpec;
|
||||
_returnType = returnType;
|
||||
_params = Params;
|
||||
_cvQualifier = cvQualifier;
|
||||
_referenceQualifier = referenceQualifier;
|
||||
_exceptionSpec = exceptionSpec;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
ReturnType.PrintLeft(Writer);
|
||||
Writer.Write(" ");
|
||||
_returnType.PrintLeft(writer);
|
||||
writer.Write(" ");
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Params.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
_params.Print(writer);
|
||||
writer.Write(")");
|
||||
|
||||
ReturnType.PrintRight(Writer);
|
||||
_returnType.PrintRight(writer);
|
||||
|
||||
CVQualifier.Print(Writer);
|
||||
_cvQualifier.Print(writer);
|
||||
|
||||
if (ReferenceQualifier.Qualifier != Reference.None)
|
||||
if (_referenceQualifier.Qualifier != Reference.None)
|
||||
{
|
||||
Writer.Write(" ");
|
||||
ReferenceQualifier.PrintQualifier(Writer);
|
||||
writer.Write(" ");
|
||||
_referenceQualifier.PrintQualifier(writer);
|
||||
}
|
||||
|
||||
if (ExceptionSpec != null)
|
||||
if (_exceptionSpec != null)
|
||||
{
|
||||
Writer.Write(" ");
|
||||
ExceptionSpec.Print(Writer);
|
||||
writer.Write(" ");
|
||||
_exceptionSpec.Print(writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class GlobalQualifiedName : ParentNode
|
||||
{
|
||||
public GlobalQualifiedName(BaseNode Child) : base(NodeType.GlobalQualifiedName, Child) { }
|
||||
public GlobalQualifiedName(BaseNode child) : base(NodeType.GlobalQualifiedName, child) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("::");
|
||||
Child.Print(Writer);
|
||||
writer.Write("::");
|
||||
Child.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,25 +5,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class InitListExpression : BaseNode
|
||||
{
|
||||
private BaseNode TypeNode;
|
||||
private List<BaseNode> Nodes;
|
||||
private BaseNode _typeNode;
|
||||
private List<BaseNode> _nodes;
|
||||
|
||||
public InitListExpression(BaseNode TypeNode, List<BaseNode> Nodes) : base(NodeType.InitListExpression)
|
||||
public InitListExpression(BaseNode typeNode, List<BaseNode> nodes) : base(NodeType.InitListExpression)
|
||||
{
|
||||
this.TypeNode = TypeNode;
|
||||
this.Nodes = Nodes;
|
||||
_typeNode = typeNode;
|
||||
_nodes = nodes;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (TypeNode != null)
|
||||
if (_typeNode != null)
|
||||
{
|
||||
TypeNode.Print(Writer);
|
||||
_typeNode.Print(writer);
|
||||
}
|
||||
|
||||
Writer.Write("{");
|
||||
Writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
|
||||
Writer.Write("}");
|
||||
writer.Write("{");
|
||||
writer.Write(string.Join<BaseNode>(", ", _nodes.ToArray()));
|
||||
writer.Write("}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,19 +4,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class IntegerCastExpression : ParentNode
|
||||
{
|
||||
private string Number;
|
||||
private string _number;
|
||||
|
||||
public IntegerCastExpression(BaseNode Type, string Number) : base(NodeType.IntegerCastExpression, Type)
|
||||
public IntegerCastExpression(BaseNode type, string number) : base(NodeType.IntegerCastExpression, type)
|
||||
{
|
||||
this.Number = Number;
|
||||
_number = number;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Child.Print(Writer);
|
||||
Writer.Write(")");
|
||||
Writer.Write(Number);
|
||||
writer.Write("(");
|
||||
Child.Print(writer);
|
||||
writer.Write(")");
|
||||
writer.Write(_number);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,37 +4,37 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class IntegerLiteral : BaseNode
|
||||
{
|
||||
private string LitteralName;
|
||||
private string LitteralValue;
|
||||
private string _literalName;
|
||||
private string _literalValue;
|
||||
|
||||
public IntegerLiteral(string LitteralName, string LitteralValue) : base(NodeType.IntegerLiteral)
|
||||
public IntegerLiteral(string literalName, string literalValue) : base(NodeType.IntegerLiteral)
|
||||
{
|
||||
this.LitteralValue = LitteralValue;
|
||||
this.LitteralName = LitteralName;
|
||||
_literalValue = literalValue;
|
||||
_literalName = literalName;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (LitteralName.Length > 3)
|
||||
if (_literalName.Length > 3)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Writer.Write(LitteralName);
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
writer.Write(_literalName);
|
||||
writer.Write(")");
|
||||
}
|
||||
|
||||
if (LitteralValue[0] == 'n')
|
||||
if (_literalValue[0] == 'n')
|
||||
{
|
||||
Writer.Write("-");
|
||||
Writer.Write(LitteralValue.Substring(1));
|
||||
writer.Write("-");
|
||||
writer.Write(_literalValue.Substring(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Writer.Write(LitteralValue);
|
||||
writer.Write(_literalValue);
|
||||
}
|
||||
|
||||
if (LitteralName.Length <= 3)
|
||||
if (_literalName.Length <= 3)
|
||||
{
|
||||
Writer.Write(LitteralName);
|
||||
writer.Write(_literalName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class LiteralOperator : ParentNode
|
||||
{
|
||||
public LiteralOperator(BaseNode Child) : base(NodeType.LiteralOperator, Child) { }
|
||||
public LiteralOperator(BaseNode child) : base(NodeType.LiteralOperator, child) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("operator \"");
|
||||
Child.PrintLeft(Writer);
|
||||
Writer.Write("\"");
|
||||
writer.Write("operator \"");
|
||||
Child.PrintLeft(writer);
|
||||
writer.Write("\"");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,20 +4,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class LocalName : BaseNode
|
||||
{
|
||||
private BaseNode Encoding;
|
||||
private BaseNode Entity;
|
||||
private BaseNode _encoding;
|
||||
private BaseNode _entity;
|
||||
|
||||
public LocalName(BaseNode Encoding, BaseNode Entity) : base(NodeType.LocalName)
|
||||
public LocalName(BaseNode encoding, BaseNode entity) : base(NodeType.LocalName)
|
||||
{
|
||||
this.Encoding = Encoding;
|
||||
this.Entity = Entity;
|
||||
_encoding = encoding;
|
||||
_entity = entity;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Encoding.Print(Writer);
|
||||
Writer.Write("::");
|
||||
Entity.Print(Writer);
|
||||
_encoding.Print(writer);
|
||||
writer.Write("::");
|
||||
_entity.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,22 +4,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class MemberExpression : BaseNode
|
||||
{
|
||||
private BaseNode LeftNode;
|
||||
private string Kind;
|
||||
private BaseNode RightNode;
|
||||
private BaseNode _leftNode;
|
||||
private string _kind;
|
||||
private BaseNode _rightNode;
|
||||
|
||||
public MemberExpression(BaseNode LeftNode, string Kind, BaseNode RightNode) : base(NodeType.MemberExpression)
|
||||
public MemberExpression(BaseNode leftNode, string kind, BaseNode rightNode) : base(NodeType.MemberExpression)
|
||||
{
|
||||
this.LeftNode = LeftNode;
|
||||
this.Kind = Kind;
|
||||
this.RightNode = RightNode;
|
||||
_leftNode = leftNode;
|
||||
_kind = kind;
|
||||
_rightNode = rightNode;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
LeftNode.Print(Writer);
|
||||
Writer.Write(Kind);
|
||||
RightNode.Print(Writer);
|
||||
_leftNode.Print(writer);
|
||||
writer.Write(_kind);
|
||||
_rightNode.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,26 +4,26 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class NameType : BaseNode
|
||||
{
|
||||
private string NameValue;
|
||||
private string _nameValue;
|
||||
|
||||
public NameType(string NameValue, NodeType Type) : base(Type)
|
||||
public NameType(string nameValue, NodeType type) : base(type)
|
||||
{
|
||||
this.NameValue = NameValue;
|
||||
_nameValue = nameValue;
|
||||
}
|
||||
|
||||
public NameType(string NameValue) : base(NodeType.NameType)
|
||||
public NameType(string nameValue) : base(NodeType.NameType)
|
||||
{
|
||||
this.NameValue = NameValue;
|
||||
_nameValue = nameValue;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return NameValue;
|
||||
return _nameValue;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write(NameValue);
|
||||
writer.Write(_nameValue);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,24 +4,24 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class NameTypeWithTemplateArguments : BaseNode
|
||||
{
|
||||
private BaseNode Prev;
|
||||
private BaseNode TemplateArgument;
|
||||
private BaseNode _prev;
|
||||
private BaseNode _templateArgument;
|
||||
|
||||
public NameTypeWithTemplateArguments(BaseNode Prev, BaseNode TemplateArgument) : base(NodeType.NameTypeWithTemplateArguments)
|
||||
public NameTypeWithTemplateArguments(BaseNode prev, BaseNode templateArgument) : base(NodeType.NameTypeWithTemplateArguments)
|
||||
{
|
||||
this.Prev = Prev;
|
||||
this.TemplateArgument = TemplateArgument;
|
||||
_prev = prev;
|
||||
_templateArgument = templateArgument;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return Prev.GetName();
|
||||
return _prev.GetName();
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Prev.Print(Writer);
|
||||
TemplateArgument.Print(Writer);
|
||||
_prev.Print(writer);
|
||||
_templateArgument.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,23 +4,23 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class NestedName : ParentNode
|
||||
{
|
||||
private BaseNode Name;
|
||||
private BaseNode _name;
|
||||
|
||||
public NestedName(BaseNode Name, BaseNode Type) : base(NodeType.NestedName, Type)
|
||||
public NestedName(BaseNode name, BaseNode type) : base(NodeType.NestedName, type)
|
||||
{
|
||||
this.Name = Name;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
{
|
||||
return Name.GetName();
|
||||
return _name.GetName();
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Child.Print(Writer);
|
||||
Writer.Write("::");
|
||||
Name.Print(Writer);
|
||||
Child.Print(writer);
|
||||
writer.Write("::");
|
||||
_name.Print(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,51 +4,51 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class NewExpression : BaseNode
|
||||
{
|
||||
private NodeArray Expressions;
|
||||
private BaseNode TypeNode;
|
||||
private NodeArray Initializers;
|
||||
private NodeArray _expressions;
|
||||
private BaseNode _typeNode;
|
||||
private NodeArray _initializers;
|
||||
|
||||
private bool IsGlobal;
|
||||
private bool IsArrayExpression;
|
||||
private bool _isGlobal;
|
||||
private bool _isArrayExpression;
|
||||
|
||||
public NewExpression(NodeArray Expressions, BaseNode TypeNode, NodeArray Initializers, bool IsGlobal, bool IsArrayExpression) : base(NodeType.NewExpression)
|
||||
public NewExpression(NodeArray expressions, BaseNode typeNode, NodeArray initializers, bool isGlobal, bool isArrayExpression) : base(NodeType.NewExpression)
|
||||
{
|
||||
this.Expressions = Expressions;
|
||||
this.TypeNode = TypeNode;
|
||||
this.Initializers = Initializers;
|
||||
_expressions = expressions;
|
||||
_typeNode = typeNode;
|
||||
_initializers = initializers;
|
||||
|
||||
this.IsGlobal = IsGlobal;
|
||||
this.IsArrayExpression = IsArrayExpression;
|
||||
_isGlobal = isGlobal;
|
||||
_isArrayExpression = isArrayExpression;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (IsGlobal)
|
||||
if (_isGlobal)
|
||||
{
|
||||
Writer.Write("::operator ");
|
||||
writer.Write("::operator ");
|
||||
}
|
||||
|
||||
Writer.Write("new ");
|
||||
writer.Write("new ");
|
||||
|
||||
if (IsArrayExpression)
|
||||
if (_isArrayExpression)
|
||||
{
|
||||
Writer.Write("[] ");
|
||||
writer.Write("[] ");
|
||||
}
|
||||
|
||||
if (Expressions.Nodes.Count != 0)
|
||||
if (_expressions.Nodes.Count != 0)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Expressions.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
_expressions.Print(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
|
||||
TypeNode.Print(Writer);
|
||||
_typeNode.Print(writer);
|
||||
|
||||
if (Initializers.Nodes.Count != 0)
|
||||
if (_initializers.Nodes.Count != 0)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Initializers.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("(");
|
||||
_initializers.Print(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public List<BaseNode> Nodes { get; protected set; }
|
||||
|
||||
public NodeArray(List<BaseNode> Nodes) : base(NodeType.NodeArray)
|
||||
public NodeArray(List<BaseNode> nodes) : base(NodeType.NodeArray)
|
||||
{
|
||||
this.Nodes = Nodes;
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
public NodeArray(List<BaseNode> Nodes, NodeType Type) : base(Type)
|
||||
public NodeArray(List<BaseNode> nodes, NodeType type) : base(type)
|
||||
{
|
||||
this.Nodes = Nodes;
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
public override bool IsArray()
|
||||
|
@ -22,9 +22,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
|
||||
writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class NoexceptSpec : ParentNode
|
||||
{
|
||||
public NoexceptSpec(BaseNode Child) : base(NodeType.NoexceptSpec, Child) { }
|
||||
public NoexceptSpec(BaseNode child) : base(NodeType.NoexceptSpec, child) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("noexcept(");
|
||||
Child.Print(Writer);
|
||||
Writer.Write(")");
|
||||
writer.Write("noexcept(");
|
||||
Child.Print(writer);
|
||||
writer.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,29 +5,29 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class PackedTemplateParameter : NodeArray
|
||||
{
|
||||
public PackedTemplateParameter(List<BaseNode> Nodes) : base(Nodes, NodeType.PackedTemplateParameter) { }
|
||||
public PackedTemplateParameter(List<BaseNode> nodes) : base(nodes, NodeType.PackedTemplateParameter) { }
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
foreach (BaseNode Node in Nodes)
|
||||
foreach (BaseNode node in Nodes)
|
||||
{
|
||||
Node.PrintLeft(Writer);
|
||||
node.PrintLeft(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
foreach (BaseNode Node in Nodes)
|
||||
foreach (BaseNode node in Nodes)
|
||||
{
|
||||
Node.PrintLeft(Writer);
|
||||
node.PrintLeft(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasRightPart()
|
||||
{
|
||||
foreach (BaseNode Node in Nodes)
|
||||
foreach (BaseNode node in Nodes)
|
||||
{
|
||||
if (Node.HasRightPart())
|
||||
if (node.HasRightPart())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,20 +4,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class PackedTemplateParameterExpansion : ParentNode
|
||||
{
|
||||
public PackedTemplateParameterExpansion(BaseNode Child) : base(NodeType.PackedTemplateParameterExpansion, Child) {}
|
||||
public PackedTemplateParameterExpansion(BaseNode child) : base(NodeType.PackedTemplateParameterExpansion, child) {}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
if (Child is PackedTemplateParameter)
|
||||
{
|
||||
if (((PackedTemplateParameter)Child).Nodes.Count != 0)
|
||||
{
|
||||
Child.Print(Writer);
|
||||
Child.Print(writer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Writer.Write("...");
|
||||
writer.Write("...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public BaseNode Child { get; private set; }
|
||||
|
||||
public ParentNode(NodeType Type, BaseNode Child) : base(Type)
|
||||
public ParentNode(NodeType type, BaseNode child) : base(type)
|
||||
{
|
||||
this.Child = Child;
|
||||
Child = child;
|
||||
}
|
||||
|
||||
public override string GetName()
|
||||
|
|
|
@ -4,42 +4,42 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class PointerType : BaseNode
|
||||
{
|
||||
private BaseNode Child;
|
||||
private BaseNode _child;
|
||||
|
||||
public PointerType(BaseNode Child) : base(NodeType.PointerType)
|
||||
public PointerType(BaseNode child) : base(NodeType.PointerType)
|
||||
{
|
||||
this.Child = Child;
|
||||
_child = child;
|
||||
}
|
||||
|
||||
public override bool HasRightPart()
|
||||
{
|
||||
return Child.HasRightPart();
|
||||
return _child.HasRightPart();
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Child.PrintLeft(Writer);
|
||||
if (Child.IsArray())
|
||||
_child.PrintLeft(writer);
|
||||
if (_child.IsArray())
|
||||
{
|
||||
Writer.Write(" ");
|
||||
writer.Write(" ");
|
||||
}
|
||||
|
||||
if (Child.IsArray() || Child.HasFunctions())
|
||||
if (_child.IsArray() || _child.HasFunctions())
|
||||
{
|
||||
Writer.Write("(");
|
||||
writer.Write("(");
|
||||
}
|
||||
|
||||
Writer.Write("*");
|
||||
writer.Write("*");
|
||||
}
|
||||
|
||||
public override void PrintRight(TextWriter Writer)
|
||||
public override void PrintRight(TextWriter writer)
|
||||
{
|
||||
if (Child.IsArray() || Child.HasFunctions())
|
||||
if (_child.IsArray() || _child.HasFunctions())
|
||||
{
|
||||
Writer.Write(")");
|
||||
writer.Write(")");
|
||||
}
|
||||
|
||||
Child.PrintRight(Writer);
|
||||
_child.PrintRight(writer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,19 +4,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
|
|||
{
|
||||
public class PostfixExpression : ParentNode
|
||||
{
|
||||
private string Operator;
|
||||
private string _operator;
|
||||
|
||||
public PostfixExpression(BaseNode Type, string Operator) : base(NodeType.PostfixExpression, Type)
|
||||
public PostfixExpression(BaseNode type, string Operator) : base(NodeType.PostfixExpression, type)
|
||||
{
|
||||
this.Operator = Operator;
|
||||
_operator = Operator;
|
||||
}
|
||||
|
||||
public override void PrintLeft(TextWriter Writer)
|
||||
public override void PrintLeft(TextWriter writer)
|
||||
{
|
||||
Writer.Write("(");
|
||||
Child.Print(Writer);
|
||||
Writer.Write(")");
|
||||
Writer.Write(Operator);
|
||||
writer.Write("(");
|
||||
Child.Print(writer);
|
||||
writer.Write(")");
|
||||
writer.Write(_operator);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue