0
votes

Using the NetworkInfo2SecurityParameter function I am trying to copy the fixed-size buffer unkRandom from from LdnNetworkInfo struct held in NetworkInfo struct to the SecurityParameter struct's buffer.

Basically I am making a method to convert these two types, and I want to copy these two arrays to another. This code features all structs relevant.

The error is happening at the Buffer.MemoryCopy() function. The error is "You cannot use fixed size buffers contained in unfixed expressions. Try using the 'fixed' statement"

unsafe void NetworkInfo2SecurityParameter(NetworkInfo info, out SecurityParameter output)
{
    output = new SecurityParameter();
    output.sessionId = info.networkId.sessionId;
    Buffer.MemoryCopy(output.unkRandom, info.ldn.unkRandom, 16, 16);
}

struct SecurityParameter {
    public unsafe fixed byte unkRandom[16];// = new byte[16];
    public SessionId sessionId;
};

struct NetworkInfo : /sf::/LargeData {
    public NetworkId networkId;
    public CommonNetworkInfo common;
    public LdnNetworkInfo ldn;
};

struct LdnNetworkInfo {
    public unsafe fixed byte unkRandom[16];// = new byte[16];
    public ushort securityMode;
    public byte stationAcceptPolicy;
    public unsafe fixed byte _unk1[3];// = new byte[3];
    public byte nodeCountMax;
    public byte nodeCount;
    //TODO non primitive array,,
    private unsafe fixed byte _nodes[sizeof(NodeInfo)*NodeCountMax]; //Needs to be fixed array, and needs to be casted to NodeInfo span, so thats why its size is this
    public unsafe fixed Span<NodeInfo> nodes => MemoryMarshal.Cast<byte, NodeInfo>(MemoryMarshal.CreateSpan(ref _nodes[0], 128));
    public ushort _unk2;
    public ushort advertiseDataSize;
    public unsafe fixed byte advertiseData[AdvertiseDataSizeMax];// = new byte[AdvertiseDataSizeMax];
    public unsafe fixed byte _unk3[148];// = new byte[148];
};

2
What is the error?Christopher
You cannot use fixed size buffers contained in unfixed expressions. Try using the 'fixed' statementTimotej Leginus
Well, the obvious question is, have you tried using the fixed statement?Heretic Monkey
If the array is just 16 bytes, could you take a pointer to the array, cast it to a int64 pointer and copy it in two 64-bit chunks?JonasH
@HereticMonkey Where?Timotej Leginus

2 Answers

0
votes

Fixed it with this approach: I created a new variable called ret, which I did copy the data to, and then I assigned ret to output.

unsafe void NetworkInfo2SecurityParameter(NetworkInfo info, out SecurityParameter output)
        {
            var ret = new SecurityParameter();
            output.sessionId = info.networkId.sessionId;
            Buffer.MemoryCopy(ret.unkRandom, info.ldn.unkRandom, 16, 16);
            output = ret;
        }
0
votes

struct is assignable, like any primitive. Undoubtedly faster than Buffer.MemoryCopy() would be:

public unsafe struct FixedSizeBufferWrapper
{
    public unsafe fixed byte unkRandom[16];
}

unsafe 
{
    fixed (byte* firstStruct = somewhere.securityParameter, otherStruct = somewhereElse.ldnNetworkInfo )
    {
        //one assignment blits all contents
        *((FixedSizeBufferWrapper*)firstStruct.unkRandom) =
        *((FixedSizeBufferWrapper*)otherStruct.unkRandom);
    }
}

We cast buffers in each of your original structs to the wrapper pointer type and dereference each pointer SO THAT we can assign one to the other; assigning fixed buffers directly is not possible.

We have to cast because (at least in my version of C#) we cannot assign anything other than a primitive type (usually byte) as the buffer, and we aren't allowed to cast inside fixed(...).