Proper Private/SemiGlobal/Global scopes for VM

This commit is contained in:
Nahuel Rocchetti 2023-08-24 08:10:35 -03:00
parent b843766cf3
commit 66ce0c14a7
7 changed files with 51 additions and 24 deletions

View file

@ -1,4 +1,6 @@
using System;
using OpenTS2.Common;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -8,6 +10,7 @@ namespace OpenTS2.Content.DBPF
{
public class ObjectDefinitionAsset : AbstractAsset
{
public SemiGlobalAsset SemiGlobal => ContentProvider.Get().GetAsset<SemiGlobalAsset>(new ResourceKey(1, GlobalTGI.GroupID, TypeIDs.SEMIGLOBAL));
public string FileName;
public enum FieldNames

View file

@ -38,8 +38,8 @@ namespace OpenTS2.SimAntics.Primitives
}
public override VMReturnValue Execute(VMContext ctx)
{
var lhsData = ctx.Node.GetUInt16Operand(0);
var rhsData = ctx.Node.GetUInt16Operand(2);
var lhsData = ctx.Node.GetInt16Operand(0);
var rhsData = ctx.Node.GetInt16Operand(2);
var signedFlag = ctx.Node.Operands[4];
var op = (Operator)ctx.Node.Operands[5];
var lhsSource = (VMDataSource)ctx.Node.Operands[6];
@ -155,9 +155,9 @@ namespace OpenTS2.SimAntics.Primitives
// Check this as it's new in TS2.
case Operator.Assign32BitValue:
rhs = ctx.GetData(rhsSource, rhsData);
var rhs2 = ctx.GetData(rhsSource, (ushort)(rhsData+1));
var rhs2 = ctx.GetData(rhsSource, (short)(rhsData+1));
ctx.SetData(lhsSource, lhsData, rhs);
ctx.SetData(lhsSource, (ushort)(lhsData+1), rhs2);
ctx.SetData(lhsSource, (short)(lhsData+1), rhs2);
return VMReturnValue.ReturnTrue;
}
return VMReturnValue.ReturnFalse;

View file

@ -48,8 +48,14 @@ namespace OpenTS2.SimAntics
return null;
}
/// <summary>
/// Adds an entity to the simulator, and assigns a unique ID to it.
/// </summary>
/// <param name="entity"></param>
public void AddEntity(VMEntity entity)
{
entity.VM = this;
entity.ID = GetUniqueID();
Entities.Add(entity);
_entitiesByID[entity.ID] = entity;
}

View file

@ -19,23 +19,23 @@ namespace OpenTS2.SimAntics
public VM VM => Entity.VM;
// TODO - still super incomplete, just enough to run basic scripts.
public short GetData(VMDataSource source, ushort dataIndex)
public short GetData(VMDataSource source, short dataIndex)
{
return source switch
{
VMDataSource.Literal => (short)dataIndex,
VMDataSource.Literal => dataIndex,
VMDataSource.Temps => Entity.Temps[dataIndex],
VMDataSource.Params => StackFrame.Arguments[dataIndex],
VMDataSource.StackObjectID => StackFrame.StackObjectID,
// TODO - unconfirmed.
VMDataSource.TempByTempIndex => Entity.Temps[Entity.Temps[dataIndex]],
VMDataSource.StackObjectsTemp => StackObjectEntity.Temps[dataIndex],
VMDataSource.Local => StackFrame.Locals[dataIndex],
VMDataSource.StackObjectsDefinition => (short)StackObjectEntity.ObjectDefinition.Fields[dataIndex],
_ => throw new ArgumentOutOfRangeException("SimAntics data source out of range!")
};
}
public void SetData(VMDataSource source, ushort dataIndex, short value)
public void SetData(VMDataSource source, short dataIndex, short value)
{
switch(source)
{

View file

@ -1,4 +1,5 @@
using System;
using OpenTS2.Content.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -15,12 +16,29 @@ namespace OpenTS2.SimAntics
public short[] Temps = new short[20];
public VMStack Stack;
public VM VM;
public VMEntity(VM vm)
public ObjectDefinitionAsset ObjectDefinition;
public uint PrivateGroupID => ObjectDefinition.GlobalTGI.GroupID;
public uint SemiGlobalGroupID
{
VM = vm;
Stack = new VMStack(this);
ID = vm.GetUniqueID();
get
{
var semiGlobal = ObjectDefinition.SemiGlobal;
if (semiGlobal == null)
return 0;
return semiGlobal.SemiGlobalGroupID;
}
}
protected VMEntity()
{
Stack = new VMStack(this);
}
public VMEntity(ObjectDefinitionAsset objectDefinition) : this()
{
ObjectDefinition = objectDefinition;
}
public void Tick()
{
Stack.Tick();

View file

@ -24,11 +24,6 @@ namespace OpenTS2.SimAntics
public short[] Locals;
public short[] Arguments;
// TODO - Return proper Group IDs. Private should come from the entity's OBJD, semiglobal from the entity's global resource.
private uint PrivateGroupID => BHAV.GlobalTGI.GroupID;
private uint SemiGlobalGroupID => 0x0;
private uint GlobalGroupID => GroupIDs.Global;
public VMStackFrame(BHAVAsset bhav, VMStack stack)
{
BHAV = bhav;
@ -181,7 +176,7 @@ namespace OpenTS2.SimAntics
var dataValueIndex = dataSourceIndex + 1;
var dataSource = (VMDataSource)ctx.Node.GetOperand(dataSourceIndex);
var dataValue = ctx.Node.GetUInt16Operand(dataValueIndex);
var dataValue = ctx.Node.GetInt16Operand(dataValueIndex);
var data = ctx.GetData(dataSource, dataValue);
@ -212,12 +207,12 @@ namespace OpenTS2.SimAntics
BHAVAsset GetBHAVForOpCode(ushort opCode)
{
// 0x0XXX is global scope, 0x1XXX is private scope and 0x2XXX is semiglobal scope.
var groupid = SemiGlobalGroupID;
var groupid = Stack.Entity.SemiGlobalGroupID;
if (opCode < 0x1000)
groupid = GlobalGroupID;
groupid = GroupIDs.Global;
else if (opCode < 0x2000)
groupid = PrivateGroupID;
groupid = Stack.Entity.PrivateGroupID;
return VM.GetBHAV(opCode, groupid);
}

View file

@ -9,6 +9,7 @@ using OpenTS2.SimAntics;
using OpenTS2.Common;
using OpenTS2.Files.Formats.DBPF;
using OpenTS2.SimAntics.Primitives;
using OpenTS2.Content.DBPF;
public class SimAnticsTest
{
@ -34,10 +35,14 @@ public class SimAnticsTest
[Test]
public void TestRunBHAV()
{
// VM Entities need to be attached to an OBJD to be aware of private/semiglobal scope.
var testObjectDefinition = new ObjectDefinitionAsset();
testObjectDefinition.TGI = new ResourceKey(1, _groupID, TypeIDs.OBJD);
var bhav = VM.GetBHAV(0x1001, _groupID);
var vm = new VM();
var entity = new VMEntity(vm);
var entity = new VMEntity(testObjectDefinition);
vm.AddEntity(entity);
var stackFrame = new VMStackFrame(bhav, entity.Stack);