Beispiel #1
0
        private static SegmentedBank GetSegBank(RomManager rommgr, int segAddr, byte?AreaID)
        {
            var seg = rommgr.GetSegBank(Conversions.ToByte(segAddr >> 24), AreaID);

            seg.ReadDataIfNull(rommgr.RomFile);
            return(seg);
        }
Beispiel #2
0
        private SegmentedBank FromStream_GetSegBank(RomManager rommgr, int segAddr, byte?areaID)
        {
            SegmentedBank seg = null;

            if (rommgr is object)
            {
                seg = rommgr.GetSegBank(Conversions.ToByte(segAddr >> 24), areaID);
                seg?.ReadDataIfNull(rommgr.RomFile);
            }

            return(seg);
        }
Beispiel #3
0
        private void Read_GetStream(ref SegmentedBank curSegBank, ref Stream s, ref BinaryReader br, ref FileStream fs, ref BinaryReader brfs, RomManager rommgr, int scriptStartInBank, Dictionary <byte, BinaryReader> dicBankBinaryReaders, Dictionary <byte, SegmentedBank> segDic)
        {
            byte bankID = Conversions.ToByte(scriptStartInBank >> 24);

            curSegBank = rommgr.GetSegBank(bankID);
            if (curSegBank is null && segDic?.ContainsKey(bankID) == true)
            {
                curSegBank = segDic[bankID];
            }

            if (curSegBank?.Data is object)
            {
                s = curSegBank.Data;
                if (dicBankBinaryReaders.ContainsKey(curSegBank.BankID))
                {
                    br = dicBankBinaryReaders[curSegBank.BankID];
                }
                else
                {
                    br = new BinaryReader(curSegBank.Data);
                    dicBankBinaryReaders.Add(curSegBank.BankID, br);
                }
            }
            else
            {
                if (fs is null)
                {
                    fs = new FileStream(rommgr.RomFile, FileMode.Open, FileAccess.Read);
                }
                if (brfs is null)
                {
                    brfs = new BinaryReader(fs);
                }
                s  = fs;
                br = brfs;
            }

            if (curSegBank is object)
            {
                s.Position = s == fs?curSegBank.SegToRomAddr(scriptStartInBank) : curSegBank.BankOffsetFromSegAddr(scriptStartInBank);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Loads a SM64 Editor Level from ROM.
        /// </summary>
        /// <param name="lvl"></param>
        /// <param name="rommgr"></param>
        /// <param name="LevelID"></param>
        /// <param name="segAddress"></param>
        public void LoadLevel(Level lvl, RomManager rommgr, ushort LevelID, uint segAddress)
        {
            int customBGStart = 0;
            int customBGEnd   = 0;

            lvl.LevelID = LevelID;

            // Load Bank 0x19
            lvl.Bank0x19 = rommgr.GetSegBank(0x19);
            lvl.Bank0x19.ReadDataIfNull(rommgr.RomFile);
            if (lvl.Bank0x19.Length < 0x10000)
            {
                lvl.Bank0x19.Length = 0x10000;
            }

            if (!lvl.Closed)
            {
                lvl.Close();
            }
            lvl.Closed = false;

            // Lade Levelscript
            lvl.Levelscript = new Levelscript();
            lvl.Levelscript.Read(rommgr, Conversions.ToInteger(segAddress));

            // Erstelle Areas / Lade Einstellungen
            bool      AreaOnFly = false;
            LevelArea tArea     = null;
            var       CurrentLevelScriptCommands = lvl.Levelscript.ToArray();
            var       cmdsToRemove = new List <LevelscriptCommand>();
            LevelArea firstArea    = null;

            foreach (LevelscriptCommand c in CurrentLevelScriptCommands)
            {
                var switchExpr = c.CommandType;
                switch (switchExpr)
                {
                case LevelscriptCommandTypes.StartArea:
                {
                    AreaOnFly = true;
                    tArea     = new SM64ELevelArea();
                    if (firstArea is null)
                    {
                        firstArea = tArea;
                    }
                    tArea.AreaID          = clStartArea.GetAreaID(c);
                    tArea.GeolayoutOffset = clStartArea.GetSegGeolayoutAddr(c);
                    tArea.Geolayout.Read(rommgr, Conversions.ToInteger(tArea.GeolayoutOffset));
                    break;
                }

                case LevelscriptCommandTypes.EndOfArea:
                {
                    tArea.Levelscript.Add(c);
                    lvl.Levelscript.Remove(c);
                    lvl.Areas.Add(tArea);
                    AreaOnFly = false;
                    break;
                }

                case LevelscriptCommandTypes.AreaMusic:
                {
                    tArea.BGMusic = clAreaMusic.GetMusicID(c);
                    break;
                }

                case LevelscriptCommandTypes.AreaMusicSimple:
                {
                    tArea.BGMusic = clAreaMusicSimple.GetMusicID(c);
                    break;
                }

                case LevelscriptCommandTypes.Tarrain:
                {
                    tArea.TerrainType = (Geolayout.TerrainTypes)clTerrian.GetTerrainType(c);
                    break;
                }

                case LevelscriptCommandTypes.Normal3DObject:
                {
                    if (clNormal3DObject.GetSegBehaviorAddr(c) == (long)0x13003420)
                    {
                    }
                    // tArea.ScrollingTextures.Add(New ManagedScrollingTexture(c))
                    else
                    {
                        tArea.Objects.Add(c);
                    }

                    break;
                }

                case LevelscriptCommandTypes.ConnectedWarp:
                {
                    if ((new[] { 0xF0, 0xF1 }).Contains(clWarp.GetWarpID(c)))
                    {
                        tArea.WarpsForGame.Add(c);
                    }
                    else
                    {
                        tArea.Warps.Add(c);
                    }

                    break;
                }

                case LevelscriptCommandTypes.PaintingWarp:
                case LevelscriptCommandTypes.InstantWarp:
                {
                    tArea.Warps.Add(c);
                    break;
                }

                case LevelscriptCommandTypes.LoadRomToRam:
                {
                    byte bankID    = clLoadRomToRam.GetSegmentedID(c);
                    int  startAddr = clLoadRomToRam.GetRomStart(c);
                    int  endAddr   = clLoadRomToRam.GetRomEnd(c);
                    switch (bankID)
                    {
                    case 0xA:             // Background-Image
                    {
                        customBGStart = startAddr;
                        customBGEnd   = endAddr - 0x140;
                        break;
                    }

                    case 0xE:
                    {
                        rommgr.SetSegBank(bankID, startAddr, endAddr);
                        break;
                    }
                    }

                    break;
                }

                case LevelscriptCommandTypes.ShowDialog:
                {
                    if (AreaOnFly)
                    {
                        tArea.ShowMessage.Enabled  = true;
                        tArea.ShowMessage.DialogID = clShowDialog.GetDialogID(c);
                    }

                    break;
                }

                case LevelscriptCommandTypes.JumpBack:
                case LevelscriptCommandTypes.JumpToSegAddr:
                {
                    if (tArea is object)
                    {
                        cmdsToRemove.Add(c);
                    }
                    break;
                }
                }

                if (AreaOnFly && !cmdsToRemove.Contains(c))
                {
                    lvl.Levelscript.Remove(c);
                    tArea.Levelscript.Add(c);
                }
            }

            // Lösche alle Jump-Commands aus dem Levelscript
            foreach (LevelscriptCommand cmd in cmdsToRemove)
            {
                lvl.Levelscript.Remove(cmd);
                cmd.Close();
            }

            // Stelle frisches Levelscript wieder her
            lvl.CreateNewLevelscript();

            // Lösche alle Objekte und Warps aus dem Levelscript
            var lvlscrptidstoremove = new[] { LevelscriptCommandTypes.Normal3DObject, LevelscriptCommandTypes.ConnectedWarp, LevelscriptCommandTypes.PaintingWarp, LevelscriptCommandTypes.InstantWarp };

            foreach (var a in lvl.Areas)
            {
                foreach (var c in a.Levelscript.Where(n => lvlscrptidstoremove.Contains(n.CommandType)).ToArray())
                {
                    a.Levelscript.Remove(c);
                }
            }

            // Lese Custom Background Image
            var fs  = new FileStream(rommgr.RomFile, FileMode.Open, FileAccess.Read);
            var br2 = new BinaryReader(fs);

            lvl.Background.Enabled = false;
            foreach (LevelArea a in lvl.Areas)
            {
                var bgglcmd = a.Geolayout.Geolayoutscript.GetFirst(GeolayoutCommandTypes.Background);
                if (cgBackground.GetBackgroundPointer(bgglcmd) == 0)
                {
                    a.Background.Type  = AreaBGs.Color;
                    a.Background.Color = cgBackground.GetRrgbaColor(bgglcmd);
                }
                else
                {
                    a.Background.Type      = AreaBGs.Levelbackground;
                    lvl.Background.ID      = (Geolayout.BackgroundIDs)cgBackground.GetBackgroundID(bgglcmd);
                    lvl.Background.Enabled = true;
                }
            }

            if (lvl.Background.Enabled && lvl.Background.ID == Geolayout.BackgroundIDs.Custom)
            {
                fs.Position = customBGStart;
                lvl.Background.ReadImage(fs, customBGStart);
            }

            int          bank0x19RomStart;
            int          bank0x19RomEnd;
            BinaryReader brToUse;

            bank0x19RomStart = 0;
            bank0x19RomEnd   = lvl.Bank0x19.Length;
            brToUse          = new BinaryReader(lvl.Bank0x19.Data);

            // Lese Area-Modelle
            var modelBank         = rommgr.GetSegBank(0xE);
            int curMdlStartOffset = modelBank.RomStart;

            for (int i = 0, loopTo = lvl.Areas.Count - 1; i <= loopTo; i++)
            {
                var a            = lvl.Areas[i];
                int newEndOffset = GetModelEnd(fs, modelBank.RomStart, Conversions.ToByte(i));
                a.Bank0x0EOffset = Conversions.ToUInteger(curMdlStartOffset);
                rommgr.SetSegBank(0xE, Conversions.ToInteger(a.Bank0x0EOffset), newEndOffset, a.AreaID);
                a.AreaModel.Collision = new Model.Collision.CollisionMap();
                a.AreaModel.Collision.FromStream(fs, modelBank.SegToRomAddr(a.CollisionPointer));
                a.AreaModel.Fast3DBuffer = new Model.Fast3D.Fast3DBuffer();
                a.AreaModel.FromStream(fs, modelBank.RomStart, 0xE000000, curMdlStartOffset, newEndOffset - curMdlStartOffset, a.Geolayout.Geopointers.ToArray(), a.CollisionPointer);
                a.AreaModel.Collision.SpecialBoxes.Clear();
                curMdlStartOffset = newEndOffset;
            }

            // Lese alle Box-Daten
            firstArea.SpecialBoxes.Clear();
            firstArea.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.Water, bank0x19RomStart, bank0x19RomStart + 0x1810));
            firstArea.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.ToxicHaze, bank0x19RomStart, bank0x19RomStart + 0x1850));
            firstArea.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.Mist, bank0x19RomStart, bank0x19RomStart + 0x18A0));
            var areaWithBoxData = lvl.Areas.FirstOrDefault(n => n.AreaModel.Collision.SpecialBoxes.Any());

            if (areaWithBoxData is object)
            {
                for (int i = 0, loopTo1 = firstArea.SpecialBoxes.Count - 1; i <= loopTo1; i++)
                {
                    var boxdata = firstArea.AreaModel.Collision.SpecialBoxes.ElementAtOrDefault(i);
                    if (boxdata is object)
                    {
                        firstArea.SpecialBoxes[i].Y = boxdata.Y;
                    }
                }
            }

            // One-Bank-0xE-System
            lvl.OneBank0xESystemEnabled = true;

            // Act Selector
            General.PatchClass.Open(fs);
            lvl.ActSelector = General.PatchClass.get_ActSelector_Enabled(LevelID);

            // Hardcoded Camera
            lvl.HardcodedCameraSettings = General.PatchClass.get_HardcodedCamera_Enabled(LevelID);
            fs.Close();

            // Object-Banks
            lvl.MyObjectBanks.Clear();
            lvl.MyObjectBanks.Add(0xC, null);
            lvl.MyObjectBanks.Add(0xD, null);
            lvl.MyObjectBanks.Add(0x9, null);
        }
        /// <summary>
        /// Loads a ROM Manager Level from ROM.
        /// </summary>
        /// <param name="lvl"></param>
        /// <param name="rommgr"></param>
        /// <param name="LevelID"></param>
        /// <param name="segAddress"></param>
        public virtual void LoadLevel(Level lvl, RomManager rommgr, ushort LevelID, uint segAddress)
        {
            int customBGStart = 0;
            int customBGEnd   = 0;

            lvl.LevelID = LevelID;

            // Load Bank 0x19
            lvl.Bank0x19 = rommgr.GetSegBank(0x19);
            lvl.Bank0x19.ReadDataIfNull(rommgr.RomFile);

            // Close if not closed & re-open
            if (!lvl.Closed)
            {
                lvl.Close();
            }
            lvl.Closed = false;

            // Lade Levelscript
            lvl.Levelscript = new Levelscript();
            lvl.Levelscript.Read(rommgr, Conversions.ToInteger(segAddress));

            // Erstelle Areas / Lade Einstellungen
            bool      AreaOnFly = false;
            LevelArea tArea     = null;
            var       CurrentLevelScriptCommands = lvl.Levelscript.ToArray();
            var       cmdsToRemove = new List <LevelscriptCommand>();

            foreach (LevelscriptCommand c in CurrentLevelScriptCommands)
            {
                var switchExpr = c.CommandType;
                switch (switchExpr)
                {
                case LevelscriptCommandTypes.StartArea:
                    AreaOnFly             = true;
                    tArea                 = new RMLevelArea();
                    tArea.AreaID          = clStartArea.GetAreaID(c);
                    tArea.GeolayoutOffset = clStartArea.GetSegGeolayoutAddr(c);     // - bank0x19.BankAddress + bank0x19.RomStart
                    tArea.Geolayout.Read(rommgr, Conversions.ToInteger(tArea.GeolayoutOffset));
                    break;

                case LevelscriptCommandTypes.EndOfArea:
                    tArea.Levelscript.Add(c);
                    lvl.Levelscript.Remove(c);
                    lvl.Areas.Add(tArea);
                    AreaOnFly = false;
                    break;

                case LevelscriptCommandTypes.AreaMusic:
                    tArea.BGMusic = clAreaMusic.GetMusicID(c);
                    break;

                case LevelscriptCommandTypes.AreaMusicSimple:
                    tArea.BGMusic = clAreaMusicSimple.GetMusicID(c);
                    break;

                case LevelscriptCommandTypes.Tarrain:
                    tArea.TerrainType = (Geolayout.TerrainTypes)clTerrian.GetTerrainType(c);
                    break;

                case LevelscriptCommandTypes.Normal3DObject:
                    var scrollTexAddrs = new List <int>(new[] { 0x400000, 0x401700 });
                    if (rommgr.RomConfig.ScrollTexConfig.UseCustomBehavior)
                    {
                        scrollTexAddrs.Add(rommgr.RomConfig.ScrollTexConfig.CustomBehaviorAddress);
                    }
                    if (scrollTexAddrs.Contains((int)clNormal3DObject.GetSegBehaviorAddr(c)))
                    {
                        tArea.ScrollingTextures.Add(new ManagedScrollingTexture(c));
                    }
                    else
                    {
                        tArea.Objects.Add(c);
                    }
                    break;

                case LevelscriptCommandTypes.ConnectedWarp:
                    if ((new[] { 0xF0, 0xF1 }).Contains(clWarp.GetWarpID(c)))
                    {
                        tArea.WarpsForGame.Add(c);
                    }
                    else
                    {
                        tArea.Warps.Add(c);
                    }
                    break;

                case LevelscriptCommandTypes.PaintingWarp:
                case LevelscriptCommandTypes.InstantWarp:
                    tArea.Warps.Add(c);
                    break;

                case LevelscriptCommandTypes.LoadRomToRam:
                    byte bankID    = clLoadRomToRam.GetSegmentedID(c);
                    int  startAddr = clLoadRomToRam.GetRomStart(c);
                    int  endAddr   = clLoadRomToRam.GetRomEnd(c);
                    switch (bankID)
                    {
                    case 0xA:         // Background-Image
                        customBGStart = startAddr;
                        customBGEnd   = endAddr - 0x140;
                        break;

                    case 0x7:         // Global Object Bank
                        if (rommgr.GlobalModelBank?.CurSeg is object && startAddr == rommgr.GlobalModelBank.CurSeg.RomStart && endAddr == rommgr.GlobalModelBank.CurSeg.RomEnd)
                        {
                            lvl.EnableGlobalObjectBank = true;
                            lvl.LastGobCmdSegLoad      = c;
                        }
                        break;

                    case 0x9:
                        if (((RMLevel)lvl).Config.EnableLocalObjectBank)
                        {
                            lvl.EnableLocalObjectBank = true;
                        }
                        lvl.LastLobCmdSegLoad = c;
                        break;
                    }
                    break;

                case LevelscriptCommandTypes.ShowDialog:
                    if (AreaOnFly)
                    {
                        tArea.ShowMessage.Enabled  = true;
                        tArea.ShowMessage.DialogID = clShowDialog.GetDialogID(c);
                    }
                    break;

                case LevelscriptCommandTypes.JumpBack:
                case LevelscriptCommandTypes.JumpToSegAddr:
                    if (tArea is object)
                    {
                        cmdsToRemove.Add(c);
                    }
                    break;
                }

                if (AreaOnFly && !cmdsToRemove.Contains(c))
                {
                    lvl.Levelscript.Remove(c);
                    tArea.Levelscript.Add(c);
                }
            }

            // Lösche alle Jump-Commands aus dem Levelscript
            foreach (LevelscriptCommand cmd in cmdsToRemove)
            {
                lvl.Levelscript.Remove(cmd);
                cmd.Close();
            }

            // Lösche alle Objekte und Warps aus dem Levelscript
            var lvlscrptidstoremove = new[] { LevelscriptCommandTypes.Normal3DObject, LevelscriptCommandTypes.ConnectedWarp, LevelscriptCommandTypes.PaintingWarp, LevelscriptCommandTypes.InstantWarp };

            foreach (var a in lvl.Areas)
            {
                foreach (var c in a.Levelscript.Where(n => lvlscrptidstoremove.Contains(n.CommandType)).ToArray())
                {
                    a.Levelscript.Remove(c);
                }
            }

            // Load Local Object Bank
            if (lvl.LastLobCmdSegLoad is object)
            {
                var seg = new SegmentedBank()
                {
                    BankID   = clLoadRomToRam.GetSegmentedID(lvl.LastLobCmdSegLoad),
                    RomStart = clLoadRomToRam.GetRomStart(lvl.LastLobCmdSegLoad),
                    RomEnd   = clLoadRomToRam.GetRomEnd(lvl.LastLobCmdSegLoad)
                };
                lvl.LocalObjectBank.ReadFromSeg(rommgr, seg, ((RMLevel)lvl).Config.LocalObjectBank);
            }

            // Lese Custom Background Image
            var fs  = new FileStream(rommgr.RomFile, FileMode.Open, FileAccess.Read);
            var br2 = new BinaryReader(fs);

            lvl.Background.Enabled = false;
            foreach (LevelArea a in lvl.Areas)
            {
                var bgglcmd = a.Geolayout.Geolayoutscript.GetFirst(GeolayoutCommandTypes.Background);
                if (cgBackground.GetBackgroundPointer(bgglcmd) == 0)
                {
                    a.Background.Type  = AreaBGs.Color;
                    a.Background.Color = cgBackground.GetRrgbaColor(bgglcmd);
                }
                else
                {
                    a.Background.Type      = AreaBGs.Levelbackground;
                    lvl.Background.ID      = (Geolayout.BackgroundIDs)cgBackground.GetBackgroundID(bgglcmd);
                    lvl.Background.Enabled = true;
                }
            }

            if (customBGStart != 0)
            {
                lvl.Background.IsCustom = true;
            }

            foreach (int val in Enum.GetValues(typeof(Geolayout.BackgroundPointers)))
            {
                if (val != 0 && customBGStart == val)
                {
                    lvl.Background.IsCustom = false;
                }
            }

            if (lvl.Background.Enabled && lvl.Background.IsCustom) // .ID = Geolayout.BackgroundIDs.Custom Then
            {
                fs.Position = customBGStart;
                lvl.Background.ReadImage(fs, customBGStart);
            }

            int          bank0x19RomStart;
            int          bank0x19RomEnd;
            BinaryReader brToUse;

            bank0x19RomStart = 0;
            bank0x19RomEnd   = lvl.Bank0x19.Length;
            brToUse          = new BinaryReader(lvl.Bank0x19.Data);

            // Lese Area-Table
            foreach (LevelArea a in lvl.Areas)
            {
                // Fast3D-Daten
                brToUse.BaseStream.Position = bank0x19RomStart + 0x5F00 + a.AreaID * 0x10;
                a.Bank0x0EOffset            = Conversions.ToUInteger(SwapInts.SwapInt32(brToUse.ReadInt32()));
                int romEnd0xE = SwapInts.SwapInt32(brToUse.ReadInt32());
                rommgr.SetSegBank(0xE, Conversions.ToInteger(a.Bank0x0EOffset), romEnd0xE, a.AreaID);

                // 2D-Kamera
                brToUse.BaseStream.Position = bank0x19RomStart + 0x5F0F + a.AreaID * 0x10;
                a.Enable2DCamera            = Bits.GetBoolOfByte(brToUse.ReadByte(), 7);
            }

            // Lese Area-Modelle
            foreach (LevelArea a in lvl.Areas)
            {
                a.AreaModel.FromStream(fs, Conversions.ToInteger(a.Bank0x0EOffset), 0xE000000, a.Fast3DBankRomStart, a.Fast3DLength, a.Geolayout.Geopointers.ToArray(), a.CollisionPointer);
            }

            // Lese alle Box-Daten
            int CurrentBoxOffset = bank0x19RomStart + 0x6A00;

            foreach (LevelArea a in lvl.Areas)
            {
                // Clear special boxes
                a.SpecialBoxes.Clear();

                // Load special boxes
                a.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.Water, bank0x19RomStart, bank0x19RomStart + 0x6000 + 0x50 * a.AreaID));
                a.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.ToxicHaze, bank0x19RomStart, bank0x19RomStart + 0x6280 + 0x50 * a.AreaID));
                a.SpecialBoxes.AddRange(SpecialBoxList.ReadTable(brToUse.BaseStream, SpecialBoxType.Mist, bank0x19RomStart, bank0x19RomStart + 0x6500 + 0x50 * a.AreaID));

                for (int i = 0; i < a.SpecialBoxes.Count; i++)
                {
                    var boxdata = a.AreaModel.Collision.SpecialBoxes.ElementAtOrDefault(i);
                    if (boxdata is object)
                    {
                        a.SpecialBoxes[i].Y = boxdata.Y;
                    }
                }
            }

            // One-Bank-0xE-System
            lvl.OneBank0xESystemEnabled = true;

            // Act Selector
            General.PatchClass.Open(fs);
            lvl.ActSelector = General.PatchClass.get_ActSelector_Enabled(LevelID);

            // Hardcoded Camera
            lvl.HardcodedCameraSettings = General.PatchClass.get_HardcodedCamera_Enabled(LevelID);

            // Area Reverb
            if (EnableLoadingAreaReverb)
            {
                foreach (var area in lvl.Areas)
                {
                    if (area is RMLevelArea && area.AreaID >= 1 && area.AreaID <= 3)
                    {
                        fs.Position = 0xEE0C0 + lvl.LevelID * 3 + area.AreaID - 1;
                        ((RMLevelArea)area).ReverbLevel = (AreaReverbLevel)fs.ReadByte();
                    }
                }
            }

            fs.Close();
        }
Beispiel #6
0
        public void Read(RomManager rommgr, int segAddress)
        {
            Close();
            Clear();
            GeopointerOffsets.Clear();
            var segBank = rommgr.GetSegBank(Conversions.ToByte(segAddress >> 24));

            if (segBank is null)
            {
                return;
            }
            segBank.ReadDataIfNull(rommgr.RomFile);
            var data = new BinaryStreamData(segBank.Data);

            data.Position = segBank.BankOffsetFromSegAddr(segAddress);
            var tb = new List <byte>();
            GeolayoutCommandTypes cb = default;
            int  subNodeIndex        = 0;
            bool ende = false;

            while (!ende)
            {
                if (data.Position >= data.Length)
                {
                    break;
                }
                cb = (GeolayoutCommandTypes)data.ReadByte();
                byte lenth = 0;
                switch (cb)
                {
                case GeolayoutCommandTypes.Background:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.CameraPreset:
                    lenth = 0x14;
                    break;

                case GeolayoutCommandTypes.DrawingDistance:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.EndOfGeolayout:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.EndOfNode:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.JumpBack:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.JumpToSegAddr:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.LoadDisplaylist:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.LoadDisplaylistWithOffset:
                    lenth = 0xC;
                    break;

                case GeolayoutCommandTypes.ObjectShadown:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.Scale1:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.Scale2:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.StartOfNode:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.SetScreenRenderArea:
                    lenth = 0xC;
                    break;

                case GeolayoutCommandTypes.BillboardModel:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.BranchAndStore:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x0A:
                {
                    var switchExpr = data.ReadByte();
                    switch (switchExpr)
                    {
                    case 0x1:
                        lenth = 0xC;
                        break;

                    default:
                        lenth = 0x8;
                        break;
                    }

                    segBank.Data.Position -= 1;
                    break;
                }

                case GeolayoutCommandTypes.x0B:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.x0C:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.x0D:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x0E:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x10:
                    lenth = 0x10;
                    break;

                case GeolayoutCommandTypes.x11:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x12:
                {
                    var switchExpr = data.ReadByte() >> 4;
                    switch (switchExpr)
                    {
                    case 0x8:
                        lenth = 0xC;
                        break;

                    default:
                        lenth = 0x8;
                        break;
                    }

                    segBank.Data.Position -= 1;
                    break;
                }

                case GeolayoutCommandTypes.x17:
                    lenth = 0x4;
                    break;

                case GeolayoutCommandTypes.x18:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x1A:
                    lenth = 0x8;
                    break;

                case GeolayoutCommandTypes.x1C:
                    lenth = 0xC;
                    break;

                case var @case when @case == GeolayoutCommandTypes.x1E:
                    lenth = 0x8;
                    break;

                case var case1 when case1 == GeolayoutCommandTypes.x1f:
                    lenth = 0x10;
                    break;

                default:
                    break;
                }

                segBank.Data.Position -= 1;
                if (lenth == 0 || segBank.Data.Position + lenth > segBank.Data.Length)
                {
                    break;
                }

                for (int i = 1, loopTo = lenth; i <= loopTo; i++)
                {
                    tb.Add(data.ReadByte());
                }

                var tCommand   = new GeolayoutCommand(tb.ToArray());
                int bankOffset = (int)(segBank.Data.Position - lenth);
                tCommand.RomAddress  = segBank.RomStart + bankOffset;
                tCommand.BankAddress = segBank.BankAddress + bankOffset;
                Add(tCommand);
                tb.Clear();

                var switchExpr1 = tCommand.CommandType;
                switch (switchExpr1)
                {
                case GeolayoutCommandTypes.EndOfGeolayout:
                    ende = true;
                    break;

                case GeolayoutCommandTypes.EndOfNode:
                    subNodeIndex -= 1;
                    break;

                case GeolayoutCommandTypes.StartOfNode:
                    subNodeIndex += 1;
                    break;
                }
            }
        }
Beispiel #7
0
 public void ReadFromSeg(RomManager rommgr, byte bankID, ObjectModelConfig config)
 {
     ReadFromSeg(rommgr, rommgr.GetSegBank(bankID), config);
 }
Beispiel #8
0
        /// <summary>Parse a Displaylist to an Object3D.</summary>
        /// <param name="obj">The Object3D where the model should be parsed to.</param>
        /// <param name="dl">The Displaylist which should be parsed.</param>
        /// <param name="rommgr">The RomManager Instance to use.</param>
        /// <param name="AreaID">The Area ID if avaiable.</param>
        public static void Convert(Object3D obj, DisplayList dl, RomManager rommgr, byte?AreaID)
        {
            if (dl.Script.Count == 0 || dl.GeoPointer is null)
            {
                return;
            }
            int cmdIndex           = 0;
            DisplayListCommand cmd = null;

            byte[]   cmdarr                = null;
            var      knownTextures         = new Dictionary <int, Material>();
            var      knownColors           = new Dictionary <int, Color>();
            var      knownVertices         = new Dictionary <int, Vertex>();
            var      knownNormals          = new Dictionary <int, Normal>();
            var      knownUVs              = new Dictionary <int, UV>();
            var      knownVertexColors     = new Dictionary <int, VertexColor>();
            var      knownShading          = new Dictionary <int, Color>();
            var      dicVertexColorShading = new Dictionary <Color, VertexColor>();
            var      pointbuffer           = new Pilz.S3DFileParser.Point[16];
            var      scaledVertices        = new List <UV>();
            Material curTexture            = null;
            Size     curTexSize            = default;
            int      curTexSegAddr         = -1;
            int      curTexWrapT           = 10497;
            int      curTexWrapS           = 10497;
            var      curTexScale           = new System.Numerics.Vector2(1.0F, 1.0F);
            var      curTexPalette         = Array.Empty <byte>();
            int      curTexPaletteSegAddr  = -1;

            N64Graphics.N64Codec?curTexFormat = default;
            uint  curGeometryMode             = 0x22205;
            Mesh  curMesh  = null;
            Color?curColor = default;
            TextureLoadedInfos curTexLoadedInfos = null;
            bool useUVOffsetFix = true;
            int  dlDepth        = 0;

            // Load Main Segmented Bank
            var curSeg = GetSegBank(rommgr, dl.GeoPointer.SegPointer, AreaID);

            if (curSeg is null)
            {
                return;
            }

            curMesh = new Mesh();

            while (cmdIndex < dl.Script.Count /*&& dl.Script[cmdIndex].CommandType != CommandTypes.EndDisplaylist*/)
            {
                cmd    = dl.Script[cmdIndex];
                cmdarr = cmd.ToArray();
                var switchExpr = cmd.CommandType; // &H20000
                switch (switchExpr)
                {
                case CommandTypes.DisplayList:
                    if (cmdarr[1] != 1)
                    {
                        dlDepth += 1;
                    }
                    break;

                case CommandTypes.EndDisplaylist:
                    if (dlDepth > 0)
                    {
                        dlDepth -= 1;
                    }
                    break;

                case CommandTypes.ClearGeometryMode:
                {
                    curGeometryMode = curGeometryMode & ~F3D_CLEARGEOMETRYMODE.GetGeometryMode(cmd);
                    break;
                }

                case CommandTypes.SetGeometryMode:
                {
                    curGeometryMode = curGeometryMode | F3D_CLEARGEOMETRYMODE.GetGeometryMode(cmd);
                    break;
                }

                case CommandTypes.Movemem:
                {
                    int  segAddr = F3D_MOVEMEM.GetSegmentedOffset(cmd);
                    byte smode   = F3D_MOVEMEM.GetLightValueMode(cmd);
                    if (smode == 0x86)         // Load Shading Light (Diffuse) Color
                    {
                        if (knownShading.ContainsKey(segAddr))
                        {
                            curColor = knownShading[segAddr];
                        }
                        else
                        {
                            var colordata = new byte[4];
                            var seg       = rommgr.GetSegBank(Conversions.ToByte(segAddr >> 24), AreaID);

                            // Read Color Data
                            seg.Data.Position = segAddr & 0xFFFFFF;
                            seg.Data.Read(colordata, 0, colordata.Length);
                            curColor = Color.FromArgb(0xFF, colordata[0], colordata[1], colordata[2]);
                            if (!dicVertexColorShading.ContainsKey((Color)curColor))
                            {
                                // Create new Vertex Color
                                var vc = new VertexColor()
                                {
                                    R = colordata[0] / 256.0F, G = colordata[1] / 256.0F, B = colordata[2] / 256.0F, A = 1.0F
                                };
                                dicVertexColorShading.Add((Color)curColor, vc);
                            }

                            // Set as Vertex Color
                            knownShading.Add(segAddr, (Color)curColor);
                        }
                    }

                    break;
                }

                case CommandTypes.Loadtlut:
                {
                    byte   paletteTileDescritpr = cmdarr[4];
                    ushort numColorsToLoadInPalette;
                    curTexPaletteSegAddr     = curTexSegAddr;
                    cmd.Position             = 5;
                    numColorsToLoadInPalette = (ushort)(cmd.ReadUInt16() >> 6);
                    var seg = rommgr.GetSegBank(Conversions.ToByte(curTexPaletteSegAddr >> 24), AreaID);
                    curTexPalette = new byte[numColorsToLoadInPalette * 2 + 1 + 1];
                    int offset = curTexPaletteSegAddr & 0xFFFFFF;
                    for (int i = 1, loopTo = numColorsToLoadInPalette + 1; i <= loopTo; i++)
                    {
                        int ii = i * 2 - 2;
                        seg.Data.Position     = offset + ii;
                        curTexPalette[ii]     = Conversions.ToByte(seg.Data.ReadByte());
                        curTexPalette[ii + 1] = Conversions.ToByte(seg.Data.ReadByte());
                    }

                    break;
                }

                case CommandTypes.Triangle1:
                {
                    var f = new Face();
                    if (curTexFormat is object)
                    {
                        ProcessTexture(obj, rommgr, AreaID, dl, (N64Graphics.N64Codec)curTexFormat, knownTextures, ref curTexture, curTexSegAddr, curTexSize, curTexWrapT, curTexWrapS, curTexScale, curTexPalette, curTexPaletteSegAddr, curColor, ref curTexLoadedInfos);
                        f.Material = curTexture;
                    }

                    for (int i = 1; i <= 3; i++)
                    {
                        byte pindex = F3D_TRI1.GetVertice(cmd, Conversions.ToByte(i));
                        if (pindex >= pointbuffer.Length)
                        {
                            return;
                        }
                        var p = pointbuffer[pindex];
                        if (p is object)
                        {
                            f.Points.Add(p);
                        }
                    }

                    // Shading (as Vertex Color)
                    if (curTexture?.Color is object && (curGeometryMode & (long)0x20000) != 0)
                    {
                        var vc = dicVertexColorShading[(Color)curTexture.Color];
                        foreach (Pilz.S3DFileParser.Point p in f.Points)
                        {
                            if (p.VertexColor is null)
                            {
                                if (dicVertexColorShading.ContainsKey((Color)curTexture.Color))
                                {
                                    p.VertexColor = vc;
                                    if (!curMesh.VertexColors.Contains(vc))
                                    {
                                        curMesh.VertexColors.Add(vc);
                                    }
                                }
                            }
                        }
                    }

                    curMesh.Faces.Add(f);
                    break;
                }

                case CommandTypes.Vertex:
                {
                    byte  num        = F3D_VTX.GetNumberOfVertices(cmd);
                    byte  startindex = F3D_VTX.GetStartIndexInVertexBuffer(cmd);
                    short datalength = F3D_VTX.GetLengthOfVertexData(cmd);
                    int   segAddr    = F3D_VTX.GetSegmentedAddress(cmd);
                    if (num > 0)
                    {
                        for (int i = 0, loopTo1 = num; i <= loopTo1; i++)
                        {
                            var p          = new Pilz.S3DFileParser.Point();
                            int curSegAddr = segAddr + i * 0x10;
                            var cs         = GetSegBank(rommgr, curSegAddr, AreaID);
                            if (cs is null)
                            {
                                continue;
                            }

                            // Vertex
                            if (knownVertices.ContainsKey(curSegAddr))
                            {
                                p.Vertex = knownVertices[curSegAddr];
                            }
                            else
                            {
                                var vert = GetVertexFromStream(cs.Data, cs.BankOffsetFromSegAddr(curSegAddr), dl.GeoPointer.ModelOffset, dl.GeoPointer.ModelScale);
                                p.Vertex = vert;
                                curMesh.Vertices.Add(vert);
                                knownVertices.Add(curSegAddr, vert);
                            }

                            // UV
                            if (knownUVs.ContainsKey(curSegAddr))
                            {
                                p.UV = knownUVs[curSegAddr];
                            }
                            else
                            {
                                var uv = GetUVFromStream(cs.Data, cs.BankOffsetFromSegAddr(curSegAddr), curTexScale, curTexSize, useUVOffsetFix);
                                p.UV = uv;
                                curMesh.UVs.Add(uv);
                                knownUVs.Add(curSegAddr, uv);
                            }

                            if ((curGeometryMode & (long)0x20000) == 0)
                            {
                                // Vertex Color
                                if (knownVertexColors.ContainsKey(curSegAddr))
                                {
                                    p.VertexColor = knownVertexColors[curSegAddr];
                                }
                                else
                                {
                                    var vc = GetVertexColorFromStream(cs.Data, cs.BankOffsetFromSegAddr(curSegAddr));
                                    p.VertexColor = vc;
                                    curMesh.VertexColors.Add(vc);
                                    knownVertexColors.Add(curSegAddr, vc);
                                }
                            }
                            // Normal
                            else if (knownNormals.ContainsKey(curSegAddr))
                            {
                                p.Normal = knownNormals[curSegAddr];
                            }
                            else
                            {
                                var n = GetNormalFromStream(cs.Data, cs.BankOffsetFromSegAddr(curSegAddr));
                                p.Normal = n;
                                curMesh.Normals.Add(n);
                                knownNormals.Add(curSegAddr, n);
                            }

                            pointbuffer[startindex + i] = p;
                        }
                    }

                    break;
                }

                case CommandTypes.SetImage:
                {
                    int newAddr = F3D_SETIMG.GetSegmentedAddress(cmd);
                    if ((uint)newAddr != 0xFFFFFFFF)
                    {
                        curTexSegAddr = newAddr;
                    }

                    break;
                }

                case CommandTypes.SetTileSize:
                {
                    curTexSize = F3D_SETTILESIZE.GetSize(cmd);
                    break;
                }

                case CommandTypes.SetTile:
                {
                    cmd.Position = 4;
                    int checkVal = cmd.ReadInt32();
                    cmd.Position = 0;
                    if (checkVal != 0x7000000)
                    {
                        if (cmdarr[4] == 0)
                        {
                            curTexFormat = F3D_SETTILE.GetTextureFormat(cmd);
                        }

                        curTexWrapT = F3D_SETTILE.GetWrapT(cmd);
                        curTexWrapS = F3D_SETTILE.GetWrapS(cmd);
                    }

                    break;
                }

                case CommandTypes.Texture:
                {
                    if ((curGeometryMode & (long)0x40000) == 0x40000)
                    {
                        curTexSize = F3D_TEXTURE.GetTextureSize(cmd);
                    }
                    else
                    {
                        curTexScale = F3D_TEXTURE.GetTextureScaling(cmd);
                    }

                    break;
                }

                case CommandTypes.SetOtherMode_H:
                {
                    uint bits            = F3D_SETOTHERMODE_H.GetModeBits(cmd);
                    bool nearestNeighbor = (bits & (long)0x2000) == 0;
                    useUVOffsetFix = !nearestNeighbor;
                    break;
                }
                }

                cmdIndex += 1;
            }

            //if (curMesh.Faces.Any())
            obj.Meshes.Add(curMesh);
        }