I've had pretty decent success in reading the ENGINE_VARS struct by modelling the structure in C#. It was a bitch, not gonna lie. I did so by creating several classes from a base class consisting of an IntPtr variable only for all of the pointers to various structs (ENGINE_BMAP, ENGINE_VIEW, etc), and then in the subclasses, I added methods to retrieve a marshalled instance of the data that that IntPtr points to. This way I could marshal all of the data directly into classes that would handle it from there for user access.
It really was a pain...
Here's the code for my classes that works, my more recent code is presently [censored] up:
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
namespace GameStudio
{
[StructLayout(LayoutKind.Sequential)]
public struct Event
{
public byte mPtr;
}
[StructLayout(LayoutKind.Sequential)] public struct Var
{
public int mValue;
public void SetValue(float value) { mValue = (int)(value * (1 << 10)); }
public void SetValue(int value) { mValue = (value << 10); }
public float ValueFloat
{
get { return ((float)mValue) / (1 << 10); }
}
public int ValueInt
{
get { return (mValue >> 10); }
}
}
[StructLayout(LayoutKind.Sequential)] public struct Vector
{
public Var mX, mY, mZ;
public Var X { get { return mX; } set { mX = value; } }
public Var Y { get { return mY; } set { mY = value; } }
public Var Z { get { return mZ; } set { mZ = value; } }
}
[StructLayout(LayoutKind.Sequential)] public struct ColorRGB
{
public Var mBlue, mGreen, mRed;
public Var Blue { get { return mBlue; } set { mBlue = value; } }
public Var Green { get { return mGreen; } set { mGreen = value; } }
public Var Red { get { return mRed; } set { mRed = value; } }
}
[StructLayout(LayoutKind.Sequential)] public struct Angle
{
public Var mPan, mTilt, mRoll;
public Var Pan { get { return mPan; } set { mPan = value; } }
public Var Tilt { get { return mTilt; } set { mTilt = value; } }
public Var Roll { get { return mRoll; } set { mRoll = value; } }
}
[StructLayout(LayoutKind.Sequential)] public struct CLink
{
public int mIndex;
public IntPtr mNext;
public String mName;
public int Index { get { return mIndex; } set { mIndex = value; } }
public CLink Next { get { return (CLink)Marshal.PtrToStructure(mNext, typeof(CLink)); } /** set { Next = (IntPtr)value; }/**/ }
public String Name { get { return mName; } set { mName = value; } }
}
[StructLayout(LayoutKind.Sequential)] public class Viewport
{
public CLink mLink; // clink
public int mType; // internal use only
public Var mLayer; // layer number (read only)
public Var mScreenX, mScreenY; // screen position in pixels
public int mFlags; // flags
public Var mScreenWidth, mScreenHeight; // screen size in pixels
public Vector mPosition; // position of the camera
public Angle mAngle; // camera angles
public Var mOffsetX, mOffsetY; // eye offsets
public Var mArc; // camera FOV, used for zooming
public Var mAspect; // width to height ratio
public Var mAmbient; // brightness
public Var mFog; // fog strength (only used when fog_end == 0)
public Var mAlpha; // transparency
public Vector mPortalVertex; // portal plane vertex
public Vector mPortalNormal; // portal plane normal
public Var mFogStart, mFogEnd; // fog start/end range in D3D mode
public Var mUnused0; // Unused
public EngineEntity mGenius; // calculates valid BSP tree leaf for the view
public EngineView mPortal; // portal view
public EngineBmap mBmap; // render target
public Var mNearZ, mFarZ; // Near and Far clipping Z ranges
}
[StructLayout(LayoutKind.Sequential)] public struct Entity
{
public CLink mLink; // clink
public String mType; // entity file name
public Vector mPosition; // position of the entity
public Angle mAngle; // euler angles
public Vector mScale; // scale factors, 0..255
public int mFlags; // entity flags
public Var mFrame; // frame number for sprites & models
public Var mNextFrame; //
public Var mSkin; //
public Var mAmbient; // -100..+100
public Var mAlbedo; // 0..100, light reflectivity
public Var mAlpha; // 0..100, transparency, default 50
public Var mLightRange; // dynamic light range in quants
public ColorRGB mColor; // dynamic light color, 0..255
public int mEMask; // event enable flags, EVF...
public int mEFlags; // hull and status flags
public Vector mBoundMin; // bounding box for entity->entity collisions
public Vector mBoundMax; // bounding box for entity->entity collisions
public Var mTriggerRange;
public Var mPush;
public Var mFloorDist; // distance to the floor - A6.23 or above
public int mSMask; // nosend_... flags - A6.20 or above
public int mClientID; // client # that has created this entity or view pointer for a layer entity
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Var[] mSkills;
public Var mPose; // current bones pose number
public EngineMaterial mMaterial;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] mInternal0;
public int mSkyFlags; // sky flags
public String mAttachName;
public Event mEvent; // event function
public Event mLocal; // client side function
public Var mLayer; // layer for 2D entities and skies
public int mInternal2;
public String mString0; // strings
public String mString1; // strings
public EngineEntity mParent; // parent entity
}
[StructLayout(LayoutKind.Sequential)] public struct Bmap
{
public CLink mLink; // clink
public int mWidth, mHeight; // size of the bitmap
public int mBytesPerPixel; // original bytes per pixel (1..4)
public IntPtr mPtr; // internal use
public IntPtr mPixels; // ptr to palettized, 565, 4444, 888 or 8888 coded original image
public int mFlags; // flags
public IntPtr mD3DTex; // LPDIRECT3DTEXTURE9
}
[StructLayout(LayoutKind.Sequential)] public struct Material
{
public CLink mLink; // clink
public ColorRGB mAmbient;
public ColorRGB mDiffuse;
public ColorRGB mSpecular;
public ColorRGB mEmissive;
public ColorRGB mMap;
public Var mAlpha;
public Var mPower; // for specular reflection
public Var mSunAlbedo;
public Var mScale0;
public Var mScale1;
public Var mCycle;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public Var[] mSkills;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public float[] mMatrix;
public int mFlags;
public String mEffect;
public int mUnused;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public EngineBmap[] mSkin;
public Event mEvent; // event function
}
[StructLayout(LayoutKind.Sequential)] public struct VarString
{
public CLink mLink; // clink
public String mString; // pointer to null terminated string
public int mLength; // allocated length of string
public int mFlags; // last bit 0 = don't save, 1 = save string at SAVE/LOAD
}
[StructLayout(LayoutKind.Sequential)] public struct EngineVar
{
public IntPtr mVar;
public Var Value
{ get { return (Var)Marshal.PtrToStructure(mVar, typeof(Var)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineVector
{
public IntPtr mVector;
public Vector Value
{ get { return (Vector)Marshal.PtrToStructure(mVector, typeof(Vector)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineColor
{
public IntPtr mColor;
public void GetObject(ref ColorRGB c) { c = (ColorRGB)Marshal.PtrToStructure(mColor, typeof(ColorRGB));}
public ColorRGB Value
{ get { return (ColorRGB)Marshal.PtrToStructure(mColor, typeof(ColorRGB)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineAngle
{
public IntPtr mAngle;
public Angle Value
{ get { return (Angle)Marshal.PtrToStructure(mAngle, typeof(Angle)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineEvent
{
public IntPtr mEvent;
public Event Value
{ get { return (Event)Marshal.PtrToStructure(mEvent, typeof(Event)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineView
{
public IntPtr mView;
public void GetObject(ref Viewport c) { c = (Viewport)Marshal.PtrToStructure(mView, typeof(Viewport)); }
public Viewport GetValue() { return (Viewport)Marshal.PtrToStructure(mView, typeof(Viewport)); }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineEntity
{
public IntPtr mEntity;
public Entity Value
{ get { return (Entity)Marshal.PtrToStructure(mEntity, typeof(Entity)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineBmap
{
public IntPtr mBmap;
public Bmap Value
{ get { return (Bmap)Marshal.PtrToStructure(mBmap, typeof(Bmap)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineMaterial
{
public IntPtr mMaterial;
public Entity Value
{ get { return (Entity)Marshal.PtrToStructure(mMaterial, typeof(Entity)); } }
}
[StructLayout(LayoutKind.Sequential)] public struct EngineString
{
public IntPtr mString;
public VarString Value
{ get { return (VarString)Marshal.PtrToStructure(mString, typeof(VarString)); } }
}