Example #1
0
        public async Task LoadAsyncLoadsWhenGivenALoader()
        {
            var loader = A.Fake<IROMLoader>();

            ROM rom = new ROM(loader);

            await rom.LoadAsync();

            A.CallTo(() => loader.LoadROMAsync()).MustHaveHappened();
        }
Example #2
0
        public async Task<ValidationResults> ValidateChecksum(string filePath)
        {
            ValidationResults results = new ValidationResults() { ROMFilePath = filePath };

            // Load ROM content
            ROM rom = new ROM(new BinROMLoader(filePath, new BinROMValidator()));
            await rom.LoadAsync();

            // Get the checksum from the ROM. Also run a checksum calculation and compare the results. If not the same,
            // update the ROM and save it
            results.ActualChecksum = rom.Checksum;
            results.CalculatedChecksum = rom.CalculateChecksum();
            results.HasChanged = results.ActualChecksum != results.CalculatedChecksum;

            if (results.ActualChecksum != results.CalculatedChecksum)
            {
                rom.Checksum = results.CalculatedChecksum;
                await rom.SaveAsync();
            }

            return results;
        }
Example #3
0
        public void EditGift()
        {
            var arc  = ROM.GetFile(GameFile.EncounterGift);
            var data = arc[0];
            var objs = FlatBufferConverter.DeserializeFrom <EncounterGift8Archive>(data);

            var gifts = objs.Table;
            var names = Enumerable.Range(0, gifts.Length).Select(z => $"{z:000}").ToArray();
            var cache = new DirectCache <EncounterGift8>(gifts);

            void Randomize()
            {
                int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
                var   pt = Data.PersonalData;

                int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
                            .Select((z, i) => new { Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame })
                            .Where(z => !z.Present).Select(z => z.Species).ToArray();

                var spec  = EditUtil.Settings.Species;
                var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
                var frand = new FormRandomizer(Data.PersonalData);

                srand.Initialize(spec, ban);
                foreach (var t in gifts)
                {
                    // swap gmax gifts and kubfu for other gmax capable species
                    if (t.CanGigantamax || t.Species == (int)Species.Kubfu)
                    {
                        t.Species = Legal.GigantamaxForms[Randomization.Util.Random.Next(Legal.GigantamaxForms.Length)];
                        t.Form    = (byte)(t.Species is (int)Species.Pikachu or(int) Species.Meowth ? 0 : frand.GetRandomForme(t.Species, false, false, false, false, Data.PersonalData.Table)); // Pikachu & Meowth altforms can't gmax
                    }
                    else
                    {
                        t.Species = srand.GetRandomSpecies(t.Species);
                        t.Form    = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
                    }

                    t.Ability   = Randomization.Util.Random.Next(1, 4); // 1, 2, or H
                    t.Ball      = (Ball)Randomization.Util.Random.Next(1, EncounterGift8.BallToItem.Length);
                    t.HeldItem  = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
                    t.Nature    = (int)Nature.Random25;
                    t.Gender    = (byte)FixedGender.Random;
                    t.ShinyLock = (int)Shiny.Random;
                    if (t.IV_HP != -4 && t.IVs.Any(z => z != 31))
                    {
                        t.IVs = new[] { -1, -1, -1, -1, -1, -1 }
                    }
                    ;
                }

                UpdateStarters(); // update placement critter data to match new randomized species
            }

            void UpdateStarters()
            {
                var container = ROM.GetFile(GameFile.Placement);
                var placement = new GFPack(container[0]);

                // a_r0501_i0101.bin for Toxel
                // a_bt0101.bin for Type: Null
                // a_wr0201_i0101.bin for Bulbasaur, Squirtle, Porygon, and Kubfu
                // a_wr0301_i0401.bin for Cosmog
                // a_d0901.bin for Poipole
                const string file     = "a_0101.bin";
                var          table    = placement.GetDataFileName(file);
                var          obj      = FlatBufferConverter.DeserializeFrom <PlacementArea8Archive>(table);
                var          critters = obj.Table[0].Critters;

                // Grookey
                critters[3].Species = (uint)gifts[0].Species;
                critters[3].Form    = gifts[0].Form;

                // Scorbunny
                critters[1].Species = (uint)gifts[3].Species;
                critters[1].Form    = gifts[3].Form;

                // Sobble
                critters[2].Species = (uint)gifts[4].Species;
                critters[2].Form    = gifts[4].Form;

                var bin = FlatBufferConverter.SerializeFrom(obj);

                placement.SetDataFileName(file, bin);
                container[0] = placement.Write();
            }

            using var form = new GenericEditor <EncounterGift8>(cache, names, "Gift Pokémon Editor", Randomize);
            form.ShowDialog();
            if (!form.Modified)
            {
                arc.CancelEdits();
            }
            else
            {
                arc[0] = FlatBufferConverter.SerializeFrom(objs);
            }
        }
Example #4
0
        public static int parse(ref Level lvl, byte seg, uint off)
        {
            ROM rom = ROM.Instance;

            byte[] data   = rom.getSegment(seg);
            bool   end    = false;
            int    endCmd = 0;

            while (!end)
            {
                //Stopwatch stopWatch = new Stopwatch();
                //stopWatch.Start();
                byte   cmdLen = data[off + 1];
                byte[] cmd    = rom.getSubArray(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                string desc         = "Unknown command";
                bool   alreadyAdded = false;
                switch (cmd[0])
                {
                case 0x00:
                case 0x01:
                    CMD_00(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    break;

                case 0x02:
                    endCmd = 2;
                    desc   = "End level script";
                    end    = true;
                    break;

                case 0x03:
                case 0x04:
                    desc = "Delay frames";
                    break;

                case 0x05:
                    endCmd       = CMD_05(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    end          = true;
                    break;

                case 0x06:
                    if (CMD_06(ref lvl, ref desc, cmd, seg, off) == 0x02)
                    {
                        end    = true;
                        endCmd = 2;
                    }
                    alreadyAdded = true;
                    break;

                case 0x07:
                    end    = true;
                    desc   = "Pop script stack and return back";
                    endCmd = 0x07;
                    break;

                case 0x08:
                    desc = "Push script stack and a 16-bit parameter onto stack";
                    break;

                case 0x09:
                    desc = "Pops script stack and parameter";
                    break;

                case 0x0A:
                    desc = "Push next level command on script stack and param 0x00000000 onto stack";
                    break;

                case 0x0B:
                    CMD_0B(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    break;

                case 0x0C:
                    CMD_0C(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    break;

                case 0x0D:
                    CMD_0D(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    break;

                case 0x0E:
                    CMD_0E(ref lvl, ref desc, cmd, seg, off);
                    alreadyAdded = true;
                    break;

                case 0x0F:
                    desc = "Skip following 0x10 (Do nothing) commands";
                    break;

                case 0x10:
                    desc = "Do nothing";
                    break;

                case 0x11:
                    desc = "Call ASM function and set level accumulator (script_accum)";
                    break;

                case 0x12:
                    desc = "Call ASM function loop and set level accumulator (script_accum)";
                    break;

                case 0x13:
                    desc = "Set level accumulator (script_accum) as 0x" + bytesToInt(cmd, 2, 2).ToString("X4");
                    break;

                case 0x14:
                    desc = "Call PushPoolState() function";
                    break;

                case 0x15:
                    desc = "Call PopPoolState() function";
                    break;

                case 0x16:
                    desc = "Copy bytes from ROM (0x" + bytesToInt(cmd, 8, 4).ToString("X8") + " to 0x" + bytesToInt(cmd, 12, 4).ToString("X8") + ") to RAM address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x17:
                    CMD_17(ref lvl, ref desc, cmd);
                    break;

                case 0x18:
                case 0x1A:
                    CMD_18(ref lvl, ref desc, cmd);
                    break;

                case 0x19:
                    desc = "Create Mario head demo (";
                    switch (cmd[3])
                    {
                    case 1:
                        desc += "No face";
                        break;

                    case 2:
                        desc += "Regular face";
                        break;

                    case 3:
                        desc += "Game over face";
                        break;
                    }
                    desc += ")";
                    break;

                case 0x1B:
                    desc = "Start loading sequence";
                    break;

                case 0x1C:
                    desc = "Level & Memory cleanup";
                    break;

                case 0x1D:
                    desc = "End loading sequence";
                    break;

                case 0x1E:
                    desc = "Allocate space for level data from pool";
                    break;

                case 0x1F:
                    //Globals.DEBUG_PLG = true;
                    CMD_1F(ref lvl, ref desc, cmd);
                    break;

                case 0x20:
                    desc = "End of area " + lvl.CurrentAreaID;
                    break;

                case 0x21:
                    CMD_21(ref lvl, ref desc, cmd);
                    break;

                case 0x22:
                    //Globals.DEBUG_PLG = false;
                    CMD_22(ref lvl, ref desc, cmd);
                    break;

                case 0x24:
                    CMD_24(ref lvl, ref desc, cmd, seg, off);
                    break;

                case 0x25:
                    desc = "Setup Mario object";
                    break;

                case 0x26:
                    CMD_26(ref lvl, ref desc, cmd, seg, off);
                    break;

                case 0x27:
                    CMD_27(ref lvl, ref desc, cmd, seg, off);
                    break;

                case 0x28:
                    CMD_28(ref lvl, ref desc, cmd, seg, off);
                    break;

                case 0x2B:
                {
                    desc = "Mario's default pos = (" +
                           (short)bytesToInt(cmd, 6, 2) + "," +
                           (short)bytesToInt(cmd, 8, 2) + "," +
                           (short)bytesToInt(cmd, 10, 2) + "), Y-Rot = " +
                           (short)bytesToInt(cmd, 4, 2) + ", start in area " + cmd[2];
                }
                break;

                case 0x2E:
                    CMD_2E(ref lvl, ref desc, cmd);
                    break;

                case 0x2F:
                    CMD_2F(ref lvl, ref desc, cmd);
                    break;

                case 0x30:
                    desc = "Show dialog message when level starts; dialog ID = 0x" + cmd[3].ToString("X2");
                    break;

                case 0x31:
                    switch (cmd[3])
                    {
                    case 0: desc = "Set default terrain to \"Normal\""; break;

                    case 1: desc = "Set default terrain to \"Normal B\""; break;

                    case 2: desc = "Set default terrain to \"Snow\""; break;

                    case 3: desc = "Set default terrain to \"Sand\""; break;

                    case 4: desc = "Set default terrain to \"Haunted House\""; break;

                    case 5: desc = "Set default terrain to \"Water levels\""; break;

                    case 6: desc = "Set default terrain to \"Slippery Slide\""; break;
                    }
                    break;

                case 0x32:
                    desc = "Do nothing";
                    break;

                case 0x33:
                    if (cmd[2] == 0x01)
                    {
                        desc = "Fade screen with color (R = " + cmd[4] + ", G = " + cmd[5] + ", B = " + cmd[6] + ", duration = " + cmd[3] + " frames)";
                    }
                    else
                    {
                        desc = "Disable screen fade";
                    }
                    break;

                case 0x34:
                    if (cmd[2] == 0x00)
                    {
                        desc = "Cancel blackout";
                    }
                    else
                    {
                        desc = "Blackout screen";
                    }
                    break;

                case 0x36:
                    desc = "Set music (Seq = 0x" + cmd[5].ToString("X2") + ")";
                    break;

                case 0x37:
                    desc = "Set music (Seq = 0x" + cmd[3].ToString("X2") + ")";
                    break;

                case 0x39:
                    CMD_39(ref lvl, ref desc, cmd);
                    break;

                case 0x3B:
                    desc = "Add jet stream; Position = (" + (short)bytesToInt(cmd, 4, 2) + "," +
                           (short)bytesToInt(cmd, 6, 2) + "," + (short)bytesToInt(cmd, 8, 2) +
                           "), Intensity = " + (short)bytesToInt(cmd, 10, 2);
                    break;
                }
                if (!alreadyAdded)
                {
                    addLSCommandToDump(ref lvl, cmd, seg, off, desc);
                }
                //stopWatch.Stop();
                // if(stopWatch.Elapsed.Milliseconds > 1)
                //    Console.WriteLine("RunTime (CMD "+cmd[0].ToString("X2")+"): " + stopWatch.Elapsed.Milliseconds + "ms");
                off += cmdLen;
            }
            return(endCmd);
        }
Example #5
0
    public static void ConvertDL(ROM SM64ROM, uint SegAddr, bool ForceROMAddr)
    {
        if (SegAddr >> 24 == 0x02)
        {
            SM64ROM.setSegment(2, 0x803156); //Force segment 2 to US addr, sometimes it gets misplaced in level script parsing
        }
        uint Offset;

        if (!ForceROMAddr)
        {
            Offset = SM64ROM.readSegmentAddr(SegAddr);                //If not forcing a ROM addr, read seg addr
        }
        else
        {
            Offset = SegAddr;
        }
        for (uint i = 0; i < AllAddresses.Length; i++)
        {
            if (Offset == AllAddresses[i])
            {
                return;                            //If already converted certain DL, skip
            }
        }
        Array.Resize(ref AllAddresses, AllAddresses.Length + 1); //If not converted yet, create new index for mem
        AllAddresses[AllAddresses.Length - 1] = Offset;          //Last index is new offset (record dl as converted)
        for (UInt32 i = Offset; i < SM64ROM.getEndROMAddr(); i += 8)
        {
            byte[] CMD = UInt64toByteArray(SM64ROM.ReadEightBytes(i));
            switch (CMD[0])
            {
            case 04:     //G_VTX
                byte vertexcount = (byte)((CMD[1] >> 4) + 1);
                byte index       = (byte)(CMD[1] & 0x0F);
                SM64ROM.changeByte(i + 1, (byte)(index * 2));   //Vertex count * 2
                UInt16 Params = (UInt16)((vertexcount << 10) | ((vertexcount * 0x10) - 1));
                SM64ROM.WriteTwoBytes(i + 2, Params);
                break;

            case 06:     //G_DL
                ConvertDL(SM64ROM, returnSegmentAddr(CMD), false);
                if (CMD[1] > 0)
                {
                    return;
                }
                break;

            case 0xB2:                       //G_RDPHalf_Cont
                SM64ROM.changeByte(i, 0xB3); //rdphalf_cont not used in newer microcodes; use rdphalf_2
                break;

            case 0xB3:                       //G_RDPHalf_2
                SM64ROM.changeByte(i, 0xB4); //rdphalf_2 change to rdphalf_1 in newer microcodes
                break;

            case 0xB4:                                 //G_RDPHalf_1
                SM64ROM.WriteFourBytes(i, 0xBC00000E); //replace G_RDPHalf_1 with G_Moveword in newer microcodes
                break;

            case 0xBF:     //G_TRI1
                for (uint j = 5; j < 8; j++)
                {
                    uint TriAddr = i + j;
                    CMD[j] /= 5;
                    SM64ROM.changeByte(TriAddr, CMD[j]);
                }
                break;

            case 0xB8:     //G_ENDDL
                return;
            }
        }
    }
Example #6
0
    private static void DecodeF3DCommands(ROM SM64ROM, uint SegOffset, bool ColourBuffer)
    {
        uint Offset   = SM64ROM.readSegmentAddr(SegOffset);
        uint CMDCount = 0;

        for (uint i = Offset; i < SM64ROM.getEndROMAddr(); i += 8)
        {
            if (SM64ROM.getByte(i) == 0xB8)
            {
                CMDCount = ((i - Offset) / 8) + 1;//Plus one command for B8
                break;
            }
        }
        byte[][] DisplayList = new byte[CMDCount][];
        //Copy DL into 2D Byte array with double loop
        for (uint i = 0; i < CMDCount; i++)
        {
            DisplayList[i] = new byte[8];
            for (uint j = 0; j < 8; j++)
            {
                DisplayList[i][j] = SM64ROM.getByte(Offset + (i * 8) + j);
            }
        }

        for (uint i = 0; i < SM64ROM.getEndROMAddr(); i++)
        {
            byte[] CMD = DisplayList[i];
            if (Textures.FirstTexLoad && ROMManager.debug) //Debug Txt
            {
                Array.Resize(ref DebugText, DebugText.Length + 1);
                DebugText[DebugText.Length - 1] = (Offset + (i * 8)).ToString("x") + ": "; //Addr:
                for (uint j = 0; j < 8; j++)
                {
                    DebugText[DebugText.Length - 1] += CMD[j].ToString("x") + " "; //F3D CMD bytes in hex
                }
            }
            if (!ColourBuffer)
            {
                switch (DisplayList[i][0])
                {
                case 0x01: //G_MTX
                    break;

                case 0x03: //movemem
                    if (RenderEdges)
                    {
                        break;
                    }
                    if (CMD[1] == 0x86)
                    {
                        float[] light0_diffuse = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_diffuse[j] = (float)SM64ROM.getByte(rgbaAddr + j) / 255f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Diffuse, light0_diffuse);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse);
                    }
                    else if (CMD[1] == 0x88)
                    {
                        float[] light0_ambient = new float[4];
                        uint    rgbaAddr       = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                        for (uint j = 0; j < 4; j++)
                        {
                            light0_ambient[j] = (((float)SM64ROM.getByte(rgbaAddr + j) / 255f) - 0.2f) * 1.25f;
                        }
                        GL.Light(LightName.Light0, LightParameter.Ambient, light0_ambient);
                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient);
                    }
                    GL.Enable(EnableCap.ColorMaterial);
                    break;

                case 0x04: //G_VTX
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06: //LoadDL (jump)
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    if (CMD[1] == 1)
                    {
                        return;
                    }
                    break;

                case 0xB1:
                    //0xB1 (TRI2) is not used in F3D v1.0
                    break;

                case 0xB2: // Unused in F3D v1.0
                    break;

                case 0xB3: //G_RDP_Half2
                    break;

                case 0xB4: //G_RDP_Half1
                    break;

                case 0xB5: //G_Quad (Unused in F3D v1.0)
                    break;

                case 0xB6: //ClearGeoMode
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 ClearBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode &= ~ClearBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB7: //SetGeoMode
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 SetBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode |= SetBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB9: //SetOtherMode
                    break;

                case 0xBA: //SetOtherMode
                    break;

                case 0xBB: //G_Texture
                    Vertex.U_Scale = Convert.ToSingle((CMD[4] << 8) | CMD[5]) / Convert.ToSingle(0xFFFF);
                    Vertex.V_Scale = Convert.ToSingle((CMD[6] << 8) | CMD[7]) / Convert.ToSingle(0xFFFF);
                    if (CMD[3] == 0x01 && Renderer.TextureEnabler && !RenderEdges)
                    {
                        GL.Enable(EnableCap.Texture2D);
                    }
                    else
                    {
                        GL.Disable(EnableCap.Texture2D);
                        Textures.T_Scale = 1f; Textures.S_Scale = 1f;
                    }
                    if (DisplayList[i][2] == 0x12)
                    {
                        Textures.MipMapping = true;
                        Textures.T_Scale    = 1f; Textures.S_Scale = 1f;//Revert mipmapping for now
                    }
                    break;

                case 0xBC: //moveword
                    break;

                case 0xBD: //PopMTX
                    break;

                case 0xBF: //TRI1
                    if (LightingEnabled && !Renderer.ViewNonRGBA)
                    {
                        break;
                    }
                    GL.Begin(BeginMode.Triangles);
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        if (!EnvMapping)
                        {
                            GL.TexCoord2(VTXBuffer[VertIndex].getUVVector());
                        }

                        if (LightingEnabled)     //Normals
                        {
                            Vector3 normals = new Vector3(VTXBuffer[VertIndex].getRGBColor());
                            if (!EnvMapping)
                            {
                                GL.Normal3(Vector3.Normalize(normals));
                            }
                            else
                            {
                                Vector4 normals4 = new Vector4(normals, 1f);
                                normals4 = Vector4.Normalize(Renderer.projection * normals4);
                                Vector3 newnorms = new Vector3(normals4.X, normals4.Y, normals4.Z);
                                GL.Normal3(newnorms);
                            }
                        }


                        else
                        {
                            GL.Color4(VTXBuffer[VertIndex].getRGBAColor());  //RGBA
                        }
                        if (RenderEdges)
                        {
                            GL.Color4(0, 0, 0, 0xFF);
                        }
                        GL.Vertex3(VTXBuffer[VertIndex].getCoordVector());
                    }
                    if (!RenderEdges)
                    {
                        Renderer.TriCount++;
                    }
                    GL.End();
                    break;

                case 0xF0: //LoadTLUT
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    CICount = (uint)((((CMD[5] << 4) + ((CMD[6] & 0xF0) >> 4)) >> 2) + 1);
                    Textures.currentPalette = Textures.LoadRGBA16TextureData(CICount, SM64ROM);
                    break;

                case 0xF2: //Settilesize
                    Textures.S_Scale = Convert.ToSingle((((CMD[5] << 4) | ((CMD[6] & 0xF0) >> 4)) >> 2) + 1);
                    Textures.T_Scale = Convert.ToSingle(((((CMD[6] & 0x0F) << 8) | CMD[7]) >> 2) + 1);
                    break;

                case 0xF3: //LoadBlock
                    if (SM64ROM.getSegmentStart(0x0E) < 0x1200000 && !Renderer.ObjectView)
                    {
                        TextureLoadRoutine(SM64ROM, 0);
                    }
                    break;

                case 0xF5: //Settile
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.TFlags  = (uint)(CMD[5] >> 2) & 3;
                    Textures.SFlags  = (uint)CMD[6] & 3;
                    int WidthBits = (((CMD[1] & 3) << 7) + CMD[2] >> 1) * 64;
                    if (CMD[4] != 0)
                    {
                        break;              //If RenderTile, continue
                    }
                    int HeightPower = ((CMD[5] & 3) << 2) | (CMD[6] >> 6);
                    int WidthPower  = (CMD[7] >> 4);
                    Textures.Width  = (uint)Math.Pow(2, WidthPower);
                    Textures.Height = (uint)Math.Pow(2, HeightPower);
                    if (Textures.currentTexAddr == 0)
                    {
                        break;
                    }
                    TextureLoadRoutine(SM64ROM, Offset + (uint)(i * 8));
                    break;

                case 0xFB: //Set Env Colour
                    if (RenderEdges)
                    {
                        break;
                    }
                    ColourCombiner = true;
                    GL.Color4((float)CMD[4] / 255f, (float)CMD[5] / 255f, (float)CMD[6] / 255f, (float)CMD[7] / 255f);
                    break;

                case 0xFC: //Setcombine
                    if (CMD[7] == 0x3C && CMD[6] == 0x79 && CMD[5] == 0xFE)
                    {
                        GL.Disable(EnableCap.Texture2D);
                    }
                    else if (Renderer.TextureEnabler)
                    {
                        GL.Enable(EnableCap.Texture2D);
                    }
                    break;

                case 0xFD: //SetTIMG
                    Textures.currentSegment = CMD[4];
                    Textures.currentTexAddr = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    if (!Textures.FirstTexLoad)
                    {
                        break;
                    }
                    Textures.BitSize = (byte)(4 * Math.Pow(2, ((CMD[1] >> 3) & 3)));
                    Textures.MODE    = (byte)(CMD[1] >> 5);
                    break;

                case 0xB8: //End DL
                    return;
                }
            }
            else
            {
                switch (DisplayList[i][0])  //Vertex Selection Colour buffer here
                {
                case 0x03:
                    break;

                case 0x04:
                    UInt32 VTXStart    = SM64ROM.readSegmentAddr(returnSegmentAddr(CMD));
                    short  numVerts    = (short)((CMD[1] >> 4) + 1);
                    int    bufferIndex = CMD[1] & 0x0F;
                    for (int j = 0; j < numVerts; j++)
                    {
                        VTXBuffer[bufferIndex + j] = Vertex.getVertex(VTXStart + (uint)(j * 0x10), SM64ROM);
                    }
                    Renderer.VertexCount += (uint)numVerts;
                    break;

                case 0x06:
                    F3D.DecodeF3DCommands(SM64ROM, returnSegmentAddr(CMD), ColourBuffer);
                    if (CMD[1] == 1)
                    {
                        return;
                    }
                    break;

                case 0xB6:
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 ClearBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode &= ~ClearBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xB7:
                    if (RenderEdges)
                    {
                        break;
                    }
                    UInt32 SetBits = (UInt32)((CMD[4] << 24) | (CMD[5] << 16) | (CMD[6] << 8) | CMD[7]);
                    GeoMode |= SetBits;
                    SetGeoMode(ColourBuffer);
                    break;

                case 0xBF:
                    if (LightingEnabled)
                    {
                        break;                      //Disable painting on non-RGBA meshes
                    }
                    Vertex[] Triangle = new Vertex[3];
                    Color4[] colour   = new Color4[3];
                    for (int j = 5; j < 8; j++)
                    {
                        int VertIndex = CMD[j] / 0x0A;
                        Triangle[j - 5] = VTXBuffer[VertIndex];
                        UInt32 Addr = Triangle[j - 5].getAddr();
                        colour[j - 5] = new Color4((byte)(Addr >> 24), (byte)((Addr >> 16) & 0xFF), (byte)((Addr >> 8) & 0xFF), (byte)(Addr & 0xFF));   //Addr to RGBA
                    }
                    Vector3 CentreCoord = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 3,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 3,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 3
                                          );
                    Vector3 OneTwoAVG = new Vector3
                                        (
                        (Triangle[0].getCoordVector().X + Triangle[1].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[1].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[1].getCoordVector().Z) / 2
                                        );
                    Vector3 TwoThreeAVG = new Vector3
                                          (
                        (Triangle[1].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[1].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[1].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );
                    Vector3 OneThreeAVG = new Vector3
                                          (
                        (Triangle[0].getCoordVector().X + Triangle[2].getCoordVector().X) / 2,
                        (Triangle[0].getCoordVector().Y + Triangle[2].getCoordVector().Y) / 2,
                        (Triangle[0].getCoordVector().Z + Triangle[2].getCoordVector().Z) / 2
                                          );

                    GL.Begin(BeginMode.Quads);
                    GL.Color4(colour[0]);     //Vert 1 quad
                    GL.Vertex3(Triangle[0].getCoordVector());
                    GL.Vertex3(OneTwoAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneThreeAVG);

                    GL.Color4(colour[1]);     //Vert 2 quad
                    GL.Vertex3(Triangle[1].getCoordVector());
                    GL.Vertex3(TwoThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(OneTwoAVG);

                    GL.Color4(colour[2]);     //Vert 3 quad
                    GL.Vertex3(Triangle[2].getCoordVector());
                    GL.Vertex3(OneThreeAVG);
                    GL.Vertex3(CentreCoord);
                    GL.Vertex3(TwoThreeAVG);
                    GL.End();
                    break;

                case 0xB8:
                    return;
                }
            }
        }
    }
Example #7
0
    public static Bitmap TextureToBitMap(uint texaddr, uint width, uint height, uint format, uint bitsize)
    {
        ROM SM64ROM = ROMManager.SM64ROM;

        if (width == 0 || height == 0)
        {
            return(new Bitmap(1, 1));
        }
        Bitmap   texture         = new Bitmap((Int32)width, (Int32)height);
        Graphics textureGraphics = Graphics.FromImage(texture);
        uint     pxaddr          = 0;
        uint     texel           = 0;

        Color[] palette = new Color[0];
        if (format == CIMODE)
        {
            palette = new Color[(int)Math.Pow(2, bitsize)];
            uint paletteaddr = texaddr + (width * height * bitsize / 0x08); //halfway into texture
            for (uint i = 0; i < palette.Length; i++)
            {
                palette[i] = RGBA16TexeltoColor(paletteaddr + (i * 2));
            }
        }
        for (uint y = 0; y < height; y++)
        {
            for (uint x = 0; x < width; x++)
            {
                if (bitsize >= 8)
                {
                    pxaddr = texaddr + texel * (bitsize / 8);
                }
                else
                {
                    pxaddr = texaddr + texel;
                }
                SolidBrush brush = new SolidBrush(Color.HotPink);
                if ((format == RGBAMODE && bitsize == 16) || format == YUVMODE) //Todo: YUV
                {
                    brush = new SolidBrush(RGBA16TexeltoColor(pxaddr));
                }
                else if (format == RGBAMODE && bitsize == 32) //RGBA32
                {
                    byte red   = SM64ROM.getByte(pxaddr);
                    byte green = SM64ROM.getByte(pxaddr + 1);
                    byte blue  = SM64ROM.getByte(pxaddr + 2);
                    byte alpha = SM64ROM.getByte(pxaddr + 3);
                    brush = new SolidBrush(Color.FromArgb(alpha, red, green, blue));
                }
                else if (format == IAMODE && bitsize == 4) //IA4
                {
                    byte pixels = SM64ROM.getByte(pxaddr);
                    byte I1     = (byte)((pixels & 0xE0) | ((pixels & 0xE0) >> 3) | (pixels & 0xE0) >> 6);
                    byte A1     = (byte)(((pixels & 0x10) >> 4) * 0xFF);
                    brush = new SolidBrush(Color.FromArgb(A1, I1, I1, I1));
                    textureGraphics.FillRectangle(brush, x, y, 1, 1);
                    x++; if (x >= width)
                    {
                        x = 0; y++;
                    }                                    //increment
                    byte I2 = (byte)((((pixels & 0x0E) << 4)) | ((pixels & 0x0E) << 1) | ((pixels & 0x0E) >> 2));
                    byte A2 = (byte)((pixels & 1) * 0xFF);
                    brush = new SolidBrush(Color.FromArgb(A2, I2, I2, I2));
                }
                else if (format == IAMODE && bitsize == 8) //IA8
                {
                    byte pixel = SM64ROM.getByte(pxaddr);
                    byte I1    = (byte)((pixel & 0xF0) | ((pixel & 0xF0) >> 4));
                    byte A1    = (byte)(((pixel & 0x0F) << 4) | (pixel & 0x0F));
                    brush = new SolidBrush(Color.FromArgb(A1, I1, I1, I1));
                }
                else if (format == IAMODE && bitsize == 16) //IA16
                {
                    byte I = SM64ROM.getByte(pxaddr);
                    byte A = SM64ROM.getByte(pxaddr + 1);
                    brush = new SolidBrush(Color.FromArgb(A, I, I, I));
                }
                else if (format == IMODE && bitsize == 8) //I8
                {
                    byte I = SM64ROM.getByte(pxaddr);
                    brush = new SolidBrush(Color.FromArgb((byte)255, I, I, I));
                }
                else if (format == IMODE && bitsize == 4)                  //I4
                {
                    byte I1 = (byte)((SM64ROM.getByte(pxaddr) >> 4) * 17); //*17 for >>4 with 0x0F range
                    brush = new SolidBrush(Color.FromArgb((byte)255, I1, I1, I1));
                    textureGraphics.FillRectangle(brush, x, y, 1, 1);
                    x++; if (x >= width)
                    {
                        x = 0; y++;
                    }                                                        //increment
                    byte I2 = (byte)((SM64ROM.getByte(pxaddr) & 0x0F) * 17); //*17 for >>4 with 0x0F range
                    brush = new SolidBrush(Color.FromArgb((byte)255, I2, I2, I2));
                }
                else if (format == CIMODE && bitsize == 4) //CI4
                {
                    int px1 = SM64ROM.getByte(pxaddr) >> 4;
                    brush = new SolidBrush(palette[px1]);
                    textureGraphics.FillRectangle(brush, x, y, 1, 1);
                    x++; if (x >= width)
                    {
                        x = 0; y++;
                    }                                    //increment
                    int px2 = SM64ROM.getByte(pxaddr) & 0x0F;
                    brush = new SolidBrush(palette[px2]);
                }
                textureGraphics.FillRectangle(brush, x, y, 1, 1);
                texel++;
            }
        }
        return(texture);
    }
Example #8
0
    public static void ResizeTexture(int F5index, int widthpower, int heightpower, out bool isFailedToResize)
    {
        uint[] F5CMDs = Textures.F5CMDArray[F5index]; ROM SM64ROM = ROMManager.SM64ROM;
        bool   isFailedToResizeUVs = false;
        byte   WidthsizeByte       = SM64ROM.getByte(F5CMDs[0] + 7);
        ushort HeightsizeShort     = SM64ROM.ReadTwoBytes(F5CMDs[0] + 5);
        int    ogHeightPower       = (HeightsizeShort >> 6 & 0x0F);
        int    ogWidthPower        = (WidthsizeByte >> 4);
        int    difx   = widthpower - ogWidthPower;
        int    dify   = heightpower - ogHeightPower;
        int    width  = (int)Math.Pow(2, widthpower);
        int    height = (int)Math.Pow(2, heightpower);
        UInt32 clamp  = (UInt32)((((width - 1) << 2) << 12) | ((height - 1) << 2));

        for (uint i = 0; i < F5CMDs.Length; i++)
        {
            SM64ROM.changeByte(F5CMDs[i] + 7, (byte)(WidthsizeByte + (difx * 16)));        //*8 for << 4 with negative carried
            SM64ROM.WriteTwoBytes(F5CMDs[i] + 5, (ushort)(HeightsizeShort + (dify * 64))); //*8 for << 6 with negative carried
            SM64ROM.WriteFourBytes(F5CMDs[i] + 12, clamp);                                 //F2 command follows F5 rendertile
            bool exitUVcorrection = false;
            for (uint j = F5CMDs[i] + 8; j < SM64ROM.getEndROMAddr(); j += 8)              //UV automatic correction
            {
                if (exitUVcorrection)
                {
                    break;
                }
                switch (SM64ROM.getByte(j))
                {
                case 0xBF:
                    UInt32     UVStart = 0;
                    double[][] UVs     = new double[2][]; for (int k = 0; k < 2; k++)
                    {
                        UVs[k] = new double[3];
                    }
                    for (uint k = j; k > j - 0x800; k -= 8)
                    {
                        if (SM64ROM.getByte(k) == 0x04)
                        {
                            UVStart = SM64ROM.readSegmentAddr(SM64ROM.ReadFourBytes(k + 4)) + 8; break;
                        }
                    }
                    if (UVStart == 0)
                    {
                        break;
                    }
                    for (uint k = 5; k < 8; k++)
                    {
                        UInt32 addr = Vertex.getAddrFromTriIndex(UVStart, SM64ROM.getByte(j + k));
                        double U    = (short)SM64ROM.ReadTwoBytes(addr);
                        double V    = (short)SM64ROM.ReadTwoBytes(addr + 2);
                        U            *= Math.Pow(2, difx);
                        V            *= Math.Pow(2, dify);
                        UVs[0][k - 5] = U;
                        UVs[1][k - 5] = V;
                    }
                    UVs = Vertex.UVChecker(UVs, out isFailedToResizeUVs);
                    if (isFailedToResizeUVs)
                    {
                        isFailedToResize = true;     // recover file
                        return;
                    }
                    for (uint k = 5; k < 8; k++)
                    {
                        UInt32 addr = Vertex.getAddrFromTriIndex(UVStart, SM64ROM.getByte(j + k));
                        if (UVs[0][k - 5] > 0x7fff || UVs[0][k - 5] < -0x8000)
                        {
                            isFailedToResize = true;
                            return;
                        }
                        SM64ROM.WriteTwoBytes(addr, (ushort)Convert.ToInt16(UVs[0][k - 5]));
                        SM64ROM.WriteTwoBytes(addr + 2, (ushort)Convert.ToInt16(UVs[1][k - 5]));
                    }
                    break;

                case 0xFD:
                    exitUVcorrection = true;
                    break;

                case 0x06:
                    exitUVcorrection = true;
                    break;

                case 0xB8:
                    exitUVcorrection = true;
                    break;
                }
            }
        }
        isFailedToResize = false;
        return;
    }
Example #9
0
        private void Save(int Lang)
        {
            string ext = GetCARCExtension(Lang);
            var    rfs = MainWindow.LoadedROM.ToFileSystem();
            int    idx = 0;

            foreach (TextBox elem in CommonTextsList.Items)
            {
                Common.DAT1.Strings[idx] = elem.Text;
                idx++;
            }
            var common  = Common.Save();
            var dmain2d = Main2D.ToFileSystem();
            var fcommon = ROMUtils.GetSFSFile("common.bmg", dmain2d);

            fcommon.Data = common;
            Main2D.FromFileSystem(dmain2d);
            var fmain2d = ROMUtils.GetSFSFile("Main2D" + ext + ".carc", rfs);

            fmain2d.Data = ROM.LZ77_Compress(Main2D.Write());
            idx          = 0;
            foreach (TextBox elem in MBChildTextsList.Items)
            {
                MBChild.DAT1.Strings[idx] = elem.Text;
                idx++;
            }
            var mbchild   = MBChild.Save();
            var dstatic2d = Static2D.ToFileSystem();
            var fmbchild  = ROMUtils.GetSFSFile("MBChild" + ext + ".bmg", dstatic2d);

            fmbchild.Data = mbchild;
            Static2D.FromFileSystem(dstatic2d);
            var fstatic2d = ROMUtils.GetSFSFile("Static2D.carc", rfs);

            fstatic2d.Data = ROM.LZ77_Compress(Static2D.Write());
            idx            = 0;
            foreach (TextBox elem in KartSelectTextsList.Items)
            {
                KartSelect.DAT1.Strings[idx] = elem.Text;
                idx++;
            }
            var ksel    = KartSelect.Save();
            var dchksel = CharacterKartSelect.ToFileSystem();
            var fksel   = ROMUtils.GetSFSFile("kart_select.bmg", dchksel);

            fksel.Data = ksel;
            CharacterKartSelect.FromFileSystem(dchksel);
            var fchksel = ROMUtils.GetSFSFile("CharacterKartSelect" + ext + ".carc", rfs);

            fchksel.Data = ROM.LZ77_Compress(CharacterKartSelect.Write());


            idx = 0;
            foreach (TextBox elem in DlPlayTextsList.Items)
            {
                Banner.DAT1.Strings[idx] = elem.Text;
                idx++;
            }
            var banner  = Banner.Save();
            var dwlmenu = WLMenu.ToFileSystem();
            var fbanner = ROMUtils.GetSFSFile("banner.bmg", dwlmenu);

            fbanner.Data = banner;
            WLMenu.FromFileSystem(dwlmenu);
            var fwlmenu = ROMUtils.GetSFSFile("WLMenu" + ext + ".carc", rfs);

            fwlmenu.Data = ROM.LZ77_Compress(WLMenu.Write());

            MainWindow.LoadedROM.FromFileSystem(rfs);
        }
Example #10
0
        /// <summary>
        /// Generate the MFORTH hash table.
        /// </summary>
        /// <param name="rom">MFORTH ROM.</param>
        /// <param name="phf1">Upon return, will contain the first
        /// PearsonHashFunction used by the hash table.</param>
        /// <param name="phf2">Upon return, will contain the second
        /// PearsonHashFunction used by the hash table.</param>
        /// <returns>The MFORTH hash table.</returns>
        private static CuckooHashTable <Word> GenerateHashTable(ROM rom, out PearsonHashFunction phf1, out PearsonHashFunction phf2)
        {
            // Initialize our random number generator.
            var random = new Random(HashTableRandomSeed);

            // Initialize our hash functions and the hash table.
            var hashFunc1 = phf1 = new PearsonHashFunction(random);
            var hashFunc2 = phf2 = new PearsonHashFunction(random);
            var hashTable = new CuckooHashTable <Word>(
                (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));

            // Generate the hash table.
#if FINDING_OPTIMAL_HASH_SEED
            int minValuesAtSecondLocation = int.MaxValue;
#endif
            for (;;)
            {
#if !FINDING_OPTIMAL_HASH_SEED
                // Display a progress dot.
                Console.Write(".");
#endif

                // Add all of the words to our hash table; assume that
                // we will be successful.
                bool haveCompleteTable = true;
                foreach (var word in rom.Words)
                {
                    if (!hashTable.TryAddValue(word))
                    {
                        haveCompleteTable = false;
                        break;
                    }
                }

#if !FINDING_OPTIMAL_HASH_SEED
                // We're done if all of the words were added to the
                // table.
                if (haveCompleteTable)
                {
                    break;
                }

                // We failed to generate a complete hash table; shuffle
                // the hash functions, clear the table, and try again.
                phf1.ShuffleAuxilliaryTable(random);
                phf2.ShuffleAuxilliaryTable(random);
                hashTable.Clear();
#else
                // Print out the results if this seed produced better
                // results than the previous best seed.
                if (haveCompleteTable &&
                    hashTable.NumValuesStoredAtSecondHash < minValuesAtSecondLocation)
                {
                    Console.WriteLine(
                        "Seed: {0}; 1st: {1}; 2nd: {2}",
                        HashTableRandomSeed,
                        hashTable.NumValuesStoredAtFirstHash,
                        hashTable.NumValuesStoredAtSecondHash);
                    minValuesAtSecondLocation = hashTable.NumValuesStoredAtSecondHash;
                }

                // Generate a new seed and re-create all of the hash
                // functions and tables.
                random    = new Random(++HashTableRandomSeed);
                hashFunc1 = phf1 = new PearsonHashFunction(random);
                hashFunc2 = phf2 = new PearsonHashFunction(random);
                hashTable = new CuckooHashTable <Word>(
                    (w) => HashName(w.Name, hashFunc1, hashFunc2, HashMask),
                    (w) => HashName(w.Name, hashFunc2, hashFunc1, HashMask));
#endif
            }

            // Ensure that all of the words in the ROM were added to the
            // hash table.
            if (rom.NumWords != hashTable.Count)
            {
                throw new InvalidDataException(
                          string.Format(
                              "Hash table only has {0} words; expected {1} words.",
                              hashTable.Count,
                              rom.NumWords));
            }

            // Return the hash table.
            return(hashTable);
        }
Example #11
0
 public void MakeData(ROM rom)
 {
     rom.Write64(lo);
     rom.Write64(hi, 8);
     rom.AddOffset(16);
 }
Example #12
0
        public int MakeF3D(ROM rom, SortedRegionList vertexBytes, ScrollFactory factory)
        {
            int start = rom.offset;

            foreach (UInt64 cmd in header)
            {
                rom.Write64(cmd);
                rom.AddOffset(8);
            }

            // TODO: This is kinda stupid assumption but we believe there are more triangles in the beginning available...
            List <ScrollingTextureDescription> tds = map.Keys.ToList();

            tds.Sort(new ScrollingTextureDescriptionComp());

            foreach (ScrollingTextureDescription td in tds)
            {
                td.MakeF3D(rom);

                // Time to do optimization magic
                List <Triangle> textureTris = map[td];

                // Create reverse map for vertices, vertices with more triangles will be used first
                Dictionary <Vertex, List <Triangle> > vertex2triMap = new Dictionary <Vertex, List <Triangle> >();
                foreach (Triangle tri in textureTris)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        Vertex v = tri.vertices[i];
                        if (!vertex2triMap.TryGetValue(v, out List <Triangle> weight))
                        {
                            vertex2triMap[v] = new List <Triangle>();
                        }
                        vertex2triMap[v].Add(tri);
                    }
                }

                // You quite literally can't eat more than that
                int vertexLength = 0x30 * textureTris.Count();
                vertexBytes.CutContigRegion(vertexLength, out int vertexPosition);

                int allocVertexStart     = vertexPosition;
                int allocVertexEnd       = allocVertexStart + vertexLength;
                int writtenVerticesCount = 0;

                // Check if there are still vertices that needs to be worked with
                // Also we must make sure all lists in v2tm are not empty!
                while (vertex2triMap.Count != 0)
                {
                    int segmentedVertexStart = rom.GetSegmentedAddress(vertexPosition);

                    // vbd is main structure that holds information about used vertices space
                    VertexBufferDescription vbd = new VertexBufferDescription((UInt32)segmentedVertexStart, 0xF);

                    // Potential triangles also have weight depending on connection to other triangles and to added vertices
                    // Weight +1 for each tri that shares vertice; +vertexPresentBonus for each vbd present vertex
                    // It is recommended to have vertexPresentBonus be more than any weight that shared vertices can give
                    // This way triangle that have the most weight will have the most vertices and potentially help others
                    Dictionary <Triangle, int> potentialTris = new Dictionary <Triangle, int>();

                    // Add triangles to vbd till it won't be able to fit in the whole triangle
                    while (vbd.freeCount != 0 && vertex2triMap.Count != 0)
                    {
                        // Right now no vertices are in vbd, pick one with the heighest weight and add it to vbd
                        if (potentialTris.Count == 0)
                        {
                            // We need at least 3 vertices to draw not present tri
                            if (vbd.freeCount < 3)
                            {
                                break;
                            }

                            KeyValuePair <Vertex, List <Triangle> > pair;
                            // Let's ask for at least 5 vertices for optimal stuff, otherwise just put the worst triangle and call it
                            if (vbd.freeCount < 5)
                            {
                                pair = vertex2triMap.Aggregate((prev, cur) => prev.Value.Count < cur.Value.Count ? prev : cur);
                            }
                            else
                            {
                                pair = vertex2triMap.Aggregate((prev, cur) => prev.Value.Count > cur.Value.Count ? prev : cur);
                            }

                            Vertex          v    = pair.Key;
                            List <Triangle> tris = pair.Value;
                            if (tris.Count == 0)
                            {
                                throw new ArithmeticException("Tris count in dict can't be 0");
                            }

                            // Put current vertex and use found tris as potential next tri to add
                            vbd.AddVertex(v);

                            // Setup all potential triangles to could be added to vbd, the ones that have this vertex in common

                            foreach (Triangle tri in tris)
                            {
                                potentialTris[tri] = 0;
                            }

                            // If vertex is in common between tris, give 1 each
                            var tripairs = tris.Zip(tris.Skip(1), (a, b) => Tuple.Create(a, b));
                            foreach (Tuple <Triangle, Triangle> tripair in tripairs)
                            {
                                Triangle tri1   = tripair.Item1;
                                Triangle tri2   = tripair.Item2;
                                int      common = tri1.CountCommon(tri2);

                                potentialTris[tri1] += common;
                                potentialTris[tri2] += common;
                            }
                        }


                        // Find tri with biggest weight
                        Triangle biggestTri = potentialTris.Aggregate((prev, cur) => prev.Value > cur.Value ? prev : cur).Key;

                        // Add all triangles in vbd
                        int[] indices = new int[3];

                        for (int i = 0; i < 3; i++)
                        {
                            Vertex v     = biggestTri.vertices[i];
                            int    index = vbd.AddVertex(v, out bool isNew);
                            indices[i] = index;

                            // Fix weights of tris if a new vertex was added to vbd (not already in vbd it is)
                            if (isNew)
                            {
                                foreach (Triangle ptri in potentialTris.Keys.ToList())
                                {
                                    if (ptri.Contains(v))
                                    {
                                        potentialTris[ptri] += vertexPresentBonus;
                                    }
                                }
                            }
                        }

                        // Draw the triangle, all vertices are guaranteed to be in
                        vbd.DrawTriangle(indices);

                        // As triangle was drawn, it needs to be removed from structs that had it
                        // vertex2map & potentialTris
                        // This way triangle won't be able to appear again
                        foreach (Vertex v in biggestTri.vertices)
                        {
                            vertex2triMap[v].Remove(biggestTri);
                            if (vertex2triMap[v].Count == 0)
                            {
                                vertex2triMap.Remove(v);
                            }
                        }

                        potentialTris.Remove(biggestTri);

                        // Setup new triangles to potentialTris
                        HashSet <Triangle> newTris = new HashSet <Triangle>();
                        foreach (Vertex v in biggestTri.vertices)
                        {
                            if (vertex2triMap.TryGetValue(v, out List <Triangle> tris))
                            {
                                foreach (Triangle tri in tris)
                                {
                                    newTris.Add(tri);
                                }
                            }
                        }

                        // Also do not take into account tris that were added already
                        // If we will take them into account, bad things will happen
                        newTris.RemoveWhere(t => potentialTris.Keys.Contains(t));

                        // As new triangles appear, proceed to fix weights
                        // First of all, initialize world: create new potential tris that will be merged later with potential tris
                        // Initial value is -vertexPresentBonus as one vertex will be counted anyways
                        Dictionary <Triangle, int> newPotentialTris = new Dictionary <Triangle, int>();
                        foreach (Triangle ntri in newTris)
                        {
                            newPotentialTris[ntri] = -vertexPresentBonus;
                        }

                        // Calculate weights for vertices that were present
                        foreach (Triangle ntri in newTris)
                        {
                            foreach (Vertex v in vbd.vbuf)
                            {
                                if (ntri.Contains(v))
                                {
                                    newPotentialTris[ntri] += vertexPresentBonus;
                                }
                            }
                        }

                        // Check between triangles new/new
                        var newNewTripairs = newTris.Zip(newTris.Skip(1), (a, b) => Tuple.Create(a, b));
                        foreach (Tuple <Triangle, Triangle> tripair in newNewTripairs)
                        {
                            Triangle tri1   = tripair.Item1;
                            Triangle tri2   = tripair.Item2;
                            int      common = tri1.CountCommon(tri2);

                            newPotentialTris[tri1] += common;
                            newPotentialTris[tri2] += common;
                        }

                        // Check between triangles new/old
                        List <Triangle> oldTris        = potentialTris.Keys.ToList();
                        var             newOldTripairs = newTris.Zip(oldTris, (a, b) => Tuple.Create(a, b));
                        foreach (Tuple <Triangle, Triangle> tripair in newOldTripairs)
                        {
                            Triangle newTri = tripair.Item1;
                            Triangle oldTri = tripair.Item2;

                            int common = newTri.CountCommon(oldTri);

                            newPotentialTris[newTri] += common;
                            potentialTris[oldTri]    += common;
                        }

                        // Merge together old and new
                        foreach (KeyValuePair <Triangle, int> pair in newPotentialTris)
                        {
                            potentialTris.Add(pair.Key, pair.Value);
                        }

                        // Check if there are triangles that have all vertexes inside the vbd
                        // All such vertices could be initially drawn so just draw them
                        // Triangles with weight over 2*vertexPresetBonus have 2+1 vertices in buffer so just draw them
                        var drawnPairs = potentialTris.Where((t, w) => w >= 2 * vertexPresentBonus);
                        foreach (KeyValuePair <Triangle, int> pair in drawnPairs)
                        {
                            Triangle ftri = pair.Key;
                            for (int i = 0; i < 3; i++)
                            {
                                Vertex v     = ftri.vertices[i];
                                int    index = vbd.AddVertex(v, out bool isNew);
                                indices[i] = index;

                                // Fix weights of tris if a new vertex was added to vbd (not already in vbd it is)
                                if (isNew)
                                {
                                    throw new ArithmeticException("Triangles with high weight has new vertices!");
                                }
                            }

                            // Draw the triangle, all vertices are guaranteed to be in
                            vbd.DrawTriangle(indices);
                            potentialTris.Remove(biggestTri);
                        }

                        // Check if there are less then 2 vertices, which are required to be able to draw any tri
                        // If there is a vertex that has vertexPresentBonus weight, we good, otherwise retreat
                        if (vbd.freeCount == 1)
                        {
                            if (potentialTris.Values.ToList().FindIndex(w => w >= vertexPresentBonus) == -1)
                            {
                                break;
                            }
                        }
                    }

                    rom.PushOffset(vertexPosition);
                    vbd.MakeData(rom);
                    writtenVerticesCount += (rom.offset - vertexPosition) / 0x10;
                    vertexPosition        = rom.offset;
                    rom.PopOffset();

                    vbd.MakeF3D(rom);
                }

                if (td.scroll != null)
                {
                    // Vertices must be rounded by 3 because skelux scrolls work like that

                    /*
                     * if (writtenVerticesCount % 3 != 0)
                     * {
                     *  int leftToRoundVertices = 3 - (writtenVerticesCount % 3);
                     *  writtenVerticesCount += leftToRoundVertices;
                     *  vertexPosition += leftToRoundVertices * 0x10;
                     * }
                     */

                    int segmentedAddress        = rom.GetSegmentedAddress(allocVertexStart);
                    List <ScrollObject> scrolls = factory.GetScrolls(writtenVerticesCount, segmentedAddress, td);
                    foreach (ScrollObject scroll in scrolls)
                    {
                        scroll.WriteScroll(rom);
                    }
                }

                vertexBytes.AddRegion(vertexPosition, allocVertexEnd - vertexPosition);
            }
            foreach (UInt64 cmd in footer)
            {
                rom.Write64(cmd);
                rom.AddOffset(8);
            }
            return(rom.offset - start);
        }
Example #13
0
 /// <summary>
 /// Returns an enumeration definition for the specified name.
 /// </summary>
 public abstract EnumValueDefinition?FindByName(ROM name);
Example #14
0
        private static void CMD_39(ref Level lvl, ref string desc, byte[] cmd)
        {
            if (cmd.Length < 8)
            {
                return;
            }
            ROM  rom = ROM.Instance;
            uint pos = bytesToInt(cmd, 4, 4);

            desc = "Place macro objects loaded from address 0x" + pos.ToString("X8");

            byte[] data = rom.getDataFromSegmentAddress_safe(pos, 10);

            lvl.getCurrentArea().MacroObjects.Clear();
            bool endList = false;

            while (!endList)
            {
                //rom.printArray(data, 10);
                uint id = bytesToInt(data, 0, 2) & 0x1FF;
                if (id == 0 || id == 0x1E)
                {
                    break;
                }
                Object3D newObj = new Object3D();
                if (rom.isSegmentMIO0(cmd[4]))
                {
                    newObj.MakeReadOnly();
                    newObj.Address = "N/A";
                }
                else
                {
                    newObj.Address = "0x" + rom.decodeSegmentAddress(pos).ToString("X");
                }

                uint   table_off = (id - 0x1F) * 8;
                byte[] entryData = rom.getSubArray(rom.Bytes, Globals.macro_preset_table + table_off, 8);
                newObj.level = lvl;
                newObj.createdFromLevelScriptCommand = Object3D.FROM_LS_CMD.CMD_39;
                newObj.setBehaviorFromAddress(bytesToInt(entryData, 0, 4));
                newObj.HideProperty(Object3D.FLAGS.ROTATION_X);
                newObj.HideProperty(Object3D.FLAGS.ROTATION_Z);
                newObj.HideProperty(Object3D.FLAGS.BPARAM_3);
                newObj.HideProperty(Object3D.FLAGS.BPARAM_4);
                newObj.ModelID = entryData[5];
                ushort firstAndSecond = (ushort)bytesToInt(data, 0, 2);
                newObj.setPresetID((ushort)(firstAndSecond & 0x1FF));
                newObj.yRot = (short)((firstAndSecond >> 9) * 2.8125);
                newObj.xPos = (short)bytesToInt(data, 2, 2);
                newObj.yPos = (short)bytesToInt(data, 4, 2);
                newObj.zPos = (short)bytesToInt(data, 6, 2);
                newObj.DontShowActs();
                newObj.MakeBehaviorReadOnly(true);
                newObj.MakeModelIDReadOnly(true);
                ushort bp = (ushort)bytesToInt(data, 8, 2);
                if (data[8] != 0)
                {
                    newObj.BehaviorParameter1 = data[8];
                }
                else
                {
                    newObj.BehaviorParameter1 = entryData[6];
                }

                if (data[9] != 0)
                {
                    newObj.BehaviorParameter2 = data[9];
                }
                else
                {
                    newObj.BehaviorParameter2 = entryData[7];
                }

                lvl.getCurrentArea().MacroObjects.Add(newObj);
                pos += 10;
                data = rom.getDataFromSegmentAddress_safe(pos, 10);
            }
            //uint end = bytesToInt(cmd, 8, 4);
            //rom.setSegment(seg, start, end, false);
        }
Example #15
0
        /* Process collision map, Special Objects, and waterboxes. */
        private static void CMD_2E(ref Level lvl, ref string desc, byte[] cmd)
        {
            ROM rom = ROM.Instance;

            if (cmd.Length < 8)
            {
                return;
            }
            desc = "Load collision, and place special objects from address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
            ushort sub_cmd = 0x40;
            byte   segment = cmd[4];
            uint   off     = bytesToInt(cmd, 5, 3);

            byte[] data = rom.getSegment(segment);
            sub_cmd = (ushort)bytesToInt(data, (int)off, 2);
            CollisionMap cmap      = lvl.getCurrentArea().collision;
            uint         num_verts = (ushort)bytesToInt(data, (int)off + 2, 2);

            off += 4;
            for (int i = 0; i < num_verts; i++)
            {
                short x = (short)bytesToInt(data, (int)off + 0, 2);
                short y = (short)bytesToInt(data, (int)off + 2, 2);
                short z = (short)bytesToInt(data, (int)off + 4, 2);
                cmap.AddVertex(new OpenTK.Vector3(x, y, z));
                off += 6;
            }

            while (sub_cmd != 0x0041)
            {
                sub_cmd = (ushort)bytesToInt(data, (int)off, 2);
                //Console.WriteLine(sub_cmd.ToString("X8"));
                if (sub_cmd == 0x0041)
                {
                    break;
                }
                //rom.printArraySection(data, (int)off, 4 + (int)collisionLength(sub_cmd));
                cmap.NewTriangleList((int)bytesToInt(data, (int)off, 2));
                uint num_tri = (ushort)bytesToInt(data, (int)off + 2, 2);
                uint col_len = collisionLength(sub_cmd);
                off += 4;
                for (int i = 0; i < num_tri; i++)
                {
                    uint a = bytesToInt(data, (int)off + 0, 2);
                    uint b = bytesToInt(data, (int)off + 2, 2);
                    uint c = bytesToInt(data, (int)off + 4, 2);
                    cmap.AddTriangle(a, b, c);
                    off += col_len;
                }
            }
            cmap.buildCollisionMap();
            off += 2;
            bool end = false;

            while (!end)
            {
                sub_cmd = (ushort)bytesToInt(data, (int)off, 2);
                switch (sub_cmd)
                {
                case 0x0042:
                    end = true;
                    break;

                case 0x0043:
                    uint num_obj = (ushort)bytesToInt(data, (int)off + 2, 2);
                    off += 4;
                    for (int i = 0; i < num_obj; i++)
                    {
                        ushort   obj_id  = (ushort)bytesToInt(data, (int)off, 2);
                        byte[]   entry   = getSpecialObjectEntry((byte)obj_id);
                        uint     obj_len = getSpecialObjectLength(obj_id);
                        Object3D newObj  = new Object3D();
                        if (rom.isSegmentMIO0(segment))
                        {
                            newObj.MakeReadOnly();
                            newObj.Address = "N/A";
                        }
                        else
                        {
                            newObj.Address = "0x" + rom.decodeSegmentAddress(segment, off).ToString("X");
                        }
                        newObj.setPresetID(obj_id);
                        newObj.level = lvl;
                        newObj.HideProperty(Object3D.FLAGS.ROTATION_X);
                        newObj.HideProperty(Object3D.FLAGS.ROTATION_Z);
                        newObj.HideProperty(Object3D.FLAGS.BPARAM_3);
                        newObj.HideProperty(Object3D.FLAGS.BPARAM_4);
                        newObj.xPos = (short)bytesToInt(data, (int)off + 2, 2);
                        newObj.yPos = (short)bytesToInt(data, (int)off + 4, 2);
                        newObj.zPos = (short)bytesToInt(data, (int)off + 6, 2);
                        newObj.BehaviorParameter1 = entry[1];
                        newObj.BehaviorParameter2 = entry[2];
                        newObj.MakeBehaviorReadOnly(true);
                        newObj.MakeModelIDReadOnly(true);
                        if (obj_len > 8)
                        {
                            newObj.yRot = (short)(bytesToInt(data, (int)off + 8, 2) * 1.40625);
                            if (obj_len > 10)
                            {
                                newObj.BehaviorParameter1            = data[off + 10];
                                newObj.BehaviorParameter2            = data[off + 11];
                                newObj.createdFromLevelScriptCommand = Object3D.FROM_LS_CMD.CMD_2E_12;
                                lvl.AddSpecialObjectPreset_12(obj_id, entry[3],
                                                              bytesToInt(entry, 4, 4), data[off + 10], data[off + 11]);
                            }
                            else
                            {
                                lvl.AddSpecialObjectPreset_10(obj_id, entry[3], bytesToInt(entry, 4, 4));
                                newObj.HideProperty(Object3D.FLAGS.BPARAM_1);
                                newObj.HideProperty(Object3D.FLAGS.BPARAM_2);
                                newObj.createdFromLevelScriptCommand = Object3D.FROM_LS_CMD.CMD_2E_10;
                            }
                        }
                        else
                        {
                            lvl.AddSpecialObjectPreset_8(obj_id, entry[3], bytesToInt(entry, 4, 4));
                            newObj.HideProperty(Object3D.FLAGS.BPARAM_1);
                            newObj.HideProperty(Object3D.FLAGS.BPARAM_2);
                            newObj.HideProperty(Object3D.FLAGS.ROTATION_Y);
                            newObj.createdFromLevelScriptCommand = Object3D.FROM_LS_CMD.CMD_2E_8;
                        }
                        newObj.ModelID = entry[3];
                        uint behavior = bytesToInt(entry, 4, 4);
                        newObj.setBehaviorFromAddress(behavior);
                        newObj.DontShowActs();
                        if (behavior != 0)
                        {
                            lvl.getCurrentArea().SpecialObjects.Add(newObj);
                        }
                        off += obj_len;
                    }
                    break;

                case 0x0044:
                    // Also skipping water boxes. Will come back to it later.
                    uint num_boxes = (ushort)bytesToInt(data, (int)off + 2, 2);
                    off += 4 + (num_boxes * 0xC);
                    break;
                }
            }
        }
Example #16
0
 public ByteRegister this[ROM r]
 {
     get { return(this[(uint)r]); }
     set { this[(uint)r] = value; }
 }
Example #17
0
        public void Load()
        {
            if (ComboIndex < 0)
            {
                LanguageCombo.SelectedIndex = 0;
            }
            var    rfs      = MainWindow.LoadedROM.ToFileSystem();
            string ext      = GetCARCExtension(LanguageCombo.SelectedIndex);
            var    cbmain2d = ROMUtils.GetFile("Main2D" + ext + ".carc", rfs);
            var    bmain2d  = ROM.LZ77_Decompress(cbmain2d);

            Main2D = new NARC(bmain2d);
            var dmain2d = Main2D.ToFileSystem();
            var common  = ROMUtils.GetFile("common.bmg", dmain2d);

            Common = new BMG(common);
            var cbstatic2d = ROMUtils.GetFile("Static2D.carc", rfs);
            var bstatic2d  = ROM.LZ77_Decompress(cbstatic2d);

            Static2D = new NARC(bstatic2d);
            var dstatic2d = Static2D.ToFileSystem();
            var mbchild   = ROMUtils.GetFile("MBChild" + ext + ".bmg", dstatic2d);

            MBChild = new BMG(mbchild);
            var cbchksel = ROMUtils.GetFile("CharacterKartSelect" + ext + ".carc", rfs);
            var bchksel  = ROM.LZ77_Decompress(cbchksel);

            CharacterKartSelect = new NARC(bchksel);
            var dchksel = CharacterKartSelect.ToFileSystem();
            var ksel    = ROMUtils.GetFile("kart_select.bmg", dchksel);

            KartSelect = new BMG(ksel);
            var cbwlmenu = ROMUtils.GetFile("WLMenu" + ext + ".carc", rfs);
            var bwlmenu  = ROM.LZ77_Decompress(cbwlmenu);

            WLMenu = new NARC(bwlmenu);
            var dwlmenu = WLMenu.ToFileSystem();
            var banner  = ROMUtils.GetFile("banner.bmg", dwlmenu);

            Banner = new BMG(banner);
            CommonTextsList.Items.Clear();
            MBChildTextsList.Items.Clear();
            KartSelectTextsList.Items.Clear();
            DlPlayTextsList.Items.Clear();
            foreach (var str in Common.DAT1.Strings)
            {
                CommonTextsList.Items.Add(new TextBox()
                {
                    TextWrapping  = TextWrapping.Wrap,
                    AcceptsReturn = true,
                    Text          = str,
                });
            }
            foreach (var str in MBChild.DAT1.Strings)
            {
                MBChildTextsList.Items.Add(new TextBox()
                {
                    TextWrapping  = TextWrapping.Wrap,
                    AcceptsReturn = true,
                    Text          = str,
                });
            }
            foreach (var str in KartSelect.DAT1.Strings)
            {
                KartSelectTextsList.Items.Add(new TextBox()
                {
                    TextWrapping  = TextWrapping.Wrap,
                    AcceptsReturn = true,
                    Text          = str,
                });
            }
            foreach (var str in Banner.DAT1.Strings)
            {
                DlPlayTextsList.Items.Add(new TextBox()
                {
                    TextWrapping  = TextWrapping.Wrap,
                    AcceptsReturn = true,
                    Text          = str,
                });
            }
        }
Example #18
0
        private void ImportTexture_Click(object sender, EventArgs e)
        {
            int index = TextureNumBox.SelectedIndex;
            // Displays an OpenFileDialog so the user can select a Cursor.
            OpenFileDialog OpenTexture = OFD();

            OpenTexture.Filter = "Image Files|*.png;*.bmp;*.jpg";
            OpenTexture.Title  = "Select a texture image file";
            if (OpenTexture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Bitmap TextureBMP  = (Bitmap)Image.FromFile(OpenTexture.FileName);
                double widthpower  = Math.Log(TextureBMP.Width, 2);
                double heightpower = Math.Log(TextureBMP.Height, 2);
                if ((widthpower % 1) != 0 || (heightpower % 1) != 0)
                {
                    MessageBox.Show("Only texture sizes in powers of 2 \n(ie 16x16, 32x32, 64x64, 128x64) are supported!", "Invalid texture resolution");
                    return;
                }
                Vector2 originalpowers = Textures.getWidthHeightPowers(index);
                if ((Math.Pow(2, originalpowers.X) * Math.Pow(2, originalpowers.Y)) < (Math.Pow(2, widthpower) * Math.Pow(2, heightpower)))
                {
                    MessageBox.Show("Texture is beyond the max data for this tile! \nTry lowering resolution or bitsize.", "Texture data too large!");
                    return;
                }
                else if (TexFormatBox.SelectedIndex == 2 && ((Math.Pow(2, originalpowers.X) * Math.Pow(2, originalpowers.Y)) < (Math.Pow(2, widthpower + 1) * Math.Pow(2, heightpower)))) //CI4 needs twice data atm for palette
                {
                    MessageBox.Show("Texture is beyond the max data for this tile! \nTry lowering resolution or bitsize.\n(CI needs extra data for palette and commands)", "Texture data too large!");
                    return;
                }
                else if (TexFormatBox.SelectedIndex == 2 && BitsizeBox.SelectedIndex == 0 && Textures.getImageColors(TextureBMP).Length > 16)
                {
                    MessageBox.Show("Texture has too many colours for CI4.\nPlease reduce colour count to 16."); return;
                }
                Textures.ResizeTexture(index, Convert.ToInt32(widthpower), Convert.ToInt32(heightpower));
                Textures.ImportBMPtoTexture(TextureBMP, index);
                UInt32[] F5CMDs = Textures.F5CMDArray[TextureNumBox.SelectedIndex]; ROM SM64ROM = ROMManager.SM64ROM;
                ROMManager.InitialiseModelLoad(ClientRectangle, RenderPanel, Width, Height);
                UpdateTextureNum();
                int    width           = TextureBMP.Width;
                int    selectedbitsize = (int)(4 * Math.Pow(2, BitsizeBox.SelectedIndex));
                ushort linesperword    = Convert.ToUInt16((64d * 2048d) / ((double)TextureBMP.Width * selectedbitsize));
                ushort texelcount      = (ushort)((double)(TextureBMP.Width * TextureBMP.Height) * ((double)selectedbitsize / 16d) - 1);
                for (uint i = 0; i < F5CMDs.Length; i++) //Update F5 scanline width
                {
                    uint F5 = F5CMDs[i];
                    if (SM64ROM.getByte(F5 - 0x10) == 0xF3)
                    {
                        SM64ROM.WriteEightBytes(F5 - 0x10, 0xF300000007000000 | (uint)(texelcount << 12) | linesperword);
                    }
                    SM64ROM.WriteTwoBytes(F5 + 1, (ushort)((SM64ROM.ReadTwoBytes(F5CMDs[i] + 1) & 0xFC00) | ((width * selectedbitsize / 64) << 1)));
                }
                TextureBMP.Dispose();
            }
        }
Example #19
0
        private List <RadioButtonWithInfo> parseOtherListJSON(JArray array, out string blockName)
        {
            ROM rom = ROM.Instance;

            blockName = "Unknown";
            List <RadioButtonWithInfo> list   = new List <RadioButtonWithInfo>();
            uint segmentAddressForLoadingData = 0;

            byte[][] tempSegments        = new byte[0x20][];
            uint[]   tempSegmentStarts   = new uint[0x20];
            bool[]   tempSegmentsAreMIO0 = new bool[0x20];

            foreach (JObject obj in array.Children())
            {
                if (obj["Block Name"] != null)
                {
                    blockName = obj["Block Name"].ToString();
                    segmentAddressForLoadingData = 0; // Reset for every new block
                }
                else if (obj["UseSegmentAddressesFromLevelScriptStartingFrom"] != null)
                {
                    segmentAddressForLoadingData = uint.Parse(obj["UseSegmentAddressesFromLevelScriptStartingFrom"].ToString(), NumberStyles.HexNumber);
                    for (int i = 0; i < 0x20; i++)
                    {
                        tempSegments[i]        = new byte[0]; // reset segments
                        tempSegmentsAreMIO0[i] = false;
                        tempSegmentStarts[i]   = 0;
                    }
                    tempSegments[0x00]        = rom.Bytes;
                    tempSegments[0x15]        = rom.cloneSegment(0x15, (byte)level.CurrentAreaID);
                    tempSegmentStarts[0x15]   = Globals.seg15_location[0];
                    tempSegments[0x02]        = rom.cloneSegment(0x02, (byte)level.CurrentAreaID);
                    tempSegmentStarts[0x02]   = Globals.seg02_location[0];
                    tempSegmentsAreMIO0[0x02] = !rom.Seg02_isFakeMIO0;
                    //Console.WriteLine("SegOff:0x{0}", segmentAddressForLoadingData.ToString("X8"));
                    parseLevelScriptTemporarlyForSegments(tempSegments, tempSegmentStarts, tempSegmentsAreMIO0, (byte)(segmentAddressForLoadingData >> 24), segmentAddressForLoadingData & 0xFFFFFF);
                }
                else
                {
                    if (checkForValidEntry(obj))
                    {
                        int    width    = int.Parse(obj["Width"].ToString());
                        int    height   = int.Parse(obj["Height"].ToString());
                        byte   format   = TextureFormats.ConvertStringToFormat(obj["Format"].ToString());
                        uint   dataSize = (uint)((TextureFormats.getNumberOfBitsForFormat(format) * width * height) / 8);
                        byte[] data;
                        if (obj["FromSegmentAddress"] != null)
                        {
                            uint segOffset = uint.Parse(obj["FromSegmentAddress"].ToString(), NumberStyles.HexNumber);
                            if (segmentAddressForLoadingData == 0)
                            {
                                data = rom.getDataFromSegmentAddress_safe(segOffset, dataSize, (byte)level.CurrentAreaID);
                            }
                            else
                            {
                                byte segment     = (byte)(segOffset >> 24);
                                uint segment_off = segOffset & 0x00FFFFFF;
                                data = rom.getSubArray_safe(tempSegments[segment], segment_off, dataSize);
                            }
                        }
                        else
                        {
                            if (rom.Type == ROM_Type.VANILLA && obj["ForExtendedROM"] != null)
                            {
                                string forExtendedROM = obj["ForExtendedROM"].ToString().ToLower();
                                if (forExtendedROM.Equals("true"))
                                {
                                    continue;
                                }
                            }
                            uint romOff = uint.Parse(obj["FromROMAddress"].ToString(), NumberStyles.HexNumber);
                            data = rom.getSubArray_safe(rom.Bytes, romOff, dataSize);
                        }
                        Bitmap   image = TextureFormats.decodeTexture(format, data, width, height, null, true);
                        string[] tags  = (string[])image.Tag;
                        Array.Resize(ref tags, tags.Length + 3);
                        uint segOff = 0;
                        if (obj["FromSegmentAddress"] != null)
                        {
                            segOff = uint.Parse(obj["FromSegmentAddress"].ToString(), NumberStyles.HexNumber);


                            if (segmentAddressForLoadingData == 0)
                            {
                                if (!rom.isSegmentMIO0((byte)(segOff >> 24), (byte)level.CurrentAreaID))
                                {
                                    tags[tags.Length - 3] = "ROM Address: " + rom.decodeSegmentAddress(segOff, (byte)level.CurrentAreaID).ToString("X");
                                }
                                else
                                {
                                    tags[tags.Length - 3] = "ROM Address: N/A";
                                }
                            }
                            else
                            {
                                byte seg_temp        = (byte)(segOff >> 24);
                                uint seg_temp_offset = segOff & 0x00FFFFFF;
                                if (tempSegmentsAreMIO0[seg_temp])
                                {
                                    tags[tags.Length - 3] = "ROM Address: N/A";
                                }
                                else
                                {
                                    tags[tags.Length - 3] = "ROM Address: " + (tempSegmentStarts[seg_temp] + seg_temp_offset).ToString("X");
                                }
                            }

                            tags[tags.Length - 2] = "Seg Addr: " + obj["FromSegmentAddress"];
                        }
                        else
                        {
                            tags[tags.Length - 3] = "ROM Address: " + obj["FromROMAddress"];
                            tags[tags.Length - 2] = "Seg Addr: N/A";
                        }
                        tags[tags.Length - 1] = "Name: " + obj["Name"];
                        image.Tag             = tags;

                        AddNewImage(ref list, image, segOff, ot_RadioButtonWithInfo_Click);

                        //Console.WriteLine("Added Other Image: " + obj["Name"]);
                    }
                    //Bitmap image = TextureFormats.decodeTexture();
                    //AddNewImage(ref list, level.ModelIDs[modelID].builder.TextureImages[i], address, ot_RadioButtonWithInfo_Click);
                }
                //Console.WriteLine(obj.ToString());
            }
            return(list);
        }
        public static void parse(ref Model3D mdl, ref Level lvl, byte seg, uint off, byte?areaID)
        {
            if (seg == 0)
            {
                return;
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg, areaID);
            bool   end  = false;

            while (!end)
            {
                byte   cmdLen       = getCmdLength(data[off]);
                byte[] cmd          = rom.getSubArray_safe(data, off, cmdLen);
                string desc         = "Unknown command";
                bool   alreadyAdded = false;

                /*
                 * if (cmd[0] != 0x05 && nodeCurrent.isSwitch && nodeCurrent.switchPos != 1)
                 * {
                 *  if (nodeCurrent.switchFunc == 0x8029DB48)
                 *  {
                 *      //rom.printArray(cmd, cmdLen);
                 *      //Console.WriteLine(nodeCurrent.switchPos);
                 *  }
                 *  nodeCurrent.switchPos++;
                 *  off += cmdLen;
                 *  continue;
                 * }*/

                switch (cmd[0])
                {
                case 0x00:
                    desc = "Branch geometry layout to address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    addGLSCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                    alreadyAdded = true;
                    CMD_00(ref mdl, ref lvl, cmd, areaID);
                    break;

                case 0x01:
                    desc = "End geometry layout";
                    end  = true;
                    break;

                case 0x02:
                    desc = "Branch geometry layout to address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    addGLSCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                    alreadyAdded = true;
                    CMD_02(ref mdl, ref lvl, cmd, areaID);

                    if (cmd[1] == 0x01)
                    {
                        if (nodeCurrent.parent == null || (nodeCurrent.parent != null && nodeCurrent.parent.callSwitch == false))
                        {
                            // If the next command is not another 0x02 command, or a 0x05 command...
                            if (data[off + cmdLen] != 0x02 && data[off + cmdLen] != 0x05)
                            {
                                end = true;
                            }
                        }
                    }
                    break;

                case 0x03:
                    desc = "Return from branch";
                    end  = true;
                    break;

                case 0x04:
                    desc = "Open New Node";
                    CMD_04();
                    break;

                case 0x05:
                    desc = "Close Node";
                    if (nodeCurrent != rootNode)
                    {
                        nodeCurrent = nodeCurrent.parent;
                    }
                    break;

                case 0x08:
                    desc = "Set screen rendering area (" +
                           "center X = " + (short)bytesToInt(cmd, 4, 2) +
                           ", center Y = " + (short)bytesToInt(cmd, 6, 2) +
                           ", Width = " + (short)(bytesToInt(cmd, 8, 2) * 2) +
                           ", Height = " + (short)(bytesToInt(cmd, 10, 2) * 2) + ")";
                    break;

                case 0x0A:
                    desc = "Set camera frustum (" +
                           "FOV = " + (short)bytesToInt(cmd, 2, 2) +
                           ", Near = " + (short)bytesToInt(cmd, 4, 2) +
                           ", Far = " + (short)bytesToInt(cmd, 6, 2) + ")";
                    break;

                case 0x0B:
                    desc = "Start geometry layout";
                    break;

                case 0x0C:
                    if (cmd[1] == 0x00)
                    {
                        desc = "Disable Z-Buffer";
                    }
                    else
                    {
                        desc = "Enable Z-Buffer";
                    }
                    break;

                case 0x0D:
                    desc = "Set render range from camera (min = " +
                           (short)bytesToInt(cmd, 4, 2) + ", max = " +
                           (short)bytesToInt(cmd, 6, 2) + ")";
                    break;

                case 0x0E:
                    desc = "Switch case with following display lists using ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    //rom.printArray(cmd, cmdLen);
                    CMD_0E(ref mdl, ref lvl, cmd);
                    break;

                case 0x10:
                    desc = "Translate and rotate";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x11:
                    //rom.printArray(cmd, cmdLen);
                    desc = "Translate Node";
                    CMD_11(ref mdl, ref lvl, cmd);
                    break;

                case 0x13:
                    desc = "Load display list 0x" + bytesToInt(cmd, 8, 4).ToString("X8") +
                           " into layer " + cmd[1] + " and offset position by (" +
                           (short)bytesToInt(cmd, 2, 2) +
                           "," + (short)bytesToInt(cmd, 2, 2) +
                           "," + (short)bytesToInt(cmd, 2, 2) +
                           ")";
                    //rom.printArray(cmd, cmdLen);
                    CMD_13(ref mdl, ref lvl, cmd, areaID);
                    break;

                case 0x14:
                    desc = "Billboard Model";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x15:
                    desc = "Load display list 0x" + bytesToInt(cmd, 4, 4).ToString("X8") +
                           " into layer " + cmd[1];
                    CMD_15(ref mdl, ref lvl, cmd, areaID);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x16:
                    desc = "Start geometry layout with a shadow. (type = " + cmd[3] +
                           ", solidity = " + cmd[5] + ", scale = " +
                           bytesToInt(cmd, 6, 2) + ")";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x17:
                    desc = "Setup display lists for level objects";
                    break;

                case 0x18:
                    desc = "Create display list(s) from the ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8")
                           + " (a0 = " + bytesToInt(cmd, 2, 2) + ")";
                    CMD_18(ref mdl, ref lvl, cmd);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x19:
                    if (bytesToInt(cmd, 4, 4) == 0x00000000)
                    {
                        desc = "Draw solid color background. Color = (";
                        ushort color = (ushort)bytesToInt(cmd, 2, 2);
                        desc += (((color >> 11) & 0x1F) * 8) + ","
                                + (((color >> 6) & 0x1F) * 8) + ","
                                + (((color >> 1) & 0x1F) * 8) + ")";
                    }
                    else
                    {
                        desc = "Draw background image. bgID = " + bytesToInt(cmd, 2, 2) +
                               ", calls ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    }
                    CMD_19(ref mdl, ref lvl, cmd, rom.decodeSegmentAddress(seg, off, areaID));
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x1D:
                    desc = "Scale following node by " + ((bytesToInt(cmd, 4, 4) / 65536.0f) * 100.0f) + "%";
                    CMD_1D(ref mdl, cmd);
                    break;

                case 0x1A:
                case 0x1E:
                case 0x1F:
                    desc = "Do nothing";
                    break;

                case 0x20:
                    desc = "Start geometry layout with render area of " + bytesToInt(cmd, 2, 2);
                    break;
                }
                if (!alreadyAdded)
                {
                    addGLSCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                }
                off += cmdLen;

                /*
                 * if (nodeCurrent.isSwitch)
                 *  nodeCurrent.switchPos++;
                 */
            }
        }
Example #21
0
        private int parseLevelScriptTemporarlyForSegments(byte[][] segments, uint[] segmentStarts, bool[] segmentsAreMIO0, byte seg, uint off)
        {
            ROM rom = ROM.Instance;

            byte[] data = segments[seg];
            if (data == null || data.Length < 1)
            {
                return(2);
            }
            bool end    = false;
            int  endCmd = 0;
            byte l_seg;
            uint l_start, l_end, l_off;

            while (!end)
            {
                byte   cmdLen = data[off + 1];
                byte[] cmd    = rom.getSubArray_safe(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                switch (cmd[0])
                {
                case 0x00:
                case 0x01:
                {
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    l_off   = bytesToInt(cmd, 13, 3);
                    segmentStarts[l_seg] = l_start;
                    segments[l_seg]      = rom.getROMSection(l_start, l_end);
                    int end_r = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    if (end_r == 0x02)
                    {
                        end    = true;
                        endCmd = 2;
                    }
                }
                break;

                case 0x02:
                    endCmd = 2;
                    end    = true;
                    break;

                case 0x05:
                    l_seg = cmd[4];
                    l_off = bytesToInt(cmd, 5, 3);
                    if (l_seg == seg)
                    {
                        if ((long)l_off - (long)off == -4)
                        {
                            //Console.WriteLine("Infinite loop detected!");
                            return(0x02);
                        }
                    }
                    endCmd = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    end    = true;
                    break;

                case 0x06:
                    l_seg = cmd[4];
                    l_off = bytesToInt(cmd, 5, 3);
                    int end_ret = parseLevelScriptTemporarlyForSegments(segments, segmentStarts, segmentsAreMIO0, l_seg, l_off);
                    if (end_ret == 0x02)
                    {
                        end    = true;
                        endCmd = 2;
                    }
                    break;

                case 0x07:
                    end    = true;
                    endCmd = 0x07;
                    break;

                case 0x17:
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    if (l_start < l_end)
                    {
                        segmentStarts[l_seg] = l_start;
                        segments[l_seg]      = rom.getROMSection(l_start, l_end);
                    }
                    //rom.setSegment(seg, start, end, false);
                    break;

                case 0x18:
                case 0x1A:
                    l_seg   = cmd[3];
                    l_start = bytesToInt(cmd, 4, 4);
                    l_end   = bytesToInt(cmd, 8, 4);
                    if (l_start < l_end)
                    {
                        byte[] MIO0_header = rom.getSubArray_safe(rom.Bytes, l_start, 0x10);
                        if (bytesToInt(MIO0_header, 0, 4) == 0x4D494F30)     // Check MIO0 signature
                        {
                            int  compressedOffset   = (int)bytesToInt(MIO0_header, 0x8, 4);
                            int  uncompressedOffset = (int)bytesToInt(MIO0_header, 0xC, 4);
                            bool isFakeMIO0         = rom.testIfMIO0IsFake(l_start, compressedOffset, uncompressedOffset);
                            segmentsAreMIO0[l_seg] = !isFakeMIO0;
                            if (isFakeMIO0)
                            {
                                segmentStarts[l_seg] = l_start + (uint)uncompressedOffset;
                            }
                            segments[l_seg] = MIO0.mio0_decode(rom.getROMSection(l_start, l_end));
                        }
                    }
                    break;

                case 0x1D:
                    end    = true;
                    endCmd = 0x02;
                    break;
                }
                off += cmdLen;
            }
            return(endCmd);
        }
Example #22
0
    public static void ImportBMPtoTexture(Bitmap bmp, int index)
    {
        ROM    SM64ROM  = ROMManager.SM64ROM;
        bool   RGBAMode = TextureAddrArray[index][1] == RGBAMODE;
        bool   IAMode   = TextureAddrArray[index][1] == IAMODE;
        bool   IMode    = TextureAddrArray[index][1] == IMODE;
        bool   CIMode   = TextureAddrArray[index][1] == CIMODE;
        bool   YUVMode  = TextureAddrArray[index][1] == YUVMODE;
        uint   bitsize  = TextureAddrArray[index][2];
        UInt32 addr     = TextureAddrArray[index][0];

        UInt32[] inttexels   = new UInt32[bmp.Width * bmp.Height];
        ushort[] shorttexels = new ushort[bmp.Width * bmp.Height];
        byte[]   bytetexels;
        int      x = 0;
        int      y = 0;

        switch (bitsize)
        {
        case 16:
            if (RGBAMode)     //RGBA16
            {
                for (uint i = 0; i < shorttexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    byte alpha = texel.A;
                    if (alpha > 0)
                    {
                        alpha = 1;
                    }
                    else
                    {
                        alpha = 0;
                    }
                    ushort colour = (ushort)
                                    (
                        ((byte)(texel.R >> 3) << 11) |
                        ((byte)(texel.G >> 3) << 6) |
                        ((byte)(texel.B >> 3) << 1) |
                        ((byte)(alpha))
                                    );
                    shorttexels[i] = colour;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < shorttexels.Length; i++)
                {
                    SM64ROM.WriteTwoBytes(addr + i * 2, shorttexels[i]);
                }
            }
            else if (IAMode)     //IA16
            {
                for (uint i = 0; i < shorttexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    ushort intensity           = (ushort)((((texel.R + texel.G + texel.B) / 3) << 8) | texel.A);
                    shorttexels[i] = intensity;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < shorttexels.Length; i++)
                {
                    SM64ROM.WriteTwoBytes(addr + i * 2, shorttexels[i]);
                }
            }
            return;

        case 32:     //RGBA32
            for (uint i = 0; i < inttexels.Length; i++)
            {
                System.Drawing.Color texel = bmp.GetPixel(x, y);
                UInt32 colour = (UInt32)((texel.R << 24) | (texel.G << 16) | (texel.B << 8) | texel.A);
                inttexels[i] = colour;
                x++; if (x >= bmp.Width)
                {
                    x = 0; y++;
                }
            }
            for (uint i = 0; i < inttexels.Length; i++)
            {
                SM64ROM.WriteFourBytes(addr + i * 4, inttexels[i]);
            }
            return;

        case 8:
            bytetexels = new byte[bmp.Width * bmp.Height];
            if (IMode)     //I8
            {
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    byte intensity             = (byte)((texel.R + texel.G + texel.B) / 3);
                    bytetexels[i] = intensity;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    SM64ROM.changeByte(addr + i, bytetexels[i]);
                }
            }
            else if (IAMode)     //IA8
            {
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    byte intensity             = (byte)((byte)((texel.R + texel.G + texel.B) / 3) & 0xF0);
                    byte alpha = (byte)((texel.A & 0xF0) >> 4);
                    byte IA    = (byte)(intensity | alpha);
                    bytetexels[i] = IA;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    SM64ROM.changeByte(addr + i, bytetexels[i]);
                }
            }
            return;

        case 4:
            bytetexels = new byte[(bmp.Width * bmp.Height) / 2];
            if (IMode)     //I4
            {
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    byte intensity1            = (byte)((byte)((texel.R + texel.G + texel.B) / 3) & 0xF0);
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                    System.Drawing.Color texel2 = bmp.GetPixel(x, y);
                    byte intensity2             = (byte)(((byte)((texel2.R + texel2.G + texel2.B) / 3) & 0xF0) >> 4);
                    byte ii = (byte)(intensity1 | intensity2);
                    bytetexels[i] = ii;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    SM64ROM.changeByte(addr + i, bytetexels[i]);
                }
            }
            else if (IAMode)     //IA4
            {
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    System.Drawing.Color texel = bmp.GetPixel(x, y);
                    byte intensity1            = (byte)((byte)(((texel.R + texel.G + texel.B) / 3) >> 5) << 5);
                    byte alpha1 = (byte)(((texel.A) >> 7) << 4);
                    byte ia1    = (byte)(intensity1 | alpha1);
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                    System.Drawing.Color texel2 = bmp.GetPixel(x, y);
                    byte intensity2             = (byte)((byte)(((texel2.R + texel2.G + texel2.B) / 3) >> 5) << 1);
                    byte alpha2 = (byte)((texel2.A) >> 7);
                    byte ia2    = (byte)(intensity2 | alpha2);
                    byte iaia   = (byte)(ia1 | ia2);
                    bytetexels[i] = iaia;
                    x++; if (x >= bmp.Width)
                    {
                        x = 0; y++;
                    }
                }
                for (uint i = 0; i < bytetexels.Length; i++)
                {
                    SM64ROM.changeByte(addr + i, bytetexels[i]);
                }
            }
            else if (CIMode)     //CI4
            {
                if (bmp.Width * bmp.Height > 0x1000)
                {
                    MessageBox.Show("CI4 cannot be above 64x64 due to\nTMEM limitations with palettes.", "Texture too large"); return;
                }
                Color[] colours     = getImageColors(bmp);
                UInt32  paletteaddr = (UInt32)(addr + (bmp.Width * bmp.Height / 2));    //Put palette right after CI data
                for (int i = 0; i < colours.Length; i++)
                {
                    byte alpha = colours[i].A;
                    if (alpha > 0)
                    {
                        alpha = 1;
                    }
                    else
                    {
                        alpha = 0;
                    }
                    ushort colour = (ushort)
                                    (
                        ((byte)(colours[i].R >> 3) << 11) |
                        ((byte)(colours[i].G >> 3) << 6) |
                        ((byte)(colours[i].B >> 3) << 1) |
                        ((byte)(alpha))
                                    );
                    SM64ROM.WriteTwoBytes((UInt32)(paletteaddr + (i * 2)), colour);
                }
                byte[] CIData = getCIData(bmp, colours);
                for (uint i = 0; i < CIData.Length; i++)
                {
                    SM64ROM.changeByte(i + addr, CIData[i]);
                }                                                        //Write CI data over texture taking up **half** memory compared to RGBA16
                UInt32   branchDLAddr    = (UInt32)(paletteaddr + 0x20); //palette size is 0x20 for ci4
                UInt32   branchDLSegAddr = 0x0E000000 | (branchDLAddr - SM64ROM.getSegmentStart(0x0E));
                UInt32[] F5CMDs          = Textures.F5CMDArray[index];
                ushort   linesperword    = Convert.ToUInt16((64d * 2048d) / ((double)bmp.Width * bitsize));
                for (uint i = 0; i < F5CMDs.Length; i++)
                {
                    SM64ROM.changeByte(F5CMDs[i] + 1, 0x40);               //CI4 format
                    bool firsttexture = (i == 0 && SM64ROM.getByte(F5CMDs[0] + 0x10) == 0xFD);
                    for (uint j = F5CMDs[i]; j > F5CMDs[i] - 0x30; j -= 8) // Update 0xFD
                    {
                        if (SM64ROM.getByte(j) == 0xF3)
                        {
                            SM64ROM.WriteEightBytes(j, 0xF3000000073FF000 | linesperword);
                        }
                        else if (SM64ROM.getByte(j) == 0xFD || firsttexture)     //includes first texture check
                        {
                            if (firsttexture)
                            {
                                j += 0x10;
                            }
                            SM64ROM.changeByte(j + 1, 0x50);     //Format and bitsize byte, 0x50 for CI4
                            SM64ROM.copyBytes(j, branchDLAddr + 0x28, 8);
                            SM64ROM.WriteTwoBytes(j, 0x0600);    //Branch to load routine
                            SM64ROM.WriteFourBytes(j + 4, branchDLSegAddr);
                            if (SM64ROM.getByte(j + 0x10) == 0x06)
                            {
                                SM64ROM.WriteEightBytes(j + 0x10, 0xE600000000000000);     //Revert the TMEM shift undo (This tex still needs TMEM shift)
                            }
                            break;
                        }
                    }
                }
                for (uint i = 0; i < F5CMDs.Length; i++)
                {
                    bool firsttexture = (i == 0 && SM64ROM.getByte(F5CMDs[0] + 0x10) == 0xFD);
                    for (uint j = F5CMDs[i]; j < SM64ROM.getEndROMAddr(); j += 8)
                    {
                        if (firsttexture && SM64ROM.getByte(j + 0x20) == 0xF3)
                        {
                            j += 0x20; SM64ROM.WriteEightBytes(j + 0x20, 0xF3000000073FF000 | linesperword);
                        }                                                                                        //Update first texture command
                        if (SM64ROM.getByte(j) == 0x06)
                        {
                            break;                                 //If next texture is CI then don't revert the tmem shift
                        }
                        else if (SM64ROM.getByte(j) == 0xE6)
                        {
                            if (SM64ROM.getByte(j - 0x10) == 0x06)
                            {
                                break;                                        //If there is already a CI jump, escape from reverting it
                            }
                            SM64ROM.changeByte(j, 0x06);
                            SM64ROM.WriteFourBytes(j + 4, branchDLSegAddr + 56);
                            break;
                        }
                        else if (SM64ROM.getByte(j) == 0xB8)
                        {
                            for (uint k = j; k > j - 0x30; k -= 8)
                            {
                                if (SM64ROM.getByte(k) == 0xBB)
                                {
                                    SM64ROM.changeByte(k, 0x06); SM64ROM.WriteFourBytes(k + 4, branchDLSegAddr + 80);
                                    /*throw new Exception(branchDLSegAddr.ToString("x")+"\n"+branchDLAddr.ToString("x")+"\n");*/
                                    break;
                                }
                            }
                            break;     //allow last texture to jump and revert TMEM shift
                        }
                    }
                }
                SM64ROM.WriteEightBytes(branchDLAddr, 0xE700000000000000);                                // Loadsync
                SM64ROM.WriteEightBytes(branchDLAddr + 8, 0xFD10000000000000 | (branchDLSegAddr - 0x20)); //load palette
                SM64ROM.WriteEightBytes(branchDLAddr + 16, 0xF500010001000000);                           //Settile (palette)
                SM64ROM.WriteEightBytes(branchDLAddr + 24, 0xF00000000103C000);                           //Load palette into TMEM
                SM64ROM.WriteEightBytes(branchDLAddr + 32, 0xBA000E0200008000);                           //shift TMEM to palette
                SM64ROM.WriteEightBytes(branchDLAddr + 48, 0xB800000000000000);                           //Break out of jump
                SM64ROM.WriteEightBytes(branchDLAddr + 56, 0xE600000000000000);                           //Loadsync for next texture
                SM64ROM.WriteEightBytes(branchDLAddr + 64, 0xBA000E0200000000);                           //shift TMEM back
                SM64ROM.WriteEightBytes(branchDLAddr + 72, 0xB800000000000000);                           //Break from jump
                SM64ROM.WriteEightBytes(branchDLAddr + 80, 0xBB000000FFFFFFFF);                           //Disable tex at end of DL
                SM64ROM.WriteEightBytes(branchDLAddr + 88, 0xBA000E0200000000);                           //shift TMEM back
                SM64ROM.WriteEightBytes(branchDLAddr + 96, 0xB800000000000000);                           //Break out of jump
            }
            return;
        }
    }
Example #23
0
 public void Load(ROM rom)
 {
 }
Example #24
0
    public static void CentreUVs(bool ChangeU, int F5index, int width, int height)
    {
        uint[] F5CMDs = Textures.F5CMDArray[F5index]; ROM SM64ROM = ROMManager.SM64ROM;
        for (uint i = 0; i < F5CMDs.Length; i++)
        {
            bool exitUVcorrection = false;
            for (uint j = F5CMDs[i] + 8; j < SM64ROM.getEndROMAddr(); j += 8)
            {
                if (exitUVcorrection)
                {
                    break;
                }
                switch (SM64ROM.getByte(j))
                {
                case 0xBF:
                    UInt32    UVStart = 0;
                    short[][] UVs     = new short[2][]; for (int k = 0; k < 2; k++)
                    {
                        UVs[k] = new short[3];
                    }
                    for (uint k = j; k > j - 0x800; k -= 8)
                    {
                        if (SM64ROM.getByte(k) == 0x04)
                        {
                            UVStart = SM64ROM.readSegmentAddr(SM64ROM.ReadFourBytes(k + 4)) + 8; break;
                        }
                    }
                    if (UVStart == 0)
                    {
                        break;
                    }
                    for (uint k = 5; k < 8; k++)
                    {
                        UInt32 addr = Vertex.getAddrFromTriIndex(UVStart, SM64ROM.getByte(j + k));
                        UVs[0][k - 5] = (short)SM64ROM.ReadTwoBytes(addr);
                        UVs[1][k - 5] = (short)SM64ROM.ReadTwoBytes(addr + 2);
                    }
                    UVs = Vertex.CentreTRIUVs(UVs, width, height, ChangeU);
                    for (uint k = 5; k < 8; k++)
                    {
                        UInt32 addr = Vertex.getAddrFromTriIndex(UVStart, SM64ROM.getByte(j + k));
                        if (ChangeU)
                        {
                            SM64ROM.WriteTwoBytes(addr, (ushort)UVs[0][k - 5]);
                        }
                        else
                        {
                            SM64ROM.WriteTwoBytes(addr + 2, (ushort)UVs[1][k - 5]);
                        }
                    }
                    break;

                case 0xFD:
                    exitUVcorrection = true;
                    break;

                case 0x06:
                    exitUVcorrection = true;
                    break;

                case 0xB8:
                    exitUVcorrection = true;
                    break;
                }
            }
        }
    }
Example #25
0
        /***************************************************************************
        *  函数名称:treeView1_NodeMouseDoubleClick()
        *  功能:组件库列表表项鼠标双击事件,在graphControl绘图控制区创建相应组件
        *  参数:sender;e
        *  返回值:无
        * *************************************************************************/
        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
            if (treeView1.SelectedNode.Level > 1)
            {
                string name;
                //int tabIndex = 0; //第一个选项卡
                name = e.Node.Name.ToString();
                switch (name)
                {
                //================================================================//
                //======================创建基本组件==============================//
                //================================================================//
                //B01 人体血压
                case "BloodPressure":
                    bloodPressure = new BloodPressure(this.graphControl, null, null, null);
                    graphControl.AddShape(bloodPressure, bloodPressure.Location);
                    break;

                //B02 人体体温
                case "Temperature":
                    temperature = new Temperature(this.graphControl, null, null, null);
                    graphControl.AddShape(temperature, new PointF(temperature.Location.X, temperature.Location.Y + 80));
                    break;

                //B03 人体心率
                case "HeartRate":
                    heartRate = new HeartRate(this.graphControl, null, null, null);
                    graphControl.AddShape(heartRate, new PointF(heartRate.Location.X, heartRate.Location.Y + 160));
                    break;

                //B04 血压传感器
                case "BloodPressureSensor":
                    bloodPressureSensor = new BloodPressureSensor(this.graphControl, null, null, null);
                    graphControl.AddShape(bloodPressureSensor, new PointF(bloodPressureSensor.Location.X + 110, bloodPressureSensor.Location.Y));
                    break;

                //B05 体温传感器
                case "TemperatureSensor":
                    temperatureSensor = new TemperatureSensor(this.graphControl, null, null, null);
                    graphControl.AddShape(temperatureSensor, new PointF(temperatureSensor.Location.X + 110, temperatureSensor.Location.Y + 80));
                    break;

                //B06 心率传感器
                case "HeartRateSensor":
                    heartRateSensor = new HeartRateSensor(this.graphControl, null, null, null);
                    graphControl.AddShape(heartRateSensor, new PointF(heartRateSensor.Location.X + 110, heartRateSensor.Location.Y + 160));
                    break;

                //B07 显示控制器
                case "DisplayController":
                    displayController = new DisplayController(this.graphControl, null, null, null);
                    graphControl.AddShape(displayController, new PointF(displayController.Location.X + 220, displayController.Location.Y));
                    break;

                //B08 音频控制器
                case "AudioController":
                    audioController = new AudioController(this.graphControl, null, null, null);
                    graphControl.AddShape(audioController, new PointF(audioController.Location.X + 220, audioController.Location.Y + 80));
                    break;

                //B09 电机控制器
                case "ElectricMachineryController":
                    electricMachineryController = new ElectricMachineryController(this.graphControl, null, null, null);
                    graphControl.AddShape(electricMachineryController, new PointF(electricMachineryController.Location.X + 220, electricMachineryController.Location.Y + 160));
                    break;

                //B10 运算器 微处理器
                case "MicroProcessor":
                    microProcessor = new MicroProcessor(this.graphControl, null, null, null);
                    graphControl.AddShape(microProcessor, new PointF(microProcessor.Location.X + 330, microProcessor.Location.Y));
                    break;

                //B11 协议转换器
                case "ProtocolConverter":
                    protocolConverter = new ProtocolConverter(this.graphControl, null, null, null);
                    graphControl.AddShape(protocolConverter, new PointF(protocolConverter.Location.X + 330, protocolConverter.Location.Y + 70));
                    break;

                //B12 数据处理器
                case "DataProcessor":
                    dataProcessor = new DataProcessor(this.graphControl, null, null, null);
                    graphControl.AddShape(dataProcessor, new PointF(dataProcessor.Location.X + 330, dataProcessor.Location.Y + 160));
                    break;

                //B13 数据分析器
                case "DataAnalyzer":
                    dataAnalyzer = new DataAnalyzer(this.graphControl, null, null, null);
                    graphControl.AddShape(dataAnalyzer, new PointF(dataAnalyzer.Location.X + 330, dataAnalyzer.Location.Y + 240));
                    break;

                //B14 有线通信模块
                case "WiredModule":
                    wiredModule = new WiredModule(this.graphControl, null, null, null);
                    graphControl.AddShape(wiredModule, new PointF(wiredModule.Location.X + 440, wiredModule.Location.Y));
                    break;

                //B15 无线通信模块
                case "WirelessModule":
                    wirelessModule = new WirelessModule(this.graphControl, null, null, null);
                    graphControl.AddShape(wirelessModule, new PointF(wirelessModule.Location.X + 440, wirelessModule.Location.Y + 80));
                    break;

                //B16 有线媒介
                case "WiredMedia":
                    wiredMedia = new WiredMedia(this.graphControl, null, null, null);
                    graphControl.AddShape(wiredMedia, new PointF(wiredMedia.Location.X + 440, wiredMedia.Location.Y + 160));
                    break;

                //B17 无线媒介
                case "WirelessMedia":
                    wirelessMedia = new WirelessMedia(this.graphControl, null, null, null);
                    graphControl.AddShape(wirelessMedia, new PointF(wirelessMedia.Location.X + 440, wirelessMedia.Location.Y + 240));
                    break;

                //18 寄存器
                case "Register":
                    register = new Register(this.graphControl, null, null, null);
                    graphControl.AddShape(register, new PointF(register.Location.X + 550, register.Location.Y));
                    break;

                //B19 存储器RAM
                case "RAM":
                    ram = new RAM(this.graphControl, null, null, null);
                    graphControl.AddShape(ram, new PointF(ram.Location.X + 550, ram.Location.Y + 80));
                    break;

                //B20 存储器ROM
                case "ROM":
                    rom = new ROM(this.graphControl, null, null, null);
                    graphControl.AddShape(rom, new PointF(rom.Location.X + 550, rom.Location.Y + 160));
                    break;

                //B21 数据存储器
                case "DataMemory":
                    dataMemory = new DataMemory(this.graphControl, null, null, null);
                    graphControl.AddShape(dataMemory, new PointF(dataMemory.Location.X + 550, dataMemory.Location.Y + 240));
                    break;

                //B22 缓冲区
                case "Buffer":
                    buffer = new MyBuffer(this.graphControl, null, null, null);
                    graphControl.AddShape(buffer, new PointF(buffer.Location.X + 550, buffer.Location.Y + 320));
                    break;

                //B23 路由模块
                case "RouteModule":
                    routeModule = new RouteModule(this.graphControl, null, null, null);
                    graphControl.AddShape(routeModule, new PointF(routeModule.Location.X + 330, routeModule.Location.Y + 320));
                    break;

                //B24 监控器
                case "Monitor":
                    monitor = new MyMonitor(this.graphControl, null, null, null);
                    graphControl.AddShape(monitor, new PointF(monitor.Location.X + 220, monitor.Location.Y + 240));
                    break;

                //B25 血压监控器
                case "BloodPressureMonitor":
                    bpMonitor = new BloodPressureMonitor(this.graphControl, null, null, null);
                    graphControl.AddShape(bpMonitor, new PointF(bpMonitor.Location.X + 220, bpMonitor.Location.Y + 280));
                    break;

                //B26 体温监控器
                case "TemperatureMonitor":
                    tempMonitor = new TemperatureMonitor(this.graphControl, null, null, null);
                    graphControl.AddShape(tempMonitor, new PointF(tempMonitor.Location.X + 220, tempMonitor.Location.Y + 320));
                    break;

                //B27 心率监控器
                case "HeartRateMonitor":
                    hrMonitor = new HeartRateMonitor(this.graphControl, null, null, null);
                    graphControl.AddShape(hrMonitor, new PointF(hrMonitor.Location.X + 220, hrMonitor.Location.Y + 360));
                    break;

                //====================================================================//
                //======================CMIoT组件库中组件=============================//
                //====================================================================//
                //C01 患者组件
                case "Patient":
                    patient = new Patient(this.graphControl);
                    graphControl.AddShape(patient, patient.Location);
                    break;

                //C02 血压传感节点
                case "BloodPressureSensorNode":
                    BPSN = new BloodPressureSensorNode(this.graphControl);
                    //BPSN_InsideForm = new InsideForm(BPSN); //构建内部结构
                    graphControl.AddShape(BPSN, BPSN.Location);
                    break;

                //C03 体温传感节点
                case "TemperatureSensorNode":
                    TSN = new TemperatureSensorNode(this.graphControl);
                    graphControl.AddShape(TSN, TSN.Location);
                    break;

                //C04 心率传感节点
                case "HeartRateSensorNode":
                    HRSN = new HeartRateSensorNode(this.graphControl);
                    graphControl.AddShape(HRSN, HRSN.Location);
                    break;

                //C05 物联网网关
                case "IoTGateway":
                    IoTG = new IoTGateway(this.graphControl);
                    graphControl.AddShape(IoTG, IoTG.Location);
                    break;

                //C06 802.11信道组件
                case "802.11Channel":
                    channel_802_11 = new Channel802_11(this.graphControl, null, null, null);
                    graphControl.AddShape(channel_802_11, channel_802_11.Location);
                    break;

                //C07 802.15.1信道组件
                case "802.15.1Channel":
                    channel802_15_1 = new Channel802_15_1(this.graphControl, null, null, null);
                    graphControl.AddShape(channel802_15_1, channel802_15_1.Location);
                    break;

                //C08 802.15.4信道组件
                case "802.15.4Channel":
                    channel802_15_4 = new Channel802_15_4(this.graphControl, null, null, null);
                    graphControl.AddShape(channel802_15_4, channel802_15_4.Location);
                    break;

                //C09 Ethernet信道组件
                case "EthernetChannel":
                    channel_ethernet = new ChannelEthernet(this.graphControl, null, null, null);
                    graphControl.AddShape(channel_ethernet, channel_ethernet.Location);
                    break;

                //C10 IPv6路由器组件
                case "IPv6Router":
                    ipv6Router = new IPv6Router(this.graphControl);
                    graphControl.AddShape(ipv6Router, ipv6Router.Location);
                    break;

                //C11 医疗服务器组件
                case "MedicalServer":
                    MS = new MedicalServer(this.graphControl);
                    graphControl.AddShape(MS, MS.Location);
                    break;
                }
            } // if (treeView1.SelectedNode.Level > 1)
        }     //treeView1_NodeMouseDoubleClick
Example #26
0
        public static void parse(ref List <ScriptDumpCommandInfo> dump, byte seg, uint off)
        {
            if (seg == 0)
            {
                return;
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg, null);
            bool   end  = false;

            while (!end)
            {
                byte   cmdLen = getCmdLength(data[off]);
                byte[] cmd    = rom.getSubArray_safe(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                string desc         = "Unknown command";
                bool   alreadyAdded = false;
                switch (cmd[0])
                {
                case 0x00:
                    desc = "Start Behavior (Object type = " + cmd[1] + ")";
                    break;

                case 0x02:
                    desc         = "Jump & link to address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    alreadyAdded = true;
                    addBehCommandToDump(ref dump, cmd, seg, off, desc);
                    parse(ref dump, cmd[4], bytesToInt(cmd, 5, 3));
                    break;

                case 0x03:
                    desc = "Return back from jump & link";
                    end  = true;
                    break;

                case 0x04:
                    desc         = "Jump to address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    alreadyAdded = true;
                    addBehCommandToDump(ref dump, cmd, seg, off, desc);
                    parse(ref dump, cmd[4], bytesToInt(cmd, 5, 3));
                    end = true;
                    break;

                case 0x05:
                    desc = "Loop " + bytesToInt(cmd, 2, 2) + " times";
                    break;

                case 0x07:
                    desc = "Infinite loop (jump back 4 bytes)";
                    break;

                case 0x08:
                    desc = "Start of loop";
                    break;

                case 0x06:
                case 0x09:
                    desc = "End of loop";
                    end  = true;
                    break;

                case 0x0A:
                    desc = "End behavior script";
                    end  = true;
                    break;

                case 0x0B:
                    desc = "End behavior script";
                    end  = true;
                    break;

                case 0x0C:
                    desc = "Call ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x0D:
                    desc = "Add (float)" + bytesToInt(cmd, 2, 2) + " to the value at obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2");
                    break;

                case 0x0E:
                    desc = "(Set value) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = (float)" + bytesToInt(cmd, 2, 2);
                    break;

                case 0x0F:
                    desc = "Add " + (short)(bytesToInt(cmd, 2, 2) & 0xFFFF) + " to the value at obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2");
                    break;

                case 0x10:
                    desc = "(Set value) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = " + (short)(bytesToInt(cmd, 2, 2) & 0xFFFF);
                    break;

                case 0x11:
                    desc = "(Set bits) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " |= 0x" + bytesToInt(cmd, 2, 2).ToString("X4");
                    break;

                case 0x12:
                    desc = "(Clear bits) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " &= (0x" + bytesToInt(cmd, 2, 2).ToString("X4") + " ^ 0xFFFF)";
                    break;

                case 0x13:
                    desc = "(Set RNG) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = " + bytesToInt(cmd, 2, 2) + " + (randU16() >> " + bytesToInt(cmd, 4, 2) + ")";
                    break;

                case 0x14:
                    desc = "(Set float from multi) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = (float)" + bytesToInt(cmd, 2, 2) + " * (float)" + bytesToInt(cmd, 4, 2) + ")";
                    break;

                case 0x15:
                    desc = "(Set float RNG from multi) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = (float)" + bytesToInt(cmd, 2, 2) + " + (randFloat() * (float)" + bytesToInt(cmd, 4, 2) + ")";
                    break;

                case 0x16:
                    desc = "(Set float RNG from add) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = (float)" + bytesToInt(cmd, 2, 2) + " + randFloat() + (float)" + bytesToInt(cmd, 4, 2);
                    break;

                case 0x17:
                    desc = "(Set RNG) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = (obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " + " + bytesToInt(cmd, 2, 2) + ") + (randU16() >> " + bytesToInt(cmd, 4, 2) + ")";
                    break;

                case 0x18:
                case 0x19:
                case 0x1A:
                    desc = "Do nothing";
                    break;

                case 0x1B:
                    desc = "Set Model ID to 0x" + bytesToInt(cmd, 2, 2).ToString("X4");
                    break;

                case 0x1C:
                    desc = "Spawn child object (Model ID = 0x" + bytesToInt(cmd, 4, 4).ToString("X4") + ", Behavior = 0x" + bytesToInt(cmd, 8, 4).ToString("X8");
                    break;

                case 0x1D:
                    desc = "Deactivate object";
                    break;

                case 0x1E:
                    desc = "Drop object to ground, and object->_0xEC |= 0x2";
                    break;

                case 0x1F:
                    desc = "(Add floats) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2")
                           + " = (float)obj->_0x" + (cmd[2] * 4 + 0x88).ToString("X2")
                           + " + (float)obj->_0x" + (cmd[3] * 4 + 0x88).ToString("X2");
                    break;

                case 0x20:
                    desc = "(Add values) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2")
                           + " = obj->_0x" + (cmd[2] * 4 + 0x88).ToString("X2")
                           + " + obj->_0x" + (cmd[3] * 4 + 0x88).ToString("X2");
                    break;

                case 0x21:
                    desc = "Set billboarding flag in graph flags (obj->_0x02 |= 0x04)";
                    break;

                case 0x22:
                    desc = "Set 0x10 flag in graph flags (obj->_0x02 |= 0x10)";
                    break;

                case 0x23:
                    desc = "Set Collision sphere size (XZ radius = " + bytesToInt(cmd, 4, 2) + ", Y radius = " + bytesToInt(cmd, 6, 2) + ")";
                    break;

                case 0x24:
                    desc = "Do nothing. (Unused function)";
                    break;

                case 0x25:
                    desc = "obj->_0x1F4 = ((obj->_0x1F4 < (obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " - 1)) ? obj->_0x1F4 + 1 : 0)";
                    break;

                case 0x26:
                    desc = "Loop " + cmd[1] + " times";
                    break;

                case 0x27:
                    desc = "(Set word) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x28:
                    desc = "Set obj->_0x3C from (obj->_0x120 + 0x" + (cmd[1] * 4).ToString("X") + ")";
                    break;

                case 0x29:
                    desc = "Spawn child object (Model ID = 0x" + bytesToInt(cmd, 4, 4).ToString("X4") + ", Behavior = 0x" + bytesToInt(cmd, 8, 4).ToString("X8") + ", B.Param = 0x" + bytesToInt(cmd, 2, 2).ToString("X4");
                    break;

                case 0x2A:
                    desc = "Set collision address (obj->_0x218) from address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");;
                    break;

                case 0x2B:
                    desc = "Set Collision sphere size (XZ radius = " + bytesToInt(cmd, 4, 2) + ", Y radius = " + bytesToInt(cmd, 6, 2) + ", obj->_0x208 = " + bytesToInt(cmd, 8, 2) + ")";
                    break;

                case 0x2C:
                    desc = "(Spawn child object) obj->_0x6C = (Model ID = 0x" + bytesToInt(cmd, 4, 4).ToString("X4") + ", Behavior = 0x" + bytesToInt(cmd, 8, 4).ToString("X8");
                    break;

                case 0x2D:
                    desc = "Set inital position. (Used in Dorrie, Fly guys, etc. to determine in which range they can move)";
                    break;

                case 0x2E:
                    desc = "obj->_0x200 = (float)" + bytesToInt(cmd, 4, 2).ToString("X4") + ", obj->_0x204 = (float)" + bytesToInt(cmd, 6, 2).ToString("X4");
                    break;

                case 0x2F:
                    desc = "(Set interaction value) obj->_0x130 = 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x30:
                    desc =
                        "(Set gravity) obj->_0x128 = " + bytesToInt(cmd, 4, 2)
                        + "f, obj->_0xE8 = " + (bytesToInt(cmd, 6, 2) / 100.0f)
                        + "f, obj->_0x158 = " + (bytesToInt(cmd, 8, 2) / 100.0f)
                        + "f, obj->_0x12C = " + (bytesToInt(cmd, 10, 2) / 100.0f)
                        + "f, obj->_0x170 = " + (bytesToInt(cmd, 12, 2) / 100.0f)
                        + "f, obj->_0x174 = " + (bytesToInt(cmd, 14, 2) / 100.0f) + "f";
                    break;

                case 0x31:
                    desc = "obj->_0x190 = 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x32:
                    desc = "Set uniform scaling to " + (bytesToInt(cmd, 2, 2) / 100f) + "%";
                    break;

                case 0x33:
                    desc = "(Clear flags in child) obj->_0x68->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " &= ~0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    break;

                case 0x34:
                    desc = "(Increment texture animate rate) if((*0x8032D5D4) / " + bytesToInt(cmd, 2, 2) + " == 0) obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + "++";
                    break;

                case 0x35:
                    desc = "(Clear lsb of graph flags) obj->_0x2 &= 0xFFFE";
                    break;

                case 0x36:
                    desc = "obj->_0x" + (cmd[1] * 4 + 0x88).ToString("X2") + " = " +
                           ((short)bytesToInt(cmd, 4, 4)).ToString("X4");
                    break;
                }
                if (!alreadyAdded)
                {
                    addBehCommandToDump(ref dump, cmd, seg, off, desc);
                }
                off += cmdLen;
            }
        }
Example #27
0
 public void ThrowsWhenGivenANullLoader()
 {
     ROM rom = new ROM(null);
 }
Example #28
0
        private void EditShop(bool shop2)
        {
            var arc  = ROM.GetFile(GameFile.Shops);
            var data = arc[0];

            int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
            var   shop = FlatBufferConverter.DeserializeFrom <ShopInventory>(data);

            if (!shop2)
            {
                var table = shop.Shop1;
                var names = table.Select((z, _) => $"{(z.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray();
                var cache = new DirectCache <Shop1>(table);
                using var form = new GenericEditor <Shop1>(cache, names, $"{nameof(Shop1)} Editor", Randomize);
                form.ShowDialog();
                if (!form.Modified)
                {
                    arc.CancelEdits();
                    return;
                }

                void Randomize()
                {
                    foreach (var shopDefinition in table)
                    {
                        var items = shopDefinition.Inventory.Items;
                        for (int i = 0; i < items.Length; i++)
                        {
                            if (Legal.Pouch_TMHM_SM.Contains((ushort)items[i]) || items[i] == 1230) // skip TMs
                            {
                                continue;
                            }
                            items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
                        }
                    }
                }
            }
            else
            {
                var table = shop.Shop2;
                var names = table.Select((z, _) => $"{(z.SWSH.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray();
                var cache = new DirectCache <Shop2>(table);
                using var form = new GenericEditor <Shop2>(cache, names, $"{nameof(Shop2)} Editor", Randomize);
                form.ShowDialog();
                if (!form.Modified)
                {
                    arc.CancelEdits();
                    return;
                }

                void Randomize()
                {
                    foreach (var shopDefinition in table)
                    {
                        foreach (var inv in shopDefinition.Inventories)
                        {
                            var items = inv.Items;
                            for (int i = 0; i < items.Length; i++)
                            {
                                items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
                            }
                        }
                    }
                }
            }
            arc[0] = FlatBufferConverter.SerializeFrom(shop);
        }
Example #29
0
 public ByteRegister this[ROM r]
 {
     get { return this[(uint)r]; }
     set { this[(uint)r] = value; }
 }
Example #30
0
        public static void parse(ref Model3D mdl, ref Level lvl, byte seg, uint off)
        {
            if (seg == 0)
            {
                return;
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg);
            bool   end  = false;

            while (!end)
            {
                byte   cmdLen = getCmdLength(data[off]);
                byte[] cmd    = rom.getSubArray(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                if (cmd[0] != 0x05 && nodeCurrent.isSwitch && nodeCurrent.switchPos != 1)
                {
                    if (nodeCurrent.switchFunc == 0x8029DB48)
                    {
                        //rom.printArray(cmd, cmdLen);
                        //Console.WriteLine(nodeCurrent.switchPos);
                    }
                    nodeCurrent.switchPos++;
                    off += cmdLen;
                    continue;
                }

                switch (cmd[0])
                {
                case 0x00:
                case 0x01:
                    end = true;
                    break;

                case 0x02:
                    CMD_02(ref mdl, ref lvl, cmd);
                    break;

                case 0x03:
                    end = true;
                    break;

                case 0x04:
                    CMD_04();
                    break;

                case 0x05:
                    if (nodeCurrent != rootNode)
                    {
                        nodeCurrent = nodeCurrent.parent;
                    }
                    break;

                case 0x0E:
                    //rom.printArray(cmd, cmdLen);
                    CMD_0E(ref mdl, ref lvl, cmd);
                    break;

                case 0x10:
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x11:
                    //rom.printArray(cmd, cmdLen);
                    CMD_11(ref mdl, ref lvl, cmd);
                    break;

                case 0x13:
                    //rom.printArray(cmd, cmdLen);
                    CMD_13(ref mdl, ref lvl, cmd);
                    break;

                case 0x15:
                    CMD_15(ref mdl, ref lvl, cmd);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x1D:
                    CMD_1D(ref mdl, cmd);
                    break;
                }
                off += cmdLen;
                if (nodeCurrent.isSwitch)
                {
                    nodeCurrent.switchPos++;
                }
            }
        }
Example #31
0
    public void writeAllSprites(SortedList <ushort, List <i_sprite> > allSprites)
    {
        int[]     pointers = new int[roomPointers.Length];
        const int blah     = 2; //inspired by HM source code

        int lowestPointer = int.MaxValue;

        foreach (int i in roomPointers)
        {
            lowestPointer = Math.Min(lowestPointer, i);
        }

        List <byte> data = new List <byte>();

        for (ushort i = 0; i < roomPointers.Length; i++)
        {
            if (!allSprites.ContainsKey(i))
            {
                allSprites.Add(i, new List <i_sprite>());
            }
        }

        foreach (ushort i in allSprites.Keys)
        {
            if (allSprites[i].Count == 0)
            {
                pointers[i] = lowestPointer + sizeOfData - blah;
            }
            else
            {
                List <byte> data2 = new List <byte>();

                byte byteSortByte = 0x0;
                bool first        = true;
                foreach (i_sprite s in allSprites[i])
                {
                    byte[] b = null;
                    if (first)
                    {
                        b     = s.getBytes(out byteSortByte);
                        first = false;
                        data2.Add(byteSortByte);
                    }
                    else
                    {
                        b = s.getBytes(out byte temp);

                        if (temp != byteSortByte)
                        {
                            throw new Exception();
                        }
                    }

                    data2 = data2.Concat(b).ToList();
                }
                data2.Add(sprite_delim);

                pointers[i] = lowestPointer + data.Count;
                data        = data.Concat(data2).ToList();
            }
        }

        if (data.Count > sizeOfData - blah)
        {
            throw new Exception();
        }

        while (data.Count < sizeOfData - blah)
        {
            data.Add(sprite_delim);
        }

        data.Add(0xAA);
        data.Add(sprite_delim);

        List <byte> pointerData = new List <byte>();

        foreach (int address in pointers)
        {
            byte[] d = new byte[]
            {
                (byte)AddressLoROM.PcToSnes_Lo(address),
                (byte)AddressLoROM.PcToSnes_Hi(address)
            };

            pointerData = pointerData.Concat(d).ToList();
        }

        ROM.Write(secondaryPointer, size, pointerData.ToArray());
        ROM.Write(lowestPointer, sizeOfData, data.ToArray());
        updatePointers();
    }
Example #32
0
        public static void parse(ref Model3D mdl, ref Level lvl, byte seg, uint off, byte?areaID, int current_depth)
        {
            if (seg == 0 || current_depth >= 300)
            {
                return; // depth was added to prevent infinite loops with 0x06 command.
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg, areaID);
            if (data == null)
            {
                return;
            }
            bool end            = false;
            bool useUVOffsetFix = true;

            while (!end)
            {
                if (off + 8 > data.Length)
                {
                    return;
                }
                byte[] cmd = rom.getSubArray_safe(data, off, 8);
                if (!Enum.IsDefined(typeof(CMD), (int)cmd[0]))
                {
                    return;
                    //throw new Exception("UNDEFINED FAST3D COMMAND: 0x"+cmd[0].ToString("X2"));
                }
                string desc         = ((CMD)cmd[0]).ToString();
                bool   alreadyAdded = false;

                switch ((CMD)cmd[0])
                {
                case CMD.F3D_NOOP:
                    desc = "Do nothing";
                    if (bytesToInt(cmd, 0, 4) != 0)
                    {
                        return;
                    }
                    break;

                case CMD.F3D_MTX:
                    desc = "G_MTX";
                    // Detect if empty data has been found.
                    if (bytesToLong(cmd, 0) == 0x0101010101010101)
                    {
                        return;
                    }
                    break;

                case CMD.F3D_MOVEMEM:
                    switchTextureStatus(ref mdl, ref tempMaterial, true, areaID);
                    F3D_MOVEMEM(ref tempMaterial, ref lvl, cmd, ref desc, areaID);
                    break;

                case CMD.F3D_VTX:
                    switchTextureStatus(ref mdl, ref tempMaterial, false, areaID);
                    //if (tempMaterial.id != 0) return;
                    if (!F3D_VTX(vertices, ref lvl, cmd, ref desc, areaID, useUVOffsetFix))
                    {
                        return;
                    }
                    break;

                case CMD.F3D_DL:
                    alreadyAdded = true;
                    if (cmd[1] == 0x00)
                    {
                        desc = "Jump and link to display list at 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    }
                    else
                    {
                        desc = "Jump to display list at 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    }

                    addF3DCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                    F3D_DL(ref mdl, ref lvl, cmd, areaID, current_depth);
                    if (cmd[1] == 1)
                    {
                        end = true;
                    }
                    break;

                case CMD.F3D_CLEARGEOMETRYMODE:
                    tempMaterial.geometryMode &= ~bytesToInt(cmd, 4, 4);
                    break;

                case CMD.F3D_SETGEOMETRYMODE:
                    tempMaterial.geometryMode |= bytesToInt(cmd, 4, 4);
                    break;

                case CMD.F3D_ENDDL:
                    desc = "End of display list";
                    end  = true;
                    break;

                case CMD.F3D_TEXTURE:
                    F3D_TEXTURE(ref tempMaterial, cmd);
                    break;

                case CMD.F3D_TRI1:
                    switchTextureStatus(ref mdl, ref tempMaterial, false, areaID);
                    //if (tempMaterial.id != 0) return;
                    F3D_TRI1(vertices, ref mdl, ref lvl, ref tempMaterial, cmd, ref desc);
                    break;

                case CMD.G_RDPLOADSYNC:
                    desc = "RDP Load sync";
                    break;

                case CMD.G_RDPPIPESYNC:
                    desc = "RDP Pipe sync";
                    break;

                case CMD.G_RDPTILESYNC:
                    desc = "RDP Tile sync";
                    break;

                case CMD.G_RDPFULLSYNC:
                    desc = "RDP Full sync";
                    break;

                case CMD.G_LOADTLUT:
                    G_LOADTLUT(cmd, ref tempMaterial, ref desc, areaID);
                    break;

                case CMD.G_SETTILESIZE:
                    switchTextureStatus(ref mdl, ref tempMaterial, true, areaID);
                    G_SETTILESIZE(cmd, ref tempMaterial, ref desc);
                    break;

                case CMD.G_LOADBLOCK:
                    desc = "Load " + (((bytesToInt(cmd, 4, 4) >> 12) & 0xFFF) + 1) + " texels into texture memory cache";
                    break;

                case CMD.G_SETTILE:
                    G_SETTILE(ref tempMaterial, cmd);
                    break;

                case CMD.G_SETFOGCOLOR:
                    mdl.builder.UsesFog  = true;
                    mdl.builder.FogColor = Color.FromArgb(cmd[4], cmd[5], cmd[6]);
                    mdl.builder.FogColor_romLocation.Add(rom.getSegmentStart(seg, areaID) + off);
                    //Console.WriteLine("Fog color = 0x{0}", bytesToInt(cmd, 4, 4).ToString("X8"));
                    break;

                case CMD.G_SETCOMBINE:
                    if (G_SETCOMBINE(ref tempMaterial, cmd))
                    {
                        switchTextureStatus(ref mdl, ref tempMaterial, true, areaID);
                    }
                    break;

                case CMD.G_SETTIMG:
                    switchTextureStatus(ref mdl, ref tempMaterial, true, areaID);
                    G_SETTIMG(ref tempMaterial, cmd, ref desc);
                    break;

                case CMD.F3D_SETOTHERMODE_H:
                    processSetOtherMode_H(cmd, ref useUVOffsetFix);
                    break;
                }
                if (!alreadyAdded)
                {
                    addF3DCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                }
                off += 8;
            }
        }
Example #33
0
        public void EditGift()
        {
            var arc  = ROM.GetFile(GameFile.EncounterGift);
            var data = arc[0];
            var objs = FlatBufferConverter.DeserializeFrom <EncounterGift8Archive>(data);

            var gifts = objs.Table;
            var names = Enumerable.Range(0, gifts.Length).Select(z => $"{z:000}").ToArray();
            var cache = new DirectCache <EncounterGift8>(gifts);

            void Randomize()
            {
                int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
                var   pt = ROM.Data.PersonalData;

                int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
                            .Select((z, i) => new { Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame })
                            .Where(z => !z.Present).Select(z => z.Species).ToArray();

                var spec  = EditUtil.Settings.Species;
                var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
                var frand = new FormRandomizer(ROM.Data.PersonalData);

                srand.Initialize(spec, ban);
                foreach (var t in gifts)
                {
                    // swap gmax gifts and kubfu for other gmax capable species
                    if (t.CanGigantamax || t.Species == Species.Kubfu)
                    {
                        t.Species = (Species)Legal.GigantamaxForms[Randomization.Util.Random.Next(Legal.GigantamaxForms.Length)];
                        t.AltForm = t.Species == Species.Pikachu || t.Species == Species.Meowth ? 0 : frand.GetRandomForme((int)t.Species, false, false, false, false, ROM.Data.PersonalData.Table); // Pikachu & Meowth altforms can't gmax
                    }
                    else
                    {
                        t.Species = (Species)srand.GetRandomSpecies((int)t.Species);
                        t.AltForm = frand.GetRandomForme((int)t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
                    }

                    t.Ability   = Randomization.Util.Random.Next(1, 4); // 1, 2, or H
                    t.Ball      = (Ball)Randomization.Util.Random.Next(1, EncounterGift8.BallToItem.Length);
                    t.HeldItem  = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
                    t.Nature    = Nature.Random25;
                    t.Gender    = FixedGender.Random;
                    t.ShinyLock = Shiny.Random;
                    if (t.IV_Hp != -4 && t.IVs.Any(z => z != 31))
                    {
                        t.IVs = new[] { -1, -1, -1, -1, -1, -1 }
                    }
                    ;
                }
            }

            using var form = new GenericEditor <EncounterGift8>(cache, names, "Gift Pokémon Editor", Randomize);
            form.ShowDialog();
            if (!form.Modified)
            {
                arc.CancelEdits();
            }
            else
            {
                arc[0] = FlatBufferConverter.SerializeFrom(objs);
            }
        }
Example #34
0
 // private ROMType _type;
 public GameboyROM(byte[] buffer)
 {
     _rom = new ROM(buffer);
     // _type = ReadByte(0xA7) == 0x34 ? ROMType.Fusion : ROMType.ZeroMission;
 }
 protected static void Cmd07 <T>(ROM rom, T state)
 {
     rom.PopOffset();
     rom.AddOffset(8); // diff between 0x07 length and 0x06 length
 }