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); }
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); }
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); } }
/// <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(); }
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; } } }
public void ReadFromSeg(RomManager rommgr, byte bankID, ObjectModelConfig config) { ReadFromSeg(rommgr, rommgr.GetSegBank(bankID), config); }
/// <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); }