public static uint ReadDLCommands(int FileNumber, UInt32 Address, ref DisplayListStruct ThisDL) { DLCommandStruct ThisCommand = new DLCommandStruct(); int Segment = (int)(Address >> 24); UInt32 Offset = (Address & 0x00FFFFFF); if (GameHandler.IsAddressValid(Address) == false) return Offset + 8; // Loop through the Display List in memory until we reach an EndDL command while (ThisCommand.ID != EndDLCmd) { // Take note of the command's data, type, name, memory location and file number ThisCommand.w0 = GameHandler.Read32(GameHandler.RAM[Segment].Data, Offset); ThisCommand.w1 = GameHandler.Read32(GameHandler.RAM[Segment].Data, Offset + 4); ThisCommand.ID = (byte)(ThisCommand.w0 >> 24); IdentifyCommand(ThisCommand.ID, ref ThisCommand.Name); ThisCommand.Address = (((UInt32)Segment << 24) | Offset); ThisCommand.InFileNumber = FileNumber; // Add the command to our Display List's command structure ThisDL.Commands.Add(ThisCommand); // If the command is a DL call or a RDP_HALF1 storage, go and process that Display List next if (ThisCommand.ID == DLCmd || ThisCommand.ID == RDPHalf1Cmd) { ReadDLCommands(FileNumber, ThisCommand.w1, ref ThisDL); } Offset += 8; } return Offset; }
public static void ReadDL(int FileNumber, UInt32 Address, ref List<DisplayListStruct> DLists) { // Some sanity checking and data extraction from the RAM address if (GameHandler.IsAddressValid(Address) == false) return; // Prepare some temporary structures DisplayListStruct ThisDL = new DisplayListStruct(); ThisDL.Commands = new List<DLCommandStruct>(); // Add identification information to the Display List ThisDL.InFileNumber = FileNumber; ThisDL.StartAddress = Address; ThisDL.EndAddress = ((Address & 0xFF000000) | ReadDLCommands(FileNumber, Address, ref ThisDL)); ThisDL.GLID = GL.GenLists(1); // Generate random color for picking ThisDL.PickColor = RandomColor(); // Add the Display List to our DL list DLists.Add(ThisDL); }
public static void ParseAllDLs(ref List<DisplayListStruct> DLists) { // Clear primitive and environment colors NGraphics.PrimColor = new NPrimColor(new Color4(0.5f, 0.5f, 0.5f, 0.5f), 0.0f, 0); NGraphics.EnvColor = new Color4(0.5f, 0.5f, 0.5f, 0.5f); GL.Arb.ProgramEnvParameter4(AssemblyProgramTargetArb.FragmentProgram, 0, NGraphics.PrimColor.Color.R, NGraphics.PrimColor.Color.G, NGraphics.PrimColor.Color.B, NGraphics.PrimColor.Color.A); GL.Arb.ProgramEnvParameter4(AssemblyProgramTargetArb.FragmentProgram, 1, NGraphics.EnvColor.R, NGraphics.EnvColor.G, NGraphics.EnvColor.B, NGraphics.EnvColor.A); // For temporary access by other functions CurrentDLists = DLists; // Loop through each Display List for parsing foreach (DisplayListStruct ThisDL in CurrentDLists) { // Again, for temporary access CurrentDL = ThisDL; // Begin new OpenGL Display List GL.NewList(ThisDL.GLID, ListMode.CompileAndExecute); // Parse all commands of the Display List ParseDL(CurrentDL); // If the current Display List is supposed to be highlighted, parse its essential commands once more if (CurrentDL.Highlight == true && ParseMode != 2) { ParseMode = 1; ParseDL(CurrentDL); ParseMode = 0; } // End the GL Display List GL.EndList(); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); } }
public static void ParseDL(DisplayListStruct ThisDL) { // See if we're told to parse everything, or just selectively if (ParseMode > 0) { if (ParseMode == 1) { // Prepare highlight rendering GL.Enable((EnableCap)All.FragmentProgram); GL.Arb.BindProgram(AssemblyProgramTargetArb.FragmentProgram, FPHighlight); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); } else if (ParseMode == 2) { GL.Disable(EnableCap.Texture2D); GL.Color4(ThisDL.PickColor); } GL.Disable(EnableCap.AlphaTest); GL.Disable(EnableCap.Lighting); // Go through every command in the current DList for (int i = 0; i < ThisDL.Commands.Count; i++) { // If it's either DL/EndDL, GeometryMode or otherwise geometry-related, execute it if (ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.VTX || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.TRI1 || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.TRI2 || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.DL || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.ENDDL || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.GEOMETRYMODE || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.MODIFYVTX || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.MTX || ThisDL.Commands[i].ID == (byte)UcodeF3DEX2.POPMTX) { UcodeCommands[ThisDL.Commands[i].ID](ThisDL.Commands[i].w0, ThisDL.Commands[i].w1); } } // Reset some changed states GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Lighting); GL.Enable(EnableCap.AlphaTest); GL.Disable((EnableCap)All.FragmentProgram); } else { // Go through every command in the current DList for (int i = 0; i < ThisDL.Commands.Count; i++) { if (i < ThisDL.Commands.Count - Macros.Max(a => a.Commands.Length)) { foreach (MacroStruct ThisMacro in Macros) { // Get the next commands from the current position in the DList byte[] NextCmds = new byte[ThisMacro.Commands.Length]; UInt32[] NextW0 = new UInt32[ThisMacro.Commands.Length + 1]; UInt32[] NextW1 = new UInt32[ThisMacro.Commands.Length + 1]; for (int j = 0; j <= ThisMacro.Commands.Length; j++) { if (j != ThisMacro.Commands.Length) NextCmds[j] = ThisDL.Commands[i + j].ID; NextW0[j] = ThisDL.Commands[i + j].w0; NextW1[j] = ThisDL.Commands[i + j].w1; } // Compare the bytes to the macro and execute it if we have a match if (CompareBytes(NextCmds, ThisMacro.Commands)) { IsMacro = true; ThisMacro.Function(NextW0, NextW1); i += ThisMacro.Commands.Length - 1; break; } } IsMacro = false; } // Execute the next command UcodeCommands[ThisDL.Commands[i].ID](ThisDL.Commands[i].w0, ThisDL.Commands[i].w1); } } return; }
private static void Ucode_F3DEX2_BRANCH_Z(UInt32 w0, UInt32 w1) { if (GameHandler.IsAddressValid(NGraphics.RDPHalf1) == false) return; uint Vtx = ShiftR(w0, 1, 11); short ZVal = (short)w1; if (CurrentVertices[Vtx].Position.Z < ZVal) { DisplayListStruct BranchDL = new DisplayListStruct(); BranchDL.Commands = new List<DLCommandStruct>(); ReadDLCommands(CurrentDL.InFileNumber, NGraphics.RDPHalf1, ref BranchDL); ParseDL(BranchDL); } }