VMStack -> VMThread

This commit is contained in:
Nahuel Rocchetti 2023-08-25 18:51:26 -03:00
parent 0229014e46
commit a0acde0273
9 changed files with 35 additions and 34 deletions

View file

@ -12,7 +12,7 @@ namespace OpenTS2.SimAntics.Primitives
{
var stackObj = ctx.StackObjectEntity;
if (stackObj != null)
ctx.VM.Scheduler.ScheduleInterrupt(stackObj.Stack);
ctx.VM.Scheduler.ScheduleInterrupt(stackObj.MainThread);
return VMReturnValue.ReturnTrue;
}
}

View file

@ -15,7 +15,7 @@ namespace OpenTS2.SimAntics.Primitives
{
var argumentIndex = ctx.Node.GetUInt16Operand(0);
var sleepTicks = (uint)Math.Max(0,(int)ctx.StackFrame.Arguments[argumentIndex]);
return new VMReturnValue(new ContinueHandler(ctx.Stack, sleepTicks));
return new VMReturnValue(new ContinueHandler(ctx.Thread, sleepTicks));
}
/// <summary>
@ -24,24 +24,24 @@ namespace OpenTS2.SimAntics.Primitives
public class ContinueHandler : VMContinueHandler
{
public uint TargetTick = 0;
VMStack _stack;
VMThread _thread;
public ContinueHandler(VMStack stack, uint ticks)
public ContinueHandler(VMThread thread, uint ticks)
{
_stack = stack;
var vm = _stack.Entity.VM;
_thread = thread;
var vm = _thread.Entity.VM;
TargetTick = vm.CurrentTick + ticks;
}
public override VMExitCode Tick()
{
if (_stack.Interrupt)
if (_thread.Interrupt)
{
// Handled!
_stack.Interrupt = false;
_thread.Interrupt = false;
return VMExitCode.True;
}
if (_stack.Entity.VM.CurrentTick >= TargetTick)
if (_thread.Entity.VM.CurrentTick >= TargetTick)
return VMExitCode.True;
return VMExitCode.Continue;
}

View file

@ -13,8 +13,8 @@ namespace OpenTS2.SimAntics
{
public VMStackFrame StackFrame;
public BHAVAsset.Node Node;
public VMStack Stack => StackFrame.Stack;
public VMEntity Entity => StackFrame.Stack.Entity;
public VMThread Thread => StackFrame.Thread;
public VMEntity Entity => StackFrame.Thread.Entity;
public VMEntity StackObjectEntity => VM.GetEntityByID(StackFrame.StackObjectID);
public VM VM => Entity.VM;

View file

@ -8,14 +8,15 @@ using System.Threading.Tasks;
namespace OpenTS2.SimAntics
{
/// <summary>
/// This is a process or thread running in the SimAntics virtual machine, with its own stack and temp variables.
/// This is a process running in the SimAntics virtual machine.
/// </summary>
public class VMEntity
{
public bool PendingDeletion = false;
public short ID = 1;
public short[] Temps = new short[20];
public VMStack Stack;
// Main thread the VM will tick.
public VMThread MainThread;
public VM VM;
public ObjectDefinitionAsset ObjectDefinition;
public uint PrivateGroupID => ObjectDefinition.GlobalTGI.GroupID;
@ -32,7 +33,7 @@ namespace OpenTS2.SimAntics
protected VMEntity()
{
Stack = new VMStack(this);
MainThread = new VMThread(this);
}
public VMEntity(ObjectDefinitionAsset objectDefinition) : this()
@ -42,7 +43,7 @@ namespace OpenTS2.SimAntics
public void Tick()
{
Stack.Tick();
MainThread.Tick();
}
public void Delete()

View file

@ -44,11 +44,11 @@ namespace OpenTS2.SimAntics
}
// TODO - Right now the way this works is that once an entity has been notified out of idle/interrupted, the first idle that gets executed on the next tick (or that continues to run if there is one already running) won't actually sleep. If no idles are ran then the interrupt is just discarded. Verify this is okay!
public void ScheduleInterrupt(VMStack stack)
public void ScheduleInterrupt(VMThread thread)
{
ScheduleWhenPossible(() =>
{
stack.Interrupt = true;
thread.Interrupt = true;
});
}

View file

@ -13,7 +13,7 @@ namespace OpenTS2.SimAntics
/// </summary>
public class VMStackFrame
{
public VMStack Stack;
public VMThread Thread;
public BHAVAsset BHAV;
public short StackObjectID = 0;
public int CurrentNode = 0;
@ -25,10 +25,10 @@ namespace OpenTS2.SimAntics
public short[] Arguments;
private static int MaxIterations = 500000;
public VMStackFrame(BHAVAsset bhav, VMStack stack)
public VMStackFrame(BHAVAsset bhav, VMThread thread)
{
BHAV = bhav;
Stack = stack;
Thread = thread;
Locals = new short[BHAV.LocalCount];
Arguments = new short[BHAV.ArgumentCount];
}
@ -119,7 +119,7 @@ namespace OpenTS2.SimAntics
var newStackFrame = CreateStackFrameForNode(context);
if (newStackFrame != null)
{
Stack.Frames.Push(newStackFrame);
Thread.Frames.Push(newStackFrame);
return newStackFrame.Tick();
}
else
@ -145,7 +145,7 @@ namespace OpenTS2.SimAntics
if (bhav == null)
return null;
var newStackFrame = new VMStackFrame(bhav, Stack);
var newStackFrame = new VMStackFrame(bhav, Thread);
newStackFrame.StackObjectID = ctx.StackFrame.StackObjectID;
GoSubFormat format = GoSubFormat.PassTemps;
@ -173,10 +173,10 @@ namespace OpenTS2.SimAntics
switch(format)
{
case GoSubFormat.PassTemps:
argAmount = Math.Min(newStackFrame.Arguments.Length, Stack.Entity.Temps.Length);
argAmount = Math.Min(newStackFrame.Arguments.Length, Thread.Entity.Temps.Length);
for (var i=0;i<argAmount;i++)
{
newStackFrame.TrySetArgument(i, Stack.Entity.Temps[i]);
newStackFrame.TrySetArgument(i, Thread.Entity.Temps[i]);
}
break;
case GoSubFormat.TS1:
@ -225,12 +225,12 @@ namespace OpenTS2.SimAntics
BHAVAsset GetBHAVForOpCode(ushort opCode)
{
// 0x0XXX is global scope, 0x1XXX is private scope and 0x2XXX is semiglobal scope.
var groupid = Stack.Entity.SemiGlobalGroupID;
var groupid = Thread.Entity.SemiGlobalGroupID;
if (opCode < 0x1000)
groupid = GroupIDs.Global;
else if (opCode < 0x2000)
groupid = Stack.Entity.PrivateGroupID;
groupid = Thread.Entity.PrivateGroupID;
return VM.GetBHAV(opCode, groupid);
}

View file

@ -7,16 +7,16 @@ using System.Threading.Tasks;
namespace OpenTS2.SimAntics
{
/// <summary>
/// Stack of scripts to run on a SimAntics entity/thread.
/// Thread running in a VM Entity.
/// </summary>
public class VMStack
public class VMThread
{
public bool Interrupt = false;
// For check trees and other things that should execute and return immediately we should set this to false.
public bool CanYield = true;
public VMEntity Entity;
public Stack<VMStackFrame> Frames = new Stack<VMStackFrame>();
public VMStack(VMEntity entity)
public VMThread(VMEntity entity)
{
Entity = entity;
}

View file

@ -45,8 +45,8 @@ public class SimAnticsTest
var entity = new VMEntity(testObjectDefinition);
vm.AddEntity(entity);
var stackFrame = new VMStackFrame(bhav, entity.Stack);
entity.Stack.Frames.Push(stackFrame);
var stackFrame = new VMStackFrame(bhav, entity.MainThread);
entity.MainThread.Frames.Push(stackFrame);
// Test BHAV:
// Multiplies Param0 by 2, stores it in Temp0
@ -61,7 +61,7 @@ public class SimAnticsTest
vm.Tick();
Assert.That(entity.Temps[0], Is.EqualTo(1200));
// Interrupt idle here, so that it doesn't sleep for 20000 ticks.
vm.Scheduler.ScheduleInterrupt(entity.Stack);
vm.Scheduler.ScheduleInterrupt(entity.MainThread);
vm.Tick();
Assert.That(entity.Temps[0], Is.EqualTo(0));
}
@ -86,8 +86,8 @@ public class SimAnticsTest
var entity = new VMEntity(testObjectDefinition);
vm.AddEntity(entity);
var stackFrame = new VMStackFrame(bhav, entity.Stack);
entity.Stack.Frames.Push(stackFrame);
var stackFrame = new VMStackFrame(bhav, entity.MainThread);
entity.MainThread.Frames.Push(stackFrame);
Assert.Throws<SimAnticsException>(() =>
{