private void ProcessInstruction()
{
var Instruction = ReadInstructionAndMoveNext();
var Params24 = Instruction.Params;
//Console.WriteLine($"ProcessInstruction: Pc={Pc}, Instruction={Instruction}");
//InstructionSwitch(GpuDisplayListRunner, Instruction.OpCode, Instruction.Params);
GpuStateStructPointer.data[Instruction.OpCode] = Instruction.Params;
switch (Instruction.OpCode)
{
// Address
case GpuOpCodes.ORIGIN_ADDR:
break;
case GpuOpCodes.OFFSET_ADDR:
GpuStateData[GpuOpCodes.OFFSET_ADDR] = Params24 << 8;
break;
// Flow
case GpuOpCodes.JUMP:
{
JumpRelativeOffset((uint)(Params24 & ~3));
break;
}
case GpuOpCodes.CALL:
{
CallRelativeOffset((uint)(Params24 & ~3));
break;
}
case GpuOpCodes.RET:
{
Ret();
break;
}
// Finishing
case GpuOpCodes.END:
{
Done = true;
GpuProcessor.GpuImpl.End(GpuStateStructPointer);
break;
}
case GpuOpCodes.FINISH:
{
GpuProcessor.GpuImpl.Finish(GpuStateStructPointer);
DoFinish(InstructionAddressCurrent, Params24, ExecuteNow: true);
break;
}
// Texture
case GpuOpCodes.TFLUSH:
GpuProcessor.GpuImpl.TextureFlush(GpuStateStructPointer);
break;
case GpuOpCodes.TSYNC:
GpuProcessor.GpuImpl.TextureSync(GpuStateStructPointer);
break;
// Kicking
case GpuOpCodes.SPLINE:
// @TODO
//auto sp_ucount = command.extract!(uint, 0, 8);
//auto sp_vcount = command.extract!(uint, 8, 8);
//auto sp_utype = command.extract!(uint, 16, 2);
//auto sp_vtype = command.extract!(uint, 18, 2);
//gpu.logWarning("OP_SPLINE(%d, %d, %d, %d)", sp_ucount, sp_vcount, sp_utype, sp_vtype);
break;
case GpuOpCodes.TRXKICK:
{
var transfer = GpuStateStructPointer.TextureTransferState;
transfer.TexelSize =
(TextureTransferStateStruct.TexelSizeEnum)Params24.Extract(0, 1);
GpuProcessor.GpuImpl.Transfer(GpuStateStructPointer);
break;
}
case GpuOpCodes.PPRIM:
{
//gpu.state.patch.type = command.extract!(PatchPrimitiveType, 0);
break;
}
case GpuOpCodes.PRIM:
{
var primitiveType = (GuPrimitiveType)Params24.Extract(16, 3);
var vertexCount = (ushort)Params24.Extract(0, 16);
#if PRIM_BATCH
var nextInstruction = *(GpuInstruction *)Memory.PspAddressToPointerUnsafe(Pc + 4);
if (_primCount == 0)
{
GpuProcessor.GpuImpl.BeforeDraw(GpuStateStructPointer);
GpuProcessor.GpuImpl.PrimStart(GlobalGpuState, GpuStateStructPointer,
primitiveType);
}
if (vertexCount > 0)
{
GpuProcessor.GpuImpl.Prim(vertexCount);
}
if (nextInstruction.OpCode == GpuOpCodes.PRIM &&
(GuPrimitiveType)nextInstruction.Params.Extract(16, 3) == primitiveType)
{
//Console.WriteLine();
_primCount++;
}
else
{
//Console.WriteLine("{0:X8}", PC);
_primCount = 0;
GpuProcessor.GpuImpl.PrimEnd();
}
#else
GpuDisplayList.GpuProcessor.GpuImpl.BeforeDraw(GpuDisplayList.GpuStateStructPointer);
GpuDisplayList.GpuProcessor.GpuImpl.PrimStart(GlobalGpuState, GpuDisplayList.GpuStateStructPointer);
GpuDisplayList.GpuProcessor.GpuImpl.Prim(GlobalGpuState, GpuDisplayList.GpuStateStructPointer, primitiveType, vertexCount);
GpuDisplayList.GpuProcessor.GpuImpl.PrimEnd(GlobalGpuState, GpuDisplayList.GpuStateStructPointer);
#endif
}
break;
case GpuOpCodes.BEZIER:
{
var uCount = (byte)Params24.Extract(0, 8);
var vCount = (byte)Params24.Extract(8, 8);
DrawBezier(uCount, vCount);
break;
}
case GpuOpCodes.ZBW:
{
GpuProcessor.MarkDepthBufferLoad(); // @TODO: Is this required?
break;
}
case GpuOpCodes.SIGNAL:
{
var signal = Params24.Extract(0, 16);
var behaviour = (SignalBehavior)Params24.Extract(16,8);
Console.Out.WriteLineColored(ConsoleColor.Green,"OP_SIGNAL: {0}, {1}",signal,behaviour);
switch (behaviour)
{
case SignalBehavior.PSP_GE_SIGNAL_NONE:
break;
case SignalBehavior.PSP_GE_SIGNAL_HANDLER_CONTINUE:
case SignalBehavior.PSP_GE_SIGNAL_HANDLER_PAUSE:
case SignalBehavior.PSP_GE_SIGNAL_HANDLER_SUSPEND:
var next = ReadInstructionAndMoveNext();
if (next.OpCode != GpuOpCodes.END)
{
throw new NotImplementedException("Error! Next Signal not an END! : " + next.OpCode);
}
break;
default:
throw new NotImplementedException($"Not implemented {behaviour}");
}
DoSignal(Pc,signal,behaviour,ExecuteNow: true);
break;
}
// Matrices
case GpuOpCodes.TMS:
{
GpuStateData[GpuOpCodes.TMS] = 0;
break;
}
case GpuOpCodes.TMATRIX:
{
var pos = GpuStateData[GpuOpCodes.TMS]++;
GpuStateData[GpuOpCodes.TMATRIX_BASE + (ushort)pos] = Params24 << 8;
break;
}
case GpuOpCodes.VMS:
{
GpuStateData[GpuOpCodes.VMS] = 0;
break;
}
case GpuOpCodes.VIEW:
{
var pos = GpuStateData[GpuOpCodes.VMS]++;
GpuStateData[GpuOpCodes.VIEW_MATRIX_BASE + (ushort)pos] = Params24 << 8;
break;
}
case GpuOpCodes.WMS:
{
GpuStateData[GpuOpCodes.WMS] = 0;
break;
}
case GpuOpCodes.WORLD:
{
var pos = GpuStateData[GpuOpCodes.WMS]++;
GpuStateData[GpuOpCodes.WORLD_MATRIX_BASE + (ushort)pos] = Params24 << 8;
break;
}
case GpuOpCodes.PMS:
{
GpuStateData[GpuOpCodes.PMS] = 0;
break;
}
case GpuOpCodes.PROJ:
{
var pos = GpuStateData[GpuOpCodes.PMS]++;
GpuStateData[GpuOpCodes.PROJ_MATRIX_BASE + (ushort)pos] = Params24 << 8;
break;
}
case GpuOpCodes.BOFS:
{
GpuStateData[GpuOpCodes.BOFS] = Params24;
break;
}
case GpuOpCodes.BONE:
{
var pos = GpuStateData[GpuOpCodes.BOFS]++;
GpuStateData[GpuOpCodes.BONE_MATRIX_BASE + (ushort)pos] = Params24 << 8;
break;
}
}
if (Debug)
{
var WritePC = Memory.GetPCWriteAddress(Pc);
Console.Error.WriteLine(
"CODE(0x{0:X}-0x{1:X}) : PC(0x{2:X}) : {3} : 0x{4:X} : Done:{5}",
InstructionAddressCurrent,
InstructionAddressStall,
WritePC,
Instruction.OpCode,
Instruction.Params,
Done
);
}
}