Exemple #1
0
 // Dump the display list of the currently selected gfx node (if applicable)
 // This can contain vertices and triangles, but also draw settings like lighting and fog
 private void DumpButton_Click(object sender, EventArgs e)
 {
     if (SelectedNode != null && (SelectedNode is GfxDisplayList || SelectedNode is GfxAnimationNode ||
                                  SelectedNode is GfxTranslatedModel || SelectedNode is GfxRotationNode))
     {
         uint address = Config.Stream.GetUInt32(SelectedNode.Address + 0x14);
         richTextBoxGfx.Text = Fast3DDecoder.DecodeList(SegmentationUtilities.DecodeSegmentedAddress(address));
     }
     else
     {
         MessageBox.Show("Select a display list node first");
     }
 }
Exemple #2
0
        // Gives a string decoding the display list starting at a given address
        public static string DecodeList(uint address, int recursionDepth = 0)
        {
            if (recursionDepth > MaxRecursionDepth)
            {
                return("Recursion too deep");
            }

            var res = new StringBuilder();

            res.AppendLine(Indent(recursionDepth) + $"Decoding list at 0x{address:X8}");
            for (int i = 0; i < MaxDisplayListLength; i++)
            {
                var firstWord  = Config.Stream.GetUInt32(address);
                var secondWord = Config.Stream.GetUInt32(address + 4);
                var opcode     = (F3DOpcode)((firstWord >> 24) & 0xFF);
                var name       = Enum.GetName(typeof(F3DOpcode), opcode);
                res.Append(Indent(recursionDepth) + $"{firstWord:X8} {secondWord:X8} " + name + " ");

                // todo: interpret the other commands
                switch (opcode)
                {
                case F3DOpcode.G_LOADBLOCK:

                    res.AppendLine();
                    break;

                case F3DOpcode.G_MOVEMEM:
                case F3DOpcode.G_SETTIMG:

                    res.AppendLine($"0x{SegmentationUtilities.DecodeSegmentedAddress(secondWord):X8}");
                    break;

                case F3DOpcode.G_MTX:
                    res.Append($"0x{SegmentationUtilities.DecodeSegmentedAddress(secondWord):X8} ");
                    var p = (firstWord >> 16) & 0xFF;
                    res.Append(((p & 0x01) != 0) ? "projection: " : "model view: ");
                    res.Append(((p & 0x02) != 0) ? "load" : "multiply");
                    res.AppendLine(((p & 0x04) != 0) ? "and push" : "and don't push");
                    break;

                case F3DOpcode.G_SETTILESIZE:
                    var h = ((secondWord & 0xFFF) + 4) / 4;
                    var w = (((secondWord >> 12) & 0xFFF) + 4) / 4;
                    res.AppendLine($"{w} * {h}");
                    break;

                case F3DOpcode.G_SETTILE:
                    var colorFormat = (firstWord >> 21) & 0x7;
                    res.Append(colorFormat < ColorModes.Length ? ColorModes[colorFormat] : "Invalid color mode");
                    int pixelBits = ((int)firstWord >> 19) & 0x3;
                    res.AppendLine(" " + (4 << pixelBits) + "-bit");
                    break;

                case F3DOpcode.G_CLEARGEOMETRYMODE:
                case F3DOpcode.G_SETGEOMETRYMODE:
                    res.AppendLine(GetGeometryFlags(secondWord));
                    break;

                case F3DOpcode.G_VTX:
                    var vertexAmount  = ((firstWord >> 20) & 0xF) + 1;
                    var startIndex    = ((firstWord >> 16) & 0xF);
                    var vertexAddress = SegmentationUtilities.DecodeSegmentedAddress(secondWord);
                    res.AppendLine($"{vertexAmount} vertices at 0x{vertexAddress:X8}, start index {startIndex}");
                    res.AppendLine(Indent(recursionDepth) + "(pos) flags (tex) (normal/color)");
                    for (byte j = 0; j < vertexAmount; j++)
                    {
                        uint add   = (uint)(vertexAddress + (j * 0x10));
                        var  x     = Config.Stream.GetInt16(add + 0x00);
                        var  y     = Config.Stream.GetInt16(add + 0x02);
                        var  z     = Config.Stream.GetInt16(add + 0x04);
                        var  flags = Config.Stream.GetUInt16(add + 0x06);
                        var  texX  = Config.Stream.GetInt16(add + 0x08);
                        var  texY  = Config.Stream.GetInt16(add + 0x0A);
                        var  r     = Config.Stream.GetByte(add + 0x0C);
                        var  g     = Config.Stream.GetByte(add + 0x0D);
                        var  b     = Config.Stream.GetByte(add + 0x0E);
                        var  a     = Config.Stream.GetByte(add + 0x0F);
                        res.AppendLine(Indent(recursionDepth) + $"({x}, {y}, {z}) 0x{flags:X4} ({texX}, {texY}) ({r}, {g}, {b}, {a})");
                    }
                    break;

                case F3DOpcode.G_TRI1:
                    var v1 = ((secondWord >> 16) & 0xFF) / 0x0A;
                    var v2 = ((secondWord >> 8) & 0xFF) / 0x0A;
                    var v3 = ((secondWord >> 0) & 0xFF) / 0x0A;
                    res.AppendLine($"indices ({v1}, {v2}, {v3})");
                    break;

                case F3DOpcode.G_DL:
                    res.AppendLine();
                    res.AppendLine(DecodeList(SegmentationUtilities.DecodeSegmentedAddress(secondWord), recursionDepth + 1));
                    break;

                default:
                    res.AppendLine();
                    break;
                }

                if (opcode == F3DOpcode.G_ENDDL)
                {
                    break;
                }
                address += 8;   //Fast 3D instructions are always 8 bytes long
            }

            return(res.ToString());
        }