Exemple #1
0
        public static List <Chunk> ReadVerts(ILogger log, byte[] fileData, int offset, int endOffset)
        {
            var   chunks        = new List <Chunk>();
            Chunk currentChunk  = new Chunk();
            Chunk previousChunk = null;

            while (offset < endOffset)
            {
                int vifCommand = fileData[offset + 3] & 0x7f;
                int numCommand = fileData[offset + 2] & 0xff;
                int immCommand = DataUtil.getLEShort(fileData, offset);
                switch (vifCommand)
                {
                case NOP_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("NOP");
                    offset += 4;
                    break;

                case STCYCL_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("STCYCL: WL: " + (immCommand >> 8) + " CL: " + (immCommand & 0xFF));
                    offset += 4;
                    break;

                case ITOP_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("ITOP: " + immCommand);
                    offset += 4;
                    break;

                case STMOD_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("STMOD: " + immCommand);
                    offset += 4;
                    break;

                case MSCAL_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("MSCAL: " + immCommand);
                    if (immCommand != 66 && immCommand != 68 && immCommand != 70)
                    {
                        DebugWriteLine("**** Microcode " + immCommand + " not supported");
                    }
                    currentChunk.mscalID = immCommand;
                    chunks.Add(currentChunk);
                    previousChunk = currentChunk;
                    currentChunk  = new Chunk();

                    offset += 4;
                    break;

                case STMASK_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    offset += 4;
                    int stmask = DataUtil.getLEInt(fileData, offset);
                    DebugWriteLine("STMASK: " + stmask);
                    offset += 4;
                    break;

                case FLUSH_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("FLUSH");
                    offset += 4;
                    break;

                case DIRECT_CMD:
                    DebugWrite(HexUtil.formatHex(offset) + " ");
                    DebugWriteLine("DIRECT, " + immCommand * 16 + " bytes");

                    GIFTag[] tags = new GIFTag[immCommand];

                    for (int i = 0; i < immCommand; i++)
                    {
                        tags[i] = new GIFTag();
                        tags[i].parse(fileData, offset + 4 + i * 16);
                    }
                    currentChunk.DIRECTGifTags.AddRange(tags);

                    offset += 4;
                    offset += immCommand * 16;
                    break;

                default:
                    if ((vifCommand & 0x60) == 0x60)
                    {
                        // unpack command
                        bool mask = ((vifCommand & 0x10) == 0x10);
                        int  vn   = (vifCommand >> 2) & 3;
                        int  vl   = vifCommand & 3;
                        int  addr = immCommand & 0x1ff;
                        bool flag = (immCommand & 0x8000) == 0x8000;
                        bool usn  = (immCommand & 0x4000) == 0x4000;

                        DebugWrite(HexUtil.formatHex(offset) + " ");
                        String debugMsg = "UNPACK: vn: " + vn + ", vl: " + vl + ", Addr: " + addr + ", num: " + numCommand;

                        if (flag)
                        {
                            debugMsg += ", Flag";
                        }
                        if (usn)
                        {
                            debugMsg += ", Unsigned";
                        }
                        if (mask)
                        {
                            debugMsg += ", Mask";
                        }
                        DebugWriteLine(debugMsg);
                        offset += 4;
                        if (vn == 1 && vl == 1)
                        {
                            // v2-16
                            // I don't know why but the UVs come after the MSCAL instruction.
                            if (previousChunk != null)
                            {
                                for (int uvnum = 0; uvnum < numCommand; ++uvnum)
                                {
                                    short u = DataUtil.getLEShort(fileData, offset);
                                    short v = DataUtil.getLEShort(fileData, offset + 2);
                                    previousChunk.uvs.Add(new UV(u, v));
                                    offset += 4;
                                }
                            }
                            else
                            {
                                int numBytes = numCommand * 4;
                                offset += numBytes;
                            }
                        }
                        else if (vn == 2 && vl == 1)
                        {
                            // v3-16
                            // each vertex is 128 bits, so num is the number of vertices
                            for (int vnum = 0; vnum < numCommand; ++vnum)
                            {
                                if (!usn)
                                {
                                    short x = DataUtil.getLEShort(fileData, offset);
                                    short y = DataUtil.getLEShort(fileData, offset + 2);
                                    short z = DataUtil.getLEShort(fileData, offset + 4);
                                    offset += 6;

                                    Vertex vertex = new Vertex();
                                    vertex.x = x;
                                    vertex.y = y;
                                    vertex.z = z;
                                    currentChunk.vertices.Add(vertex);
                                }
                                else
                                {
                                    int x = DataUtil.getLEUShort(fileData, offset);
                                    int y = DataUtil.getLEUShort(fileData, offset + 2);
                                    int z = DataUtil.getLEUShort(fileData, offset + 4);
                                    offset += 6;

                                    VLoc vloc = new VLoc();
                                    vloc.v1 = x;
                                    vloc.v2 = y;
                                    vloc.v3 = z;
                                    currentChunk.vlocs.Add(vloc);
                                }
                            }
                            offset = (offset + 3) & ~3;
                        }
                        else if (vn == 2 && vl == 2)
                        {
                            // v3-8
                            int idx = offset;
                            for (int vnum = 0; vnum < numCommand; ++vnum)
                            {
                                SByteVector vec = new SByteVector();
                                vec.x = (sbyte)fileData[idx++];
                                vec.y = (sbyte)fileData[idx++];
                                vec.z = (sbyte)fileData[idx++];
                                currentChunk.normals.Add(vec);
                            }
                            int numBytes = ((numCommand * 3) + 3) & ~3;
                            offset += numBytes;
                        }
                        else if (vn == 3 && vl == 0)
                        {
                            // v4-32
                            log.LogLine("v4-32 data, " + numCommand + (numCommand == 1 ? " entry" : " entries") + ", addr=" + addr);
                            if (1 == numCommand)
                            {
                                currentChunk.gifTag0 = new GIFTag();
                                currentChunk.gifTag0.parse(fileData, offset);
                                DebugWrite(HexUtil.formatHex(offset) + " ");
                                DebugWriteLine("GifTag: " + currentChunk.gifTag0.ToString());
                            }
                            else if (2 == numCommand)
                            {
                                currentChunk.gifTag0 = new GIFTag();
                                currentChunk.gifTag0.parse(fileData, offset);
                                currentChunk.gifTag1 = new GIFTag();
                                currentChunk.gifTag1.parse(fileData, offset + 16);

                                DebugWrite(HexUtil.formatHex(offset) + " ");
                                DebugWriteLine("GifTag0: " + currentChunk.gifTag0.ToString());
                                DebugWrite(HexUtil.formatHex(offset) + " ");
                                DebugWriteLine("GifTag1: " + currentChunk.gifTag1.ToString());
                            }
                            else
                            {
                                log.LogLine("unknown number of gif commands.");
                            }
                            int numBytes = numCommand * 16;
                            offset += numBytes;
                        }
                        else if (vn == 3 && vl == 1)
                        {
                            // v4-16
                            log.LogLine("v4-16 data, " + numCommand + (numCommand == 1 ? " entry" : " entries") + ", addr=" + addr);
                            int numShorts = numCommand * 4;
                            if (usn)
                            {
                                currentChunk.extraVlocs = new ushort[numShorts];
                                for (int i = 0; i < numCommand; ++i)
                                {
                                    currentChunk.extraVlocs[i * 4]     = DataUtil.getLEUShort(fileData, offset + i * 8);
                                    currentChunk.extraVlocs[i * 4 + 1] = DataUtil.getLEUShort(fileData, offset + i * 8 + 2);
                                    currentChunk.extraVlocs[i * 4 + 2] = DataUtil.getLEUShort(fileData, offset + i * 8 + 4);
                                    currentChunk.extraVlocs[i * 4 + 3] = DataUtil.getLEUShort(fileData, offset + i * 8 + 6);
                                }
                            }
                            else
                            {
                                log.LogLine("Unsupported tag");
                            }
                            offset += numShorts * 2;
                        }
                        else if (vn == 3 && vl == 2)
                        {
                            // v4-8
                            int numBytes = numCommand * 4;
                            currentChunk.vertexWeights = new List <VertexWeight>();
                            int curVertex = 0;
                            for (int i = 0; i < numCommand; ++i)
                            {
                                VertexWeight vw = new VertexWeight();
                                vw.startVertex = curVertex;
                                vw.bone1       = fileData[offset++] / 4;
                                vw.boneWeight1 = fileData[offset++];
                                vw.bone2       = fileData[offset++];
                                if (vw.bone2 == 0xFF)
                                {
                                    // Single bone
                                    vw.boneWeight2 = 0;
                                    int count = fileData[offset++];
                                    curVertex += count;
                                }
                                else
                                {
                                    vw.bone2      /= 4;
                                    vw.boneWeight2 = fileData[offset++];
                                    ++curVertex;

                                    if (vw.boneWeight1 + vw.boneWeight2 < 255)
                                    {
                                        ++i;
                                        vw.bone3       = fileData[offset++] / 4;
                                        vw.boneWeight3 = fileData[offset++];
                                        vw.bone4       = fileData[offset++];
                                        int bw4 = fileData[offset++];
                                        if (vw.bone4 != 255)
                                        {
                                            vw.bone4      /= 4;
                                            vw.boneWeight4 = bw4;
                                        }
                                    }
                                }
                                vw.endVertex = curVertex - 1;
                                currentChunk.vertexWeights.Add(vw);
                            }
                        }
                        else
                        {
                            DebugWriteLine("Unknown vnvl combination: vn=" + vn + ", vl=" + vl);
                            offset = endOffset;
                        }
                    }
                    else
                    {
                        DebugWriteLine("Unknown command: " + vifCommand);
                        offset = endOffset;
                    }
                    break;
                }
            }
            return(chunks);
        }
Exemple #2
0
 public override String ToString()
 {
     return(HexUtil.formatHexUShort(v1) + ", " + HexUtil.formatHexUShort(v2) + ", " + HexUtil.formatHexUShort(v3));
 }