/// <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(); }