mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 04:48:53 +00:00
227 lines
7.8 KiB
C#
227 lines
7.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Runtime.InteropServices;
|
|
using Cosmos.Common;
|
|
using Cosmos.Debug.Kernel;
|
|
|
|
namespace Cosmos.IL2CPU
|
|
{
|
|
// todo: optimize this, probably using assembler
|
|
public static partial class VTablesImpl
|
|
{
|
|
// this field seems to be always empty, but the VTablesImpl class is embedded in the final exe.
|
|
public static VTable[] mTypes;
|
|
|
|
static VTablesImpl()
|
|
{
|
|
|
|
}
|
|
|
|
public static bool IsInstance(uint aObjectType, uint aDesiredObjectType)
|
|
{
|
|
var xCurrentType = aObjectType;
|
|
if (aObjectType == 0)
|
|
{
|
|
return true;
|
|
}
|
|
do
|
|
{
|
|
if (xCurrentType == aDesiredObjectType)
|
|
{
|
|
return true;
|
|
}
|
|
if (xCurrentType == mTypes[xCurrentType].BaseTypeIdentifier)
|
|
{
|
|
return false;
|
|
}
|
|
xCurrentType = mTypes[xCurrentType].BaseTypeIdentifier;
|
|
}
|
|
while (xCurrentType != 0);
|
|
return false;
|
|
}
|
|
|
|
public static void SetTypeInfo(int aType, uint aBaseType, uint[] aMethodIndexes, uint[] aMethodAddresses, uint aMethodCount)
|
|
//public static void SetTypeInfo(int aType, uint aBaseType, uint aMethodIndexesA, uint aMethodIndexesB, uint aMethodAddressesA, uint aMethodAddressesB, uint aMethodCount)
|
|
{
|
|
if (aType == 2)
|
|
{
|
|
EnableDebug = true;
|
|
Debug("DoTest");
|
|
DebugHex("aMethodIndexes.Length", (uint)aMethodIndexes.Length);
|
|
EnableDebug = false;
|
|
}
|
|
//var xType = mTypes[aType];
|
|
//xType.BaseTypeIdentifier = aBaseType;
|
|
//xType.MethodIndexes = aMethodIndexes;
|
|
//xType.MethodAddresses = aMethodAddresses;
|
|
//xType.MethodCount = (int)aMethodCount;
|
|
//mTypes[aType] = xType;
|
|
|
|
//Debug("SetTypeInfo");
|
|
//DebugHex("Type", (uint) aType);
|
|
//DebugHex("BaseType", (uint) aBaseType);
|
|
//DebugHex("MethodCount", aMethodCount);
|
|
////DebugHex("aMethodAddressesA", aMethodAddressesA);
|
|
////DebugHex("aMethodAddressesB", aMethodAddressesB);
|
|
////DebugHex("aMethodIndexesA", aMethodIndexesA);
|
|
////DebugHex("aMethodIndexesB", aMethodIndexesB);
|
|
//DebugHex("mTypes.Length", (uint)mTypes.Length);
|
|
//DebugHex("aMethodAddresses.Length", (uint)aMethodAddresses.Length);
|
|
//DebugHex("aMethodIndexes.Length", (uint)aMethodIndexes.Length);
|
|
|
|
mTypes[aType].BaseTypeIdentifier = aBaseType;
|
|
mTypes[aType].MethodIndexes = aMethodIndexes;
|
|
mTypes[aType].MethodAddresses = aMethodAddresses;
|
|
mTypes[aType].MethodCount = (int) aMethodCount;
|
|
//Debugger.DoBochsBreak();
|
|
//DebugHex("Read back BaseType", mTypes[aType].BaseTypeIdentifier);
|
|
|
|
if (aType > 0x98)
|
|
{
|
|
//DebugHex("BaseType of 0x00000098", mTypes[0x00000098].BaseTypeIdentifier);
|
|
}
|
|
//if (aBaseType != mTypes[aType].BaseTypeIdentifier)
|
|
//{
|
|
// DebugAndHalt("Fout!");
|
|
//}
|
|
//DebugHex("Read back aMethodAddresses.Length", (uint)mTypes[aType].MethodAddresses.Length);
|
|
|
|
}
|
|
|
|
public static void SetMethodInfo(int aType, int aMethodIndex, uint aMethodIdentifier, uint aMethodAddress)
|
|
{
|
|
//var xType = mTypes[aType];
|
|
//DebugHex("BaseTypeID from type", xType.BaseTypeIdentifier);
|
|
//var xArray = mTypes[aType].MethodAddresses;
|
|
//Debug("Na array");
|
|
//DebugHex("Array length", (uint)xArray.Length);
|
|
//DebugHex("Array[0]", xArray[0]);
|
|
//DebugHex("Array[1]", xArray[1]);
|
|
//DebugHex("Array[2]", xArray[2]);
|
|
//DebugHex("Array[3]", xArray[3]);
|
|
|
|
//Debugger.DoBochsBreak();
|
|
mTypes[aType].MethodIndexes[aMethodIndex] = aMethodIdentifier;
|
|
mTypes[aType].MethodAddresses[aMethodIndex] = aMethodAddress;
|
|
//if (aType == 0x9D && aMethodIdentifier == 0x9C)
|
|
//{
|
|
// Debug("SetMethodInfo");
|
|
// DebugHex("Type", (uint)aType);
|
|
// DebugHex("MethodId", (uint)aMethodIdentifier);
|
|
// DebugHex("Read back MethodId: ", (uint)mTypes[aType].MethodIndexes[aMethodIndex]);
|
|
// DebugHex("MethodIdx", (uint)aMethodIndex);
|
|
// DebugHex("aMethodAddress", (uint)aMethodAddress);
|
|
// DebugHex("Read back address: ", (uint)mTypes[aType].MethodAddresses[aMethodIndex]);
|
|
//}
|
|
|
|
if (mTypes[aType].MethodIndexes[aMethodIndex] != aMethodIdentifier)
|
|
{
|
|
DebugAndHalt("Setting went wrong! (1)");
|
|
}
|
|
//DebugAndHalt("Klaar");
|
|
//if (mTypes[aType].MethodAddresses[aMethodIndex] != aMethodAddress)
|
|
//{
|
|
// DebugHex("aMethodAddress", aMethodAddress);
|
|
// DebugHex("MethodAddress from array", mTypes[aType].MethodAddresses[aMethodIndex]);
|
|
// DebugAndHalt("Setting went wrong! (2)");
|
|
//}
|
|
}
|
|
|
|
public static uint GetMethodAddressForType(uint aType, uint aMethodId)
|
|
{
|
|
if (aType > 0xFFFF)
|
|
{
|
|
EnableDebug = true;
|
|
DebugHex("Type", aType);
|
|
DebugHex("MethodId", aMethodId);
|
|
Debugger.SendKernelPanic(KernelPanicTypes.VMT_TypeIdInvalid);
|
|
while (true)
|
|
;
|
|
}
|
|
var xCurrentType = aType;
|
|
DebugHex("Type", xCurrentType);
|
|
DebugHex("MethodId", aMethodId);
|
|
do
|
|
{
|
|
DebugHex("Now checking type", xCurrentType);
|
|
var xCurrentTypeInfo = mTypes[xCurrentType];
|
|
DebugHex("It's basetype is", xCurrentTypeInfo.BaseTypeIdentifier);
|
|
|
|
if (xCurrentTypeInfo.MethodIndexes == null)
|
|
{
|
|
EnableDebug = true;
|
|
DebugHex("MethodIndexes is null for type", aType);
|
|
Debugger.SendKernelPanic(KernelPanicTypes.VMT_MethodIndexesNull);
|
|
while (true)
|
|
;
|
|
}
|
|
if (xCurrentTypeInfo.MethodAddresses == null)
|
|
{
|
|
EnableDebug = true;
|
|
DebugHex("MethodAddresses is null for type", aType);
|
|
Debugger.SendKernelPanic(KernelPanicTypes.VMT_MethodAddressesNull);
|
|
while (true)
|
|
;
|
|
}
|
|
|
|
for (int i = 0; i < xCurrentTypeInfo.MethodIndexes.Length; i++)
|
|
{
|
|
if (xCurrentTypeInfo.MethodIndexes[i] == aMethodId)
|
|
{
|
|
var xResult = xCurrentTypeInfo.MethodAddresses[i];
|
|
if (xResult < 1048576) // if pointer is under 1MB, some issue exists!
|
|
{
|
|
EnableDebug = true;
|
|
DebugHex("Result", (uint)xResult);
|
|
DebugHex("i", (uint)i);
|
|
DebugHex("MethodCount", (uint)xCurrentTypeInfo.MethodCount);
|
|
DebugHex("MethodAddresses.Length", (uint)xCurrentTypeInfo.MethodAddresses.Length);
|
|
Debug("Method found, but address is invalid!");
|
|
Debugger.SendKernelPanic(KernelPanicTypes.VMT_MethodFoundButAddressInvalid);
|
|
while (true)
|
|
;
|
|
}
|
|
Debug("Found.");
|
|
return xResult;
|
|
}
|
|
}
|
|
if (xCurrentType == xCurrentTypeInfo.BaseTypeIdentifier)
|
|
{
|
|
Debug("Ultimate base type already found!");
|
|
break;
|
|
}
|
|
xCurrentType = xCurrentTypeInfo.BaseTypeIdentifier;
|
|
}
|
|
while (true);
|
|
//}
|
|
EnableDebug = true;
|
|
Debugger.DoSend("Type");
|
|
Debugger.DoSendNumber(aType);
|
|
Debugger.DoSend("MethodId");
|
|
Debugger.DoSendNumber(aMethodId);
|
|
Debugger.DoSend("Not FOUND!");
|
|
Debugger.SendKernelPanic(KernelPanicTypes.VMT_MethodNotFound);
|
|
while (true)
|
|
;
|
|
throw new Exception("Cannot find virtual method!");
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size = 24)]
|
|
public struct VTable
|
|
{
|
|
[FieldOffset(0)]
|
|
public uint BaseTypeIdentifier;
|
|
|
|
[FieldOffset(4)]
|
|
public int MethodCount;
|
|
|
|
[FieldOffset(8)]
|
|
public uint[] MethodIndexes;
|
|
|
|
[FieldOffset(16)]
|
|
public uint[] MethodAddresses;
|
|
}
|
|
}
|