ophura
ophura
CC#
Created by discount on 4/16/2024 in #help
✅ skill issue
$close
27 replies
CC#
Created by R3dMiztX on 4/17/2024 in #help
✅ Array help C++
:AA_02_UwU:
6 replies
CC#
Created by discount on 4/16/2024 in #help
✅ skill issue
:AA_Ayame_Hmp:
27 replies
CC#
Created by discount on 4/16/2024 in #help
✅ skill issue
a restart may help
27 replies
CC#
Created by discount on 4/16/2024 in #help
✅ skill issue
and by the way, it's called IntelliSense the suggestion thing you're talking about xd
27 replies
CC#
Created by Bunta Fujiwara (文太) on 4/13/2024 in #help
✅ Can't Authenticate User
:catgasm:
122 replies
CC#
Created by Black in Italian on 4/8/2024 in #help
Unity MonoBehaviour and Photon Confusion
why?
14 replies
CC#
Created by gwon8266 on 12/4/2023 in #help
Minimum Required Knowledge before I am job ready.
yeah, the least amount of skills needed are always listed on the job offer anyway...
6 replies
CC#
Created by AdiZ on 11/19/2023 in #help
✅ Quick - Unity "using" directive
when using static is used against a type, it means to import all static members of said type (the type itself is excluded, unless it's been imported by another using). static members include: - nested types - fields with the static modifier - properties with the static modifier - methods with the static modifier - fields with the const modifier it's important to note that the type itself doesn't have to be static. additionally, the use of the using keyword in this syntax:
using NewNamespace = Namespace;
using NewNamespace = Namespace;
or
using NewNamespace = Namespace.NestedNamespace;
using NewNamespace = Namespace.NestedNamespace;
or
using NewType = Namespace.Type;
using NewType = Namespace.Type;
is meant to introduce an alias for a given namespace and/or type. the following however:
using Type = Namespace.Type;
using Type = Namespace.Type;
is used to import a single type rather than define an alias for it, to exclude all other types in said Namespace that might cause ambiguity or some other issues...
8 replies
CC#
Created by ophura on 11/18/2023 in #help
Calculate Field Offset Based On Members' Name
nvm, this tweak fixed the miscalculation
internal unsafe long GetOffsetOf<T>(string target, string startAtField = null!)
where T : unmanaged
{
var currentHex = GetHexValue(dump[1]);
var previousHex = 0;
var startFieldPresent = !string.IsNullOrEmpty(startAtField);
var offsetSum = 0;

for (var index = 2; index < dump.Length; index++)
{
var fieldName = GetFieldName(dump[index - 2]);

// target reached!
if (fieldName.Equals(target)) break;

// skip duplicates of sequentially laid values,
// only considering the first occurrence.
if (currentHex != previousHex)
{
var fieldTypeSize = currentHex - previousHex;
previousHex = currentHex;

if (startFieldPresent)
{
if (fieldName.Equals(startAtField))
startFieldPresent = false;
else
offsetSum -= fieldTypeSize;
}
else
{
offsetSum += fieldTypeSize;
Console.WriteLine("{0}: {1}", fieldName, fieldTypeSize);
}
}

currentHex = GetHexValue(dump[index]);
}

var offset = checked(Math.Abs(offsetSum)*((long)sizeof(T)));
Console.WriteLine("{0} _[{1}];", typeof(T).Name.ToLower(), offset);
return offset;
}
internal unsafe long GetOffsetOf<T>(string target, string startAtField = null!)
where T : unmanaged
{
var currentHex = GetHexValue(dump[1]);
var previousHex = 0;
var startFieldPresent = !string.IsNullOrEmpty(startAtField);
var offsetSum = 0;

for (var index = 2; index < dump.Length; index++)
{
var fieldName = GetFieldName(dump[index - 2]);

// target reached!
if (fieldName.Equals(target)) break;

// skip duplicates of sequentially laid values,
// only considering the first occurrence.
if (currentHex != previousHex)
{
var fieldTypeSize = currentHex - previousHex;
previousHex = currentHex;

if (startFieldPresent)
{
if (fieldName.Equals(startAtField))
startFieldPresent = false;
else
offsetSum -= fieldTypeSize;
}
else
{
offsetSum += fieldTypeSize;
Console.WriteLine("{0}: {1}", fieldName, fieldTypeSize);
}
}

currentHex = GetHexValue(dump[index]);
}

var offset = checked(Math.Abs(offsetSum)*((long)sizeof(T)));
Console.WriteLine("{0} _[{1}];", typeof(T).Name.ToLower(), offset);
return offset;
}
5 replies
CC#
Created by ophura on 11/18/2023 in #help
Calculate Field Offset Based On Members' Name
the idea is that the offset result is a value that could be used in a C struct like so:
#define OFFSET_RESULT 16
typedef struct _placeholder_t {
unsigned int MaximumLength;
unsigned int Length; // this is the starting field.
unsigned char /* aka: byte */ Padding[OFFSET_RESULT];
void* ConsoleHandle; // this is the target.
} placeholder_t;
#define OFFSET_RESULT 16
typedef struct _placeholder_t {
unsigned int MaximumLength;
unsigned int Length; // this is the starting field.
unsigned char /* aka: byte */ Padding[OFFSET_RESULT];
void* ConsoleHandle; // this is the target.
} placeholder_t;
so the next member after the Padding fixed size array is the target, in other words: ConsoleHandle
5 replies
CC#
Created by ophura on 11/18/2023 in #help
Calculate Field Offset Based On Members' Name
and finally, here is the usage
using System;
using WinDbg;

var dtd = new DisplayTypeDump(
dump: DUMP,
seperator: Environment.NewLine
);

var offset = dtd.GetOffsetInBytes(
target: "ConsoleHandle",
startField: "Length"
);

Console.WriteLine(offset); // NOTE: output is 16
using System;
using WinDbg;

var dtd = new DisplayTypeDump(
dump: DUMP,
seperator: Environment.NewLine
);

var offset = dtd.GetOffsetInBytes(
target: "ConsoleHandle",
startField: "Length"
);

Console.WriteLine(offset); // NOTE: output is 16
5 replies
CC#
Created by ophura on 11/18/2023 in #help
Calculate Field Offset Based On Members' Name
and the following is the code used to make the calculation
namespace WinDbg;

using System;

/// <summary>
/// represents a class for working with type dumps of <see href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/">WinDbg</see>
/// <see href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/dt--display-type-">td</see> command.
/// </summary>
internal class DisplayTypeDump
{
private readonly string[] dump;

/// <summary>
/// initializes a new instance of the <see cref="DisplayTypeDump"/> class.
/// </summary>
/// <param name="dump">an array of strings representing the type dump.</param>
internal DisplayTypeDump(string[] dump) => this.dump = dump;

/// <summary>
/// initializes a new instance of the <see cref="DisplayTypeDump"/> class.
/// </summary>
/// <param name="dump">a string representing the type dump.</param>
/// <param name="seperator">the separator used to split the dump string.</param>
internal DisplayTypeDump(string dump, string seperator) =>
this.dump = dump.Split(seperator);

/// <summary>
/// represents the 32nd character of the ASCII table.
/// </summary>
private const char BlankSpace = (char)ConsoleKey.Spacebar;

/// <summary>
/// gets the hexadecimal value from a given string.
/// </summary>
/// <param name="vessel">the input string containing the hexadecimal value.</param>
/// <returns>the hexadecimal value as an integer.</returns>
internal static int GetHexValue(string vessel)
{
const int HexBase = 16;
var start = new Index(3);
var end = new Index(vessel.IndexOf(BlankSpace, 6));
var hexNumberString = vessel[start..end];
var hexValue = Convert.ToInt32(hexNumberString, HexBase);
return hexValue;
}

/// <summary>
/// gets the field name from the input string.
/// </summary>
/// <param name="vessel">the input string containing the field name.</param>
/// <returns>the extracted field name.</returns>
internal static string GetFieldName(string vessel)
{
var start = new Index(7);
var end = new Index(vessel.IndexOf(BlankSpace, start.Value));
var fieldName = vessel[start..end];
return fieldName;
}

/// <summary>
/// gets the offset in bytes for a target field in the type dump.
/// </summary>
/// <param name="target">the target field whose offset is to be calculated.</param>
/// <param name="startField">the optional starting field for offset calculation.</param>
/// <returns>the offset in bytes.</returns>
internal int GetOffsetInBytes(string target, string startField = null!)
{
var previousHex = 0;
var startFieldProvided = !string.IsNullOrEmpty(startField);
var offsetSum = 0;

for (var i = 0; i < dump.Length; ++i)
{
var fieldName = GetFieldName(dump[i]);

// target reached!
if (fieldName.Equals(target)) break;

var currentHex = GetHexValue(dump[i]);

// skip duplicates of sequentially laid values,
// only considering the first occurrence.
// --------------------------------------------
// potentially skipping the very first value
// of the array since it's often 0.
if (currentHex == previousHex) continue;

if (startFieldProvided && !fieldName.Equals(startField))
{
offsetSum -= currentHex;
continue;
}

offsetSum += currentHex;
previousHex = currentHex;
}

return Math.Abs(offsetSum);
}
}
namespace WinDbg;

using System;

/// <summary>
/// represents a class for working with type dumps of <see href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/">WinDbg</see>
/// <see href="https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/dt--display-type-">td</see> command.
/// </summary>
internal class DisplayTypeDump
{
private readonly string[] dump;

/// <summary>
/// initializes a new instance of the <see cref="DisplayTypeDump"/> class.
/// </summary>
/// <param name="dump">an array of strings representing the type dump.</param>
internal DisplayTypeDump(string[] dump) => this.dump = dump;

/// <summary>
/// initializes a new instance of the <see cref="DisplayTypeDump"/> class.
/// </summary>
/// <param name="dump">a string representing the type dump.</param>
/// <param name="seperator">the separator used to split the dump string.</param>
internal DisplayTypeDump(string dump, string seperator) =>
this.dump = dump.Split(seperator);

/// <summary>
/// represents the 32nd character of the ASCII table.
/// </summary>
private const char BlankSpace = (char)ConsoleKey.Spacebar;

/// <summary>
/// gets the hexadecimal value from a given string.
/// </summary>
/// <param name="vessel">the input string containing the hexadecimal value.</param>
/// <returns>the hexadecimal value as an integer.</returns>
internal static int GetHexValue(string vessel)
{
const int HexBase = 16;
var start = new Index(3);
var end = new Index(vessel.IndexOf(BlankSpace, 6));
var hexNumberString = vessel[start..end];
var hexValue = Convert.ToInt32(hexNumberString, HexBase);
return hexValue;
}

/// <summary>
/// gets the field name from the input string.
/// </summary>
/// <param name="vessel">the input string containing the field name.</param>
/// <returns>the extracted field name.</returns>
internal static string GetFieldName(string vessel)
{
var start = new Index(7);
var end = new Index(vessel.IndexOf(BlankSpace, start.Value));
var fieldName = vessel[start..end];
return fieldName;
}

/// <summary>
/// gets the offset in bytes for a target field in the type dump.
/// </summary>
/// <param name="target">the target field whose offset is to be calculated.</param>
/// <param name="startField">the optional starting field for offset calculation.</param>
/// <returns>the offset in bytes.</returns>
internal int GetOffsetInBytes(string target, string startField = null!)
{
var previousHex = 0;
var startFieldProvided = !string.IsNullOrEmpty(startField);
var offsetSum = 0;

for (var i = 0; i < dump.Length; ++i)
{
var fieldName = GetFieldName(dump[i]);

// target reached!
if (fieldName.Equals(target)) break;

var currentHex = GetHexValue(dump[i]);

// skip duplicates of sequentially laid values,
// only considering the first occurrence.
// --------------------------------------------
// potentially skipping the very first value
// of the array since it's often 0.
if (currentHex == previousHex) continue;

if (startFieldProvided && !fieldName.Equals(startField))
{
offsetSum -= currentHex;
continue;
}

offsetSum += currentHex;
previousHex = currentHex;
}

return Math.Abs(offsetSum);
}
}
5 replies